quant-indicators 0.7.0

Pure indicator math library for trading — MA, RSI, Bollinger, MACD, ATR, HRP
Documentation
use super::*;
use crate::test_helpers::helpers::{make_candle, ts};
use rust_decimal::Decimal;
use rust_decimal_macros::dec;

#[test]
fn momentum_uptrend() {
    let candles: Vec<Candle> = (0..10)
        .map(|i| make_candle(Decimal::from(100 + i * 5), ts(i)))
        .collect();

    let mom = Momentum::new(3).expect("valid Momentum period");
    let series = mom.compute(&candles).expect("sufficient data for Momentum");

    // Momentum should be positive and constant (price rises by 5 each period)
    // Momentum = 5 * 3 = 15 each time
    for (_, v) in series.values() {
        assert_eq!(*v, dec!(15), "Momentum should be 15 for +5/period trend");
    }
}

#[test]
fn momentum_downtrend() {
    let candles: Vec<Candle> = (0..10)
        .map(|i| make_candle(Decimal::from(200 - i * 5), ts(i)))
        .collect();

    let mom = Momentum::new(3).expect("valid Momentum period");
    let series = mom.compute(&candles).expect("sufficient data for Momentum");

    for (_, v) in series.values() {
        assert_eq!(*v, dec!(-15), "Momentum should be -15 for -5/period trend");
    }
}

#[test]
fn momentum_flat() {
    let candles: Vec<Candle> = (0..10).map(|i| make_candle(dec!(100), ts(i))).collect();

    let mom = Momentum::new(3).expect("valid Momentum period");
    let series = mom.compute(&candles).expect("sufficient data for Momentum");

    for (_, v) in series.values() {
        assert_eq!(*v, dec!(0), "Momentum should be 0 for flat prices");
    }
}

#[test]
fn momentum_insufficient_data() {
    let candles: Vec<Candle> = (0..3).map(|i| make_candle(dec!(100), ts(i))).collect();

    let mom = Momentum::new(5).expect("valid Momentum period");
    let result = mom.compute(&candles);

    assert!(matches!(
        result,
        Err(IndicatorError::InsufficientData {
            required: 6,
            actual: 3
        })
    ));
}

#[test]
fn momentum_period_zero() {
    let result = Momentum::new(0);
    assert!(matches!(
        result,
        Err(IndicatorError::InvalidParameter { .. })
    ));
}

#[test]
fn momentum_name() {
    let mom = Momentum::new(10).expect("valid Momentum period");
    assert_eq!(mom.name(), "Momentum(10)");
}