quantwave_core/indicators/patterns/
cdlhammer.rs1use crate::indicators::patterns::candle_settings::{
5 BODY_SHORT, CandleWindow, NEAR, RollingCandleAvg, SHADOW_LONG, SHADOW_VERY_SHORT, lower_shadow,
6 real_body, upper_shadow,
7};
8use crate::traits::Next;
9
10const LOOKBACK: usize = 11; #[derive(Debug, Clone)]
13#[allow(non_camel_case_types)]
14pub struct CDLHAMMER {
15 bars_seen: usize,
16 window: CandleWindow,
17 body_short: RollingCandleAvg,
18 shadow_long: RollingCandleAvg,
19 shadow_vs: RollingCandleAvg,
20 near: RollingCandleAvg,
21}
22
23impl CDLHAMMER {
24 pub fn new() -> Self {
25 Self {
26 bars_seen: 0,
27 window: CandleWindow::new(2),
28 body_short: RollingCandleAvg::new(BODY_SHORT),
29 shadow_long: RollingCandleAvg::new(SHADOW_LONG),
30 shadow_vs: RollingCandleAvg::new(SHADOW_VERY_SHORT),
31 near: RollingCandleAvg::new(NEAR),
32 }
33 }
34}
35
36impl Default for CDLHAMMER {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl Next<(f64, f64, f64, f64)> for CDLHAMMER {
43 type Output = f64;
44
45 fn next(&mut self, (open, high, low, close): (f64, f64, f64, f64)) -> Self::Output {
46 self.bars_seen += 1;
47 self.window.push(open, high, low, close);
48 self.body_short.push(open, high, low, close);
49 self.shadow_long.push(open, high, low, close);
50 self.shadow_vs.push(open, high, low, close);
51 self.near.push(open, high, low, close);
52
53 if self.bars_seen <= LOOKBACK {
54 return 0.0;
55 }
56
57 let curr = self.window.bar(0);
58 let prev = self.window.bar(1);
59
60 let out = (real_body(curr.open, curr.close) < self.body_short.val(0)
61 && lower_shadow(curr.open, curr.low, curr.close) > self.shadow_long.val(0)
62 && upper_shadow(curr.open, curr.high, curr.close) < self.shadow_vs.val(0)
63 && curr.open.min(curr.close) <= prev.low + self.near.val(1)) 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_cdlhammer_parity,
75 CDLHAMMER,
76 talib_rs::pattern::cdl_hammer
77 );
78}