finlib_ta/indicators/
minimum.rs

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