finlib_ta/indicators/
true_range.rs1use core::fmt;
2
3use crate::helpers::max3;
4use crate::{Close, High, Low, Next, Reset};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
53#[derive(Debug, Clone)]
54pub struct TrueRange {
55 prev_close: Option<f64>,
56}
57
58impl TrueRange {
59 pub fn new() -> Self {
60 Self { prev_close: None }
61 }
62}
63
64impl Default for TrueRange {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl fmt::Display for TrueRange {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 write!(f, "TRUE_RANGE()")
73 }
74}
75
76impl Next<f64> for TrueRange {
77 type Output = f64;
78
79 fn next(&mut self, input: f64) -> Self::Output {
80 let distance = match self.prev_close {
81 Some(prev) => (input - prev).abs(),
82 None => 0.0,
83 };
84 self.prev_close = Some(input);
85 distance
86 }
87}
88
89impl<T: High + Low + Close> Next<&T> for TrueRange {
90 type Output = f64;
91
92 fn next(&mut self, bar: &T) -> Self::Output {
93 let max_dist = match self.prev_close {
94 Some(prev_close) => {
95 let dist1 = bar.high() - bar.low();
96 let dist2 = (bar.high() - prev_close).abs();
97 let dist3 = (bar.low() - prev_close).abs();
98 max3(dist1, dist2, dist3)
99 }
100 None => bar.high() - bar.low(),
101 };
102 self.prev_close = Some(bar.close());
103 max_dist
104 }
105}
106
107impl Reset for TrueRange {
108 fn reset(&mut self) {
109 self.prev_close = None;
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use crate::test_helper::*;
117 use alloc::format;
118
119 test_indicator!(TrueRange);
120
121 #[test]
122 fn test_next_f64() {
123 let mut tr = TrueRange::new();
124 assert_eq!(round(tr.next(2.5)), 0.0);
125 assert_eq!(round(tr.next(3.6)), 1.1);
126 assert_eq!(round(tr.next(3.3)), 0.3);
127 }
128
129 #[test]
130 fn test_next_bar() {
131 let mut tr = TrueRange::new();
132
133 let bar1 = Bar::new().high(10).low(7.5).close(9);
134 let bar2 = Bar::new().high(11).low(9).close(9.5);
135 let bar3 = Bar::new().high(9).low(5).close(8);
136
137 assert_eq!(tr.next(&bar1), 2.5);
138 assert_eq!(tr.next(&bar2), 2.0);
139 assert_eq!(tr.next(&bar3), 4.5);
140 }
141
142 #[test]
143 fn test_reset() {
144 let mut tr = TrueRange::new();
145
146 let bar1 = Bar::new().high(10).low(7.5).close(9);
147 let bar2 = Bar::new().high(11).low(9).close(9.5);
148
149 tr.next(&bar1);
150 tr.next(&bar2);
151
152 tr.reset();
153 let bar3 = Bar::new().high(60).low(15).close(51);
154 assert_eq!(tr.next(&bar3), 45.0);
155 }
156
157 #[test]
158 fn test_default() {
159 TrueRange::default();
160 }
161
162 #[test]
163 fn test_display() {
164 let indicator = TrueRange::new();
165 assert_eq!(format!("{}", indicator), "TRUE_RANGE()");
166 }
167}