cxmr_ta_core/indicators/
standard_deviation.rs1use std::fmt;
2
3use crate::errors::*;
4use crate::{Calculate, Close, Next, Reset};
5
6#[derive(Debug, Clone)]
40pub struct StandardDeviation {
41 n: u32,
42 index: usize,
43 count: u32,
44 m: f64,
45 m2: f64,
46 vec: Vec<f64>,
47}
48
49impl StandardDeviation {
50 pub fn new(n: u32) -> Result<Self> {
51 match n {
52 0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
53 _ => {
54 let std = StandardDeviation {
55 n,
56 index: 0,
57 count: 0,
58 m: 0.0,
59 m2: 0.0,
60 vec: vec![0.0; n as usize],
61 };
62 Ok(std)
63 }
64 }
65 }
66}
67
68impl Calculate for StandardDeviation {
69 fn calc(&mut self, input: f64) -> f64 {
70 self.index = (self.index + 1) % (self.n as usize);
71
72 let old_val = self.vec[self.index];
73 self.vec[self.index] = input;
74
75 if self.count < self.n {
76 self.count += 1;
77 let delta = input - self.m;
78 self.m += delta / self.count as f64;
79 let delta2 = input - self.m;
80 self.m2 += delta * delta2;
81 } else {
82 let delta = input - old_val;
83 let old_m = self.m;
84 self.m += delta / self.n as f64;
85 let delta2 = input - self.m + old_val - old_m;
86 self.m2 += delta * delta2;
87 }
88
89 (self.m2 / self.count as f64).sqrt()
90 }
91}
92
93impl<T: Close> Next<T> for StandardDeviation {
94 fn next(&mut self, input: &T) -> f64 {
95 self.calc(input.close())
96 }
97}
98
99impl Reset for StandardDeviation {
100 fn reset(&mut self) {
101 self.index = 0;
102 self.count = 0;
103 self.m = 0.0;
104 self.m2 = 0.0;
105 for i in 0..(self.n as usize) {
106 self.vec[i] = 0.0;
107 }
108 }
109}
110
111impl Default for StandardDeviation {
112 fn default() -> Self {
113 Self::new(9).unwrap()
114 }
115}
116
117impl fmt::Display for StandardDeviation {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 write!(f, "SD({})", self.n)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use crate::test_helper::*;
127
128 test_indicator!(StandardDeviation);
129
130 #[test]
131 fn test_new() {
132 assert!(StandardDeviation::new(0).is_err());
133 assert!(StandardDeviation::new(1).is_ok());
134 }
135
136 #[test]
137 fn test_next() {
138 let mut sd = StandardDeviation::new(4).unwrap();
139 assert_eq!(sd.calc(10.0), 0.0);
140 assert_eq!(sd.calc(20.0), 5.0);
141 assert_eq!(round(sd.calc(30.0)), 8.165);
142 assert_eq!(round(sd.calc(20.0)), 7.071);
143 assert_eq!(round(sd.calc(10.0)), 7.071);
144 assert_eq!(round(sd.calc(100.0)), 35.355);
145 }
146
147 #[test]
148 fn test_next_with_bars() {
149 fn bar(close: f64) -> Bar {
150 Bar::new().close(close)
151 }
152
153 let mut sd = StandardDeviation::new(4).unwrap();
154 assert_eq!(sd.next(&bar(10.0)), 0.0);
155 assert_eq!(sd.next(&bar(20.0)), 5.0);
156 assert_eq!(round(sd.next(&bar(30.0))), 8.165);
157 assert_eq!(round(sd.next(&bar(20.0))), 7.071);
158 assert_eq!(round(sd.next(&bar(10.0))), 7.071);
159 assert_eq!(round(sd.next(&bar(100.0))), 35.355);
160 }
161
162 #[test]
163 fn test_next_same_values() {
164 let mut sd = StandardDeviation::new(3).unwrap();
165 assert_eq!(sd.calc(4.2), 0.0);
166 assert_eq!(sd.calc(4.2), 0.0);
167 assert_eq!(sd.calc(4.2), 0.0);
168 assert_eq!(sd.calc(4.2), 0.0);
169 }
170
171 #[test]
172 fn test_reset() {
173 let mut sd = StandardDeviation::new(4).unwrap();
174 assert_eq!(sd.calc(10.0), 0.0);
175 assert_eq!(sd.calc(20.0), 5.0);
176 assert_eq!(round(sd.calc(30.0)), 8.165);
177
178 sd.reset();
179 assert_eq!(sd.calc(20.0), 0.0);
180 }
181
182 #[test]
183 fn test_default() {
184 StandardDeviation::default();
185 }
186
187 #[test]
188 fn test_display() {
189 let sd = StandardDeviation::new(5).unwrap();
190 assert_eq!(format!("{}", sd), "SD(5)");
191 }
192}