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>
This commit is contained in:
Adriano Dal Pastro
2026-06-19 15:16:03 +00:00
parent 8401a280b9
commit 14522262e6
383 changed files with 1971 additions and 779 deletions
@@ -0,0 +1,90 @@
"""VALIDA GridWorker — forward-tracking == backtest grid_mtm (gate obbligatorio del progetto).
Il GridWorker (sim/paper) bootstrappa la storia FULL (start fisso) e mappa il capitale forward
dal deploy: capital = initial * eq[-1]/base_norm. Proprieta' da validare:
[A] LOGICA: la griglia sul feed full == backtest (stesso n_trades/win).
[B] FORWARD: deployato a T0 (bootstrap up to T0), dopo aver ticcato fino a T1 il capitale
e' initial * eq_full(T1)/eq_full(T0) — cioe' il ritorno della griglia DA T0 (causale).
[C] RESUME: reistanziato (rilegge base_norm da status.json) -> stesso capitale.
Config = la finale del re-gate pulito: BTC 1h range1.5 rd0.20 ru0.06 L6 sl0.10 tp0.03.
uv run python scripts/analysis/validate_grid_worker.py
"""
from __future__ import annotations
import shutil
import sys
import tempfile
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 scripts.analysis.grid_game_gate import grid_mtm
from scripts.analysis.ladder_search import regime_mask
from src.live.grid_worker import GridWorker
CFG = dict(tf="1h", range_down=0.20, range_up=0.06, levels=6,
sl_buf=0.10, tp_buf=0.03, max_bars=720, regime="range", trend_max=1.5)
ASSET, INIT, POS, LEV, FEE = "BTC", 1000.0, 0.15, 3.0, 0.0005
def _eq_last(df, mask):
cfg_bt = {k: v for k, v in CFG.items() if k not in ("regime", "trend_max")}
eqd, st = grid_mtm(ASSET, **cfg_bt, pos=POS, lev=LEV, fee_side=FEE, deploy_mask=mask, df=df)
return float(eqd.iloc[-1]), st
def main():
df = load_data(ASSET, "1h")
n = len(df)
nboot = n - 400 # deploy a T0 = nboot, poi 400 barre forward
mask_full = regime_mask(ASSET, "1h", trend_max=CFG["trend_max"])
F, st_full = _eq_last(df, mask_full) # eq full @ T1 (== backtest)
B, _ = _eq_last(df.iloc[:nboot].reset_index(drop=True), mask_full[:nboot]) # eq @ T0 (causale)
expected = INIT * F / B
print(f"[backtest] eq@T0={B:.4f} eq@T1={F:.4f} -> capitale forward atteso {expected:,.2f} "
f"(trades full {st_full['trades']}, win {st_full['win']:.1f}%)")
wd = Path(tempfile.mkdtemp(prefix="gridval_"))
try:
boot = df.iloc[:nboot].reset_index(drop=True)
w = GridWorker("GRID_BTC", ASSET, CFG, INIT, wd, leverage=LEV,
position_size=POS, fee_side=FEE, hist=boot)
# [A] logica: tick col feed full -> n_trades come backtest
w.tick(df)
dA = abs(w.n_trades - st_full["trades"])
print(f"[A] logica n_trades worker {w.n_trades} vs backtest {st_full['trades']} "
f"{'OK' if dA == 0 else 'MISMATCH'}")
# [B] forward: deploy a T0 (base), poi fino a T1
wd2 = Path(tempfile.mkdtemp(prefix="gridval_fwd_"))
wf = GridWorker("GRID_BTC", ASSET, CFG, INIT, wd2, leverage=LEV,
position_size=POS, fee_side=FEE, hist=boot)
wf.tick(boot) # deploy: base_norm=B, capital=initial
cap0 = wf.capital
wf.tick(df.iloc[:n - 200].reset_index(drop=True))
wf.tick(df) # fino a T1
dB = abs(wf.capital - expected)
print(f"[B] forward: cap@deploy {cap0:,.2f} (atteso {INIT:,.0f}) cap@T1 {wf.capital:,.2f} "
f"(atteso {expected:,.2f}) delta {dB:.4f} {'OK' if dB < 0.05 else 'MISMATCH'}")
# [C] resume
wr = GridWorker("GRID_BTC", ASSET, CFG, INIT, wd2, leverage=LEV,
position_size=POS, fee_side=FEE, hist=boot)
wr.tick(df)
dC = abs(wr.capital - wf.capital)
print(f"[C] resume cap {wr.capital:,.2f} delta {dC:.4f} "
f"{'OK' if dC < 0.05 else 'MISMATCH'} (base_norm persistito)")
ok = dA == 0 and dB < 0.05 and dC < 0.05
print(f"\n{'VALIDAZIONE OK: GridWorker forward-tracking == backtest' if ok else 'VALIDAZIONE FALLITA'}")
shutil.rmtree(wd2, ignore_errors=True)
finally:
shutil.rmtree(wd, ignore_errors=True)
if __name__ == "__main__":
main()