ux_indicators/indicators/
sd.rs

1#![allow(dead_code)]
2
3use std::fmt;
4
5use crate::errors::*;
6use crate::{Close, Next, Reset};
7
8use crate::{Factory};
9use crate::indicators::SimpleMovingAverage;
10
11pub struct SdFactory {
12}
13
14impl SdFactory {
15    pub fn new() -> Self {
16        Self{}
17    }
18}
19
20impl Factory for SdFactory {
21    fn create() -> Box<dyn Next<f64, Output = Box<[f64]>>> {
22        Box::new(SimpleMovingAverage::default())
23    }
24}
25
26/// Standard deviation (SD).
27///
28/// Returns the standard deviation of the last n values.
29///
30/// # Formula
31///
32/// ![SD formula](https://wikimedia.org/api/rest_v1/media/math/render/svg/2845de27edc898d2a2a4320eda5f57e0dac6f650)
33///
34/// Where:
35///
36/// * _σ_ - value of standard deviation for N given probes.
37/// * _N_ - number of probes in observation.
38/// * _x<sub>i</sub>_ - i-th observed value from N elements observation.
39///
40/// # Parameters
41///
42/// * _n_ - number of periods (integer greater than 0)
43///
44/// # Example
45///
46/// ```
47/// use core::indicators::StandardDeviation;
48/// use core::Next;
49///
50/// let mut sd = StandardDeviation::new(3).unwrap();
51/// assert_eq!(sd.next(10.0), 0.0);
52/// assert_eq!(sd.next(20.0), 5.0);
53/// ```
54///
55/// # Links
56///
57/// * [Standard Deviation, Wikipedia](https://en.wikipedia.org/wiki/Standard_deviation)
58///
59
60#[derive(Debug, Clone)]
61pub struct StandardDeviation {
62    n: u32,
63    index: usize,
64    count: u32,
65    m: f64,
66    m2: f64,
67    vec: Vec<f64>,
68}
69
70impl StandardDeviation {
71    pub fn new(n: u32) -> Result<Self> {
72        match n {
73            0 => Err(Error::from_kind(ErrorKind::InvalidParameter)),
74            _ => {
75                let std = StandardDeviation {
76                    n,
77                    index: 0,
78                    count: 0,
79                    m: 0.0,
80                    m2: 0.0,
81                    vec: vec![0.0; n as usize],
82                };
83                Ok(std)
84            }
85        }
86    }
87
88    pub(super) fn mean(&self) -> f64 {
89        self.m
90    }
91}
92
93impl Next<f64> for StandardDeviation {
94    type Output = f64;
95
96    fn next(&mut self, input: f64) -> Self::Output {
97        self.index = (self.index + 1) % (self.n as usize);
98
99        let old_val = self.vec[self.index];
100        self.vec[self.index] = input;
101
102        if self.count < self.n {
103            self.count += 1;
104            let delta = input - self.m;
105            self.m += delta / self.count as f64;
106            let delta2 = input - self.m;
107            self.m2 += delta * delta2;
108        } else {
109            let delta = input - old_val;
110            let old_m = self.m;
111            self.m += delta / self.n as f64;
112            let delta2 = input - self.m + old_val - old_m;
113            self.m2 += delta * delta2;
114        }
115
116        (self.m2 / self.count as f64).sqrt()
117    }
118}
119
120impl<'a, T: Close> Next<&'a T> for StandardDeviation {
121    type Output = f64;
122
123    fn next(&mut self, input: &'a T) -> Self::Output {
124        self.next(input.close())
125    }
126}
127
128impl Reset for StandardDeviation {
129    fn reset(&mut self) {
130        self.index = 0;
131        self.count = 0;
132        self.m = 0.0;
133        self.m2 = 0.0;
134        for i in 0..(self.n as usize) {
135            self.vec[i] = 0.0;
136        }
137    }
138}
139
140impl Default for StandardDeviation {
141    fn default() -> Self {
142        Self::new(9).unwrap()
143    }
144}
145
146impl fmt::Display for StandardDeviation {
147    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
148        write!(f, "SD({})", self.n)
149    }
150}
151
152#[cfg(test)]
153mod tests {
154    use super::*;
155    use crate::test_helper::*;
156
157    // test_indicator!(StandardDeviation);
158
159    #[test]
160    fn test_new() {
161        assert!(StandardDeviation::new(0).is_err());
162        assert!(StandardDeviation::new(1).is_ok());
163    }
164
165    #[test]
166    fn test_next() {
167        let mut sd = StandardDeviation::new(4).unwrap();
168        assert_eq!(sd.next(10.0), 0.0);
169        assert_eq!(sd.next(20.0), 5.0);
170        assert_eq!(round(sd.next(30.0)), 8.165);
171        assert_eq!(round(sd.next(20.0)), 7.071);
172        assert_eq!(round(sd.next(10.0)), 7.071);
173        assert_eq!(round(sd.next(100.0)), 35.355);
174    }
175
176    #[test]
177    fn test_next_with_bars() {
178        fn bar(close: f64) -> Bar {
179            Bar::new().close(close)
180        }
181
182        let mut sd = StandardDeviation::new(4).unwrap();
183        assert_eq!(sd.next(&bar(10.0)), 0.0);
184        assert_eq!(sd.next(&bar(20.0)), 5.0);
185        assert_eq!(round(sd.next(&bar(30.0))), 8.165);
186        assert_eq!(round(sd.next(&bar(20.0))), 7.071);
187        assert_eq!(round(sd.next(&bar(10.0))), 7.071);
188        assert_eq!(round(sd.next(&bar(100.0))), 35.355);
189    }
190
191    #[test]
192    fn test_next_same_values() {
193        let mut sd = StandardDeviation::new(3).unwrap();
194        assert_eq!(sd.next(4.2), 0.0);
195        assert_eq!(sd.next(4.2), 0.0);
196        assert_eq!(sd.next(4.2), 0.0);
197        assert_eq!(sd.next(4.2), 0.0);
198    }
199
200    #[test]
201    fn test_reset() {
202        let mut sd = StandardDeviation::new(4).unwrap();
203        assert_eq!(sd.next(10.0), 0.0);
204        assert_eq!(sd.next(20.0), 5.0);
205        assert_eq!(round(sd.next(30.0)), 8.165);
206
207        sd.reset();
208        assert_eq!(sd.next(20.0), 0.0);
209    }
210
211    #[test]
212    fn test_default() {
213        StandardDeviation::default();
214    }
215
216    #[test]
217    fn test_display() {
218        let sd = StandardDeviation::new(5).unwrap();
219        assert_eq!(format!("{}", sd), "SD(5)");
220    }
221}