quantaxis_rs/indicators/
moving_average.rs1use std::f64::NAN;
2use std::fmt;
3
4use crate::{Close, Next, Reset, Update};
5use crate::errors::*;
6
7#[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 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 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 let mut indicator = $i::default();
174
175 let first_output = indicator.next(12.3);
177
178 indicator.next(&bar);
180
181 indicator.reset();
183 assert_eq!(indicator.next(12.3), first_output);
184
185 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}