ta_lib_in_rust/indicators/volatility/
natr.rs

1use crate::indicators::volatility::calculate_atr;
2use polars::prelude::*;
3
4/// Calculates Normalized Average True Range (NATR)
5/// NATR is the ATR value divided by the closing price, expressed as a percentage.
6/// Formula: (ATR / Close) * 100
7///
8/// # Arguments
9///
10/// * `df` - DataFrame containing the price data
11/// * `window` - Window size for ATR (typically 14)
12///
13/// # Returns
14///
15/// Returns a PolarsResult containing the NATR Series
16pub fn calculate_natr(df: &DataFrame, window: usize) -> PolarsResult<Series> {
17    // Calculate ATR
18    let atr = calculate_atr(df, window)?;
19
20    // Get closing prices
21    let close = df.column("close")?.f64()?;
22
23    // Calculate NATR: (ATR / Close) * 100
24    let mut natr_values = Vec::with_capacity(df.height());
25
26    for i in 0..df.height() {
27        let atr_val = atr.f64()?.get(i).unwrap_or(f64::NAN);
28        let close_val = close.get(i).unwrap_or(f64::NAN);
29
30        if !atr_val.is_nan() && !close_val.is_nan() && close_val != 0.0 {
31            let natr = (atr_val / close_val) * 100.0;
32            natr_values.push(natr);
33        } else {
34            natr_values.push(f64::NAN);
35        }
36    }
37
38    Ok(Series::new("natr".into(), natr_values))
39}