use super::*;
use crate::test_helpers::helpers::{make_candle, ts};
use rust_decimal_macros::dec;
#[test]
fn stddev_constant_prices_is_zero() {
let candles: Vec<Candle> = (0..5).map(|i| make_candle(dec!(100), ts(i))).collect();
let stddev = StdDev::new(3).expect("valid StdDev period");
let series = stddev
.compute(&candles)
.expect("sufficient data for StdDev");
assert_eq!(series.len(), 3);
for (_, value) in series.values() {
assert_eq!(*value, dec!(0));
}
}
#[test]
fn stddev_basic() {
let candles: Vec<Candle> = vec![
make_candle(dec!(10), ts(0)),
make_candle(dec!(12), ts(1)),
make_candle(dec!(14), ts(2)),
];
let stddev = StdDev::new(3).expect("valid StdDev period");
let series = stddev
.compute(&candles)
.expect("sufficient data for StdDev");
assert_eq!(series.len(), 1);
let value = series.decimal_values()[0];
let diff = (value - dec!(1.6329931619)).abs();
assert!(diff < dec!(0.0001), "Expected ~1.633, got {}", value);
}
#[test]
fn stddev_insufficient_data() {
let candles: Vec<Candle> = vec![make_candle(dec!(100), ts(0)), make_candle(dec!(102), ts(1))];
let stddev = StdDev::new(3).expect("valid StdDev period");
let result = stddev.compute(&candles);
assert!(matches!(
result,
Err(IndicatorError::InsufficientData {
required: 3,
actual: 2
})
));
}
#[test]
fn stddev_period_zero() {
let result = StdDev::new(0);
assert!(matches!(
result,
Err(IndicatorError::InvalidParameter { .. })
));
}
#[test]
fn stddev_name() {
let stddev = StdDev::new(20).expect("valid StdDev period");
assert_eq!(stddev.name(), "StdDev(20)");
}
#[test]
fn stddev_warmup_period() {
let stddev = StdDev::new(14).expect("valid StdDev period");
assert_eq!(stddev.warmup_period(), 14);
}
#[test]
fn stddev_period_accessor() {
let stddev = StdDev::new(10).expect("valid StdDev period");
assert_eq!(stddev.period(), 10);
}
#[test]
fn stddev_rolling_window() {
let candles: Vec<Candle> = (0..10)
.map(|i| make_candle(Decimal::from(i * 10), ts(i)))
.collect();
let stddev = StdDev::new(3).expect("valid StdDev period");
let series = stddev
.compute(&candles)
.expect("sufficient data for StdDev");
assert_eq!(series.len(), 8);
let expected = dec!(8.1649658);
for (_, v) in series.values() {
let diff = (*v - expected).abs();
assert!(diff < dec!(0.001), "StdDev should be ~8.165, got {}", v);
}
}
#[test]
fn decimal_sqrt_zero() {
assert_eq!(decimal_sqrt(dec!(0)), dec!(0));
}
#[test]
fn decimal_sqrt_perfect_square() {
let result = decimal_sqrt(dec!(4));
let diff = (result - dec!(2)).abs();
assert!(
diff < dec!(0.0000001),
"sqrt(4) should be 2, got {}",
result
);
}
#[test]
fn decimal_sqrt_non_perfect() {
let result = decimal_sqrt(dec!(2));
let diff = (result - dec!(1.41421356)).abs();
assert!(
diff < dec!(0.0001),
"sqrt(2) should be ~1.414, got {}",
result
);
}