finlib_ta/indicators/
minimum.rs1use 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#[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}