wickra_core/indicators/
macd_fix.rs1use crate::error::Result;
4use crate::indicators::macd::{MacdIndicator, MacdOutput};
5use crate::traits::Indicator;
6
7#[derive(Debug, Clone)]
28pub struct MacdFix {
29 inner: MacdIndicator,
30}
31
32impl MacdFix {
33 pub fn new(signal: usize) -> Result<Self> {
38 Ok(Self {
39 inner: MacdIndicator::new(12, 26, signal)?,
40 })
41 }
42
43 pub fn signal_period(&self) -> usize {
45 self.inner.periods().2
46 }
47}
48
49impl Indicator for MacdFix {
50 type Input = f64;
51 type Output = MacdOutput;
52
53 #[inline]
54 fn update(&mut self, value: f64) -> Option<MacdOutput> {
55 self.inner.update(value)
56 }
57
58 fn reset(&mut self) {
59 self.inner.reset();
60 }
61
62 #[inline]
63 fn warmup_period(&self) -> usize {
64 self.inner.warmup_period()
65 }
66
67 #[inline]
68 fn is_ready(&self) -> bool {
69 self.inner.is_ready()
70 }
71
72 #[inline]
73 fn name(&self) -> &'static str {
74 "MACDFIX"
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::traits::BatchExt;
82
83 #[test]
84 fn rejects_zero_signal() {
85 assert!(MacdFix::new(0).is_err());
86 }
87
88 #[test]
89 fn accessors_report_config() {
90 let m = MacdFix::new(9).unwrap();
91 assert_eq!(m.signal_period(), 9);
92 assert_eq!(m.name(), "MACDFIX");
93 assert!(!m.is_ready());
94 assert_eq!(
95 m.warmup_period(),
96 MacdIndicator::new(12, 26, 9).unwrap().warmup_period()
97 );
98 }
99
100 #[test]
101 fn matches_macd_with_fixed_periods() {
102 let prices: Vec<f64> = (0..80)
103 .map(|i| 100.0 + (f64::from(i) * 0.3).sin() * 5.0)
104 .collect();
105 let fix: Vec<Option<MacdOutput>> = MacdFix::new(9).unwrap().batch(&prices);
106 let classic: Vec<Option<MacdOutput>> =
107 MacdIndicator::new(12, 26, 9).unwrap().batch(&prices);
108 assert_eq!(fix, classic);
109 assert!(fix.iter().any(Option::is_some));
110 }
111
112 #[test]
113 fn reset_clears_state() {
114 let prices: Vec<f64> = (0..80).map(|i| 100.0 + f64::from(i)).collect();
115 let mut m = MacdFix::new(9).unwrap();
116 let _ = m.batch(&prices);
117 assert!(m.is_ready());
118 m.reset();
119 assert!(!m.is_ready());
120 }
121}