finlib_ta/indicators/
mean_absolute_deviation.rs1use core::fmt;
2use alloc::boxed::Box;
3use alloc::vec;
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use crate::errors::{Result, TaError};
9use crate::{Close, Next, Period, Reset};
10
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[derive(Debug, Clone)]
34pub struct MeanAbsoluteDeviation {
35 period: usize,
36 index: usize,
37 count: usize,
38 sum: f64,
39 deque: Box<[f64]>,
40}
41
42impl MeanAbsoluteDeviation {
43 pub fn new(period: usize) -> Result<Self> {
44 match period {
45 0 => Err(TaError::InvalidParameter),
46 _ => Ok(Self {
47 period,
48 index: 0,
49 count: 0,
50 sum: 0.0,
51 deque: vec![0.0; period].into_boxed_slice(),
52 }),
53 }
54 }
55}
56
57impl Period for MeanAbsoluteDeviation {
58 fn period(&self) -> usize {
59 self.period
60 }
61}
62
63impl Next<f64> for MeanAbsoluteDeviation {
64 type Output = f64;
65
66 fn next(&mut self, input: f64) -> Self::Output {
67 self.sum = if self.count < self.period {
68 self.count = self.count + 1;
69 self.sum + input
70 } else {
71 self.sum + input - self.deque[self.index]
72 };
73
74 self.deque[self.index] = input;
75 self.index = if self.index + 1 < self.period {
76 self.index + 1
77 } else {
78 0
79 };
80
81 let mean = self.sum / self.count as f64;
82
83 let mut mad = 0.0;
84 for value in &self.deque[..self.count] {
85 mad += (value - mean).abs();
86 }
87 mad / self.count as f64
88 }
89}
90
91impl<T: Close> Next<&T> for MeanAbsoluteDeviation {
92 type Output = f64;
93
94 fn next(&mut self, input: &T) -> Self::Output {
95 self.next(input.close())
96 }
97}
98
99impl Reset for MeanAbsoluteDeviation {
100 fn reset(&mut self) {
101 self.index = 0;
102 self.count = 0;
103 self.sum = 0.0;
104 for i in 0..self.period {
105 self.deque[i] = 0.0;
106 }
107 }
108}
109
110impl Default for MeanAbsoluteDeviation {
111 fn default() -> Self {
112 Self::new(9).unwrap()
113 }
114}
115
116impl fmt::Display for MeanAbsoluteDeviation {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 write!(f, "MAD({})", self.period)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use crate::test_helper::*;
126 use alloc::format;
127
128 test_indicator!(MeanAbsoluteDeviation);
129
130 #[test]
131 fn test_new() {
132 assert!(MeanAbsoluteDeviation::new(0).is_err());
133 assert!(MeanAbsoluteDeviation::new(1).is_ok());
134 }
135
136 #[test]
137 fn test_next() {
138 let mut mad = MeanAbsoluteDeviation::new(5).unwrap();
139
140 assert_eq!(round(mad.next(1.5)), 0.0);
141 assert_eq!(round(mad.next(4.0)), 1.25);
142 assert_eq!(round(mad.next(8.0)), 2.333);
143 assert_eq!(round(mad.next(4.0)), 1.813);
144 assert_eq!(round(mad.next(4.0)), 1.48);
145 assert_eq!(round(mad.next(1.5)), 1.48);
146 }
147
148 #[test]
149 fn test_reset() {
150 let mut mad = MeanAbsoluteDeviation::new(5).unwrap();
151
152 assert_eq!(round(mad.next(1.5)), 0.0);
153 assert_eq!(round(mad.next(4.0)), 1.25);
154
155 mad.reset();
156
157 assert_eq!(round(mad.next(1.5)), 0.0);
158 assert_eq!(round(mad.next(4.0)), 1.25);
159 }
160
161 #[test]
162 fn test_default() {
163 MeanAbsoluteDeviation::default();
164 }
165
166 #[test]
167 fn test_display() {
168 let indicator = MeanAbsoluteDeviation::new(10).unwrap();
169 assert_eq!(format!("{}", indicator), "MAD(10)");
170 }
171}