"""Locks the FROZEN prevday-breakout lead (src/strategies/prevday_breakout.py) so the forward-monitor track record is against an immutable signal. Pins: causal, bounded, non-trivial (long & short), and the frozen params unchanged. """ import sys from pathlib import Path import numpy as np ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) from src.backtest.harness import load # noqa: E402 from src.strategies import prevday_breakout as pb # noqa: E402 def test_frozen_params_unchanged(): assert (pb.ANCHOR_DAYS, pb.BUFFER_K, pb.ALLOW_SHORT) == (1, 0.30, True) assert (pb.TARGET_VOL, pb.VOL_WIN_DAYS, pb.LEV_CAP) == (0.20, 30, 2.0) def test_target_causal_bounded_nontrivial(): df = load("BTC", "1h") t = pb.target(df) assert len(t) == len(df) assert np.all(np.isfinite(t)) assert np.all(np.abs(t) <= pb.LEV_CAP + 1e-9) # symmetric book actually takes BOTH sides over history assert (t > 0).any() and (t < 0).any() # CAUSAL: recomputing on a truncated prefix matches the full run on its tail cut = int(len(df) * 0.85) sub = pb.target(df.iloc[:cut].reset_index(drop=True)) assert np.max(np.abs(sub[cut - 120:cut] - t[cut - 120:cut])) < 1e-9