quantaxis_rs/indicators/
minimum.rs

1use std::f64::INFINITY;
2use std::fmt;
3
4use crate::errors::*;
5use crate::{Low, Next, Reset};
6
7/// Returns the lowest value in a given time frame.
8///
9/// # Parameters
10///
11/// * _n_ - size of the time frame (integer greater than 0). Default value is 14.
12///
13/// # Example
14///
15/// ```
16/// use quantaxis_rs::indicators::Minimum;
17/// use quantaxis_rs::Next;
18///
19/// let mut min = Minimum::new(3).unwrap();
20/// assert_eq!(min.next(10.0), 10.0);
21/// assert_eq!(min.next(11.0), 10.0);
22/// assert_eq!(min.next(12.0), 10.0);
23/// assert_eq!(min.next(13.0), 11.0);
24/// ```
25#[derive(Debug, Clone)]
26pub struct Minimum {
27    n: usize,
28    vec: Vec<f64>,
29    min_index: usize,
30    cur_index: usize,
31}
32
33impl Minimum {
34    pub fn new(n: u32) -> Result<Self> {
35        let n = n as usize;
36
37        if n <= 0 {
38            return Err(Error::from_kind(ErrorKind::InvalidParameter));
39        }
40
41        let indicator = Self {
42            n: n,
43            vec: vec![INFINITY; n],
44            min_index: 0,
45            cur_index: 0,
46        };
47
48        Ok(indicator)
49    }
50
51    fn find_min_index(&self) -> usize {
52        let mut min = ::std::f64::INFINITY;
53        let mut index: usize = 0;
54
55        for (i, &val) in self.vec.iter().enumerate() {
56            if val < min {
57                min = val;
58                index = i;
59            }
60        }
61
62        index
63    }
64}
65
66impl Next<f64> for Minimum {
67    type Output = f64;
68
69    fn next(&mut self, input: f64) -> Self::Output {
70        self.cur_index = (self.cur_index + 1) % (self.n as usize);
71        self.vec[self.cur_index] = input;
72
73        if input < self.vec[self.min_index] {
74            self.min_index = self.cur_index;
75        } else if self.min_index == self.cur_index {
76            self.min_index = self.find_min_index();
77        }
78
79        self.vec[self.min_index]
80    }
81}
82
83impl<'a, T: Low> Next<&'a T> for Minimum {
84    type Output = f64;
85
86    fn next(&mut self, input: &'a T) -> Self::Output {
87        self.next(input.low())
88    }
89}
90
91impl Reset for Minimum {
92    fn reset(&mut self) {
93        for i in 0..self.n {
94            self.vec[i] = INFINITY;
95        }
96    }
97}
98
99impl Default for Minimum {
100    fn default() -> Self {
101        Self::new(14).unwrap()
102    }
103}
104
105impl fmt::Display for Minimum {
106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107        write!(f, "MIN({})", self.n)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use crate::test_helper::*;
115    macro_rules! test_indicator {
116        ($i:tt) => {
117            #[test]
118            fn test_indicator() {
119                let bar = Bar::new();
120
121                // ensure Default trait is implemented
122                let mut indicator = $i::default();
123
124                // ensure Next<f64> is implemented
125                let first_output = indicator.next(12.3);
126
127                // ensure next accepts &DataItem as well
128                indicator.next(&bar);
129
130                // ensure Reset is implemented and works correctly
131                indicator.reset();
132                assert_eq!(indicator.next(12.3), first_output);
133
134                // ensure Display is implemented
135                format!("{}", indicator);
136            }
137        };
138    }
139    test_indicator!(Minimum);
140
141    #[test]
142    fn test_new() {
143        assert!(Minimum::new(0).is_err());
144        assert!(Minimum::new(1).is_ok());
145    }
146
147    #[test]
148    fn test_next() {
149        let mut min = Minimum::new(3).unwrap();
150
151        assert_eq!(min.next(4.0), 4.0);
152        assert_eq!(min.next(1.2), 1.2);
153        assert_eq!(min.next(5.0), 1.2);
154        assert_eq!(min.next(3.0), 1.2);
155        assert_eq!(min.next(4.0), 3.0);
156        assert_eq!(min.next(6.0), 3.0);
157        assert_eq!(min.next(7.0), 4.0);
158        assert_eq!(min.next(8.0), 6.0);
159        assert_eq!(min.next(-9.0), -9.0);
160        assert_eq!(min.next(0.0), -9.0);
161    }
162
163    #[test]
164    fn test_next_with_bars() {
165        fn bar(low: f64) -> Bar {
166            Bar::new().low(low)
167        }
168
169        let mut min = Minimum::new(3).unwrap();
170
171        assert_eq!(min.next(&bar(4.0)), 4.0);
172        assert_eq!(min.next(&bar(4.0)), 4.0);
173        assert_eq!(min.next(&bar(1.2)), 1.2);
174        assert_eq!(min.next(&bar(5.0)), 1.2);
175    }
176
177    #[test]
178    fn test_reset() {
179        let mut min = Minimum::new(10).unwrap();
180
181        assert_eq!(min.next(5.0), 5.0);
182        assert_eq!(min.next(7.0), 5.0);
183
184        min.reset();
185        assert_eq!(min.next(8.0), 8.0);
186    }
187
188    #[test]
189    fn test_default() {
190        Minimum::default();
191    }
192
193    #[test]
194    fn test_display() {
195        let indicator = Minimum::new(10).unwrap();
196        assert_eq!(format!("{}", indicator), "MIN(10)");
197    }
198}