cxmr_ta_core/indicators/
minimum.rs1use std::f64::INFINITY;
2use std::fmt;
3
4use crate::errors::*;
5use crate::{Calculate, Low, Next, Reset};
6
7#[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 Calculate for Minimum {
67 fn calc(&mut self, input: f64) -> f64 {
68 self.cur_index = (self.cur_index + 1) % (self.n as usize);
69 self.vec[self.cur_index] = input;
70
71 if input < self.vec[self.min_index] {
72 self.min_index = self.cur_index;
73 } else if self.min_index == self.cur_index {
74 self.min_index = self.find_min_index();
75 }
76
77 self.vec[self.min_index]
78 }
79}
80
81impl<T: Low> Next<T> for Minimum {
82 fn next(&mut self, input: &T) -> f64 {
83 self.calc(input.low())
84 }
85}
86
87impl Reset for Minimum {
88 fn reset(&mut self) {
89 for i in 0..self.n {
90 self.vec[i] = INFINITY;
91 }
92 }
93}
94
95impl Default for Minimum {
96 fn default() -> Self {
97 Self::new(14).unwrap()
98 }
99}
100
101impl fmt::Display for Minimum {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 write!(f, "MIN({})", self.n)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::test_helper::*;
111
112 test_indicator!(Minimum);
113
114 #[test]
115 fn test_new() {
116 assert!(Minimum::new(0).is_err());
117 assert!(Minimum::new(1).is_ok());
118 }
119
120 #[test]
121 fn test_next() {
122 let mut min = Minimum::new(3).unwrap();
123
124 assert_eq!(min.calc(4.0), 4.0);
125 assert_eq!(min.calc(1.2), 1.2);
126 assert_eq!(min.calc(5.0), 1.2);
127 assert_eq!(min.calc(3.0), 1.2);
128 assert_eq!(min.calc(4.0), 3.0);
129 assert_eq!(min.calc(6.0), 3.0);
130 assert_eq!(min.calc(7.0), 4.0);
131 assert_eq!(min.calc(8.0), 6.0);
132 assert_eq!(min.calc(-9.0), -9.0);
133 assert_eq!(min.calc(0.0), -9.0);
134 }
135
136 #[test]
137 fn test_next_with_bars() {
138 fn bar(low: f64) -> Bar {
139 Bar::new().low(low)
140 }
141
142 let mut min = Minimum::new(3).unwrap();
143
144 assert_eq!(min.next(&bar(4.0)), 4.0);
145 assert_eq!(min.next(&bar(4.0)), 4.0);
146 assert_eq!(min.next(&bar(1.2)), 1.2);
147 assert_eq!(min.next(&bar(5.0)), 1.2);
148 }
149
150 #[test]
151 fn test_reset() {
152 let mut min = Minimum::new(10).unwrap();
153
154 assert_eq!(min.calc(5.0), 5.0);
155 assert_eq!(min.calc(7.0), 5.0);
156
157 min.reset();
158 assert_eq!(min.calc(8.0), 8.0);
159 }
160
161 #[test]
162 fn test_default() {
163 Minimum::default();
164 }
165
166 #[test]
167 fn test_display() {
168 let indicator = Minimum::new(10).unwrap();
169 assert_eq!(format!("{}", indicator), "MIN(10)");
170 }
171}