finlib_ta/indicators/
maximum.rs

1use 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/// Returns the highest 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::Maximum;
20/// use finlib_ta::Next;
21///
22/// let mut max = Maximum::new(3).unwrap();
23/// assert_eq!(max.next(7.0), 7.0);
24/// assert_eq!(max.next(5.0), 7.0);
25/// assert_eq!(max.next(4.0), 7.0);
26/// assert_eq!(max.next(4.0), 5.0);
27/// assert_eq!(max.next(8.0), 8.0);
28/// ```
29#[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}