feat(dashboard): box forward-monitor STATARB-RESID (lead ortogonale+eseguibile)

Aggiunge il forward-monitor STATARB-RESID al dashboard accanto a PREVDAY (sezione
③·c FORWARD-MONITOR): carica data/paper_statarb/state.json, mostra doppio libro
MODELED/REAL-$600, ret/maxDD/fill-haircut, posizione spread corrente e giorni forward.
Warn aggiornato: LEAD sotto deflated-Sharpe -> forward per confermare l'edge, non deploy.

Smoke-test html() OK (box presente, dati live). Test 146/146.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-06-29 21:20:56 +00:00
parent c52e0ab3f8
commit ee82e0a056
+21 -2
View File
@@ -22,6 +22,7 @@ from src.version import APP_VERSION
PAPER = PROJECT_ROOT / "data" / "paper_portfolio" / "state.json" PAPER = PROJECT_ROOT / "data" / "paper_portfolio" / "state.json"
PREVDAY = PROJECT_ROOT / "data" / "paper_prevday" / "state.json" PREVDAY = PROJECT_ROOT / "data" / "paper_prevday" / "state.json"
COMBO = PROJECT_ROOT / "data" / "paper_combo" / "state.json" COMBO = PROJECT_ROOT / "data" / "paper_combo" / "state.json"
STATARB = PROJECT_ROOT / "data" / "paper_statarb" / "state.json"
_CACHE = {"t": 0.0, "data": None} _CACHE = {"t": 0.0, "data": None}
_TTL = 120.0 _TTL = 120.0
@@ -53,6 +54,7 @@ def build():
paper = json.loads(PAPER.read_text()) if PAPER.exists() else None paper = json.loads(PAPER.read_text()) if PAPER.exists() else None
prevday = json.loads(PREVDAY.read_text()) if PREVDAY.exists() else None prevday = json.loads(PREVDAY.read_text()) if PREVDAY.exists() else None
combo = json.loads(COMBO.read_text()) if COMBO.exists() else None combo = json.loads(COMBO.read_text()) if COMBO.exists() else None
statarb = json.loads(STATARB.read_text()) if STATARB.exists() else None
try: try:
gtaa_w = gtaa_weights() # pesi ETF correnti azionabili (cache eq_*) gtaa_w = gtaa_weights() # pesi ETF correnti azionabili (cache eq_*)
except Exception: except Exception:
@@ -75,7 +77,7 @@ def build():
full=bt["full"], holdout=bt["holdout"], weights=bt["weights"], full=bt["full"], holdout=bt["holdout"], weights=bt["weights"],
per_sleeve=bt["per_sleeve"], yearly=bt["yearly"], per_sleeve=bt["per_sleeve"], yearly=bt["yearly"],
positions=pf.current_positions(), spark=spark, paper=paper, prevday=prevday, positions=pf.current_positions(), spark=spark, paper=paper, prevday=prevday,
combo=combo, gtaa_weights=gtaa_w, deribit=deribit, combo=combo, statarb=statarb, gtaa_weights=gtaa_w, deribit=deribit,
shadow=shadow, trades=trades, freq=freq, bh=None, shadow=shadow, trades=trades, freq=freq, bh=None,
) )
_CACHE.update(t=time.time(), data=data) _CACHE.update(t=time.time(), data=data)
@@ -143,6 +145,22 @@ def html():
f"forward da {pd.Timestamp(pv['start_ts'], unit='ms').date()}") f"forward da {pd.Timestamp(pv['start_ts'], unit='ms').date()}")
else: else:
prevday_html = "non inizializzato (gira <code>scripts/live/paper_prevday.py</code>)" prevday_html = "non inizializzato (gira <code>scripts/live/paper_prevday.py</code>)"
sa = d.get("statarb")
if sa:
days = (sa["last_ts"] - sa["start_ts"]) / 86400_000
rm = sa["cap_modeled"] / 2000.0 - 1
rr = sa["cap_real"] / 600.0 - 1
statarb_html = (
f"<b>${sa['cap_modeled']:,.2f}</b> modeled (€2k nom.) &nbsp;·&nbsp; "
f"<b>${sa['cap_real']:,.2f}</b> real-$600 (min-order $5)<br>"
f"ret <b>{rm*100:+.2f}%</b> / <b>{rr*100:+.2f}%</b> &nbsp;·&nbsp; "
f"maxDD {sa['dd_modeled']*100:.1f}% / {sa['dd_real']*100:.1f}% &nbsp;·&nbsp; "
f"fill-haircut {(rm-rr)*100:+.2f}pp<br>"
f"posizione spread (long ETH / short BTC per unità): <b>{sa['pos_real']:+.3f}</b> &nbsp;·&nbsp; "
f"{sa['n_bars']} barre 1d (~{days:.0f}g) · {sa['n_trades']} flip · "
f"forward da {pd.Timestamp(sa['start_ts'], unit='ms').date()}")
else:
statarb_html = "non inizializzato (gira <code>scripts/live/paper_statarb.py</code>)"
cb = d.get("combo") cb = d.get("combo")
if cb: if cb:
cdays = (pd.Timestamp(cb["last"]) - pd.Timestamp(cb["start"])).days cdays = (pd.Timestamp(cb["last"]) - pd.Timestamp(cb["start"])).days
@@ -288,7 +306,8 @@ th{{color:#8a93a0;font-weight:500}}.y{{display:inline-block;background:#161b22;b
<p class=warn>⚠️ Accumulo = proiezione condizionata (storico bull crypto → pianifica sul conservativo); nessuna leva; SKH01 research/forward-monitor (solo TP01 armato live). A €50/g servono ~€177k @conservativo: la via è capitale+tempo, non leva.</p> <p class=warn>⚠️ Accumulo = proiezione condizionata (storico bull crypto → pianifica sul conservativo); nessuna leva; SKH01 research/forward-monitor (solo TP01 armato live). A €50/g servono ~€177k @conservativo: la via è capitale+tempo, non leva.</p>
<div class="section">③·c FORWARD-MONITOR — lead paper (non deploy)</div> <div class="section">③·c FORWARD-MONITOR — lead paper (non deploy)</div>
<div class=box><b>PREVDAY range-breakout</b> — lead ORTOGONALE a TP01 (corr ~0.15 full / ~0 hold; marginal ADDS, non-hedge, robusto allo shift del confine-giorno). Forward-only, <b>nessuna esecuzione reale</b>:<br>{prevday_html}</div> <div class=box><b>PREVDAY range-breakout</b> — lead ORTOGONALE a TP01 (corr ~0.15 full / ~0 hold; marginal ADDS, non-hedge, robusto allo shift del confine-giorno). Forward-only, <b>nessuna esecuzione reale</b>:<br>{prevday_html}</div>
<p class=warn>⚠️ LEAD in osservazione, NON deployato. Sopravvissuto alla verifica avversariale dell'onda intraday; lo teniamo in paper per validarlo fuori-campione-vero. I due libri (modeled vs real-$600) mostrano l'haircut di fill che lo scettico aveva segnalato.</p> <div class=box><b>STATARB-RESID ETH/BTC</b> — lead ORTOGONALE <b>ed ESEGUIBILE</b> (relative-momentum del residuo ETH−β·BTC, dollar-neutral 2 gambe; corr→book 0.03, β-mkt 0.01; marginal ADDS). Primo stream insieme scorrelato ED eseguibile a $600 (haircut ~0, <b>NON STAT-MODE</b>). Forward-only, <b>nessuna esecuzione reale</b>:<br>{statarb_html}</div>
<p class=warn>⚠️ LEAD in osservazione, NON deployati. PREVDAY è sopravvissuto alla verifica avversariale dell'onda intraday. STATARB-RESID (sweep 5-thread 2026-06-29) rompe i muri di ortogonalità ed eseguibilità ma resta sotto il deflated-Sharpe (Sharpe ~0.84, DSR <0.95 su storia ~2.5 anni) → il forward serve a confermare l'edge fuori-campione-vero prima di un eventuale deploy a 2 gambe. I due libri (modeled vs real-$600) mostrano l'haircut di fill (atteso ~0 a 1d).</p>
<p class=warn>⚠️ Paper/monitor. XS01 e' STAT-MODE (book a 19 gambe market-neutral, non eseguibile a €2k, storia ~2.5 anni). VRP01 = lead short-vol MODELLATO (non deploy pieno). SKH01 (Skyhook dual-TF regime+breakout, BTC/ETH) = diversificatore quasi-ortogonale (corr ~0.09) aggiunto @25%: alza il FULL Sharpe del portafoglio 1.68→2.13 e dimezza il DD (14→8%) — RESEARCH/forward-monitor (book a 230m, causalita' verificata su harness ma costi reali e codice d'esecuzione da validare prima del deploy). TP01 e' l'unico deployable pieno.</p> <p class=warn>⚠️ Paper/monitor. XS01 e' STAT-MODE (book a 19 gambe market-neutral, non eseguibile a €2k, storia ~2.5 anni). VRP01 = lead short-vol MODELLATO (non deploy pieno). SKH01 (Skyhook dual-TF regime+breakout, BTC/ETH) = diversificatore quasi-ortogonale (corr ~0.09) aggiunto @25%: alza il FULL Sharpe del portafoglio 1.68→2.13 e dimezza il DD (14→8%) — RESEARCH/forward-monitor (book a 230m, causalita' verificata su harness ma costi reali e codice d'esecuzione da validare prima del deploy). TP01 e' l'unico deployable pieno.</p>
</body></html>""" </body></html>"""