Files
PythagorasGoal/scripts/research/r0703_vrpimp_structgrid.py
Adriano Dal Pastro 26f8d27a61 research(wave-0703): migliora+proteggi VRP01 — 7 filoni, 0 miglioramenti, anchor-audit VRP01 chiuso (4/4 sleeve)
Goal: migliorare la strategia short-vol (famiglia Albimarini/VRP01) e
proteggerla dai DD. Workflow 26 agenti (7 filoni + 2 lenti avversariali
+ scettico incrociato). Esito: NON migliorabile; la protezione DD si
compra SOLO con la size.

- Griglia 288 strutture: nessuna batte VRP01 (DSR 0.000; meta' griglia
  = 3a occorrenza "0-perdite/Sharpe implausibile" dopo CC01/ALB-A).
- 4 overlay DD (exit-spike/SL-MTM/ala-coda/cooldown): 4/4 REFUTED dal
  null de-levering — la protezione crash vive gia' nel gate IV-rank.
- Gate nuovi: 4o fallimento su 4 (l'alpha e' il binario IV-rank>0.30).
- Sizing: 12% deploy ~ 0.27 Kelly onesto (anti-rovina); disambiguazione
  unita' obbligatoria vs 12% peso book (0.014 Kelly, fattore 19x).
- Gate term-structure VIX/VXV su SPX (dSh +0.90, DSR 0.992) = confound
  di modello al 100% -> nuova regola: riprezzare term-structure-consistent
  prima di credere a un gate vol su strutture BS-flat.
- ANCHOR-AUDIT VRP01 CHIUSO: primo sleeve SENZA luck (fase canonica =
  peggiore delle 7 -> numeri di ammissione conservativi). Audit anchor
  ora completo su 4/4 sleeve ancorati.

Book/pesi INVARIATI. Nessun nuovo sleeve. 168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:05:19 +00:00

427 lines
24 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""R0703 VRPIMP-STRUCTGRID — griglia ONESTA di struttura short-vol vs VRP01 canonico.
FILONE 1 (2026-07-03). L'audit ALB-A (r0702_alb_structure) ha testato UNA cella a priori
(z=2.0σ, ali +1σ, tenor 5g). Domanda: nella griglia onesta
distanza z ∈ {1.0, 1.5, 2.0, 2.5}σ × tenor ∈ {3, 5, 7, 10}g × ali dz ∈ {+0.5, +1.0, +2.0}σ
× lato {put-only, call-only, entrambi} × struttura {vertical, condor, diagonal T+1}
esiste una cella che batte VRP01 canonico (put credit spread settimanale Δ-0.28/-0.10, gate
IV-rank) in modo che SOPRAVVIVE a (a) selezione IN-SAMPLE-ONLY, (b) deflated-Sharpe sul numero
TOTALE di celle, (c) banda f, (d) plateau dei vicini, (e) null del de-levering?
MAPPATURA lato×struttura (9 combo nominali -> 6 DISTINTE, per non contare doppio):
vertical×put = VERT-PUT vertical×call = VERT-CALL vertical×both ≡ CONDOR
condor×put ≡ VERT-PUT condor×call ≡ VERT-CALL condor×both = CONDOR
diagonal×{put,call,both} = DIAG-PUT / DIAG-CALL / DIAG-2 (Albimarini)
Totale celle = 4z × 4tenor × 3dz × 6 strutture = 288 (tutte contate nel deflated-Sharpe).
REGOLE RISPETTATE:
- Gate IV-rank CANONICO sempre attivo, NON riottimizzato (vrp>0 AND 0.30<=ivr<=0.90,
identico a VRP01 combo e a r0702_alb_structure gated=True).
- Selezione cella SOLO su Sharpe PRE-holdout (2021-03 .. 2024-12); hold-out 2025-26 mai
guardato per scegliere. DSR (Bailey & LdP, altlib.deflated_sharpe) su tutte le 288 celle.
- Pattern "0-perdite = Sharpe implausibile" (CC01, ALB-A): le celle con < MIN_LOSS_IS
perdite attive in-sample sono ESCLUSE DALLA SELEZIONE E DICHIARATE (coda mai campionata
-> Sharpe non informativo). Il criterio usa SOLO dati in-sample (niente peek).
- Banda f {0.6, 0.8, 1.0, 1.3} + scenario skew (f_put=1.3 / f_call=0.7) su ogni claim
(pricing BS FLAT su DVOL-30g: il deep-OTM e' banda, non stima puntuale).
- Banda d'ancora (regola 2026-07-02): la cella scelta si riporta su TUTTE le fasi di
partenza 0..tenor-1 (il costrutto e' ancorato alla cadenza tenor_d).
- NULL DEL DE-LEVERING (lezione TP01×DVOL): ogni vantaggio di DD della cella si confronta
con VRP01 semplicemente scalato allo stesso DD (Sharpe invariante per scala).
- Confronto apples-to-apples: oltre a VRP01 canonico (motore options_vrp_v2, capitale=K_short,
fee=12.5% del premio) si riporta il BRIDGE (stessa struttura di VRP01 nel motore nuovo:
vert-put z=0.583 dz=0.699 7g, capitale=S0, fee per-gamba) — battere solo VRP01 canonico
ma non il bridge = artefatto di convenzione fee/capitale, non struttura.
MACCHINERIA RIUSATA (non riscritta): motore di r0702_alb_structure (bs_put/bs_call/_fee_frac/
metrics/to_daily_lumped, VALIDATO vs run_structure cella-per-cella in testa al run),
options_vrp_v2.vrp_spread_weekly (VRP01 canonico esatto), altlib.deflated_sharpe/marginal_vs_tp01.
Regola standing: NIENTE short-vol da modello in deploy — l'esito massimo e' conoscenza/LEAD.
uv run python scripts/research/r0703_vrpimp_structgrid.py
"""
from __future__ import annotations
import json
import math
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
sys.path.insert(0, str(PROJECT_ROOT / "scripts" / "research" / "alt"))
import numpy as np, pandas as pd # noqa: E402
from scipy.stats import norm # noqa: E402
from scripts.research.options_vrp_lab import bs_put, load_series, per_year # noqa: E402
from scripts.research.options_vrp_v2 import vrp_spread_weekly, _ivrank, _rv30 # noqa: E402
from scripts.research.r0702_alb_structure import ( # noqa: E402
bs_call, _fee_frac, run_structure, metrics, to_daily_lumped, DAY, HOLDOUT)
import altlib as al # noqa: E402
SCRATCH = Path("/tmp/claude-1001/-opt-docker-PythagorasGoal/e00896d3-d4bb-4f2a-b471-55a1d88a12ba/scratchpad")
F_SWEEP = (0.6, 0.8, 1.0, 1.3)
F_SKEW = dict(f_put=1.3, f_call=0.7) # skew crypto-shaped: put ricche, call povere
Z_GRID = (1.0, 1.5, 2.0, 2.5)
TENOR_GRID = (3, 5, 7, 10)
DZ_GRID = (0.5, 1.0, 2.0)
STRUCTS = (("same", "put", "VERT-PUT"), ("same", "call", "VERT-CALL"), ("same", "both", "CONDOR"),
("diag", "put", "DIAG-PUT"), ("diag", "call", "DIAG-CALL"), ("diag", "both", "DIAG-2"))
MIN_ACT_IS = 30 # trade attivi minimi in-sample per credere allo Sharpe IS
MIN_LOSS_IS = 3 # perdite attive minime IS: <3 = coda mai campionata (CC01/ALB-A) -> ESCLUSA
CUTS = ("2022-01-01", "2023-01-01", "2024-01-01", "2025-01-01") # persistenza multi-cut
# bridge = la struttura ESATTA di VRP01 dentro il motore nuovo (delta -0.28/-0.10, 7g)
Z_BRIDGE = float(-norm.ppf(0.28)) # ~0.583
DZ_BRIDGE = float(-norm.ppf(0.10)) - Z_BRIDGE # ~0.699
# --------------------------------------------------------------------------- dati + gate cache
_S: dict = {}
def S(asset):
"""(px, dv, idx, skip) con gate canonico VRP01 precomputato (identico a r0702/options_vrp_v2)."""
if asset not in _S:
J = load_series(asset)
px = J["px"].values.astype(float)
dv = (J["dvol"].values / 100.0).astype(float)
n = len(px)
skip = np.zeros(n, dtype=bool)
for i in range(n):
rv = _rv30(px, i)
ivr = _ivrank(dv, i)
skip[i] = ((not np.isnan(rv) and (dv[i] - rv) <= 0)
or (not np.isnan(ivr) and (ivr < 0.30 or ivr > 0.90)))
_S[asset] = (px, dv, J.index, skip)
return _S[asset]
# --------------------------------------------------------------------------- motore generalizzato
def run_cell(asset, expiry, side, z, dz, tenor_d, f_put=1.0, f_call=1.0, offset=0):
"""Vendita sistematica non-overlapping della struttura, cadenza tenor_d, GATE CANONICO SEMPRE.
expiry: 'same' (long stessa scadenza) | 'diag' (long T+1g, mark BS a exit — vega)
side: 'put' | 'call' | 'both'
Identica contabilita' di r0702_alb_structure.run_structure (validata sotto): capitale = S0,
fee Deribit per gamba 0.03% notional cap 12.5% premio, delivery 0.015% su short ITM, exit fee
sulle long residue del diag. offset = fase d'ancora (banda d'ancora)."""
px, dv, idx, skip = S(asset)
n = len(px)
T = tenor_d / 365.25
T_long = T + DAY if expiry == "diag" else T
rets = {}
i = 60 + offset
while i + tenor_d < n:
j = i + tenor_d
if skip[i]:
rets[idx[j]] = 0.0
i = j
continue
S0 = px[i]; sig = dv[i]; m = sig * math.sqrt(T)
S1 = px[j]; sig1 = dv[j]
credit = short_pay = long_val = exit_fee = deliv = 0.0
legs = []
if side in ("put", "both"):
Ks = S0 * math.exp(-z * m); Kl = S0 * math.exp(-(z + dz) * m)
ps = bs_put(S0, Ks, T, sig) / S0 * f_put
pl = bs_put(S0, Kl, T_long, sig) / S0 * f_put
credit += ps - pl; legs += [ps, pl]
short_pay += max(0.0, Ks - S1) / S0
deliv += _fee_frac(max(0.0, Ks - S1) / S0, rate=0.00015)
if expiry == "diag":
lv = bs_put(S1, Kl, DAY, sig1) / S0 * f_put
long_val += lv
exit_fee += _fee_frac(lv, notional_ratio=S1 / S0)
else:
long_val += max(0.0, Kl - S1) / S0
if side in ("call", "both"):
Ks = S0 * math.exp(+z * m); Kl = S0 * math.exp(+(z + dz) * m)
cs = bs_call(S0, Ks, T, sig) / S0 * f_call
cl = bs_call(S0, Kl, T_long, sig) / S0 * f_call
credit += cs - cl; legs += [cs, cl]
short_pay += max(0.0, S1 - Ks) / S0
deliv += _fee_frac(max(0.0, S1 - Ks) / S0, rate=0.00015)
if expiry == "diag":
lv = bs_call(S1, Kl, DAY, sig1) / S0 * f_call
long_val += lv
exit_fee += _fee_frac(lv, notional_ratio=S1 / S0)
else:
long_val += max(0.0, S1 - Kl) / S0
entry_fee = sum(_fee_frac(v) for v in legs)
rets[idx[j]] = credit - short_pay + long_val - entry_fee - exit_fee - deliv
i = j
return pd.Series(rets)
def book_cell(expiry, side, z, dz, tenor_d, **kw):
rB = run_cell("BTC", expiry, side, z, dz, tenor_d, **kw)
rE = run_cell("ETH", expiry, side, z, dz, tenor_d, **kw)
return pd.concat({"B": rB, "E": rE}, axis=1, join="inner").mean(axis=1)
def vrp01_book(f):
return pd.concat({a[0]: vrp_spread_weekly(a, defined_risk=True, f=f, gate_vrp=True,
gate_ivr=0.30, crash_skip=0.90)
for a in ("BTC", "ETH")}, axis=1, join="inner").mean(axis=1)
# --------------------------------------------------------------------------- utilita' report
def _sh_window(r, tenor_d, start=None, end=None):
w = r
if start is not None:
w = w[w.index >= pd.Timestamp(start, tz="UTC")]
if end is not None:
w = w[w.index < pd.Timestamp(end, tz="UTC")]
ppy = 365.25 / tenor_d
return float(w.mean() / w.std() * np.sqrt(ppy)) if len(w) > 5 and w.std() > 0 else float("nan")
def dd_of(r, lam=1.0):
eq = np.cumprod(1 + lam * r.values)
pk = np.maximum.accumulate(eq)
return float(np.max((pk - eq) / pk))
def scale_to_dd(r, dd_target):
"""λ tale che il maxDD di λ·r == dd_target (null del de-levering)."""
lo, hi = 0.01, 3.0
for _ in range(60):
mid = 0.5 * (lo + hi)
if dd_of(r, mid) > dd_target:
hi = mid
else:
lo = mid
return 0.5 * (lo + hi)
def validate_engine():
"""run_cell deve riprodurre ESATTAMENTE run_structure (motore ALB-A validato) su 3 kind."""
print(" [validazione motore] run_cell vs r0702_alb_structure.run_structure (z=2, dz=1, 5g, gated):")
ok = True
for kind, (expiry, side) in (("diag", ("diag", "both")), ("condor", ("same", "both")),
("vert", ("same", "put"))):
for a in ("BTC", "ETH"):
ref = run_structure(a, kind, z=2.0, dz=1.0, tenor_d=5, gated=True)
new = run_cell(a, expiry, side, 2.0, 1.0, 5)
d = float((ref - new).abs().max()) if len(ref) == len(new) else float("inf")
ok &= d < 1e-12
print(f" {kind:<7}{a}: n={len(new):>4} max|Δ|={d:.2e}")
if not ok:
raise SystemExit("ENGINE MISMATCH: run_cell non riproduce run_structure — stop.")
print(" -> motore identico (riuso validato, non riscrittura).")
def main():
print("=" * 112)
print(" R0703 VRPIMP-STRUCTGRID — griglia onesta 288 celle di struttura short-vol vs VRP01 canonico")
print(" Gate IV-rank canonico SEMPRE attivo (mai riottimizzato). Selezione IN-SAMPLE-ONLY (pre-2025).")
print(" ⚠️ SKEW: pricing BS FLAT su DVOL-30g -> banda f {0.6,0.8,1.0,1.3} + scenario fp=1.3/fc=0.7.")
print(" Regola standing: NIENTE short-vol da modello in deploy — esito massimo = conoscenza/LEAD.")
print("=" * 112)
validate_engine()
# ------------------------------------------------------------- (1) VRP01 canonico + bridge
print("\n (1) BASELINE — VRP01 canonico (options_vrp_v2 COMBO) e bridge motore-nuovo, banda f")
hdr = (f" {'riga':<38} {'ShF':>6} {'ShIS':>6} {'ShH':>6} {'CAGR':>7} {'maxDD':>6} "
f"{'worst':>7} {'win%':>5} {'att%':>5}")
print(hdr)
vrp = {}
for f in F_SWEEP:
vrp[f] = vrp01_book(f)
mm = metrics(vrp[f], 7); mi = metrics(vrp[f][vrp[f].index < HOLDOUT], 7)
print(f" VRP01 canonico f={f:<4} {'':<16} {mm['sh']:>6.2f} {mi['sh']:>6.2f} {mm['sh_h']:>6.2f} "
f"{mm['cagr']*100:>+6.1f}% {mm['dd']*100:>5.1f}% {mm['worst']*100:>+6.2f}% "
f"{mm['win']*100:>4.0f}% {mm['act']*100:>4.0f}%")
bridge = {}
for f in F_SWEEP:
bridge[f] = book_cell("same", "put", Z_BRIDGE, DZ_BRIDGE, 7, f_put=f, f_call=f)
mm = metrics(bridge[f], 7); mi = metrics(bridge[f][bridge[f].index < HOLDOUT], 7)
print(f" bridge vert-put Δ-0.28/-0.10 7g f={f:<4} {mm['sh']:>6.2f} {mi['sh']:>6.2f} {mm['sh_h']:>6.2f} "
f"{mm['cagr']*100:>+6.1f}% {mm['dd']*100:>5.1f}% {mm['worst']*100:>+6.2f}% "
f"{mm['win']*100:>4.0f}% {mm['act']*100:>4.0f}%")
print(" (bridge = stessa struttura di VRP01 nel motore-griglia: e' il confronto apples-to-apples;")
print(" battere VRP01 ma non il bridge = artefatto di convenzione fee/capitale, non struttura)")
# ------------------------------------------------------------- (2) griglia 288 celle, f=1.0
print(f"\n (2) GRIGLIA {len(STRUCTS)}x{len(Z_GRID)}x{len(DZ_GRID)}x{len(TENOR_GRID)} = "
f"{len(STRUCTS)*len(Z_GRID)*len(DZ_GRID)*len(TENOR_GRID)} celle (f=1.0, gate canonico)")
cells = {}
for expiry, side, lab in STRUCTS:
for z in Z_GRID:
for dz in DZ_GRID:
for tn in TENOR_GRID:
r = book_cell(expiry, side, z, dz, tn)
r_is = r[r.index < HOLDOUT]
act_is = r_is[r_is != 0]
rec = dict(expiry=expiry, side=side, lab=lab, z=z, dz=dz, tn=tn, r=r,
mi=metrics(r_is, tn), mm=metrics(r, tn),
nact_is=int(len(act_is)), nloss_is=int((act_is < 0).sum()))
rec["eligible"] = (rec["nact_is"] >= MIN_ACT_IS and rec["nloss_is"] >= MIN_LOSS_IS)
cells[(lab, z, dz, tn)] = rec
all_full_sh = [c["mm"]["sh"] for c in cells.values()]
all_is_sh = [c["mi"]["sh"] for c in cells.values()]
n_cells = len(cells)
inel = [c for c in cells.values() if not c["eligible"]]
print(f" celle totali {n_cells} | ESCLUSE dalla selezione (implausibili: <{MIN_LOSS_IS} perdite IS "
f"o <{MIN_ACT_IS} trade IS): {len(inel)} — dichiarate sotto, contate comunque nel DSR")
# il pattern '0-perdite': cosa avremmo scelto SENZA il filtro
naive = max(cells.values(), key=lambda c: c["mi"]["sh"])
print(f"\n [pattern CC01/ALB-A] best IS SENZA filtro implausibilita': {naive['lab']} z={naive['z']} "
f"dz={naive['dz']} {naive['tn']}g -> ShIS {naive['mi']['sh']:.2f} (perdite IS: {naive['nloss_is']}, "
f"trade IS: {naive['nact_is']}) | suo hold-out ShH {naive['mm']['sh_h']:+.2f}")
top_inel = sorted(inel, key=lambda c: c["mi"]["sh"], reverse=True)[:8]
print(" top celle ESCLUSE (ShIS alto MA coda mai campionata in-sample -> Sharpe non informativo):")
for c in top_inel:
print(f" {c['lab']:<10} z={c['z']} dz={c['dz']} {c['tn']:>2}g ShIS {c['mi']['sh']:>6.2f} "
f"perdite-IS {c['nloss_is']:>2} su {c['nact_is']:>3} trade -> ShH {c['mm']['sh_h']:>+6.2f}")
# ------------------------------------------------------------- (3) selezione in-sample-only
elig = [c for c in cells.values() if c["eligible"]]
ch = max(elig, key=lambda c: c["mi"]["sh"])
print(f"\n (3) SELEZIONE IN-SAMPLE-ONLY (fra le {len(elig)} eleggibili) + top-10")
print(f" {'cella':<34} {'ShIS':>6} {'ShF':>6} {'ShH':>6} {'DD':>6} {'worst':>7} {'lossIS':>7}")
for c in sorted(elig, key=lambda c: c["mi"]["sh"], reverse=True)[:10]:
mark = " <== SCELTA" if c is ch else ""
print(f" {c['lab']:<10} z={c['z']} dz={c['dz']} tenor={c['tn']:>2}g{'':<6} {c['mi']['sh']:>6.2f} "
f"{c['mm']['sh']:>6.2f} {c['mm']['sh_h']:>6.2f} {c['mm']['dd']*100:>5.1f}% "
f"{c['mm']['worst']*100:>+6.2f}% {c['nloss_is']:>4}/{c['nact_is']:<4}{mark}")
tn = ch["tn"]
dsr_full, sr0_full = al.deflated_sharpe(ch["mm"]["sh"], all_full_sh, ch["r"], dpy=365.25 / tn)
r_is = ch["r"][ch["r"].index < HOLDOUT]
dsr_is, sr0_is = al.deflated_sharpe(ch["mi"]["sh"], all_is_sh, r_is, dpy=365.25 / tn)
print(f"\n DSR cella scelta (N={n_cells} trial): FULL {dsr_full:.3f} (null-max ~{sr0_full:.2f}) | "
f"IS {dsr_is:.3f} (null-max ~{sr0_is:.2f}) | PASS richiede >= 0.95")
# nota anti-hindsight: la cella col miglior HOLD-OUT fra le eleggibili NON e' selezionabile
# (selection-on-holdout, gate 2026-06-29); la riporto solo per chiudere la domanda ovvia.
hb = max(elig, key=lambda c: c["mm"]["sh_h"])
dsr_hb, _ = al.deflated_sharpe(hb["mm"]["sh"], all_full_sh, hb["r"], dpy=365.25 / hb["tn"])
rank_is = 1 + sum(1 for c in elig if c["mi"]["sh"] > hb["mi"]["sh"])
print(f" [anti-hindsight] best HOLD-OUT fra le eleggibili: {hb['lab']} z={hb['z']} dz={hb['dz']} "
f"{hb['tn']}g (ShIS {hb['mi']['sh']:.2f}, rank-IS #{rank_is}, ShH {hb['mm']['sh_h']:.2f}, "
f"DSR {dsr_hb:.3f}) — sceglierla = selection-on-holdout, VIETATO; e comunque DSR<0.95.")
# ------------------------------------------------------------- (4) cella scelta: banda f vs VRP01
print(f"\n (4) CELLA SCELTA {ch['lab']} z={ch['z']} dz={ch['dz']} {tn}g — banda f vs VRP01 e bridge")
print(f" {'f':<22} {'cella ShF/ShH':>16} {'VRP01 ShF/ShH':>16} {'bridge ShF/ShH':>16} "
f"{'cella DD/worst':>17} {'VRP01 DD/worst':>17}")
ch_f = {}
beats_vrp = beats_bridge = True
for f in F_SWEEP:
rr = book_cell(ch["expiry"], ch["side"], ch["z"], ch["dz"], tn, f_put=f, f_call=f)
ch_f[f] = rr
m = metrics(rr, tn); v = metrics(vrp[f], 7); b = metrics(bridge[f], 7)
beats_vrp &= (m["sh"] > v["sh"]) and (m["sh_h"] > v["sh_h"])
beats_bridge &= (m["sh"] > b["sh"]) and (m["sh_h"] > b["sh_h"])
print(f" f={f:<20} {m['sh']:>7.2f}/{m['sh_h']:>6.2f} {v['sh']:>8.2f}/{v['sh_h']:>6.2f} "
f"{b['sh']:>8.2f}/{b['sh_h']:>6.2f} {m['dd']*100:>7.1f}%/{m['worst']*100:>+6.2f}% "
f"{v['dd']*100:>7.1f}%/{v['worst']*100:>+6.2f}%")
rr = book_cell(ch["expiry"], ch["side"], ch["z"], ch["dz"], tn, **F_SKEW)
m = metrics(rr, tn)
print(f" SKEW fp=1.3/fc=0.7 {m['sh']:>7.2f}/{m['sh_h']:>6.2f} (VRP01/bridge non hanno lato call)")
py_c = per_year(ch_f[1.0]); py_v = per_year(vrp[1.0])
print(" per-anno cella f=1.0: " + " ".join(f"{y}:{v*100:+5.1f}%" for y, v in sorted(py_c.items())))
print(" per-anno VRP01 f=1.0: " + " ".join(f"{y}:{v*100:+5.1f}%" for y, v in sorted(py_v.items())))
# persistenza multi-cut del presunto vantaggio (ΔSh cella - bridge, finestre [cut, end))
print(" multi-cut ΔSh (cella - bridge | cella - VRP01) su [cut, fine):")
for cut in CUTS:
d_b = _sh_window(ch_f[1.0], tn, start=cut) - _sh_window(bridge[1.0], 7, start=cut)
d_v = _sh_window(ch_f[1.0], tn, start=cut) - _sh_window(vrp[1.0], 7, start=cut)
print(f" {cut}: {d_b:+.2f} | {d_v:+.2f}")
# ------------------------------------------------------------- (5) banda d'ancora
print(f"\n (5) BANDA D'ANCORA — cella scelta su tutte le {tn} fasi di partenza (offset 0..{tn-1})")
anch = []
for o in range(tn):
ro = book_cell(ch["expiry"], ch["side"], ch["z"], ch["dz"], tn, offset=o)
mo = metrics(ro, tn)
anch.append((o, mo["sh"], mo["sh_h"]))
print(f" offset {o}: ShF {mo['sh']:>5.2f} ShH {mo['sh_h']:>+5.2f}")
shf = [a[1] for a in anch]; shh = [a[2] for a in anch]
print(f" banda ShF [{min(shf):.2f}, {max(shf):.2f}] mediana {np.median(shf):.2f} | "
f"ShH [{min(shh):+.2f}, {max(shh):+.2f}] mediana {np.median(shh):+.2f}")
# ------------------------------------------------------------- (6) plateau dei vicini
print(f"\n (6) PLATEAU — slice {ch['lab']} dz={ch['dz']}: matrice z × tenor (ShIS / ShH)")
print(" " + "".join(f"{t:>14}g" for t in TENOR_GRID))
for z in Z_GRID:
rowtxt = f" z={z:<4}"
for t in TENOR_GRID:
c = cells[(ch["lab"], z, ch["dz"], t)]
star = "*" if (z == ch["z"] and t == tn) else " "
rowtxt += f" {c['mi']['sh']:>5.2f}/{c['mm']['sh_h']:>+5.2f}{star}"
print(rowtxt)
print(" vicini dz (a z/tenor scelti): " + " ".join(
f"dz={d}: ShIS {cells[(ch['lab'], ch['z'], d, tn)]['mi']['sh']:.2f}/"
f"ShH {cells[(ch['lab'], ch['z'], d, tn)]['mm']['sh_h']:+.2f}" for d in DZ_GRID))
neigh = []
zi, ti, di = Z_GRID.index(ch["z"]), TENOR_GRID.index(tn), DZ_GRID.index(ch["dz"])
for (gi, grid, mk) in ((zi, Z_GRID, "z"), (ti, TENOR_GRID, "tn"), (di, DZ_GRID, "dz")):
for step in (-1, +1):
k = gi + step
if 0 <= k < len(grid):
key = dict(z=ch["z"], tn=tn, dz=ch["dz"]); key[mk] = grid[k]
neigh.append(cells[(ch["lab"], key["z"], key["dz"], key["tn"])])
n_pos = sum(1 for c in neigh if c["mi"]["sh"] > 0 and c["mm"]["sh_h"] > 0)
print(f" vicini adiacenti (±1 passo per asse): {len(neigh)} | con ShIS>0 E ShH>0: {n_pos}")
# ------------------------------------------------------------- (7) null del de-levering
print("\n (7) NULL DEL DE-LEVERING — il vantaggio DD della cella e' replicabile scalando VRP01?")
m_c = metrics(ch_f[1.0], tn); m_v = metrics(vrp[1.0], 7)
lam = scale_to_dd(vrp[1.0], m_c["dd"])
scaled = lam * vrp[1.0]
m_s = metrics(scaled, 7)
print(f" cella: Sh {m_c['sh']:.2f} / ShH {m_c['sh_h']:.2f} DD {m_c['dd']*100:.1f}% "
f"worst {m_c['worst']*100:+.2f}% CAGR {m_c['cagr']*100:+.1f}%")
print(f" VRP01 pieno: Sh {m_v['sh']:.2f} / ShH {m_v['sh_h']:.2f} DD {m_v['dd']*100:.1f}% "
f"worst {m_v['worst']*100:+.2f}% CAGR {m_v['cagr']*100:+.1f}%")
print(f" VRP01 × λ={lam:.2f}: Sh {m_s['sh']:.2f} / ShH {m_s['sh_h']:.2f} DD {m_s['dd']*100:.1f}% "
f"worst {m_s['worst']*100:+.2f}% CAGR {m_s['cagr']*100:+.1f}%")
delever_kills = (m_c["dd"] < m_v["dd"]) and (m_s["sh"] >= m_c["sh"]) and (m_s["sh_h"] >= m_c["sh_h"])
print(" -> lo scaling lascia lo Sharpe invariato: ogni vantaggio di DD e' replicabile con λ,"
f" la cella vale SOLO se Sh/ShH superiori. delever_null_kills={delever_kills}")
# ------------------------------------------------------------- (8) marginale/corr
print("\n (8) CORRELAZIONE + MARGINALE (informativo, non promozione: regola standing short-vol)")
d_c = to_daily_lumped(ch_f[1.0]); d_v = to_daily_lumped(vrp[1.0])
w_c = (1 + d_c).resample("168h", origin="epoch").prod() - 1 # origin comune (lezione '7D')
w_v = (1 + d_v).resample("168h", origin="epoch").prod() - 1
Jw = pd.concat({"c": w_c, "v": w_v}, axis=1, join="inner").dropna()
print(f" corr settimanale cella~VRP01: {Jw['c'].corr(Jw['v']):+.2f} "
f"(alta = stesso trade in altri vestiti)")
mv = al.marginal_vs_tp01(d_c)
print(f" marginal_vs_tp01[cella]: verdict={mv.get('marginal_verdict')} corr={mv.get('corr_full')} "
f"IS-Sh={mv.get('cand_insample_sharpe')} insample_edge={mv.get('has_insample_edge')} "
f"hedge={mv.get('is_hedge')} robust_oos={mv.get('robust_oos')}")
# ------------------------------------------------------------- (9) verdetto
print("\n (9) VERDETTO")
dsr_pass = bool(np.isfinite(dsr_full) and dsr_full >= 0.95 and np.isfinite(dsr_is) and dsr_is >= 0.95)
wins = beats_vrp and beats_bridge and dsr_pass and not delever_kills
print(f" batte VRP01 su tutta la banda f (ShF e ShH): {beats_vrp}")
print(f" batte il bridge (stesso motore) su tutta la banda f: {beats_bridge}")
print(f" DSR>=0.95 su {n_cells} celle (FULL {dsr_full:.3f} / IS {dsr_is:.3f}): {dsr_pass}")
print(f" sopravvive al null del de-levering: {not delever_kills}")
print(f" ==> {'ESISTE una cella che batte VRP01 onestamente' if wins else 'NESSUNA cella batte VRP01 onestamente'}")
print(" (esecuzione: comunque STAT-MODE — niente short-vol da modello in deploy;")
print(" muri di size Deribit invariati dal filone capital-scaling: spread ETH ~2.6k+, BTC ~4.7k+)")
# dump metriche per il report
SCRATCH.mkdir(parents=True, exist_ok=True)
dump = {f"{k[0]}|z{k[1]}|dz{k[2]}|t{k[3]}": dict(
is_sh=c["mi"]["sh"], full_sh=c["mm"]["sh"], hold_sh=c["mm"]["sh_h"], dd=c["mm"]["dd"],
worst=c["mm"]["worst"], nact_is=c["nact_is"], nloss_is=c["nloss_is"], eligible=c["eligible"])
for k, c in cells.items()}
(SCRATCH / "r0703_structgrid_results.json").write_text(json.dumps(dump, indent=1))
print(f"\n [dump] {SCRATCH / 'r0703_structgrid_results.json'}")
if __name__ == "__main__":
main()