cxmr_ta_core/indicators/
maximum.rs1use std::f64::INFINITY;
2use std::fmt;
3
4use crate::errors::*;
5use crate::{Calculate, High, Next, Reset};
6
7#[derive(Debug, Clone)]
27pub struct Maximum {
28 n: usize,
29 vec: Vec<f64>,
30 max_index: usize,
31 cur_index: usize,
32}
33
34impl Maximum {
35 pub fn new(n: u32) -> Result<Self> {
36 let n = n as usize;
37
38 if n == 0 {
39 return Err(Error::from_kind(ErrorKind::InvalidParameter));
40 }
41
42 let indicator = Self {
43 n: n,
44 vec: vec![-INFINITY; n],
45 max_index: 0,
46 cur_index: 0,
47 };
48 Ok(indicator)
49 }
50
51 fn find_max_index(&self) -> usize {
52 let mut max = -INFINITY;
53 let mut index: usize = 0;
54
55 for (i, &val) in self.vec.iter().enumerate() {
56 if val > max {
57 max = val;
58 index = i;
59 }
60 }
61
62 index
63 }
64}
65
66impl Calculate for Maximum {
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.max_index] {
72 self.max_index = self.cur_index;
73 } else if self.max_index == self.cur_index {
74 self.max_index = self.find_max_index();
75 }
76
77 self.vec[self.max_index]
78 }
79}
80
81impl<T: High> Next<T> for Maximum {
82 fn next(&mut self, input: &T) -> f64 {
83 self.calc(input.high())
84 }
85}
86
87impl Reset for Maximum {
88 fn reset(&mut self) {
89 for i in 0..self.n {
90 self.vec[i] = -INFINITY;
91 }
92 }
93}
94
95impl Default for Maximum {
96 fn default() -> Self {
97 Self::new(14).unwrap()
98 }
99}
100
101impl fmt::Display for Maximum {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 write!(f, "MAX({})", self.n)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::test_helper::*;
111
112 test_indicator!(Maximum);
113
114 #[test]
115 fn test_new() {
116 assert!(Maximum::new(0).is_err());
117 assert!(Maximum::new(1).is_ok());
118 }
119
120 #[test]
121 fn test_next() {
122 let mut max = Maximum::new(3).unwrap();
123
124 assert_eq!(max.calc(4.0), 4.0);
125 assert_eq!(max.calc(1.2), 4.0);
126 assert_eq!(max.calc(5.0), 5.0);
127 assert_eq!(max.calc(3.0), 5.0);
128 assert_eq!(max.calc(4.0), 5.0);
129 assert_eq!(max.calc(0.0), 4.0);
130 assert_eq!(max.calc(-1.0), 4.0);
131 assert_eq!(max.calc(-2.0), 0.0);
132 assert_eq!(max.calc(-1.5), -1.0);
133 }
134
135 #[test]
136 fn test_next_with_bars() {
137 fn bar(high: f64) -> Bar {
138 Bar::new().high(high)
139 }
140
141 let mut max = Maximum::new(2).unwrap();
142
143 assert_eq!(max.next(&bar(1.1)), 1.1);
144 assert_eq!(max.next(&bar(4.0)), 4.0);
145 assert_eq!(max.next(&bar(3.5)), 4.0);
146 assert_eq!(max.next(&bar(2.0)), 3.5);
147 }
148
149 #[test]
150 fn test_reset() {
151 let mut max = Maximum::new(100).unwrap();
152 assert_eq!(max.calc(4.0), 4.0);
153 assert_eq!(max.calc(10.0), 10.0);
154 assert_eq!(max.calc(4.0), 10.0);
155
156 max.reset();
157 assert_eq!(max.calc(4.0), 4.0);
158 }
159
160 #[test]
161 fn test_default() {
162 Maximum::default();
163 }
164
165 #[test]
166 fn test_display() {
167 let indicator = Maximum::new(7).unwrap();
168 assert_eq!(format!("{}", indicator), "MAX(7)");
169 }
170}