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