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}