ux_indicators/indicators/
tr.rs1#![allow(dead_code)]
2
3use std::fmt;
4
5use crate::helpers::max3;
6use crate::{Close, High, Low, Next, Reset};
7
8use crate::{Factory};
9use crate::indicators::SimpleMovingAverage;
10
11pub struct TrFactory {
12}
13
14impl TrFactory {
15 pub fn new() -> Self {
16 Self{}
17 }
18}
19
20impl Factory for TrFactory {
21 fn create() -> Box<dyn Next<f64, Output = Box<[f64]>>> {
22 Box::new(SimpleMovingAverage::default())
23 }
24}
25
26#[derive(Debug, Clone)]
72pub struct TrueRange {
73 prev_close: Option<f64>,
74}
75
76impl TrueRange {
77 pub fn new() -> Self {
78 Self { prev_close: None }
79 }
80}
81
82impl Default for TrueRange {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl fmt::Display for TrueRange {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 write!(f, "TRUE_RANGE()")
91 }
92}
93
94impl Next<f64> for TrueRange {
95 type Output = f64;
96
97 fn next(&mut self, input: f64) -> Self::Output {
98 let distance = match self.prev_close {
99 Some(prev) => (input - prev).abs(),
100 None => 0.0,
101 };
102 self.prev_close = Some(input);
103 distance
104 }
105}
106
107impl<'a, T: High + Low + Close> Next<&'a T> for TrueRange {
108 type Output = f64;
109
110 fn next(&mut self, bar: &'a T) -> Self::Output {
111 let max_dist = match self.prev_close {
112 Some(prev_close) => {
113 let dist1 = bar.high() - bar.low();
114 let dist2 = (bar.high() - prev_close).abs();
115 let dist3 = (bar.low() - prev_close).abs();
116 max3(dist1, dist2, dist3)
117 }
118 None => bar.high() - bar.low(),
119 };
120 self.prev_close = Some(bar.close());
121 max_dist
122 }
123}
124
125impl Reset for TrueRange {
126 fn reset(&mut self) {
127 self.prev_close = None;
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134 use crate::test_helper::*;
135
136 #[test]
139 fn test_next_f64() {
140 let mut tr = TrueRange::new();
141 assert_eq!(round(tr.next(2.5)), 0.0);
142 assert_eq!(round(tr.next(3.6)), 1.1);
143 assert_eq!(round(tr.next(3.3)), 0.3);
144 }
145
146 #[test]
147 fn test_next_bar() {
148 let mut tr = TrueRange::new();
149
150 let bar1 = Bar::new().high(10).low(7.5).close(9);
151 let bar2 = Bar::new().high(11).low(9).close(9.5);
152 let bar3 = Bar::new().high(9).low(5).close(8);
153
154 assert_eq!(tr.next(&bar1), 2.5);
155 assert_eq!(tr.next(&bar2), 2.0);
156 assert_eq!(tr.next(&bar3), 4.5);
157 }
158
159 #[test]
160 fn test_reset() {
161 let mut tr = TrueRange::new();
162
163 let bar1 = Bar::new().high(10).low(7.5).close(9);
164 let bar2 = Bar::new().high(11).low(9).close(9.5);
165
166 tr.next(&bar1);
167 tr.next(&bar2);
168
169 tr.reset();
170 let bar3 = Bar::new().high(60).low(15).close(51);
171 assert_eq!(tr.next(&bar3), 45.0);
172 }
173
174 #[test]
175 fn test_default() {
176 TrueRange::default();
177 }
178
179 #[test]
180 fn test_display() {
181 let indicator = TrueRange::new();
182 assert_eq!(format!("{}", indicator), "TRUE_RANGE()");
183 }
184}