ta_lib_in_rust/indicators/oscillators/
ppo.rs

1use polars::prelude::*;
2
3/// Calculate Percentage Price Oscillator (PPO)
4///
5/// Returns a Series with PPO values
6pub fn calculate_ppo(
7    df: &DataFrame,
8    close_col: &str,
9    fast_period: usize,
10    slow_period: usize,
11) -> PolarsResult<Series> {
12    let close = df.column(close_col)?.f64()?;
13    let len = df.height();
14    let mut ema_fast = vec![f64::NAN; len];
15    let mut ema_slow = vec![f64::NAN; len];
16    let alpha_fast = 2.0 / (fast_period as f64 + 1.0);
17    let alpha_slow = 2.0 / (slow_period as f64 + 1.0);
18    for i in 0..len {
19        if i == 0 {
20            ema_fast[i] = close.get(i).unwrap_or(f64::NAN);
21            ema_slow[i] = close.get(i).unwrap_or(f64::NAN);
22        } else {
23            ema_fast[i] = alpha_fast * close.get(i).unwrap_or(f64::NAN)
24                + (1.0 - alpha_fast) * ema_fast[i - 1];
25            ema_slow[i] = alpha_slow * close.get(i).unwrap_or(f64::NAN)
26                + (1.0 - alpha_slow) * ema_slow[i - 1];
27        }
28    }
29    let mut ppo = vec![f64::NAN; len];
30    for i in 0..len {
31        if ema_slow[i] != 0.0 {
32            ppo[i] = 100.0 * (ema_fast[i] - ema_slow[i]) / ema_slow[i];
33        }
34    }
35    Ok(Series::new("ppo".into(), ppo))
36}