quantaxis_rs/indicators/
true_range.rs

1use std::fmt;
2
3use crate::helpers::max3;
4use crate::{Close, High, Low, Next, Reset, Update};
5
6
7#[derive(Debug, Clone)]
8pub struct TrueRange {
9
10
11    prev_closeque: Vec<f64>
12
13}
14
15impl TrueRange {
16    pub fn new() -> Self {
17        Self {  prev_closeque:vec![] }
18    }
19}
20
21impl Default for TrueRange {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl fmt::Display for TrueRange {
28    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29        write!(f, "TRUE_RANGE()")
30    }
31}
32
33impl Next<f64> for TrueRange {
34    type Output = f64;
35
36    fn next(&mut self, input: f64) -> Self::Output {
37        if self.prev_closeque.len()<1{
38            self.prev_closeque.push(input);
39            0.0
40        }else {
41            let distance = match self.prev_closeque[self.prev_closeque.len() - 1] {
42                prev => (input - prev).abs(),
43                _ => 0.0
44            };
45
46            self.prev_closeque.push(input);
47            distance
48        }
49
50
51    }
52}
53impl Update<f64> for TrueRange {
54    type Output = f64;
55
56    fn update(&mut self, input: f64) -> Self::Output {
57
58        if self.prev_closeque.len()<2{
59            let u = self.prev_closeque.last_mut().unwrap();
60            *u = input;
61            0.0
62        }else{
63            let distance = match self.prev_closeque[self.prev_closeque.len() -2]{
64                prev => (input - prev).abs(),
65                _ => 0.0
66            };
67
68            let u = self.prev_closeque.last_mut().unwrap();
69            *u = input;
70            //self.prev_close = Some(input);
71            distance
72        }
73
74    }
75}
76
77impl<'a, T: High + Low + Close> Next<&'a T> for TrueRange {
78    type Output = f64;
79
80    fn next(&mut self, bar: &'a T) -> Self::Output {
81        if self.prev_closeque.len()<1{
82            self.prev_closeque.push(bar.close());
83            bar.high()- bar.low()
84        }else{
85            let max_dist = match self.prev_closeque[self.prev_closeque.len() - 1] {
86                prev_close => {
87                    let dist1 = bar.high() - bar.low();
88                    let dist2 = (bar.high() - prev_close).abs();
89                    let dist3 = (bar.low() - prev_close).abs();
90                    max3(dist1, dist2, dist3)
91                }
92                _ => bar.high() - bar.low(),
93            };
94            self.prev_closeque.push(bar.close());
95            max_dist
96        }
97    }
98}
99impl<'a, T: High + Low + Close> Update<&'a T> for TrueRange {
100    type Output = f64;
101
102    fn update(&mut self, bar: &'a T) -> Self::Output {
103        if self.prev_closeque.len()<2{
104            let u = self.prev_closeque.last_mut().unwrap();
105            *u = bar.close();
106            bar.high() - bar.low()
107        }else{
108            let max_dist = match self.prev_closeque[self.prev_closeque.len() -2] {
109                prev_close => {
110                    let dist1 = bar.high() - bar.low();
111                    let dist2 = (bar.high() - prev_close).abs();
112                    let dist3 = (bar.low() - prev_close).abs();
113                    max3(dist1, dist2, dist3)
114                }
115                _ => bar.high() - bar.low(),
116            };
117            let u = self.prev_closeque.last_mut().unwrap();
118            *u = bar.close();
119            max_dist
120        }
121
122    }
123}
124
125impl Reset for TrueRange {
126    fn reset(&mut self) {
127        self.prev_closeque = vec![];
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134    use crate::test_helper::*;
135    macro_rules! test_indicator {
136        ($i:tt) => {
137            #[test]
138            fn test_indicator() {
139                let bar = Bar::new();
140
141                // ensure Default trait is implemented
142                let mut indicator = $i::default();
143
144                // ensure Next<f64> is implemented
145                let first_output = indicator.next(12.3);
146
147                // ensure next accepts &DataItem as well
148                indicator.next(&bar);
149
150                // ensure Reset is implemented and works correctly
151                indicator.reset();
152                assert_eq!(indicator.next(12.3), first_output);
153
154                // ensure Display is implemented
155                format!("{}", indicator);
156            }
157        };
158    }
159    test_indicator!(TrueRange);
160
161    #[test]
162    fn test_next_f64() {
163        let mut tr = TrueRange::new();
164        assert_eq!(round(tr.next(2.5)), 0.0);
165        assert_eq!(round(tr.next(3.6)), 1.1);
166        assert_eq!(round(tr.next(3.3)), 0.3);
167    }
168
169
170
171    #[test]
172    fn test_update_f64() {
173        let mut tr = TrueRange::new();
174        assert_eq!(round(tr.next(2.5)), 0.0);
175
176        assert_eq!(round(tr.update(3.3)), 0.0);
177
178
179        let mut tr = TrueRange::new();
180        assert_eq!(round(tr.next(2.5)), 0.0);
181        println!("{:#?}", tr);
182        assert_eq!(round(tr.update(3.3)), 0.0);
183        println!("{:#?}", tr);
184        // println!("{:#?}",tr.next(2.5));
185        assert_eq!(round(tr.next(2.5)), 0.8);
186        println!("{:#?}", tr);
187        assert_eq!(round(tr.update(3.6)), 0.3);
188        println!("{:#?}", tr);
189
190    }
191
192    #[test]
193    fn test_next_bar() {
194        let mut tr = TrueRange::new();
195
196        let bar1 = Bar::new().high(10).low(7.5).close(9);
197        let bar2 = Bar::new().high(11).low(9).close(9.5);
198        let bar3 = Bar::new().high(9).low(5).close(8);
199
200        assert_eq!(tr.next(&bar1), 2.5);
201        assert_eq!(tr.next(&bar2), 2.0);
202        assert_eq!(tr.next(&bar3), 4.5);
203    }
204
205    #[test]
206    fn test_reset() {
207        let mut tr = TrueRange::new();
208
209        let bar1 = Bar::new().high(10).low(7.5).close(9);
210        let bar2 = Bar::new().high(11).low(9).close(9.5);
211
212        tr.next(&bar1);
213        tr.next(&bar2);
214
215        tr.reset();
216        let bar3 = Bar::new().high(60).low(15).close(51);
217        assert_eq!(tr.next(&bar3), 45.0);
218    }
219
220    #[test]
221    fn test_default() {
222        TrueRange::default();
223    }
224
225    #[test]
226    fn test_display() {
227        let indicator = TrueRange::new();
228        assert_eq!(format!("{}", indicator), "TRUE_RANGE()");
229    }
230}