equity_scanner/utils/
indicators.rs

1use crate::equity::InvalidData;
2
3pub fn calculate_rsi(prices: &Vec<f64>, period: usize) -> Result<Vec<f64>, InvalidData> {
4    let mut rsi_values = Vec::new();
5    let mut avg_gain = 0.0;
6    let mut avg_loss = 0.0;
7
8    if prices.len() <= period {
9        return Err(InvalidData);
10    }
11
12    for i in 1..=period {
13        let change = prices[i] - prices[i - 1];
14        if change > 0.0 {
15            avg_gain += change;
16        } else {
17            avg_loss -= change;
18        }
19    }
20
21    avg_gain /= period as f64;
22    avg_loss /= period as f64;
23
24    let first_rsi = 100.0 - (100.0 / (1.0 + (avg_gain / avg_loss)));
25    rsi_values.push(first_rsi);
26
27    for i in (period + 1)..prices.len() {
28        let change = prices[i] - prices[i - 1];
29        let gain = if change > 0.0 { change } else { 0.0 };
30        let loss = if change < 0.0 { -change } else { 0.0 };
31
32        avg_gain = (avg_gain * (period as f64 - 1.0) + gain) / period as f64;
33        avg_loss = (avg_loss * (period as f64 - 1.0) + loss) / period as f64;
34
35        let rs = avg_gain / avg_loss;
36        let rsi = 100.0 - (100.0 / (1.0 + rs));
37        rsi_values.push(rsi);
38    }
39
40    Ok(rsi_values)
41}
42
43pub fn max(sizes: &[usize]) -> usize {
44    *sizes.iter().max().unwrap()
45}