ux_indicators/indicators/
atr.rs

1#![allow(dead_code)]
2
3use std::fmt;
4
5use crate::errors::*;
6use crate::indicators::{ExponentialMovingAverage, TrueRange};
7use crate::{Close, High, Low, Next, Reset};
8
9use crate::{Factory};
10use crate::indicators::SimpleMovingAverage;
11
12pub struct AtrFactory {
13}
14
15impl AtrFactory {
16    pub fn new() -> Self {
17        Self{}
18    }
19}
20
21impl Factory for AtrFactory {
22    fn create() -> Box<dyn Next<f64, Output = Box<[f64]>>> {
23        Box::new(SimpleMovingAverage::default())
24    }
25}
26
27
28/// Average true range (ATR).
29///
30/// A technical analysis volatility indicator, originally developed by J. Welles Wilder.
31/// The average true range is an N-day smoothed moving average of the true range values.
32/// This implementation uses exponential moving average.
33///
34/// # Formula
35///
36/// ATR(length)<sub>t</sub> = EMA(length) of TR<sub>t</sub>
37///
38/// Where:
39///
40/// * _EMA(n)_ - [exponential moving average](struct.ExponentialMovingAverage.html) with smoothing period _length_
41/// * _TR<sub>t</sub>_ - [true range](struct.TrueRange.html) for period _t_
42///
43/// # Parameters
44///
45/// * _length_ - smoothing period of EMA (integer greater than 0)
46///
47/// # Example
48///
49/// ```
50/// extern crate core;
51/// #[macro_use] extern crate assert_approx_eq;
52///
53/// use core::{Next, DataItem};
54/// use core::indicators::AverageTrueRange;
55///
56/// fn main() {
57///     let data = vec![
58///         // open, high, low, close, atr
59///         (9.7   , 10.0, 9.0, 9.5  , 1.0),    // tr = high - low = 10.0 - 9.0 = 1.0
60///         (9.9   , 10.4, 9.8, 10.2 , 0.95),   // tr = high - prev_close = 10.4 - 9.5 = 0.9
61///         (10.1  , 10.7, 9.4, 9.7  , 1.125),  // tr = high - low = 10.7 - 9.4 = 1.3
62///         (9.1   , 9.2 , 8.1, 8.4  , 1.3625), // tr = prev_close - low = 9.7 - 8.1 = 1.6
63///     ];
64///     let mut indicator = AverageTrueRange::new(3).unwrap();
65///
66///     for (open, high, low, close, atr) in data {
67///         let di = DataItem::builder()
68///             .high(high)
69///             .low(low)
70///             .close(close)
71///             .open(open)
72///             .volume(1000.0)
73///             .build().unwrap();
74///         assert_approx_eq!(indicator.next(&di), atr);
75///     }
76/// }
77
78#[derive(Debug, Clone)]
79pub struct AverageTrueRange {
80    true_range: TrueRange,
81    ema: ExponentialMovingAverage,
82}
83
84impl AverageTrueRange {
85    pub fn new(length: u32) -> Result<Self> {
86        let indicator = Self {
87            true_range: TrueRange::new(),
88            ema: ExponentialMovingAverage::new(length)?,
89        };
90        Ok(indicator)
91    }
92}
93
94impl Next<f64> for AverageTrueRange {
95    type Output = f64;
96
97    fn next(&mut self, input: f64) -> Self::Output {
98        self.ema.next(self.true_range.next(input))
99    }
100}
101
102impl<'a, T: High + Low + Close> Next<&'a T> for AverageTrueRange {
103    type Output = f64;
104
105    fn next(&mut self, input: &'a T) -> Self::Output {
106        self.ema.next(self.true_range.next(input))
107    }
108}
109
110impl Reset for AverageTrueRange {
111    fn reset(&mut self) {
112        self.true_range.reset();
113        self.ema.reset();
114    }
115}
116
117impl Default for AverageTrueRange {
118    fn default() -> Self {
119        Self::new(14).unwrap()
120    }
121}
122
123impl fmt::Display for AverageTrueRange {
124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125        write!(f, "ATR({})", self.ema.length())
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132    use crate::test_helper::*;
133
134    // test_indicator!(AverageTrueRange);
135
136    #[test]
137    fn test_new() {
138        assert!(AverageTrueRange::new(0).is_err());
139        assert!(AverageTrueRange::new(1).is_ok());
140    }
141    #[test]
142    fn test_next() {
143        let mut atr = AverageTrueRange::new(3).unwrap();
144
145        let bar1 = Bar::new().high(10).low(7.5).close(9);
146        let bar2 = Bar::new().high(11).low(9).close(9.5);
147        let bar3 = Bar::new().high(9).low(5).close(8);
148
149        assert_eq!(atr.next(&bar1), 2.5);
150        assert_eq!(atr.next(&bar2), 2.25);
151        assert_eq!(atr.next(&bar3), 3.375);
152    }
153
154    #[test]
155    fn test_reset() {
156        let mut atr = AverageTrueRange::new(9).unwrap();
157
158        let bar1 = Bar::new().high(10).low(7.5).close(9);
159        let bar2 = Bar::new().high(11).low(9).close(9.5);
160
161        atr.next(&bar1);
162        atr.next(&bar2);
163
164        atr.reset();
165        let bar3 = Bar::new().high(60).low(15).close(51);
166        assert_eq!(atr.next(&bar3), 45.0);
167    }
168
169    #[test]
170    fn test_default() {
171        AverageTrueRange::default();
172    }
173
174    #[test]
175    fn test_display() {
176        let indicator = AverageTrueRange::new(8).unwrap();
177        assert_eq!(format!("{}", indicator), "ATR(8)");
178    }
179}