research(wave-0822): ORTHO-SCREEN 7/7 scartato (e uno screen largo non puo' passare il proprio DSR); XS-LITE falsifica il muro dei 20k di XS01

This commit is contained in:
Adriano Dal Pastro
2026-08-22 17:12:15 +00:00
parent 14c1a75a7e
commit bd5b634209
6 changed files with 256 additions and 79 deletions
+46 -16
View File
@@ -360,7 +360,10 @@ def sezione2(curve: pd.DataFrame) -> dict:
print("\n (c) IL CONFOUND DI QUESTO FILONE — la pendenza e' informazione NUOVA o RV riciclata?")
rvp = (r1.rolling(24).std() * np.sqrt(24 * 365) * 100).reindex(idx)
rvf = (r1.shift(-24).rolling(24).std().shift(-23) * np.sqrt(24 * 365) * 100).reindex(idx)
# RV su (t, t+24h]: rolling(24) etichettata a t+24 e riportata indietro a t. (Una prima
# stesura aveva uno shift di troppo e misurava la finestra (+24h, +47h): corretto in
# sessione confrontando con una seconda implementazione a serie rovesciata.)
rvf = (r1.rolling(24).std().shift(-24) * np.sqrt(24 * 365) * 100).reindex(idx)
cf = curve[curve.asset == a].copy()
cf["hr"] = pd.to_datetime(cf["hr"], utc=True).dt.as_unit("ns")
ivf = cf.set_index("hr")[f"iv_{FRONT}"].reindex(idx)
@@ -563,9 +566,14 @@ def sezione3(chain: pd.DataFrame, atm_exp: pd.DataFrame, curve: pd.DataFrame) ->
f"({prem/CAPITALE:.0%} del conto), vega ${vega:.2f}/pt-vol, fee ${fee:.2f}/gamba")
print(f" carry lordo ${carry_g:+.3f}/giorno per struttura; attrito per giro "
f"${friz:.2f} => {friz/carry_g:.0f} giorni per andare in pari")
print(f"\n Un calendar spread e' DUE gambe: a $635 una sola struttura ETH impegna il")
print(f" ~15-30% del conto e rende centesimi al giorno. BTC e' fuori dal lotto minimo.")
print(f" Il bersaglio dichiarato e' 50 EUR/giorno: qui si parla di due ordini di grandezza sotto.")
print("\n Un calendar spread e' DUE gambe. Cio' che la tabella mostra e' il PREMIO di UNA")
print(" gamba al lotto minimo: BTC 26% del conto, ETH 10%. Il premio non e' tutto il")
print(" fabbisogno — la gamba CORTA vuole margine, e la misura del 2026-07-30 su una")
print(" struttura BTC a rischio definito dava $6.210 di collaterale per lotto. Quindi:")
print(" BTC resta fuori per il margine, ETH entra ma una sola struttura impegna il")
print(" 10-25% del conto per un carry LORDO di centesimi al giorno.")
print(" Il bersaglio dichiarato e' 50 EUR/giorno: qui siamo 2-3 ordini di grandezza sotto,")
print(" e il conto non regge la SECONDA struttura che servirebbe per diversificare.")
TRIALS.append(("Q2: 2 asset x eseguibilita' al lotto minimo", 2))
@@ -671,17 +679,31 @@ def sezione4(curve: pd.DataFrame) -> None:
hold = tgt.shift(1).fillna(0.0)
net = (hold * d["r"] - A.FEE_SIDE * hold.diff().abs().fillna(0.0)).dropna()
dd_c = A._dd_ret(net)
# ⚠️ il k giusto e' il PIU' GRANDE che sta sotto il DD del candidato, non il primo che
# trovi salendo da 0.05: partendo dal basso si confronta il candidato con un baseline
# quasi spento, che ha un DD ridicolo e uno Sharpe gonfiato dal rapporto. (Errore
# commesso e corretto in sessione: dava "candidato sopra il null" con k=0.05.)
ks = np.arange(0.05, 3.01, 0.05)
best = None
for k in np.arange(0.05, 1.01, 0.05):
for k in ks[::-1]:
b = k * d["r"].reindex(net.index)
if A._dd_ret(b) <= dd_c:
best = (k, A._sh(b), A._dd_ret(b))
best = (float(k), A._sh(b), A._dd_ret(b))
break
print(f" {a}: candidato Sharpe {A._sh(net):+.2f} maxDD {dd_c:.2%} | "
+ (f"buy&hold de-leverato k={best[0]:.2f} -> stesso DD ({best[2]:.2%}) con Sharpe "
f"{best[1]:+.2f} => {'IL CANDIDATO NON SOPRAVVIVE' if best[1] >= A._sh(net) else 'candidato sopra il null'}"
if best else "nessun k<=1 raggiunge quel DD"))
TRIALS.append((f"Q3 {a}: 20 valori di k nel null de-levering", 20))
sh_c = A._sh(net)
if best is None:
print(f" {a}: candidato Sharpe {sh_c:+.2f} maxDD {dd_c:.2%} | nessun k in "
f"[0.05,3.00] raggiunge quel DD")
else:
verdict = ("IL CANDIDATO NON SOPRAVVIVE (il de-levering fa meglio)"
if best[1] >= sh_c else "candidato sopra il null di de-levering")
print(f" {a}: candidato Sharpe {sh_c:+.2f} maxDD {dd_c:.2%} | buy&hold a leva "
f"k={best[0]:.2f} -> stesso o minor DD ({best[2]:.2%}) con Sharpe {best[1]:+.2f}"
f" => {verdict}")
imp = A.implausible_sharpe(net)
print(f" implausible_sharpe sul candidato di finestra: implausible="
f"{imp['implausible']} {imp['reasons']}")
TRIALS.append((f"Q3 {a}: 60 valori di k nel null de-levering", 60))
# ===========================================================================================
@@ -745,15 +767,24 @@ def sezione5(curve: pd.DataFrame) -> None:
if k in rep:
print(f" {k:20s} = {rep[k]}")
imp = A.implausible_sharpe(era)
print(f" implausible_sharpe: flagged={imp.get('flagged')} ({imp.get('reasons')})")
print(f" implausible_sharpe (proxy, era DVOL): implausible={imp['implausible']} "
f"{imp['reasons']}")
print(f" earns_slot = (assoluto non-FAIL) AND (marginale ADDS): qui il marginale e' "
f"{rep.get('marginal_verdict')} -> **earns_slot = False**.")
TRIALS.append(("Sez.5: 2 varianti proxy (long-only, L/S) x 1 soglia", 2))
sub("(c) il precedente che questo replica")
print(" `dvol_directional.py` (2026-06-29) testo' VRP-Z = z-score causale di (IV-RV) come")
print(" segnale DIREZIONALE su 5 anni, con la griglia completa: verdetto **HEDGE,")
print(" earns_slot=False** — paga solo quando TP01 e' debole, quindi non e' alpha.")
print(" La pendenza della term structure e', su questa lente, la stessa variabile con la")
print(" gamba realizzata sostituita da una implicita. Il filone non e' nuovo: e' quello.")
print(" earns_slot=False**. Qui, con la variante a SOGLIA BINARIA invece che a z-score,")
print(" il verdetto misurato e' NEUTRAL con uplift NEGATIVO — un verdetto diverso, la")
print(" stessa conclusione (earns_slot=False in entrambi). La differenza sta nella")
print(" variante, non nell'esito, e va riportata cosi': non sto dichiarando una replica")
print(" che non ho fatto.")
print(" Il punto strutturale resta: la pendenza e' il premio di vol con la gamba")
print(" REALIZZATA sostituita da una IMPLICITA (SEZIONE 2c: corr(pendenza, RV passata)")
print(" = -0.50/-0.57). Non e' una variabile nuova per questo progetto: e' quella, con")
print(" un rumore di misura piu' basso e 5 anni di storia in meno.")
# ===========================================================================================
@@ -778,7 +809,6 @@ def sezione6() -> None:
def main() -> None:
hr("r0822_term_structure — TERM STRUCTURE DELLA VOL IMPLICITA BTC/ETH")
print(__doc__.split("METODO.")[0].strip()[:0] or "", end="")
chain = load_quoted_chain()
sezione0(chain)
atm_exp = build_atm_by_expiry(chain)