5cce7acfe1
Il lead ortogonale a TP01 sopravvissuto all'onda intraday entra in forward-monitor (stesso trattamento di XS01 STAT-MODE / STA05), NON in esecuzione reale. - src/strategies/prevday_breakout.py: segnale CONGELATO (params fissi anchor=1, k=0.30, simmetrico, vol-target 0.20/30/2.0), self-contained. Bit-identico all'agent di ricerca (max diff 0.0): BTC full Sh 1.18/hold 0.92, ETH 1.09/1.42; marginal ADDS, earns_slot, corr_hold -0.01, non-hedge. - scripts/live/paper_prevday.py: forward-only paper, traccia DUE libri — MODELED ($2000 continuo) e REAL-$600 (salta i ribilanciamenti < min-order $5) -> il gap = haircut di fill reale che lo scettico aveva segnalato. Inizializzato forward-only da oggi. - cron_daily.sh: avanza il monitor ogni giorno. - test: param congelati + causale + bounded + long-short. Suite intera verde. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
34 lines
1.2 KiB
Python
34 lines
1.2 KiB
Python
"""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
|