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:
@@ -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()
|
||||
Reference in New Issue
Block a user