ta/indicators/
mean_absolute_deviation.rs

1use 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/// Mean Absolute Deviation (MAD)
10///
11/// The mean absolute deviation of a data set is the average of the absolute deviations from a
12/// central point. It is a summary statistic of statistical dispersion or variability.
13/// In the general form, the central point can be a mean, median, mode, or the result of any other
14/// measure of central tendency or any random data point related to the given data set.
15/// The absolute values of the differences between the data points and their central tendency are
16/// totaled and divided by the number of data points.
17///
18/// # Formula
19///
20/// MAD(_period_) = { x<sub>1</sub> - ABS(AVG(_period_)), ..., x<sub>_period_</sub> - ABS(AVG(_period_)) } / _period_
21///
22/// # Parameters
23///
24/// * _period_ - number of periods (integer greater than 0). Default is 9.
25///
26/// # Links
27///
28/// * [Mean Absolute Deviation, Wikipedia](https://en.wikipedia.org/wiki/Mean_absolute_deviation)
29///
30#[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}