Files
Adriano Dal Pastro 76120b59c2 research(wave-0702bis): ondata video-claims — Elliott 3/3 e Albimarini 2/2 scartati, mappa capital scaling 2-5k
Sei agenti, nessun sopravvissuto:
- ELL-A range-cycle: rumore (0/24 Bonferroni; nessuna cella weekly regge
  a tutte le 7 ancore). Lezione pandas: resample("7D", origin) IGNORA
  origin -> usare "168h" per le bande d'ancora weekly.
- ELL-B Fibonacci: l'edge apparente e' la POSIZIONE dei livelli, non i
  numeri (null location-matched: pctl 0.39-0.68); confluenza FAIL 4/4.
- ELL-C canale: Donchian travestito (non batte il Donchian equivalente,
  DSR 0.685, IS 1.40 -> HOLD -0.87; target 1.618 = caso; anchor-luck 4h).
- ALB-A diagonale: il condor stessa-scadenza la batte a ogni f; senza
  gate IV-rank tutte le strutture perdono (3a conferma: l'alpha del VRP
  e' il gate); fee-negativa su Deribit a qualsiasi size; 2o caso
  "0-perdite = Sharpe implausibile" dopo CC01.
- ALB-B claims: 82%/PF 5.16/"420%" consistente con zero skill (P=20-45%,
  78.6% delle finestre 6-mesi lo produce); replay con code reali =
  rovina 1998/2002/2020; la diagonale passa il 12-40% della perdita naked.
- Capital scaling 600->2-5k: unico vincolo binding = cap $300/asset
  (a 5k book al 49% del target) -> AL DEPOSITO alzare a equity/2;
  min_order $5 lasciare; XS01 ~20k confermata; aspettativa onesta
  de-luckata 2k ~EUR 0.6-0.8/g, 5k ~EUR 1.4-2/g.

Nessun nuovo sleeve, book live invariato. 168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:31:38 +00:00

334 lines
19 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.
"""R0702 ALB-STRUCTURE — double diagonal deep-OTM "Albimarini" vs struttura VRP01.
FILONE: video didattici claimano su SPY una vendita sistematica di DOUBLE DIAGONAL a credito
(2 short scadenza T a ~9% di distanza su ~6 giorni + 2 long scadenza T+1g, entrambi i lati) con
82% win, PF 5.16, "420% annuo". Qui la STRUTTURA (non il gate — lezione 2026-07-01: il gate
IV-rank>0.30 canonico NON si riottimizza) viene portata su BTC/ETH Deribit (che ha scadenze
giornaliere) e modellata onestamente sul nostro stack DVOL, contro il VRP01 canonico
(put credit spread settimanale -0.28/-0.10, gate vrp>0 + ivr>=0.30 + crash-skip 0.90).
⚠️ CAVEAT SKEW — IN TESTA, NON IN FONDO: il pricing e' Black-Scholes FLAT sulla DVOL (IV ATM 30g).
Il deep-OTM (qui 1.5-3.0 sigma ~ 8-25% di distanza) e' ESATTAMENTE dove il flat-vol sbaglia di piu':
su crypto lo smile e' ripido su ENTRAMBE le ali (su equity solo put). Il premio reale delle ali e'
probabilmente > modello (f>1) per le put e variabile per le call; la calibrazione reale che abbiamo
(f~1.0) e' ATM-ish delta -0.28 su finestra calma, NON copre il deep-OTM. Quindi OGNI numero va letto
come BANDA sul fattore premio f in {0.6, 0.8, 1.0, 1.3} + uno scenario skew asimmetrico
(f_put=1.3 / f_call=0.7), MAI come stima puntuale. In piu' la DVOL e' IV a 30g usata per tenor 3-6g
(term structure ignorata; snapshot vol_term 2026-06: iv_7d vs iv_30d entro ~±3pt in calma, ma in
stress il front-end esplode -> il modello SOTTOSTIMA il mark-to-market avverso in crash).
Distanza in unita' di VOL, non il 9% fisso di SPY: 9%/6g su SPY (IV~16%) = ~3.5-4 sigma; BTC si
muove del 9% in 6 giorni spesso. Cella centrale dichiarata A PRIORI: z=2.0 sigma, ali dz=+1.0 sigma,
tenor 5g (centro del range 3-6g del video). z=3.0 in griglia = cella "fedele al video".
Riusa: options_vrp_lab (bs_put, load_series, per_year), options_vrp_v2 (vrp_spread_weekly = VRP01,
_ivrank, _rv30), altlib.marginal_vs_tp01. Fee Deribit opzioni per gamba: 0.03% del notional cap
12.5% del premio (+ delivery 0.015% cap 12.5% sull'ITM a scadenza; il diagonale paga anche la fee
di USCITA per vendere le long residue a T). NON deploy: regola standing "niente short-vol da
modello in deploy" — l'esito massimo e' conoscenza sulla struttura.
uv run python scripts/research/r0702_alb_structure.py
"""
from __future__ import annotations
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
from scipy.stats import norm
from scripts.research.options_vrp_lab import bs_put, load_series, per_year
from scripts.research.options_vrp_v2 import vrp_spread_weekly, _ivrank, _rv30
HOLDOUT = pd.Timestamp("2025-01-01", tz="UTC")
DAY = 1.0 / 365.25
# cella centrale DICHIARATA A PRIORI (prima di guardare qualsiasi risultato)
CENTRAL = dict(z=2.0, dz=1.0, tenor_d=5)
F_SWEEP = (0.6, 0.8, 1.0, 1.3) # banda skew simmetrica
F_SKEW = dict(f_put=1.3, f_call=0.7) # scenario skew crypto-shaped (put ricche, call povere)
def bs_call(S, K, T, sig):
if T <= 0 or sig <= 0:
return max(S - K, 0.0)
d1 = (np.log(S / K) + 0.5 * sig ** 2 * T) / (sig * np.sqrt(T))
return S * norm.cdf(d1) - K * norm.cdf(d1 - sig * np.sqrt(T)) # r=0
def _fee_frac(prem_frac, notional_ratio=1.0, rate=0.0003):
"""Fee Deribit per gamba come frazione di S0: rate*notional cap 12.5% del premio."""
return min(rate * notional_ratio, 0.125 * max(prem_frac, 0.0))
def run_structure(asset, kind, z=2.0, dz=1.0, tenor_d=5, f_put=1.0, f_call=1.0,
gated=False, collect=None):
"""Vendita sistematica non-overlapping della struttura, cadenza = tenor_d.
kind: 'diag' = double diagonal Albimarini (short T entrambi i lati, long T+1g piu' OTM)
'condor' = iron condor STESSA scadenza (controllo del claim '+1 giorno')
'vert' = vertical put credit spread deep-OTM (solo lato put, stessa scadenza)
Strike: K = S0*exp(±z·σ√T) (z in sigma dell'orizzonte SHORT); ali a z+dz.
gated=True -> gate CANONICO VRP01 (vrp>0 AND ivr>=0.30 AND ivr<=0.90), NON riottimizzato.
Ritorna Series di rendimenti per-periodo su capitale = S0 (spot a entry), indice = scadenza.
collect (dict) accumula diagnostica per la decomposizione diag-vs-condor."""
J = load_series(asset)
px = J["px"].values; dv = J["dvol"].values / 100.0; idx = J.index
n = len(px); T = tenor_d / 365.25
T_long = T + DAY if kind == "diag" else T
has_call = kind in ("diag", "condor")
rets = {}
i = 60
while i + tenor_d < n:
S0 = px[i]; sig = dv[i]
if gated:
rv = _rv30(px, i); ivr = _ivrank(dv, i)
skip = ((not np.isnan(rv) and (sig - rv) <= 0)
or (not np.isnan(ivr) and (ivr < 0.30 or ivr > 0.90)))
if skip:
rets[idx[i + tenor_d]] = 0.0
i += tenor_d
continue
m = sig * np.sqrt(T)
Kp_s = S0 * np.exp(-z * m); Kp_l = S0 * np.exp(-(z + dz) * m)
Kc_s = S0 * np.exp(+z * m); Kc_l = S0 * np.exp(+(z + dz) * m)
# premi a entry (frazione di S0), f per lato
ps = bs_put(S0, Kp_s, T, sig) / S0 * f_put # short put
pl = bs_put(S0, Kp_l, T_long, sig) / S0 * f_put # long put (T o T+1g)
legs = [ps, pl]
cs = cl = 0.0
if has_call:
cs = bs_call(S0, Kc_s, T, sig) / S0 * f_call
cl = bs_call(S0, Kc_l, T_long, sig) / S0 * f_call
legs += [cs, cl]
credit = (ps + cs) - (pl + cl)
# exit a scadenza degli short
j = i + tenor_d
S1 = px[j]; sig1 = dv[j]
short_pay = max(0.0, Kp_s - S1) / S0 + (max(0.0, S1 - Kc_s) / S0 if has_call else 0.0)
if kind == "diag": # long con 1 giorno residuo: mark BS alla DVOL di uscita (vega!)
lp = bs_put(S1, Kp_l, DAY, sig1) / S0 * f_put
lc = bs_call(S1, Kc_l, DAY, sig1) / S0 * f_call
long_val = lp + lc
exit_fee = sum(_fee_frac(v, notional_ratio=S1 / S0) for v in (lp, lc))
else: # stessa scadenza: valore = solo intrinseco
long_val = max(0.0, Kp_l - S1) / S0 + (max(0.0, S1 - Kc_l) / S0 if has_call else 0.0)
exit_fee = 0.0
entry_fee = sum(_fee_frac(v) for v in legs)
# delivery fee su gambe short ITM a scadenza (0.015% cap 12.5%)
deliv = _fee_frac(max(0.0, Kp_s - S1) / S0, rate=0.00015)
if has_call:
deliv += _fee_frac(max(0.0, S1 - Kc_s) / S0, rate=0.00015)
pnl = credit - short_pay + long_val - entry_fee - exit_fee - deliv
rets[idx[j]] = pnl
if collect is not None:
# costo extra del T+1 a entry e valore residuo recuperato a exit (vs intrinseco)
pl_T = bs_put(S0, Kp_l, T, sig) / S0 * f_put
cl_T = (bs_call(S0, Kc_l, T, sig) / S0 * f_call) if has_call else 0.0
intr = max(0.0, Kp_l - S1) / S0 + (max(0.0, S1 - Kc_l) / S0 if has_call else 0.0)
collect.setdefault("extra_cost", []).append((pl + cl) - (pl_T + cl_T))
collect.setdefault("recovered", []).append((long_val - intr) if kind == "diag" else 0.0)
collect.setdefault("short_pay", []).append(short_pay)
collect.setdefault("credit", []).append(credit)
i += tenor_d
return pd.Series(rets)
def book(kind, **kw):
rB = run_structure("BTC", kind, **kw); rE = run_structure("ETH", kind, **kw)
return pd.concat({"B": rB, "E": rE}, axis=1, join="inner").mean(axis=1)
def metrics(r, tenor_d):
"""Metriche su rendimenti per-periodo (cadenza tenor_d). win/PF solo sui periodi ATTIVI."""
r = r.dropna()
ppy = 365.25 / tenor_d
if len(r) < 3 or r.std() == 0:
return dict(sh=0.0, sh_h=0.0, cagr=0.0, dd=0.0, worst=0.0, win=0.0, pf=0.0, act=0.0)
def _sh(x):
return float(x.mean() / x.std() * np.sqrt(ppy)) if len(x) > 2 and x.std() > 0 else 0.0
eq = np.cumprod(1 + r.values); pk = np.maximum.accumulate(eq)
yrs = len(r) / ppy
act = r[r != 0.0]
pos = act[act > 0].sum(); neg = -act[act < 0].sum()
return dict(
sh=_sh(r), sh_h=_sh(r[r.index >= HOLDOUT]),
cagr=float(eq[-1] ** (1 / yrs) - 1) if yrs > 0 and eq[-1] > 0 else -1.0,
dd=float(np.max((pk - eq) / pk)), worst=float(r.min()),
win=float((act > 0).mean()) if len(act) else 0.0,
pf=float(pos / neg) if neg > 0 else float("inf"),
act=float((r != 0.0).mean()), n_act=int(len(act)))
def row(label, r, tenor_d):
mm = metrics(r, tenor_d)
pf = f"{mm['pf']:5.2f}" if np.isfinite(mm["pf"]) else " inf"
print(f" {label:<40} {mm['sh']:>6.2f} {mm['sh_h']:>6.2f} {mm['cagr']*100:>+6.1f}% "
f"{mm['dd']*100:>5.1f}% {mm['worst']*100:>+6.2f}% {pf} {mm['win']*100:>4.0f}% {mm['act']*100:>4.0f}%")
return mm
def to_daily_lumped(wk):
"""Rendimenti per-periodo -> griglia giornaliera con lump alla scadenza (convenzione
_vrp_combo_returns: preserva lo Sharpe annualizzato, niente smoothing)."""
wk = wk.sort_index()
days = pd.date_range(wk.index.min().normalize(), wk.index.max().normalize(), freq="1D", tz="UTC")
daily = pd.Series(0.0, index=days)
daily.loc[wk.index.normalize()] = wk.values
return daily
HDR = f" {'struttura':<40} {'ShF':>6} {'ShH':>6} {'CAGR':>7} {'maxDD':>6} {'worst':>7} {'PF':>5} {'win%':>5} {'att%':>5}"
def main():
print("=" * 110)
print(" R0702 ALB-STRUCTURE — double diagonal deep-OTM (Albimarini) vs vertical vs condor vs VRP01")
print(" Capitale = SPOT a entry (S0) per le strutture nuove; VRP01 canonico = strike corto (sua convenzione).")
print(" ⚠️ SKEW: pricing BS FLAT su DVOL-30g; il deep-OTM e' banda-f, non stima puntuale. Term structure ignorata.")
print("=" * 110)
z, dz, tn = CENTRAL["z"], CENTRAL["dz"], CENTRAL["tenor_d"]
for a in ("BTC", "ETH"):
J = load_series(a)
sig = J["dvol"].mean() / 100.0
d5 = sig * np.sqrt(tn / 365.25)
print(f" {a}: DVOL media {sig*100:.0f}% -> 1σ su {tn}g = {d5*100:.1f}% | z=2.0 = {2*d5*100:.1f}% "
f"| z=3.0 = {3*d5*100:.1f}% (il '9% su SPY/6g' ≈ 3.5-4σ equity)")
# ------------------------------------------------------------------ (1) VRP01 canonico
print(f"\n (1) VRP01 CANONICO (riproduzione options_vrp_v2 COMBO: spread -0.28/-0.10 7g, vrp>0+ivr30+cs90)")
print(HDR)
vrp = {}
for f in F_SWEEP:
vrp[f] = pd.concat({"B": vrp_spread_weekly("BTC", defined_risk=True, f=f, gate_vrp=True,
gate_ivr=0.30, crash_skip=0.90),
"E": vrp_spread_weekly("ETH", defined_risk=True, f=f, gate_vrp=True,
gate_ivr=0.30, crash_skip=0.90)},
axis=1, join="inner").mean(axis=1)
row(f"VRP01 gated f={f}", vrp[f], 7)
vrp_nog = pd.concat({"B": vrp_spread_weekly("BTC", defined_risk=True, f=1.0),
"E": vrp_spread_weekly("ETH", defined_risk=True, f=1.0)},
axis=1, join="inner").mean(axis=1)
row("VRP01 NO-gate f=1.0", vrp_nog, 7)
# bridge di validazione del motore: vertical -0.28-equivalente (z~0.58, dz~0.70, 7g) ~ VRP01
zb = float(-norm.ppf(0.28)); dzb = float(-norm.ppf(0.10)) - zb
br = book("vert", z=zb, dz=dzb, tenor_d=7, f_put=1.0, f_call=1.0, gated=True)
row(f"[bridge] vert z={zb:.2f} dz={dzb:.2f} 7g gated", br, 7)
print(" (bridge ~ VRP01 a meno di convenzione strike/capitale: valida il motore nuovo)")
# ------------------------------------------------------------------ (2) tabella principale
print(f"\n (2) STRUTTURE ALLA CELLA CENTRALE A PRIORI (z={z}σ, ali +{dz}σ, tenor {tn}g) — banda f")
scen = [(f, f, f"f={f}") for f in F_SWEEP] + [(F_SKEW["f_put"], F_SKEW["f_call"], "SKEW fp=1.3/fc=0.7")]
streams = {}
for gated, gtag in ((False, "NO-GATE"), (True, "GATE canonico (vrp>0+ivr30+cs90)")):
print(f"\n --- {gtag} ---")
print(HDR)
for kind, ktag in (("diag", "DIAG double-diagonal T+1g"),
("condor", "CONDOR iron condor stessa T"),
("vert", "VERT put spread stessa T")):
for fp, fc, ftag in scen:
r = book(kind, z=z, dz=dz, tenor_d=tn, f_put=fp, f_call=fc, gated=gated)
row(f"{ktag} {ftag}", r, tn)
streams[(kind, gated, ftag)] = r
# distanze alternative (sweep trasparente, selezione SOLO in-sample; f=1.0 gated)
print(f"\n (3) SWEEP DISTANZA/TENOR (gated, f=1.0) — selezione cella SOLO su Sharpe PRE-holdout")
print(f" {'cella':<40} {'ShF-IS':>7} {'ShH':>6} {'DD':>6} {'worst':>7} {'PF':>5} {'win%':>5}")
best = None
for kind in ("diag", "condor", "vert"):
for zz in (1.5, 2.0, 2.5, 3.0):
for tt in (3, 5):
r = book(kind, z=zz, dz=dz, tenor_d=tt, f_put=1.0, f_call=1.0, gated=True)
ris = r[r.index < HOLDOUT]
mm = metrics(r, tt); mi = metrics(ris, tt)
pf = f"{mm['pf']:5.2f}" if np.isfinite(mm["pf"]) else " inf"
act = r[r != 0.0]
nloss = int((act < 0).sum())
tag = " <- video ~3.5σ" if zz == 3.0 and tt == 5 and kind == "diag" else ""
if nloss == 0:
tag += " ⚠️ 0 perdite su tutta la storia = coda MAI campionata (lezione CC01: Sharpe implausibile -> rischio nascosto)"
print(f" {kind:<7} z={zz} dz={dz} tenor={tt}g{'':<14} {mi['sh']:>7.2f} {mm['sh_h']:>6.2f} "
f"{mm['dd']*100:>5.1f}% {mm['worst']*100:>+6.2f}% {pf} {mm['win']*100:>4.0f}% n={len(act):>3}{tag}")
if best is None or mi["sh"] > best[1]:
best = ((kind, zz, tt), mi["sh"], mm["sh_h"])
print(f" -> cella best IN-SAMPLE: {best[0]} (ShF-IS {best[1]:.2f}) | suo hold-out ShH {best[2]:.2f}")
print(" Le celle z>=2.5/5g vendono un evento ~1% mai occorso nel subsample gated (~140 trade):")
print(" Sharpe 'inf/5.9' = premio senza coda osservata, NON edge. E' il punto cieco CC01 in forma opzioni.")
# ------------------------------------------------------------------ (4) claim del video
print(f"\n (4) TEST CLAIM VIDEO: la long a T+1g domina la long a STESSA T? (z={z}, dz={dz}, {tn}g, f=1.0)")
for gated in (False, True):
colD, colC = {}, {}
rD = pd.concat({a[0]: run_structure(a, "diag", z=z, dz=dz, tenor_d=tn, gated=gated, collect=colD)
for a in ("BTC", "ETH")}, axis=1, join="inner").mean(axis=1)
rC = pd.concat({a[0]: run_structure(a, "condor", z=z, dz=dz, tenor_d=tn, gated=gated, collect=colC)
for a in ("BTC", "ETH")}, axis=1, join="inner").mean(axis=1)
mD, mC = metrics(rD, tn), metrics(rC, tn)
ec = np.array(colD["extra_cost"]); rec = np.array(colD["recovered"])
sp = np.array(colD["short_pay"]); crd = np.array(colD["credit"])
crash = sp > np.quantile(sp, 0.95)
gt = "GATE" if gated else "NO-GATE"
print(f" [{gt}] DIAG ShF {mD['sh']:+.2f}/ShH {mD['sh_h']:+.2f} worst {mD['worst']*100:+.2f}% | "
f"CONDOR ShF {mC['sh']:+.2f}/ShH {mC['sh_h']:+.2f} worst {mC['worst']*100:+.2f}%")
print(f" costo extra T+1 a entry: {ec.mean()*1e4:+.1f} bps/trade | residuo recuperato a exit: "
f"{rec.mean()*1e4:+.1f} bps (nei 5% peggiori: {rec[crash].mean()*1e4:+.1f} bps vs extra {ec[crash].mean()*1e4:+.1f})")
print(f" trade a CREDITO netto: {(crd>0).mean()*100:.0f}% (credito medio {crd.mean()*1e4:+.1f} bps di S0)")
dY = per_year(rD); cY = per_year(rC)
print(" Δ(diag-condor) per anno: " + " ".join(f"{y}:{(dY[y]-cY.get(y,0))*100:+.2f}%" for y in sorted(dY)))
# ------------------------------------------------------------------ (5) per-anno
print(f"\n (5) PER-ANNO (gated, f=1.0) — 2022 = LUNA+FTX e' il banco di prova")
for tag, r, tt in (("DIAG", streams[("diag", True, "f=1.0")], tn),
("CONDOR", streams[("condor", True, "f=1.0")], tn),
("VERT", streams[("vert", True, "f=1.0")], tn),
("VRP01", vrp[1.0], 7)):
py = per_year(r)
print(f" {tag:<7} " + " ".join(f"{y}:{v*100:+5.1f}%" for y, v in sorted(py.items())))
# ------------------------------------------------------------------ (6) marginale
print(f"\n (6) MARGINALE vs TP01 e vs VRP01 (daily-lumped; corr su griglia settimanale)")
import altlib as al
tp = al.tp01_baseline_daily()
dv_daily = to_daily_lumped(streams[("diag", True, "f=1.0")])
vr_daily = to_daily_lumped(vrp[1.0])
tp_w = (1 + tp).resample("W").prod() - 1
di_w = (1 + dv_daily).resample("W").prod() - 1
vr_w = (1 + vr_daily).resample("W").prod() - 1
Jw = pd.concat({"tp": tp_w, "di": di_w, "vr": vr_w}, axis=1, join="inner").dropna()
print(f" corr settimanale: DIAG~TP01 {Jw['tp'].corr(Jw['di']):+.2f} | DIAG~VRP01 {Jw['di'].corr(Jw['vr']):+.2f} "
f"| VRP01~TP01 {Jw['tp'].corr(Jw['vr']):+.2f}")
for name, dd in (("DIAG gated f=1.0", dv_daily), ("VRP01 gated f=1.0 (riferimento)", vr_daily)):
mv = al.marginal_vs_tp01(dd)
print(f" marginal_vs_tp01[{name}]: verdict={mv.get('marginal_verdict')} corr={mv.get('corr_full')} "
f"uplift w25 full/hold={mv['blends']['w25']['uplift_full']}/{mv['blends']['w25']['uplift_hold']} "
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')} multicut={mv.get('multicut_uplift')}")
print(" ⚠️ Un verdetto ADDS qui NON promuove: lo stream vende coda che nel subsample gated non ha mai")
print(" colpito (hold-out Sh 3+ = assenza di eventi, non alpha) — vale la lezione CC01, e vale la regola")
print(" standing 'niente short-vol da modello in deploy'.")
# ------------------------------------------------------------------ (7) eseguibilita'
print(f"\n (7) ESEGUIBILITA' DERIBIT (min 0.1 BTC / 1 ETH per gamba; diag = 4 gambe/asset, book = 8)")
for a, minc in (("BTC", 0.1), ("ETH", 1.0)):
J = load_series(a); S = float(J["px"].iloc[-1]); sig = float(J["dvol"].iloc[-1]) / 100.0
w = dz * sig * np.sqrt(tn / 365.25) # larghezza ala in frazione di S
notional = minc * S
maxloss = w * notional # margine ~ max loss defined-risk (per lato)
col = {}
run_structure(a, "diag", z=z, dz=dz, tenor_d=tn, gated=True, collect=col)
cbps = np.mean(col["credit"]) * 1e4 if col.get("credit") else float("nan")
print(f" {a}: spot ~${S:,.0f} -> notional min {minc} = ${notional:,.0f}/gamba | ala {w*100:.1f}% "
f"-> margine/max-loss min ~${maxloss:,.0f} | credito tipico {cbps:+.0f} bps = ${notional*cbps/1e4:,.0f}/trade")
print(" -> a $600: UN diagonale BTC min-size impegna >50% del capitale su un trade 5g = NON eseguibile.")
print(" Scala minima: sleeve opzioni al ~12% con margine <= peso richiede >~$3-5k per il solo BTC")
print(" min-size; book 50/50 con granularita' (>=3-5 step di size) ~= $15-25k. STAT-MODE, come VRP01.")
print("\n NB ONESTO: win-rate alto e' STRUTTURALE nel deep-OTM (vendi eventi rari), non e' edge. Il verdetto")
print(" sta in Sharpe/PF/coda attraverso la banda f e il 2022. Regola standing: niente short-vol da modello")
print(" in deploy — esito massimo = aggiornamento di conoscenza sulla STRUTTURA.")
if __name__ == "__main__":
main()