use super::*;
use crate::indicators::test_support::*;
#[test]
fn sar_resume_is_bit_identical_to_full() {
let (high, low, _close) = ohlc(160);
let (accel, max) = (0.02, 0.2);
let full = sar(&high, &low, accel, max);
for &from in &[2usize, 3, 10, 40, 80, 120, 159] {
let st = sar_final_state(&high[..from], &low[..from], accel, max).unwrap();
let (tail, _) = sar_resume(&high, &low, accel, max, from, &st).unwrap();
assert_bits(&tail, &full[from..], "sar");
}
let mut saw_up = false;
let mut saw_down = false;
for w in full.windows(2) {
if w[1] > w[0] {
saw_up = true;
}
if w[1] < w[0] {
saw_down = true;
}
}
assert!(saw_up && saw_down, "fixture must swing both ways");
}
#[test]
fn sarext_resume_is_bit_identical_to_full() {
let (high, low, _close) = ohlc(160);
let (offset, ail, al, aml, ais, as_, ams) = (0.1, 0.02, 0.02, 0.2, 0.03, 0.03, 0.25);
for &start in &[0.0_f64, 1.0, -1.0] {
let full = sarext(&high, &low, start, offset, ail, al, aml, ais, as_, ams);
for &from in &[2usize, 5, 30, 70, 110, 159] {
let st = sarext_final_state(
&high[..from],
&low[..from],
start,
offset,
ail,
al,
aml,
ais,
as_,
ams,
)
.unwrap();
let (tail, _) =
sarext_resume(&high, &low, offset, ail, al, aml, ais, as_, ams, from, &st)
.unwrap();
assert_bits(&tail, &full[from..], "sarext");
}
}
}
#[test]
fn sarext_final_state_bootstrap_and_offset() {
let (high, low, _close) = ohlc(80);
let (al, aml, as_, ams) = (0.02, 0.2, 0.02, 0.2);
let bootstrap = |start: f64| -> (Vec<f64>, Vec<f64>) {
let full = sarext(&high, &low, start, 0.0, al, al, aml, as_, as_, ams);
let st =
sarext_final_state(&high, &low, start, 0.0, al, al, aml, as_, as_, ams).unwrap();
(full, st)
};
let (full_zero, _) = bootstrap(0.0);
let (full_long, _) = bootstrap(5.0); let (full_short, _) = bootstrap(-5.0); assert_ne!(
full_zero[1].to_bits(),
full_long[1].to_bits(),
"long bootstrap distinct"
);
assert_ne!(
full_zero[1].to_bits(),
full_short[1].to_bits(),
"short bootstrap distinct"
);
assert_ne!(
full_long[1].to_bits(),
full_short[1].to_bits(),
"long != short bootstrap"
);
let s_no_off =
sarext_final_state(&high, &low, 0.0, 0.0, al, al, aml, as_, as_, ams).unwrap();
let s_off = sarext_final_state(&high, &low, 0.0, 0.1, al, al, aml, as_, as_, ams).unwrap();
assert_ne!(
s_no_off[4].to_bits(),
s_off[4].to_bits(),
"offset must move the stop"
);
}
#[test]
fn sar_guards_decline() {
let one_h = [10.0];
let one_l = [8.0];
assert!(sar_final_state(&one_h, &one_l, 0.02, 0.2).is_none());
assert!(
sarext_final_state(&one_h, &one_l, 0.0, 0.0, 0.02, 0.02, 0.2, 0.02, 0.02, 0.2)
.is_none()
);
let st = vec![1.0, 0.02, 10.0, 8.0, 10.0, 8.0];
let (h, l, _c) = ohlc(20);
assert!(sar_resume(&h, &l, 0.02, 0.2, 1, &st).is_none());
let st7 = vec![1.0, 0.02, 0.02, 10.0, 8.0, 10.0, 8.0];
assert!(sarext_resume(&h, &l, 0.0, 0.02, 0.02, 0.2, 0.02, 0.02, 0.2, 1, &st7).is_none());
}
#[test]
fn ma_family_state_guards() {
let data = series(60);
assert!(ema_final_state(&data, 0).is_none());
assert!(kama_final_state(&data, 0).is_none());
assert!(kama_final_state(&data[..5], 30).is_none());
let mut nan_head = series(60);
for x in nan_head.iter_mut().take(3) {
*x = f64::NAN;
}
let via_head = kama_final_state(&nan_head, 10).unwrap();
let via_tail = kama_final_state(&nan_head[3..], 10).unwrap();
assert_eq!(
via_head[0].to_bits(),
via_tail[0].to_bits(),
"kama leading-NaN recursion"
);
assert_eq!(via_head[1].to_bits(), via_tail[1].to_bits());
let st = kama_final_state(&data, 10).unwrap();
assert!(kama_resume(&data, 0, 20, &st).is_none());
assert!(kama_resume(&data, 10, 10, &st).is_none()); assert!(kama_resume(&data, 10, 1000, &st).is_none());
let (h, l, c) = ohlc(60);
assert!(atr_final_state(&h, &l, &c, 0).is_none());
assert!(atr_final_state(&h, &l, &c, 100).is_none());
let st = atr_final_state(&h, &l, &c, 14).unwrap();
assert!(atr_resume(&h, &l, &c, 14, 0, &st).is_none());
}