quantaxis_rs/indicators/
moving_average.rs

1use std::f64::NAN;
2use std::fmt;
3
4use crate::{Close, Next, Reset, Update};
5use crate::errors::*;
6
7/// moving average (ma).
8///
9/// # Formula
10///
11/// ![ma](https://wikimedia.org/api/rest_v1/media/math/render/svg/e2bf09dc6deaf86b3607040585fac6078f9c7c89)
12///
13/// Where:
14///
15/// * _MA<sub>t</sub>_ - value of moving average at a point of time _t_
16/// * _n_ - number of periods (length)
17/// * _p<sub>t</sub>_ - input value at a point of time _t_
18///
19/// # Parameters
20///
21/// * _n_ - number of periods (integer greater than 0)
22///
23/// # Example
24///
25/// ```
26/// use quantaxis_rs::indicators::MovingAverage;
27/// use quantaxis_rs::Next;
28///
29/// let mut ma = MovingAverage::new(3).unwrap();
30/// assert_eq!(ma.next(10.0), 0.0);
31/// assert_eq!(ma.next(11.0), 0.0);
32/// assert_eq!(ma.next(12.0), 11.0);
33/// assert_eq!(ma.next(13.0), 12.0);
34/// ```
35///
36#[derive(Debug, Clone)]
37pub struct MovingAverage {
38    pub(crate) n: u32,
39    index: usize,
40    count: u32,
41    sum: f64,
42    vec: Vec<f64>,
43    pub cached: Vec<f64>
44}
45
46impl MovingAverage {
47    pub fn new(n: u32) -> Result<Self> {
48        match n {
49            0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
50            _ => {
51                let indicator = Self {
52                    n,
53                    index: 0,
54                    count: 1,
55                    sum: 0.0,
56                    vec: vec![0.0; n as usize],
57                    cached: vec![0.0; n as usize],
58                };
59                Ok(indicator)
60            }
61        }
62    }
63
64    pub fn is_real(&self)->bool{
65        self.count-1 >= self.n
66    }
67}
68
69impl Next<f64> for MovingAverage {
70    type Output = f64;
71
72    fn next(&mut self, input: f64) -> Self::Output {
73        self.index = (self.index + 1) % (self.n as usize);
74
75        let old_val = self.vec[self.index];
76        self.vec[self.index] = input;
77        let mut res = 0.0;
78
79        if self.count < self.n {
80            self.sum = self.sum - old_val + input;
81        } else {
82            self.sum = self.sum - old_val + input;
83            res = self.sum / (self.n as f64);
84        }
85        self.count += 1;
86        self.cached.push(res);
87        self.cached.remove(0);
88        res
89    }
90}
91
92
93impl<'a, T: Close> Next<&'a T> for MovingAverage {
94    type Output = f64;
95
96    fn next(&mut self, input: &'a T) -> Self::Output {
97        self.next(input.close())
98    }
99}
100
101impl Update<f64> for MovingAverage {
102    type Output = f64;
103
104    fn update(&mut self, input: f64) -> Self::Output {
105        //self.index = (self.index + 1) % (self.n as usize);
106
107        let old_val = self.vec[self.index];
108        self.vec[self.index] = input;
109        let mut res = 0.0;
110        self.count -= 1;
111        if self.count < self.n {
112            self.sum = self.sum - old_val + input;
113        } else {
114            self.sum = self.sum - old_val + input;
115            res = self.sum / (self.n as f64);
116        }
117        self.count += 1;
118        //println!("VEC {:#?} index {}, count {}", self.vec, self.index, self.count);
119        self.cached.remove((self.n - 1) as usize);
120        self.cached.push(res);
121        res
122    }
123}
124
125
126impl<'a, T: Close> Update<&'a T> for MovingAverage {
127    type Output = f64;
128
129    fn update(&mut self, input: &'a T) -> Self::Output {
130        self.update(input.close())
131    }
132}
133
134
135impl Reset for MovingAverage {
136    fn reset(&mut self) {
137        self.index = 0;
138        self.count = 0;
139        self.sum = 0.0;
140        for i in 0..(self.n as usize) {
141            self.vec[i] = 0.0;
142            self.cached[i] = 0.0;
143        }
144
145    }
146}
147
148impl Default for MovingAverage {
149    fn default() -> Self {
150        Self::new(9).unwrap()
151    }
152}
153
154impl fmt::Display for MovingAverage {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        write!(f, "ma({})", self.n)
157    }
158}
159
160#[cfg(test)]
161mod tests {
162    use crate::test_helper::*;
163
164    use super::*;
165
166    macro_rules! test_indicator {
167        ($i:tt) => {
168            #[test]
169            fn test_indicator() {
170                let bar = Bar::new();
171
172                // ensure Default trait is implemented
173                let mut indicator = $i::default();
174
175                // ensure Next<f64> is implemented
176                let first_output = indicator.next(12.3);
177
178                // ensure next accepts &DataItem as well
179                indicator.next(&bar);
180
181                // ensure Reset is implemented and works correctly
182                indicator.reset();
183                assert_eq!(indicator.next(12.3), first_output);
184
185                // ensure Display is implemented
186                format!("{}", indicator);
187            }
188        };
189    }
190    test_indicator!(MovingAverage);
191
192    #[test]
193    fn test_new() {
194        assert!(MovingAverage::new(0).is_err());
195        assert!(MovingAverage::new(1).is_ok());
196    }
197
198    #[test]
199    fn test_next() {
200        let mut ma = MovingAverage::new(4).unwrap();
201        assert_eq!(ma.next(4.0), 0.0);
202        assert_eq!(ma.next(5.0), 0.0);
203        assert_eq!(ma.next(6.0), 0.0);
204        assert_eq!(ma.next(6.0), 5.25);
205        assert_eq!(ma.next(6.0), 5.75);
206        assert_eq!(ma.next(6.0), 6.0);
207        assert_eq!(ma.next(2.0), 5.0);
208    }
209
210    #[test]
211    fn test_real() {
212        let mut ma = MovingAverage::new(4).unwrap();
213        ma.next(1.0);
214        assert_eq!(ma.is_real(), false);
215        ma.next(2.0);
216        assert_eq!(ma.is_real(), false);
217        ma.next(3.0);
218        assert_eq!(ma.is_real(), false);
219        ma.next(4.0);
220        assert_eq!(ma.is_real(), true);
221
222
223    }
224
225    #[test]
226    fn test_update() {
227        let mut ma = MovingAverage::new(2).unwrap();
228        assert_eq!(ma.next(5.0), 0.0);
229        assert_eq!(ma.update(6.0), 0.0);
230        assert_eq!(ma.next(7.0), 6.5);
231        assert_eq!(ma.update(8.0), 7.0);
232        assert_eq!(ma.next(9.0), 8.5);
233    }
234
235
236    #[test]
237    fn test_cached() {
238        let mut ma = MovingAverage::new(2).unwrap();
239        assert_eq!(ma.next(4.0), 0.0);
240        assert_eq!(ma.next(5.0), 4.5);
241        assert_eq!(ma.next(6.0), 5.5);
242        println!("{:#?}", ma.cached);
243        assert_eq!(ma.next(6.0), 6.0);
244        println!("{:#?}", ma.cached);
245        assert_eq!(ma.next(6.0), 6.0);
246        println!("{:#?}", ma.cached);
247        assert_eq!(ma.next(6.0), 6.0);
248        println!("{:#?}", ma.cached);
249        assert_eq!(ma.next(2.0), 4.0);
250        println!("{:#?}", ma.cached);
251    }
252
253    #[test]
254    fn test_next_with_bars() {
255        fn bar(close: f64) -> Bar {
256            Bar::new().close(close)
257        }
258
259        let mut ma = MovingAverage::new(3).unwrap();
260        assert_eq!(ma.next(&bar(4.0)), 0.0);
261        assert_eq!(ma.next(&bar(4.0)), 0.0);
262        assert_eq!(ma.next(&bar(7.0)), 5.0);
263        assert_eq!(ma.next(&bar(1.0)), 4.0);
264    }
265
266    #[test]
267    fn test_reset() {
268        let mut ma = MovingAverage::new(4).unwrap();
269        assert_eq!(ma.next(4.0), 0.0);
270        assert_eq!(ma.next(5.0), 0.0);
271        assert_eq!(ma.next(6.0), 0.0);
272        assert_eq!(ma.next(5.0), 5.0);
273        ma.reset();
274        assert_eq!(ma.next(99.0), 0.0);
275    }
276
277    #[test]
278    fn test_default() {
279        MovingAverage::default();
280    }
281
282    #[test]
283    fn test_display() {
284        let ma = MovingAverage::new(5).unwrap();
285        assert_eq!(format!("{}", ma), "ma(5)");
286    }
287}