Skip to main content

quantwave_core/indicators/patterns/
cdlrickshawman.rs

1//! Native O(1) streaming CDLRICKSHAWMAN (matches `talib_rs::pattern::cdl_rickshawman`).
2//! Source: TA-Lib
3
4use crate::indicators::patterns::candle_settings::{
5    BODY_DOJI, CandleWindow, NEAR, RollingCandleAvg, SHADOW_LONG, lower_shadow, real_body,
6    upper_shadow,
7};
8use crate::traits::Next;
9
10const LOOKBACK: usize = 10; // max(10, 0, 5)
11
12#[derive(Debug, Clone)]
13#[allow(non_camel_case_types)]
14pub struct CDLRICKSHAWMAN {
15    bars_seen: usize,
16    window: CandleWindow,
17    body_doji: RollingCandleAvg,
18    shadow_long: RollingCandleAvg,
19    near: RollingCandleAvg,
20}
21
22impl CDLRICKSHAWMAN {
23    pub fn new() -> Self {
24        Self {
25            bars_seen: 0,
26            window: CandleWindow::new(1),
27            body_doji: RollingCandleAvg::new(BODY_DOJI),
28            shadow_long: RollingCandleAvg::new(SHADOW_LONG),
29            near: RollingCandleAvg::new(NEAR),
30        }
31    }
32}
33
34impl Default for CDLRICKSHAWMAN {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40impl Next<(f64, f64, f64, f64)> for CDLRICKSHAWMAN {
41    type Output = f64;
42
43    fn next(&mut self, (open, high, low, close): (f64, f64, f64, f64)) -> Self::Output {
44        self.bars_seen += 1;
45        self.window.push(open, high, low, close);
46        self.body_doji.push(open, high, low, close);
47        self.shadow_long.push(open, high, low, close);
48        self.near.push(open, high, low, close);
49
50        if self.bars_seen <= LOOKBACK {
51            return 0.0;
52        }
53
54        let curr = self.window.bar(0);
55
56        let mid = curr.low + (curr.high - curr.low) / 2.0;
57        let near_avg = self.near.val(0);
58
59        let out = (real_body(curr.open, curr.close) <= self.body_doji.val(0)
60            && lower_shadow(curr.open, curr.low, curr.close) > self.shadow_long.val(0)
61            && upper_shadow(curr.open, curr.high, curr.close) > self.shadow_long.val(0)
62            && curr.open.min(curr.close) <= mid + near_avg
63            && curr.open.max(curr.close) >= mid - near_avg) as i32
64            * 100;
65
66        out as f64
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    crate::test_pattern_parity!(
74        test_cdlrickshawman_parity,
75        CDLRICKSHAWMAN,
76        talib_rs::pattern::cdl_rickshawman
77    );
78}