Files
PythagorasGoal/Old/scripts/analysis/validate_honest_workers.py
Adriano Dal Pastro 14522262e6 chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera
libreria "validata OOS" era artefatto di feed contaminato (print fantasma del
feed Cerbero TESTNET + storico Binance/USDT).

- Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e
  CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia
  (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample
  (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE
  50-82% barre flat; XRP/BNB non certificabili).
- Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni
  portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST
  con segnale residuo, da ri-validare in isolamento.
- Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio,
  runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/
  portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/
  (preservati, non cancellati). Diario consolidato in un unico documento.
- Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal +
  src/backtest/engine + load_data; tool dati certificati (rebuild_history,
  certify_feed, audit_feed, multi_source_check).
- Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico
  (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:20:59 +00:00

113 lines
4.5 KiB
Python

"""Validazione dei worker live multi-asset (TR01/ROT02/TSM01): il replay bar-by-bar del
worker riproduce la funzione di backtest di riferimento?
Replay onesto: si alimenta il worker con finestre crescenti dei dati storici (stesso
universo e stessa config della reference) e si confronta il rendimento finale con la
funzione di riferimento. Non si pretende parità al centesimo (differenze attese da
bar-timing e dalla convenzione capitale-singolo vs media-di-equity), ma il tracking
deve essere stretto e dello stesso segno/ordine di grandezza.
Riferimenti:
TR01 -> honest_improve2._tr_basket_daily
ROT02 -> honest_improve2._rot_daily_equity
TSM01 -> tsmom_research.tsmom_sim
Run: uv run python scripts/analysis/validate_honest_workers.py
"""
from __future__ import annotations
import sys
from pathlib import Path
import numpy as np
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from scripts.analysis.explore_lab import get_df
from scripts.analysis.honest_lab import available_assets
from src.live.basket_trend_worker import BasketTrendWorker
from src.live.rotation_worker import RotationWorker
from src.live.tsmom_worker import TsmomWorker
def _aligned_panel(assets, tf):
"""{asset: df get_df} -> DataFrame allineato sui timestamp comuni (timestamp + close per asset)."""
frames = {}
for a in assets:
try:
d = get_df(a, tf)[["timestamp", "close"]].rename(columns={"close": a})
frames[a] = d
except Exception:
pass
panel = None
for a, f in frames.items():
panel = f if panel is None else panel.merge(f, on="timestamp", how="inner")
return panel.sort_values("timestamp").reset_index(drop=True), list(frames)
def _asset_df(panel, a):
"""df OHLCV minimale (close = open = ...) per un asset dal panel allineato."""
c = panel[a].values
return pd.DataFrame({"timestamp": panel["timestamp"].values,
"open": c, "high": c, "low": c, "close": c, "volume": 1.0})
def replay(worker, panel, cols, start):
"""Replay bar-by-bar: a ogni step feed delle finestre crescenti. Ritorna ret% finale."""
n = len(panel)
for i in range(start, n):
sub = panel.iloc[: i + 1]
data = {a: _asset_df(sub, a) for a in cols}
worker.tick(data)
return (worker.capital / worker.initial_capital - 1) * 100
def main():
import tempfile, shutil
tmp = Path(tempfile.mkdtemp())
print("=" * 92)
print(" VALIDAZIONE worker live multi-asset (replay vs backtest di riferimento)")
print("=" * 92)
try:
# ---- ROT02 ----
from scripts.analysis.honest_improve2 import _rot_daily_equity
idx = pd.date_range("2021-01-01", "2026-05-26", freq="1D", tz="UTC")
ref_rot = (_rot_daily_equity(idx).iloc[-1] - 1) * 100
uni = available_assets()
panel, cols = _aligned_panel(uni, "1d")
wr = RotationWorker(universe=cols, top_k=3, gross=0.45, tf="1d",
capital=1000.0, data_dir=tmp)
rot = replay(wr, panel, cols, start=101)
print(f" ROT02 worker={rot:+.0f}% reference={ref_rot:+.0f}% "
f"univ={len(cols)} barre={len(panel)}")
# ---- TSM01 ----
from scripts.analysis.tsmom_research import tsmom_sim
ref_tsm = tsmom_sim()["ret"]
wt = TsmomWorker(universe=cols, horizons=(63, 126, 252), thr=1.0, gross=0.30,
tf="1d", capital=1000.0, data_dir=tmp)
tsm = replay(wt, panel, cols, start=253)
print(f" TSM01 worker={tsm:+.0f}% reference={ref_tsm:+.0f}%")
# ---- TR01 ----
from scripts.analysis.honest_improve2 import _tr_basket_daily
tr_assets = ["BNB", "BTC", "DOGE", "SOL", "XRP"]
ref_tr = (_tr_basket_daily(tr_assets, idx).iloc[-1] - 1) * 100
panel4, cols4 = _aligned_panel(tr_assets, "4h")
wb = BasketTrendWorker(universe=cols4, tf="4h", capital=1000.0, data_dir=tmp)
tr = replay(wb, panel4, cols4, start=101)
print(f" TR01 worker={tr:+.0f}% reference={ref_tr:+.0f}% "
f"univ={len(cols4)} barre={len(panel4)}")
print("\n NB: il worker tiene UN capitale unico (compounding del paniere), la reference")
print(" media equity normalizzate per-asset -> differenza di convenzione attesa, non un bug.")
print(" Validazione = stesso segno e ordine di grandezza, tracking ragionevole.")
finally:
shutil.rmtree(tmp, ignore_errors=True)
if __name__ == "__main__":
main()