ARIMA_SAX_Hybrid_Forecaster/tests/test_nolookahead.py

52 lines
2 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
"""RESEARCH HARD-STOP TEST: no-lookahead enforcement.
A failing test here is a HARD STOP. Both SAX and ARIMA forecasts must be
invariant to any change in bars AFTER the forecast origin, and must not carry
actual (future) outcome information.
"""
import pytest
from src.forecasting.target import ForecastContext
from src.sax import SaxConfig, SaxAnalogForecaster
from src.arima import ArimaConfig, ArimaModel
from tests.helpers import make_series, clone_with_future
@pytest.fixture
def context():
return ForecastContext(symbol="XAUUSD", timeframe="H1", horizon=12, atr_period=20)
def test_sax_forecast_unchanged_by_future(context):
s = make_series(n=700, seed=3)
origin = 400
model = SaxAnalogForecaster(SaxConfig(window_length=24, word_length=8,
alphabet_size=5, min_analogs=5))
rec_a = model.forecast(s, origin, context)
s_future = clone_with_future(s, origin, mut=100000.0)
rec_b = model.forecast(s_future, origin, context)
assert rec_a.to_dict() == rec_b.to_dict(), (
"SAX forecast changed when a FUTURE bar changed -> lookahead leak"
)
def test_forecast_carries_no_actual_outcome(context):
s = make_series(700, seed=4)
model = SaxAnalogForecaster(SaxConfig(window_length=5, min_analogs=5))
rec = model.forecast(s, 400, context)
assert rec.outcome_boundary is None or rec.outcome_boundary >= rec.forecast_origin
# forecast must be frozen: no actual (future) outcome may be attached here
assert rec.actual_forward_return is None
assert rec.actual_forward_return_ATR is None
def test_arima_forecast_unchanged_by_future(context):
s = make_series(300, seed=5)
origin = 220
model = ArimaModel(ArimaConfig(p=1, d=0, q=0, fit_window=150))
s_future = clone_with_future(s, origin, mut=5000.0)
a = model.forecast(s, origin, context)
b = model.forecast(s_future, origin, context)
assert a.normalized_expected_return == b.normalized_expected_return
assert a.arima_state == b.arima_state