"""Re-validazione: il StrategyWorker REALE tradi MR01 con edge netto? Guida il worker vero (generate_signals + nuova logica exit TP/SL/max_bars) su finestre mobili di dati 1h storici, simulando il polling live. Conferma che sulla finestra OOS l'edge netto (dopo fee 0.10% RT) sopravvive alla meccanica del worker (exit su prezzo corrente, piu' conservativa del backtest high/low). """ from __future__ import annotations import contextlib import os import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(PROJECT_ROOT)) from src.data.downloader import load_data from src.live.strategy_loader import load_strategy from src.live.strategy_worker import StrategyWorker OOS_FRAC = 0.30 WIN = 250 # barre per finestra di poll (warmup bb_window=50 + ATR) def replay(asset: str, params: dict): df = load_data(asset, "1h").reset_index(drop=True) n = len(df) split = int(n * (1 - OOS_FRAC)) strat = load_strategy("MR01_bollinger_fade") w = StrategyWorker(strat, asset, "1h", capital=1000.0, position_size=0.15, leverage=3.0, hold_bars=3, params=params, data_dir=Path(f"/tmp/replay_{asset}")) w._notify = lambda *a, **k: None # stato pulito for attr, val in dict(capital=1000.0, in_position=False, direction=0, entry_price=0, bars_held=0, total_trades=0, total_wins=0, last_bar_ts=0, tp=0.0, sl=0.0, max_bars=0).items(): setattr(w, attr, val) start = max(split, WIN) with contextlib.redirect_stdout(open(os.devnull, "w")): for j in range(start, n): w.tick(df.iloc[j - WIN + 1 : j + 1]) ret = (w.capital / 1000 - 1) * 100 acc = w.total_wins / w.total_trades * 100 if w.total_trades else 0.0 import pandas as pd period = (f"{pd.to_datetime(df['timestamp'].iloc[start], unit='ms', utc=True).date()}" f"->{pd.to_datetime(df['timestamp'].iloc[-1], unit='ms', utc=True).date()}") return w.total_trades, acc, ret, w.capital, period def main(): print("=" * 90) print(" RE-VALIDAZIONE WORKER REALE su MR01 (OOS, fee 0.10% RT, leva 3x) — finestra poll 250b") print("=" * 90) params = dict(bb_window=50, k=2.5, sl_atr=2.0, max_bars=24) print(f" {'Asset':>6s}{'Periodo OOS':>26s}{'Trade':>7s}{'Win%':>7s}{'Ret%':>9s}{'Cap€':>9s}") print(" " + "-" * 80) for asset in ["BTC", "ETH"]: t, acc, ret, cap, period = replay(asset, params) print(f" {asset:>6s}{period:>26s}{t:>7d}{acc:>7.1f}{ret:>+9.1f}{cap:>9.0f}") print(" " + "-" * 80) print(" Atteso: Ret% positivo (l'edge mean-reversion sopravvive alla meccanica del worker).") if __name__ == "__main__": main()