use super::*;
use crate::test_helpers::helpers::{make_candle, ts};
use rust_decimal_macros::dec;
#[test]
fn rsi_overbought() {
let candles: Vec<Candle> = (0..20)
.map(|i| make_candle(Decimal::from(100 + i * 2), ts(i)))
.collect();
let rsi = Rsi::new(14).expect("valid RSI period");
let series = rsi.compute(&candles).expect("sufficient data for RSI");
let values = series.decimal_values();
for value in &values {
assert!(
*value > dec!(70),
"RSI {} should be > 70 for uptrend",
value
);
}
}
#[test]
fn rsi_oversold() {
let candles: Vec<Candle> = (0..20)
.map(|i| make_candle(Decimal::from(200 - i * 2), ts(i)))
.collect();
let rsi = Rsi::new(14).expect("valid RSI period");
let series = rsi.compute(&candles).expect("sufficient data for RSI");
let values = series.decimal_values();
for value in &values {
assert!(
*value < dec!(30),
"RSI {} should be < 30 for downtrend",
value
);
}
}
#[test]
fn rsi_neutral() {
let candles: Vec<Candle> = (0..20).map(|i| make_candle(dec!(100), ts(i))).collect();
let rsi = Rsi::new(14).expect("valid RSI period");
let series = rsi.compute(&candles).expect("sufficient data for RSI");
let values = series.decimal_values();
for value in &values {
assert_eq!(*value, dec!(50), "RSI should be 50 for no movement");
}
}
#[test]
fn rsi_range() {
let candles: Vec<Candle> = vec![
make_candle(dec!(100), ts(0)),
make_candle(dec!(105), ts(1)),
make_candle(dec!(98), ts(2)),
make_candle(dec!(110), ts(3)),
make_candle(dec!(95), ts(4)),
make_candle(dec!(115), ts(5)),
make_candle(dec!(90), ts(6)),
];
let rsi = Rsi::new(3).expect("valid RSI period");
let series = rsi.compute(&candles).expect("sufficient data for RSI");
for (_, value) in series.values() {
assert!(
*value >= Decimal::ZERO && *value <= Decimal::from(100),
"RSI {} should be in [0, 100]",
value
);
}
}
#[test]
fn rsi_insufficient_data() {
let candles: Vec<Candle> = (0..5).map(|i| make_candle(dec!(100), ts(i))).collect();
let rsi = Rsi::new(14).expect("valid RSI period");
let result = rsi.compute(&candles);
assert!(matches!(
result,
Err(IndicatorError::InsufficientData {
required: 15,
actual: 5
})
));
}
#[test]
fn rsi_period_zero() {
let result = Rsi::new(0);
assert!(matches!(
result,
Err(IndicatorError::InvalidParameter { .. })
));
}
#[test]
fn rsi_name() {
let rsi = Rsi::new(14).expect("valid RSI period");
assert_eq!(rsi.name(), "RSI(14)");
}
#[test]
fn rsi_warmup_period() {
let rsi = Rsi::new(14).expect("valid RSI period");
assert_eq!(rsi.warmup_period(), 15); }