market-rs 0.1.2

A library which provides a simple interface for interacting with a market
Documentation
use crate::formula::ema;

pub fn ema_crossover(
    prices: Vec<f64>,
    slow_period: usize,
    fast_period: usize,
    confirmation_candles: usize,
) -> Vec<f64> {
    let slow_ema = ema(prices.clone(), slow_period);
    let fast_ema = ema(prices, fast_period);
    let mut crossover_signals = Vec::new();

    for i in 0..slow_ema.len() {
        if i == 0 {
            crossover_signals.push(0.0);
        } else {
            let prev_slow = slow_ema[i - 1];
            let prev_fast = fast_ema[i - 1];
            let curr_slow = slow_ema[i];
            let curr_fast = fast_ema[i];

            // Check for bullish crossover (fast EMA crosses above slow EMA)
            if prev_fast <= prev_slow && curr_fast > curr_slow {
                // Check if fast EMA was below slow EMA for the required confirmation candles
                let mut confirmed = true;
                let start_idx = i.saturating_sub(confirmation_candles);

                for j in start_idx..i {
                    if fast_ema[j] > slow_ema[j] {
                        confirmed = false;
                        break;
                    }
                }

                if confirmed && i >= confirmation_candles {
                    crossover_signals.push(1.0); // Confirmed bullish signal
                } else {
                    crossover_signals.push(0.0); // Not confirmed
                }
            }
            // Check for bearish crossover (fast EMA crosses below slow EMA)
            else if prev_fast >= prev_slow && curr_fast < curr_slow {
                // Check if fast EMA was above slow EMA for the required confirmation candles
                let mut confirmed = true;
                let start_idx = i.saturating_sub(confirmation_candles);

                for j in start_idx..i {
                    if fast_ema[j] < slow_ema[j] {
                        confirmed = false;
                        break;
                    }
                }

                if confirmed && i >= confirmation_candles {
                    crossover_signals.push(-1.0); // Confirmed bearish signal
                } else {
                    crossover_signals.push(0.0); // Not confirmed
                }
            } else {
                crossover_signals.push(0.0); // No crossover
            }
        }
    }
    crossover_signals
}

// #[cfg(test)]
// mod tests {
//     use super::*;
//
//     #[test]
//     fn test_ema_crossover() {
//         let prices = vec![10.0, 12.0, 11.0, 13.0, 15.0, 14.0, 16.0, 18.0, 17.0, 19.0];
//         let signals = ema_crossover(prices, 3, 2);
//
//         // Should have same length as input
//         assert_eq!(signals.len(), 10);
//
//         // First signal should be 0 (no crossover possible)
//         assert_eq!(signals[0], 0.0);
//     }
// }