indexes_rs/v1/atr/
main.rs

1//! # Average True Range (ATR) Module
2//!
3//! This module implements a simplified Average True Range (ATR) indicator.
4//! In this version, the true range is calculated as the absolute difference between the
5//! current closing price and the previous closing price. (Note that the full ATR calculation
6//! typically uses the high, low, and previous close values, but this simplified version
7//! uses only the close values.)
8//!
9//! The ATR is computed as the average of the true range over a specified period.
10//!
11//! # Examples
12//!
13//! ```rust
14//! use indexes_rs::v1::atr::main::ATR;
15//!
16//! // Create an ATR indicator with a period of 14
17//! let mut atr = ATR::new(14);
18//!
19//! // Feed a series of closing prices
20//! let prices = vec![100.0, 101.0, 100.5, 102.0, 101.5, 102.5, 103.0, 102.0, 101.0, 100.0,
21//!                   100.5, 101.0, 102.0, 101.5, 102.5];
22//!
23//! for price in prices {
24//!     if let Some(atr_value) = atr.calculate(price) {
25//!         println!("ATR: {:.2}", atr_value);
26//!     }
27//! }
28//! ```
29
30use std::collections::VecDeque;
31
32/// A simplified Average True Range (ATR) indicator.
33///
34/// This ATR calculates the true range as the absolute difference between the current closing price and the previous closing price.
35/// It then computes the ATR as the average of these true ranges over a specified period.
36pub struct ATR {
37    /// The period over which to calculate the ATR.
38    period: usize,
39    /// A sliding window of true range values.
40    values: VecDeque<f64>,
41    /// The previous closing price.
42    prev_close: Option<f64>,
43}
44
45impl ATR {
46    /// Creates a new ATR indicator with the specified period.
47    ///
48    /// # Arguments
49    ///
50    /// * `period` - The number of periods over which to calculate the ATR.
51    ///
52    /// # Example
53    ///
54    /// ```rust
55    /// use indexes_rs::v1::atr::main::ATR;
56    ///
57    /// let atr = ATR::new(14);
58    /// ```
59    pub fn new(period: usize) -> Self {
60        ATR {
61            period,
62            values: VecDeque::with_capacity(period),
63            prev_close: None,
64        }
65    }
66
67    /// Calculates the current ATR value using the latest closing price.
68    ///
69    /// The true range is computed as the absolute difference between the current closing price and the previous closing price.
70    /// This true range is stored in a sliding window; once the window contains `period` values, the ATR is returned as their average.
71    ///
72    /// # Arguments
73    ///
74    /// * `close` - The latest closing price.
75    ///
76    /// # Returns
77    ///
78    /// * `Some(f64)` containing the ATR value if enough data is available.
79    /// * `None` if there aren't enough values yet.
80    pub fn calculate(&mut self, close: f64) -> Option<f64> {
81        // Compute the true range based on the previous close, or 0.0 if none exists.
82        let true_range = self.prev_close.map_or(0.0, |prev| (close - prev).abs());
83
84        self.values.push_back(true_range);
85        if self.values.len() > self.period {
86            self.values.pop_front();
87        }
88
89        self.prev_close = Some(close);
90
91        if self.values.len() == self.period {
92            Some(self.values.iter().sum::<f64>() / self.period as f64)
93        } else {
94            None
95        }
96    }
97}