cxmr_ta_core/indicators/
maximum.rs

1use std::f64::INFINITY;
2use std::fmt;
3
4use crate::errors::*;
5use crate::{Calculate, High, Next, Reset};
6
7/// Returns the highest value in a given time frame.
8///
9/// # Parameters
10///
11/// * _n_ - size of the time frame (integer greater than 0). Default value is 14.
12///
13/// # Example
14///
15/// ```
16/// use ta::indicators::Maximum;
17/// use ta::{Calculate, Next};
18///
19/// let mut max = Maximum::new(3).unwrap();
20/// assert_eq!(max.calc(7.0), 7.0);
21/// assert_eq!(max.calc(5.0), 7.0);
22/// assert_eq!(max.calc(4.0), 7.0);
23/// assert_eq!(max.calc(4.0), 5.0);
24/// assert_eq!(max.calc(8.0), 8.0);
25/// ```
26#[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}