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