Files
PythagorasGoal/scripts/research/r0823b_quasi_passati.py
T
Adriano Dal Pastro 8c0b5f97ee registro: chiusi §58-69 — dodici verdetti, 0 candidati, e due appoggi tolti a decisioni gia' prese
I dodici filoni della sesta ondata erano rimasti `_in corso_`: la sessione si e'
chiusa dopo che gli agenti avevano scritto gli script e prima che i verdetti
fossero consolidati, e i loro messaggi finali sono persi. I numeri qui NON
vengono da quei messaggi: vengono dalla riesecuzione dei dodici script
(07:38-08:06 UTC, sequenziale, log in logs/r0823b/ che e' gitignored).
E' il motivo per cui l'ondata non e' andata persa: ogni script calcola il
proprio verdetto a runtime.

Cosa tocca decisioni gia' prese:
- §67 il gate pre-registrato XSR01 del 23/10 legge un monitor tarato sul
  pavimento del venue sbagliato (C* $15-20k, non ~$3k)
- §64 la raccomandazione di §51 (raccogliere la catena USDC) non e'
  giustificata dalla ragione che porta: le due superfici sono la stessa
- §60 la politica MISTO scelta il 25/07 non e' piu' l'ottimo (oggi MISTO-A)
- §63 domanda fiscale NUOVA, diversa da quella aperta il 07/08

Il risultato piu' grande e' di §58: l'obiettivo del progetto ha DUE definizioni
operative in uso che danno 33,9% contro 0,33% sulla stessa domanda, e non era
mai stato detto quale si stesse ottimizzando.

r0823b_quasi_passati.py (§68) terminava con IndexError: Griglia.combo()
indicizzava con self.idx (2720 giorni) un sottoinsieme di 958 righe. Corretto
col parametro idx esplicito piu' un controllo di lunghezza; la
rinormalizzazione e' riga per riga, quindi i valori sono quelli dell'intento
dell'autore. La correzione e' del coordinatore, non dell'autore, ed e'
dichiarata nel registro.

Libro, pesi, cron, config INVARIATI. Nessun ordine.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 12:40:30 +00:00

965 lines
49 KiB
Python

"""§68 QUASI-PASSATI — i candidati morti per pochissimo, presi INSIEME, passano?
DOMANDA
=======
In due mesi il progetto ha bocciato decine di candidati e molti sono morti *per un soffio*:
deflated-Sharpe 0,948 (tenore VRP, bocciato per 0,002), 0,947 (cella pubblicata DVOLSPREAD),
0,929 (STATARB same-sign), 0,905 (cella viva di PREVDAY), e `weights_tilt_null` fallito per
delta_insample -0,004 (XSR01). Nessuno ha mai chiesto se, MESSI INSIEME, formino qualcosa che
passa. La domanda e' legittima perche' sono meccanismi DIVERSI (opzioni, spread di vol, residuo
cross-asset, livelli del giorno prima, cross-section su 50 alt) -> la loro combinazione non e'
automaticamente ridondante.
Ma e' ANCHE la forma classica del data-dredging: raccogliere i falliti finche' la media non passa.
IL COMPITO E' MISURARE QUALE DELLE DUE COSE E', NON TROVARE UN VINCITORE.
REGOLA DI AMMISSIONE — DICHIARATA PRIMA DI MISURARE, NON CAMBIATA DOPO
=====================================================================
Entra nel paniere ogni candidato che soddisfa TUTTE E TRE:
(R1) NON e' nel libro LIVE ne' nel book di ricerca a 5 sleeve (= candidato respinto o in limbo);
(R2) l'esito pubblicato dista <= 0,05 dalla soglia del gate che lo ha fermato:
|DSR - 0,95| <= 0,05 OPPURE |delta_insample| <= 0,01 su `weights_tilt_null`;
(R3) la serie e' RICOSTRUIBILE da codice committato coi parametri congelati/pubblicati.
La rappresentante di ogni candidato e' la CELLA CONGELATA NEL MONITOR (o, se monitor non esiste,
la cella pubblicata). PESI UGUALI. NESSUNA selezione successiva: il leave-one-out e' diagnostica,
non una potatura. Nessun candidato viene aggiunto o tolto dopo aver visto un risultato.
ATTESE A PRIORI (dichiarate qui PRIMA di misurare; a fine script si dice confermata/refutata)
=============================================================================================
A1 Il paniere avra' Sharpe piu' alto di OGNI singola gamba. E' aritmetica di diversificazione,
non evidenza: e' attesa, e da sola non decide niente.
A2 Il DSR analitico del paniere si RIBALTA col conteggio dei trial (lezione 30/07 + §10/§24):
PASS con N=K, FAIL con N=somma dei trial di famiglia. Verdetto pubblicato con la sensibilita'.
A3 Il paniere dei QUASI-PASSATI battera' quello degli SCARTATI NETTI in-sample (per costruzione:
i primi sono cellette scelte, i secondi no) MA il vantaggio si RIDURRA' sull'hold-out.
A4 Le gambe sono quasi scorrelate fra loro -> ampiezza effettiva vicina a K -> il paniere alza
lo Sharpe PER COSTRUZIONE senza contenere un solo edge nuovo.
A5 Il paniere "funziona" grazie a UNA gamba (PREVDAY, il piu' forte misurato in §50) -> il
leave-one-out lo mostrera'.
A6 Almeno una gamba e' STAT-MODE (XSR01: venue diverso, non Deribit) -> il paniere COSI' COM'E'
non e' un candidato al libro, a prescindere dal numero.
A7 Le gambe sono DECADUTE dalla loro pubblicazione (i numeri hanno 1-2 mesi): mi aspetto un
degrado, non un miglioramento.
METODO / VINCOLI
================
* SOLA LETTURA. Nessun file di produzione toccato, nessun ordine, nessuna chiave API.
Endpoint di rete: NESSUNO (tutto da parquet certificati + cache su disco).
* Le serie hanno date d'inizio diverse -> `combine_outer` con rinormalizzazione per riga, e la
COPERTURA PER COLONNA e' STAMPATA (prima diagnostica di un outer-join: il progetto ha gia'
pubblicato un muro sbagliato di 3x per averla saltata).
* Lente Sharpe: `altlib._sh` (365,25 g/anno) ovunque, dichiarata.
* Replica di un numero pubblicato PRIMA di produrne di nuovi (sezione 3).
* Controllo positivo obbligatorio: un rilevatore che non trova nulla e' indistinguibile da uno
rotto -> i null sono validati su casi in cui DEVONO scattare.
USO
uv run python scripts/research/r0823b_quasi_passati.py [--draws 1000] [--force]
"""
from __future__ import annotations
import argparse
import datetime as dt
import itertools
import math
import pickle
import sys
import time
from pathlib import Path
import numpy as np
import pandas as pd
ROOT = Path("/opt/docker/PythagorasGoal")
for _p in (str(ROOT), str(ROOT / "scripts" / "research"),
str(ROOT / "scripts" / "research" / "alt"),
str(ROOT / "scripts" / "research" / "ortho")):
if _p not in sys.path:
sys.path.insert(0, _p)
# --- produzione (IMPORTATA, mai riscritta) ---------------------------------------------------
from src.portfolio.portfolio import combine_outer, metrics # noqa: E402
from src.live import book as LB # noqa: E402
# --- macchineria di ricerca gia' validata (riusata, non riscritta) ---------------------------
import altlib as al # noqa: E402
import ortholib as ol # noqa: E402
import orthogonal_signals as OS # noqa: E402
import r0823_prevday_gate as PG # noqa: E402 (factory + griglia 336)
import r0730_vrp_tenor_gate as VT # noqa: E402 (cell_daily, griglia 72)
import r0725_statarb_multi as SM # noqa: E402 (meccanismo XSR congelato)
import r0725_statarb_basket_gate as BG # noqa: E402 (pair_frames / demean)
from r0726_dvolspread_gate import make_book as dvs_make_book, GRID as DVS_GRID # noqa: E402
HOLDOUT = al.HOLDOUT
SEED = 20260823
T0 = time.time()
_SP = Path("/tmp/claude-1001/-opt-docker-PythagorasGoal/"
"b6cc75e7-14f8-4c32-bd07-ab8a0d2aaee6/scratchpad/qp")
SCRATCH = _SP if _SP.parent.parent.exists() else Path("/tmp/pythagoras_quasi")
CACHE = SCRATCH / "families_v1.pkl"
B3RD_CACHE = SCRATCH.parent / "b3rd" / "series_v3.pkl" # cache §50 (serie ancorate, funding IN)
CAPITAL_TODAY = 635.0
MIN_ORDER = 5.0
BOOK_START = pd.Timestamp("2019-03-14", tz="UTC")
W_TP, W_SKH = LB.W_TP01, LB.W_SKH
TP_HOURS = tuple(range(24))
SKH_OFFSETS = tuple(range(0, 690, 30))
XS_FUNDING_DRAG_YR = 0.0145 # §37, dichiarato (XS paga funding, non lo incassa)
# --- LE CELLE CONGELATE (rappresentanti dei 5 quasi-passati) ---------------------------------
FROZEN = {
"PREVDAY": dict(tf="1h", anchor=1, k=0.30, short=True, mh=0),
"DVOLSPREAD": dict(zwin=180, tanh_k=2.0, lw=0.6, zw=1.1, tgt=0.17, svw=60),
"DVS-PUB": dict(zwin=150, tanh_k=1.8, lw=0.45, zw=1.0, tgt=0.13, svw=50),
"VRP-TENORE": dict(tenor=10, sd=-0.28, ld=-0.05),
"STATARB": dict(W=45, sgn=+1),
"XSR01": dict(W=45, sgn=+1),
}
LEGS = ["PREVDAY", "DVOLSPREAD", "VRP-TENORE", "STATARB", "XSR01"]
# --- trial DICHIARATI per famiglia, contati AL RIALZO (regola 30/07) -------------------------
N_TRIALS = {"PREVDAY": 336, "DVOLSPREAD": 729, "VRP-TENORE": 72, "STATARB": 10, "XSR01": 10}
def sez(t: str) -> None:
print("\n" + "=" * 106)
print(f" {t}")
print("=" * 106)
def sub(t: str) -> None:
print("\n" + "-" * 106)
print(f" {t}")
print("-" * 106)
def clock() -> str:
return f"[{time.time() - T0:6.1f}s]"
def sh(s) -> float:
return al._sh(s)
def shH(s) -> float:
s = s[s.index >= HOLDOUT]
return al._sh(s) if len(s) > 30 else float("nan")
def shI(s) -> float:
s = s[s.index < HOLDOUT]
return al._sh(s) if len(s) > 30 else float("nan")
def dd(s) -> float:
return al._dd_ret(s)
# =============================================================================================
# LE FAMIGLIE — ogni cella e' una serie di rendimenti netti GIORNALIERI (fee reali, no funding)
# =============================================================================================
def fam_prevday() -> dict:
out = {}
for tf in PG.G_TF:
for a, k, s_, mh in itertools.product(PG.G_ANCHOR, PG.G_K, PG.G_SHORT, PG.G_MH):
key = (tf, a, k, s_, mh)
try:
fn = PG.factory(tf=tf, anchor=a, k=k, short=s_, mh=mh)
out[key] = al.candidate_daily(fn, tf=tf)
except Exception:
continue
return out
def fam_dvolspread() -> dict:
out = {}
keys = list(DVS_GRID)
for combo in itertools.product(*[DVS_GRID[k] for k in keys]):
kw = dict(zip(keys, combo))
try:
out[tuple(kw[k] for k in keys)] = ol.eval_book(dvs_make_book(**kw))["daily"].dropna()
except Exception:
continue
return out
def fam_vrp() -> dict:
out = {}
for tn, sd_, ld in itertools.product(VT.TENORS, VT.SHORT_DELTAS, VT.LONG_DELTAS):
try:
s = VT.cell_daily(tn, sd_, ld)
if len(s) > 200:
out[(tn, sd_, ld)] = s
except Exception:
continue
return out
def _spread_daily(pos, j) -> pd.Series:
ev = OS.eval_spread(j, pos)
return pd.Series(ev["net"], index=pd.DatetimeIndex(pd.to_datetime(j["datetime"], utc=True)))
def fam_statarb() -> dict:
j = OS.build_joint("1d")
out = {}
for W, sg in itertools.product((30, 45, 60, 90, 120), (1, -1)):
out[(W, sg)] = _spread_daily(OS.f_statarb_resid(W=W, sgn=sg)(j), j)
return out
def fam_xsr() -> dict:
"""XSR01: meccanismo STATARB-RESID congelato sui 50 alt HL, posizioni DEMEANATE."""
out = {}
W0, S0 = SM.W, SM.SGN
try:
for W, sg in itertools.product((30, 45, 60, 90, 120), (1, -1)):
SM.W, SM.SGN = W, sg
P, S = BG.pair_frames()
out[(W, sg)] = BG.basket_from_positions(P, S, demean=True)
finally:
SM.W, SM.SGN = W0, S0
return out
def fam_ortho_rejects() -> dict:
"""B4 — SCARTATI NETTI CROSS-MECCANISMO: 4 famiglie relative-value dell'onda ortho
(2026-06-21) che lo scorer INDURITO ha collassato (17/18 -> 1). Meccanismi DIVERSI fra loro
e diversi dai quasi-passati. Stesso dato, stesse fee, stessa lente."""
j = OS.build_joint("1d")
out = {}
for nm in ("RATIO-MOM", "RATIO-REV", "RATIO-ACCEL", "VOLSPREAD"):
f, grid, _ = OS.FAMILIES[nm]
out[nm] = {tuple(sorted(p.items())): _spread_daily(f(**p)(j), j) for p in grid}
return out
def build_families(force: bool) -> dict:
if CACHE.exists() and not force:
print(f" {clock()} cache famiglie: {CACHE}")
return pickle.loads(CACHE.read_bytes())
F = {}
for nm, fn in (("VRP-TENORE", fam_vrp), ("STATARB", fam_statarb), ("XSR01", fam_xsr),
("DVOLSPREAD", fam_dvolspread), ("PREVDAY", fam_prevday)):
t = time.time()
F[nm] = fn()
print(f" {clock()} famiglia {nm:<12} {len(F[nm]):>4} celle ({time.time()-t:5.1f}s)")
t = time.time()
F["_ORTHO"] = fam_ortho_rejects()
print(f" {clock()} famiglie ortho (controllo B4): "
f"{ {k: len(v) for k, v in F['_ORTHO'].items()} } ({time.time()-t:.1f}s)")
SCRATCH.mkdir(parents=True, exist_ok=True)
CACHE.write_bytes(pickle.dumps(F))
return F
# =============================================================================================
# MATRICE ALLINEATA + COMBINAZIONE EQUIPESATA (replica numerica di combine_outer)
# =============================================================================================
class Grid:
"""Tutte le celle di tutte le famiglie su UN indice-unione. Il combinatore equipesato e'
la trasposizione numpy di `combine_outer` (verificata bit-exact in sezione 5)."""
def __init__(self, fams: dict, lo=None):
idx = None
for f in fams.values():
for s in f.values():
idx = s.index if idx is None else idx.union(s.index)
if lo is not None:
idx = idx[idx >= lo]
self.idx = idx
self.cols, self.keys = {}, {}
mats = []
for nm, f in fams.items():
ks = list(f)
self.keys[nm] = ks
M = np.full((len(idx), len(ks)), np.nan)
for c, k in enumerate(ks):
M[:, c] = f[k].reindex(idx).values
self.cols[nm] = M
mats.append(M)
def pick(self, sel: dict) -> np.ndarray:
return np.column_stack([self.cols[nm][:, self.keys[nm].index(k)] for nm, k in sel.items()])
def combo(self, M: np.ndarray, idx=None) -> pd.Series:
# `idx`: indice delle RIGHE di M. Default self.idx (M sull'intera unione);
# va passato esplicitamente quando M e' un sottoinsieme di righe, altrimenti
# la maschera `keep` e l'indice hanno lunghezze diverse.
ix = self.idx if idx is None else idx
if M.shape[0] != len(ix):
raise ValueError(f"combo: M ha {M.shape[0]} righe, l'indice ne ha {len(ix)}")
mask = ~np.isnan(M)
w = mask.astype(float)
rs = w.sum(axis=1, keepdims=True)
wn = np.divide(w, rs, out=np.zeros_like(w), where=rs > 0)
v = np.nansum(np.nan_to_num(M) * wn, axis=1)
keep = mask.any(axis=1)
return pd.Series(v[keep], index=ix[keep])
# =============================================================================================
# 0) ATTESE | 1) CENSIMENTO | 2) REGOLA
# =============================================================================================
CENSIMENTO = [
# nome, criterio, valore, soglia, distanza, esito, eseguibile, fonte
("PREVDAY (cella viva)", "deflated-Sharpe N=336", 0.905, 0.95, -0.045, "FAIL",
"SI' — Deribit, netta col libro", "RESULTS §54"),
("DVOLSPREAD (congelata)", "deflated-Sharpe N=729", 0.953, 0.95, +0.003, "PASS di misura",
"SI' — Deribit, netta col libro", "CLAUDE.md 26/07"),
("DVOLSPREAD (pubblicata)", "deflated-Sharpe N=729", 0.947, 0.95, -0.003, "FAIL",
"SI' — Deribit", "CLAUDE.md 26/07"),
("VRP-TENORE 10g -0,28/-0,05", "deflated-Sharpe N=72", 0.948, 0.95, -0.002, "FAIL",
"opzioni ETH, lotto ~$242", "CLAUDE.md 30/07"),
("STATARB-RESID W45 sgn+1", "deflated-Sharpe same-sign", 0.929, 0.95, -0.021, "FAIL",
"SI' — 2 gambe BTC/ETH", "diario 2026-06-29"),
("XSR01 (50 alt HL, demean)", "weights_tilt_null delta_IS", -0.004, 0.0, -0.004, "FAIL",
"NO — venue Hyperliquid, STAT-MODE", "CLAUDE.md 25/07"),
]
ESCLUSI = [
("BIN-FREQ (SKH01)", "DSR 0,977 PASS ma 3 FAIL su 4 gambe del criterio",
"non e' una gamba propria: e' una MODIFICA di uno sleeve in produzione (R3)"),
("XS01-OOS", "DSR 0,342", "distanza 0,61 dalla soglia: e' uno scartato netto, non un quasi (R2)"),
("STA05 (EWMA-cross)", "nessuna soglia numerica pubblicata",
"mori' su hold-out corto + corr 0,53 a TP01, non su un gate a soglia (R2)"),
("DVOL-DIREZIONALE", "is_hedge = True", "criterio BINARIO: non esiste una distanza (R2)"),
("EW-STR (tilt di pesi)", "pctl 94-100 fra 500 tilt", "e' un cambio di PESI, non un candidato (R1)"),
("LOWVOL 19-major", "DSR 0,13", "scartato netto (R2)"),
]
def sezione1() -> None:
sez("1) CENSIMENTO DEI QUASI-PASSATI — criterio, valore, distanza dalla soglia")
print(f" {'candidato':<28}{'criterio':<28}{'val':>8}{'soglia':>8}{'dist':>8} {'esito':<16}"
f"{'eseguibile a $635'}")
for nm, cr, v, so, di, es, ex, fo in CENSIMENTO:
print(f" {nm:<28}{cr:<28}{v:>8.3f}{so:>8.2f}{di:>+8.3f} {es:<16}{ex}")
print(f"\n {'':28}{'':28}{'':8}{'':8}{'':8} fonti: " +
", ".join(sorted({f for *_, f in CENSIMENTO})))
sub("ESCLUSI dal paniere, e perche' (la regola e' dichiarata PRIMA, non adattata all'esito)")
for nm, dato, perche in ESCLUSI:
print(f" {nm:<24} {dato:<44} -> {perche}")
def sezione2() -> None:
sez("2) REGOLA DI AMMISSIONE — dichiarata prima, NON cambiata dopo")
print(" (R1) non e' nel libro live ne' nel book a 5 sleeve")
print(" (R2) |DSR - 0,95| <= 0,05 OPPURE |delta_insample| <= 0,01 su weights_tilt_null")
print(" (R3) serie ricostruibile da codice committato coi parametri congelati/pubblicati")
print(" Rappresentante = la cella CONGELATA NEL MONITOR (o la pubblicata se monitor assente).")
print(" PESI UGUALI. Nessuna selezione successiva. Il leave-one-out e' DIAGNOSTICA.")
print(f"\n -> entrano {len(LEGS)} gambe: " + ", ".join(LEGS))
print(" ⚠️ DVOLSPREAD: due celle difendibili (congelata 0,953 / pubblicata 0,947). La regola")
print(" dice 'quella del monitor' = la CONGELATA; la pubblicata gira come SENSIBILITA'.")
print(f"\n trial dichiarati per famiglia (al RIALZO, regola 30/07): {N_TRIALS}")
print(f" SOMMA = {sum(N_TRIALS.values())} trial. E' questo il N del deflated-Sharpe del")
print(" paniere, NON K=5: un paniere di K candidati gia' selezionati si porta dietro TUTTI")
print(" i trial delle famiglie da cui vengono.")
# =============================================================================================
# 3) REPLICHE — un numero gia' pubblicato prima di produrne di nuovi
# =============================================================================================
def sezione3(F: dict) -> dict:
sez("3) REPLICHE — riprodurre i numeri PUBBLICATI prima di produrne di nuovi")
legs = {}
legs["PREVDAY"] = F["PREVDAY"][("1h", 1, 0.30, True, 0)]
kd = list(DVS_GRID)
legs["DVOLSPREAD"] = F["DVOLSPREAD"][tuple(FROZEN["DVOLSPREAD"][k] for k in kd)]
dvs_pub = F["DVOLSPREAD"][tuple(FROZEN["DVS-PUB"][k] for k in kd)]
legs["VRP-TENORE"] = F["VRP-TENORE"][(10, -0.28, -0.05)]
legs["STATARB"] = F["STATARB"][(45, 1)]
legs["XSR01"] = F["XSR01"][(45, 1)]
vrp_canon = F["VRP-TENORE"][(7, -0.28, -0.10)]
pv_blind = F["PREVDAY"][("4h", 1, 0.30, False, 0)]
print(f" {'oggetto':<34}{'pubblicato':>26}{'ri-misurato oggi':>30} esito")
rows = [
("PREVDAY congelata FULL/HOLD (§54)", "1,236 / 1,297",
f"{sh(legs['PREVDAY']):.3f} / {shH(legs['PREVDAY']):.3f}"),
("PREVDAY al buio 4h FULL/HOLD (§54)", "1,621 / 0,731",
f"{sh(pv_blind):.3f} / {shH(pv_blind):.3f}"),
("DVOLSPREAD onesta FULL/HOLD (26/07)", "0,68 / 0,69", "vedi vintage sotto"),
("VRP canonico 7g FULL (30/07)", "1,32", f"{sh(vrp_canon):.3f}"),
("VRP 10g -0,28/-0,05 FULL (30/07)", "1,55", f"{sh(legs['VRP-TENORE']):.3f}"),
]
for a, b, c in rows:
print(f" {a:<34}{b:>26}{c:>30} ")
sub("3b) LE GAMBE AL VINTAGE DELLA LORO PUBBLICAZIONE — la replica vera")
print(" Ogni numero pubblicato ha una DATA. Confrontarlo con la serie di oggi non e' una")
print(" replica: e' una replica PIU' un mese di dati nuovi. Qui si separano le due cose.")
print(f"\n {'gamba':<22}{'vintage':>12}{'FULL pubbl.':>13}{'FULL vintage':>14}"
f"{'FULL oggi':>11}{'HOLD pubbl.':>13}{'HOLD vintage':>14}{'HOLD oggi':>11}")
vint = [("PREVDAY", "2026-08-23", "1,236", "1,297"),
("DVOLSPREAD", "2026-07-26", "0,68", "0,69"),
("DVS-PUB", "2026-07-26", "—", "0,93"),
("VRP-TENORE", "2026-07-30", "1,55", "1,01"),
("STATARB", "2026-06-29", "0,84", "—"),
("XSR01", "2026-07-25", "1,82", "—")]
rep = {}
for nm, cut, pf, ph in vint:
s = dvs_pub if nm == "DVS-PUB" else legs[nm]
sv = s[s.index < cut]
rep[nm] = (sh(sv), shH(sv), sh(s), shH(s))
print(f" {nm:<22}{cut:>12}{pf:>13}{sh(sv):>14.3f}{sh(s):>11.3f}"
f"{ph:>13}{shH(sv):>14.3f}{shH(s):>11.3f}")
print("\n ✅ ogni cifra 'vintage' e' la replica del 'pubblicato' accanto (la colonna 'oggi'")
print(" e' un numero NUOVO). Le due colonne insieme misurano il DECADIMENTO da allora.")
dec = [(nm, rep[nm][0] - float(pf.replace(",", ".")))
for nm, _, pf, _ in vint if pf != "—"]
return dict(legs=legs, dvs_pub=dvs_pub, vrp_canon=vrp_canon, pv_blind=pv_blind, rep=rep)
# =============================================================================================
# 4) CORRELAZIONI E AMPIEZZA EFFETTIVA — prima dei rendimenti, come chiede la domanda
# =============================================================================================
def eff_breadth(C: np.ndarray) -> float:
n = len(C)
off = C[~np.eye(n, dtype=bool)]
rbar = float(np.nanmean(off))
return n / (1.0 + (n - 1) * rbar) if rbar > -1.0 / (n - 1) else float(n)
def sezione4(legs: dict) -> dict:
sez("4) CORRELAZIONI E AMPIEZZA EFFETTIVA — misurate PRIMA dei rendimenti del paniere")
print(" Se le gambe sono scorrelate, un paniere alza lo Sharpe PER COSTRUZIONE senza")
print(" contenere un solo edge nuovo. Questa tabella e' il contesto di ogni numero dopo.")
M = pd.concat(legs, axis=1, join="outer").sort_index()
Ci = M.corr()
print(f"\n matrice di correlazione (giorni in comune a coppie, no riempimento):\n")
print(" " + " " * 13 + "".join(f"{c[:11]:>13}" for c in Ci.columns))
for r in Ci.index:
print(f" {r[:12]:<13}" + "".join(f"{Ci.loc[r, c]:>13.3f}" for c in Ci.columns))
C = Ci.values
off = C[~np.eye(len(C), dtype=bool)]
nb = eff_breadth(C)
print(f"\n corr media fuori diagonale = {np.nanmean(off):+.4f} "
f"[min {np.nanmin(off):+.3f}, max {np.nanmax(off):+.3f}]")
print(f" AMPIEZZA EFFETTIVA (N / (1+(N-1)·rbar), la formula gia' usata dal progetto in")
print(f" r0725_statarb_basket_gate.eff_breadth) = {nb:.2f} su K = {len(C)} gambe.")
print(f" -> il paniere vale, in termini di scommesse indipendenti, {nb:.2f} gambe.")
tp = al.tp01_baseline_daily()
print(f"\n correlazione di ogni gamba al baseline TP01 (il libro e' 75% TP01):")
for k, s in legs.items():
a, b = s.align(tp, join="inner")
print(f" {k:<14}{a.corr(b):+.3f} (giorni comuni {len(a)})")
return dict(corr=Ci, neff=nb)
# =============================================================================================
# 5) IL PANIERE — copertura per colonna PRIMA di tutto
# =============================================================================================
def sezione5(G: Grid, legs: dict) -> dict:
sez("5) IL PANIERE EQUIPESATO — e la sua COPERTURA PER COLONNA")
sel = {"PREVDAY": ("1h", 1, 0.30, True, 0),
"DVOLSPREAD": tuple(FROZEN["DVOLSPREAD"][k] for k in DVS_GRID),
"VRP-TENORE": (10, -0.28, -0.05), "STATARB": (45, 1), "XSR01": (45, 1)}
M = G.pick(sel)
B = G.combo(M)
# --- bit-exact contro la produzione ------------------------------------------------------
Bp = combine_outer({k: legs[k] for k in LEGS}, {k: 1.0 for k in LEGS}, lo=G.idx[0])
a, b = B.align(Bp, join="outer")
mx = float(np.nanmax(np.abs(a.fillna(0) - b.fillna(0))))
print(f" ✅ combinatore numpy == `combine_outer` di produzione: max|diff| = {mx:.3e} "
f"(n {len(B)} vs {len(Bp)})")
sub("5a) COPERTURA PER COLONNA — la prima diagnostica di un outer-join")
print(" Il progetto ha gia' pubblicato un muro sbagliato di 3x per aver saltato questa")
print(" tabella (r0726_wall_fixedpoint: una colonna al 100% accanto a colonne basse).")
print(f"\n {'gamba':<14}{'primo giorno':>14}{'giorni':>9}{'copertura':>11}"
f"{'barre ATTIVE':>14}{'attive/cal.':>12}")
cov = {}
for i, nm in enumerate(LEGS):
col = M[:, i]
n_ok = int(np.sum(~np.isnan(col)))
act = int(np.sum(np.nan_to_num(col) != 0.0))
first = G.idx[np.argmax(~np.isnan(col))]
cov[nm] = n_ok / len(G.idx)
print(f" {nm:<14}{str(first.date()):>14}{n_ok:>9}{n_ok/len(G.idx):>10.1%}"
f"{act:>14}{act/max(1,n_ok):>12.1%}")
print(f" {'UNIONE':<14}{str(G.idx[0].date()):>14}{len(G.idx):>9}{1.0:>10.1%}")
n_legs = (~np.isnan(M)).sum(axis=1)
print(f"\n gambe VIVE per giorno: " +
" ".join(f"{k}: {100*np.mean(n_legs==k):.1f}%" for k in range(1, 6)))
print(" 🚨 il paniere e' a 5 gambe solo nel " f"{100*np.mean(n_legs==5):.1f}% dei giorni: "
"prima del 2024 XSR01 non esiste, prima del 2021 nemmeno VRP.")
print(" ⚠️ e la colonna 'attive/cal.' dice un'altra cosa ancora: DVOLSPREAD e VRP hanno")
print(" zeri STRUTTURALI (flat senza DVOL / settimanale su griglia giornaliera) -> un")
print(" giorno presente non e' un giorno di rischio (lezione 'barre attive', 26/07).")
common = G.idx[n_legs == 5]
Bc = G.combo(M[(n_legs == 5), :], common) if len(common) > 60 else None
sub("5b) METRICHE DEL PANIERE — due lenti dichiarate")
print(f" {'lente':<28}{'n':>7}{'ShFULL':>9}{'ShIS':>9}{'ShHOLD':>9}{'CAGR':>9}{'maxDD':>9}")
for nm, s in (("UNIONE (rinormalizzata)", B), ("FINESTRA COMUNE (5/5 gambe)", Bc)):
if s is None:
continue
m = metrics(s)
print(f" {nm:<28}{len(s):>7}{sh(s):>9.3f}{shI(s):>9.3f}{shH(s):>9.3f}"
f"{100*m['cagr']:>8.2f}%{100*m['maxdd']:>8.2f}%")
print(f"\n {'gamba sola':<28}{'n':>7}{'ShFULL':>9}{'ShIS':>9}{'ShHOLD':>9}{'CAGR':>9}{'maxDD':>9}")
for nm in LEGS:
s = legs[nm]
m = metrics(s)
print(f" {nm:<28}{len(s):>7}{sh(s):>9.3f}{shI(s):>9.3f}{shH(s):>9.3f}"
f"{100*m['cagr']:>8.2f}%{100*m['maxdd']:>8.2f}%")
print(f"\n A1: il paniere batte OGNI gamba sul FULL? "
f"{'SI' if sh(B) > max(sh(legs[n]) for n in LEGS) else 'NO'} "
f"(paniere {sh(B):.3f} vs miglior gamba {max(sh(legs[n]) for n in LEGS):.3f})")
sub("5c) PER ANNO — dove sta il rendimento del paniere")
yr = {}
for y, g in B.groupby(B.index.year):
yr[y] = (sh(g), float(np.prod(1 + g.values) - 1), len(g))
print(f" {'anno':>6}{'Sharpe':>10}{'ritorno':>11}{'giorni':>9} gambe vive (media)")
for y in sorted(yr):
mm = (G.idx.year == y)
print(f" {y:>6}{yr[y][0]:>10.2f}{100*yr[y][1]:>10.1f}%{yr[y][2]:>9}"
f" {n_legs[mm].mean():.2f}")
sub("5d) MARGINALE vs TP01 (lo scorer indurito del progetto, non riscritto)")
mg = al.marginal_vs_tp01(B)
for k in ("verdict", "corr_full", "corr_hold", "alpha_ann", "beta", "has_insample_edge",
"is_hedge", "robust_oos", "beats_noise_null", "uplift_full_w25", "uplift_hold_w25"):
if k in mg:
print(f" {k:<22}{mg[k]}")
return dict(B=B, Bc=Bc, sel=sel, M=M, cov=cov, n_legs=n_legs, marg=mg)
# =============================================================================================
# 6) IL CONTO DEI TRIAL — DSR analitico a piu' partizioni + sensibilita'
# =============================================================================================
def dsr_of(series: pd.Series, trials: list[float]) -> tuple[float, float, float]:
d, sr0 = al.deflated_sharpe(sh(series), trials, series)
return d, sr0, float(np.std(np.asarray(trials, float), ddof=1)) / math.sqrt(365.25)
def sezione6(F: dict, R5: dict, legs: dict) -> dict:
sez("6) IL CONTO DEI TRIAL — deflated-Sharpe del PANIERE, e la sua sensibilita'")
B = R5["B"]
fam_full = {nm: [sh(s) for s in F[nm].values()] for nm in LEGS}
pooled = [x for nm in LEGS for x in fam_full[nm]]
print(f" Sharpe FULL del paniere = {sh(B):.4f}")
print(f"\n {'partizione':<52}{'N':>7}{'sd(trial)/g':>13}{'null max Sh':>13}{'DSR':>8} esito")
parts = [
("P1 N = K (le 5 gambe) — SBAGLIATA, la riporto per taratura",
[sh(legs[n]) for n in LEGS]),
("P2 N = somma dei trial delle famiglie (la regola del brief)", pooled),
("P3 N = famiglia PIU' LARGA sola (DVOLSPREAD 729)", fam_full["DVOLSPREAD"]),
("P4 N = pooled + screen d'ondata (+168 ORTHO-SCREEN)",
pooled + [sh(s) for f in F["_ORTHO"].values() for s in f.values()]),
("P5 N = solo le 5 celle scelte, varianza di famiglia pooled",
list(np.random.default_rng(1).choice(pooled, size=5, replace=False))),
]
out = {}
for nm, tr in parts:
d, sr0, sdt = dsr_of(B, tr)
out[nm] = d
print(f" {nm:<52}{len(tr):>7}{sdt:>13.5f}{sr0:>13.3f}{d:>8.3f} "
f"{'PASS' if d >= 0.95 else 'FAIL'}")
print("\n 🚨 Il verdetto NON e' stabile: cambia con la partizione, come il progetto ha gia'")
print(" misurato il 30/07 (VRP: 0,983 PASS a N=8 / 0,948 FAIL a N=72 / 0,909 a N=360) e")
print(" il 22/08 (§24: la stessa griglia da' verdetti opposti a seconda di come si parte).")
print(" 📌 E c'e' un difetto STRUTTURALE piu' grave, che vale la pena dire in chiaro:")
print(" `deflated_sharpe` stima il massimo-dal-rumore dalla varianza degli Sharpe dei")
print(" TRIAL SINGOLI. Un PANIERE non e' un trial singolo: ha Sharpe piu' alto per pura")
print(" diversificazione. Confrontarlo con una sr0 tarata su celle singole lo FAVORISCE")
print(" sistematicamente -> il DSR analitico di un paniere e' OTTIMISTA a ogni N.")
print(" Il test giusto e' EMPIRICO: la distribuzione dei PANIERI (sezione 7).")
# sensibilita': quale sd(trial) ribalta il verdetto
lo, hi = 1e-4, 1.0
for _ in range(60):
mid = 0.5 * (lo + hi)
scaled = list(np.asarray(pooled) * (mid / (np.std(pooled, ddof=1) / math.sqrt(365.25)))
) if np.std(pooled, ddof=1) > 0 else pooled
d, _, _ = dsr_of(B, scaled)
if d >= 0.95:
lo = mid
else:
hi = mid
print(f"\n sensibilita': con N={len(pooled)} il verdetto si ribalta a "
f"sd(trial giornaliera) = {0.5*(lo+hi):.5f}; misurata = "
f"{np.std(pooled, ddof=1)/math.sqrt(365.25):.5f}.")
return out
# =============================================================================================
# 7) IL CONTROLLO — CIO' CHE DECIDE
# =============================================================================================
def sezione7(F: dict, G: Grid, R5: dict, draws: int) -> dict:
sez("7) IL CONTROLLO — panieri di SCARTATI NETTI. E' QUESTO IL TEST, non lo Sharpe del paniere")
B = R5["B"]
rng = np.random.default_rng(SEED)
real = (sh(B), shI(B), shH(B), dd(B))
# in-sample ranking per famiglia (mai l'hold-out: sarebbe selection-on-holdout)
rank = {}
for nm in LEGS:
ks = G.keys[nm]
vals = np.array([shI(F[nm][k]) for k in ks])
rank[nm] = dict(keys=ks, ins=vals, order=np.argsort(np.nan_to_num(vals, nan=-9)))
frozen_idx = {nm: G.keys[nm].index(R5["sel"][nm]) for nm in LEGS}
print(" rango IN-SAMPLE della cella congelata dentro la propria famiglia "
"(mai l'hold-out: sarebbe selection-on-holdout)")
for nm in LEGS:
o = list(rank[nm]["order"][::-1])
r = o.index(frozen_idx[nm]) + 1
print(f" {nm:<14}{r:>4} / {len(o):<5} (pctl in-sample "
f"{100*(1-(r-1)/len(o)):.0f}°, ShIS {rank[nm]['ins'][frozen_idx[nm]]:+.3f})")
def draw_basket(picker) -> tuple:
cols = []
for nm in LEGS:
cols.append(G.cols[nm][:, picker(nm)])
M = np.column_stack(cols)
s = G.combo(M)
return sh(s), shI(s), shH(s), dd(s)
def bottom(nm):
o = rank[nm]["order"] # crescente: i primi sono i peggiori in-sample
return int(rng.choice(o[:max(1, len(o) // 2)]))
def matched(nm):
o = list(rank[nm]["order"][::-1])
r = o.index(frozen_idx[nm]) / max(1, len(o) - 1)
cand = [i for i in range(len(o)) if abs(i / max(1, len(o) - 1) - r) <= 0.10]
return int(o[int(rng.choice(cand))])
def anyc(nm):
return int(rng.integers(len(G.keys[nm])))
res = {}
for tag, pick in (("B1 SCARTATI NETTI (meta' peggiore in-sample, stesse famiglie)", bottom),
("B2 RANGO APPAIATO (stesso pctl in-sample +-10pp)", matched),
("B0 CELLA A CASO (qualunque cella della famiglia)", anyc)):
t = time.time()
arr = np.array([draw_basket(pick) for _ in range(draws)])
res[tag] = arr
print(f"\n {tag} ({draws} panieri, {time.time()-t:.1f}s)")
print(f" {'metrica':<10}{'reale':>9}{'p10':>9}{'mediana':>9}{'p90':>9}{'max':>9}"
f"{'pctl del reale':>17}")
for i, mn in enumerate(("ShFULL", "ShIS", "ShHOLD", "maxDD")):
c = arr[:, i]
pc = 100.0 * float((c < real[i]).mean())
print(f" {mn:<10}{real[i]:>9.3f}{np.percentile(c,10):>9.3f}"
f"{np.median(c):>9.3f}{np.percentile(c,90):>9.3f}{np.max(c):>9.3f}"
f"{pc:>16.1f}°")
# --- B3: null di diversificazione (marginali CONSERVATE, correlazione distrutta) ----------
sub("B3 NULL DI DIVERSIFICAZIONE — stesse gambe, correlazione incrociata DISTRUTTA")
print(" Ogni gamba viene ruotata circolarmente di un lag casuale >= 60 giorni: lo Sharpe")
print(" MARGINALE di ciascuna resta IDENTICO, sparisce solo la relazione fra gambe (e con")
print(" TP01). Se il paniere reale non batte questa distribuzione, non contiene nulla oltre")
print(" a 'K serie con quei marginali, quasi scorrelate'. Turnover invariato -> fee-neutrale.")
M0 = R5["M"]
arr = []
for _ in range(draws):
cols = []
for i in range(M0.shape[1]):
col = M0[:, i]
ok = ~np.isnan(col)
v = col[ok].copy()
v = np.roll(v, int(rng.integers(60, max(61, len(v) - 60))))
nc = np.full_like(col, np.nan)
nc[ok] = v
cols.append(nc)
s = G.combo(np.column_stack(cols))
arr.append((sh(s), shI(s), shH(s), dd(s)))
arr = np.array(arr)
res["B3"] = arr
print(f"\n {'metrica':<10}{'reale':>9}{'p10':>9}{'mediana':>9}{'p90':>9}{'max':>9}"
f"{'pctl del reale':>17}")
for i, mn in enumerate(("ShFULL", "ShIS", "ShHOLD", "maxDD")):
c = arr[:, i]
print(f" {mn:<10}{real[i]:>9.3f}{np.percentile(c,10):>9.3f}{np.median(c):>9.3f}"
f"{np.percentile(c,90):>9.3f}{np.max(c):>9.3f}"
f"{100.0*float((c<real[i]).mean()):>16.1f}°")
# --- B4: cross-meccanismo, scartati netti veri --------------------------------------------
sub("B4 SCARTATI NETTI CROSS-MECCANISMO — 4 famiglie relative-value refutate dall'onda ortho")
print(" RATIO-MOM / RATIO-REV / RATIO-ACCEL / VOLSPREAD: meccanismi DIVERSI fra loro e dai")
print(" quasi-passati, tutti collassati dallo scorer indurito (17/18 -> 1, 21/06). Stessa")
print(" selezione dei quasi-passati (miglior cella IN-SAMPLE di ogni famiglia) + estrazioni.")
OF = F["_ORTHO"]
Go = Grid(OF)
best = {}
for nm, f in OF.items():
ks = list(f)
best[nm] = ks[int(np.argmax([np.nan_to_num(shI(f[k]), nan=-9) for k in ks]))]
Mb = Go.pick(best)
Bo = Go.combo(Mb)
print(f"\n paniere dei 4 SCARTATI NETTI, celle scelte in-sample: ShFULL {sh(Bo):+.3f} "
f"ShIS {shI(Bo):+.3f} ShHOLD {shH(Bo):+.3f} maxDD {100*dd(Bo):.1f}% n {len(Bo)}")
Cb = pd.concat({k: OF[k][v] for k, v in best.items()}, axis=1).corr().values
print(f" corr media fuori diagonale {np.nanmean(Cb[~np.eye(len(Cb),dtype=bool)]):+.3f} -> "
f"ampiezza effettiva {eff_breadth(Cb):.2f} su 4")
arr = []
for _ in range(draws):
s = Go.combo(np.column_stack([Go.cols[nm][:, int(rng.integers(len(Go.keys[nm])))]
for nm in OF]))
arr.append((sh(s), shI(s), shH(s), dd(s)))
arr = np.array(arr)
res["B4"] = arr
print(f"\n {draws} panieri a cella casuale dalle stesse 4 famiglie refutate:")
print(f" {'metrica':<10}{'quasi-pass.':>13}{'p10':>9}{'mediana':>9}{'p90':>9}{'max':>9}"
f"{'pctl dei quasi':>17}")
for i, mn in enumerate(("ShFULL", "ShIS", "ShHOLD", "maxDD")):
c = arr[:, i]
print(f" {mn:<10}{real[i]:>13.3f}{np.percentile(c,10):>9.3f}{np.median(c):>9.3f}"
f"{np.percentile(c,90):>9.3f}{np.max(c):>9.3f}"
f"{100.0*float((c<real[i]).mean()):>16.1f}°")
# --- CONTROLLO POSITIVO -------------------------------------------------------------------
sub("CONTROLLO POSITIVO — un rilevatore che non segnala e' indistinguibile da uno rotto")
print(" Se il confronto 'reale vs panieri casuali' avesse potenza ZERO, tutto quanto sopra")
print(" sarebbe privo di significato. Lo si prova costruendo un paniere che DEVE stare in")
print(" cima: la MIGLIOR cella in-sample di ognuna delle 5 famiglie.")
bestQ = {}
for nm in LEGS:
o = rank[nm]["order"]
bestQ[nm] = G.keys[nm][int(o[-1])]
Bb = G.combo(G.pick(bestQ))
B0 = res["B0 CELLA A CASO (qualunque cella della famiglia)"]
pIS = 100.0 * float((B0[:, 1] < shI(Bb)).mean())
print(f" paniere 'migliori in-sample': ShIS {shI(Bb):+.3f} -> pctl {pIS:.1f}deg della")
print(f" distribuzione B0 (atteso ~100deg se il test ha potenza: e' il massimo per")
print(f" costruzione, quindi un pctl basso significherebbe rilevatore ROTTO).")
print(f" Il suo ShHOLD e' {shH(Bb):+.3f} contro mediana B0 {np.median(B0[:,2]):+.3f}:")
print(f" e' QUESTO il pezzo di scelta in-sample che sopravvive fuori campione.")
if pIS < 90.0:
print(" RILEVATORE SOSPETTO: il paniere costruito per stare in cima NON ci sta.")
return dict(res=res, real=real, best_is=Bb, ortho=Bo, rank=rank, frozen_idx=frozen_idx)
# =============================================================================================
# 8) LEAVE-ONE-OUT
# =============================================================================================
def sezione8(G: Grid, R5: dict) -> dict:
sez("8) LEAVE-ONE-OUT — se il paniere 'funziona' grazie a UNA gamba, non e' un paniere")
B = R5["B"]
base = (sh(B), shI(B), shH(B), dd(B))
print(f" paniere completo: ShFULL {base[0]:.3f} ShIS {base[1]:.3f} ShHOLD {base[2]:.3f} "
f"maxDD {100*base[3]:.2f}%")
print(f"\n {'tolta':<14}{'ShFULL':>9}{'dShFULL':>10}{'ShHOLD':>9}{'dShHOLD':>10}"
f"{'maxDD':>9}{'d maxDD pp':>12}")
out = {}
for nm in LEGS:
keep = [k for k in LEGS if k != nm]
s = G.combo(G.pick({k: R5["sel"][k] for k in keep}))
out[nm] = (sh(s), shH(s), dd(s))
print(f" {nm:<14}{sh(s):>9.3f}{sh(s)-base[0]:>+10.3f}{shH(s):>9.3f}"
f"{shH(s)-base[2]:>+10.3f}{100*dd(s):>8.2f}%{100*(dd(s)-base[3]):>+12.2f}")
worst = min(out, key=lambda k: out[k][0])
print(f"\n la gamba il cui ritiro costa di piu' sul FULL: {worst} "
f"({out[worst][0]-base[0]:+.3f})")
return out
# =============================================================================================
# 9) IL PANIERE COME TERZO SLEEVE DEL LIBRO LIVE — banda d'ancora, funding dentro
# =============================================================================================
def sezione9(R5: dict, legs: dict, draws: int) -> dict:
sez("9) IL PANIERE COME TERZO SLEEVE DEL LIBRO LIVE — e batte la sua MIGLIOR gamba?")
if not B3RD_CACHE.exists():
print(f" ⚠️ cache §50 assente ({B3RD_CACHE}) -> sezione SALTATA. Non e' un risultato.")
return {}
S = pickle.loads(B3RD_CACHE.read_bytes())
print(f" cache §50 riusata (serie ancorate, FUNDING DENTRO): {list(S)[:8]}...")
# replica del baseline §50 prima di ogni delta
rng = np.random.default_rng(SEED)
hs = rng.choice(TP_HOURS, size=draws)
os_ = rng.choice(SKH_OFFSETS, size=draws)
hs_sa = rng.choice(TP_HOURS, size=draws)
base, dPV, dBK, dBK4 = [], [], [], []
# gambe funding-consistenti: PREVDAY/STATARB/DVOLSPREAD dalla cache §50 (funding dentro),
# VRP (opzioni: nessun funding di perp) e XSR01 con il drag dichiarato di §37.
xsr = legs["XSR01"] - XS_FUNDING_DRAG_YR / 365.25
vrp = legs["VRP-TENORE"]
W_CAND = 0.15
for i in range(draws):
c2 = {"TP01": S["TP01"][hs[i]], "SKH01": S["SKH01"][os_[i]]}
b = combine_outer(c2, {"TP01": W_TP, "SKH01": W_SKH}, lo=BOOK_START)
mb, mbh = metrics(b), metrics(b[b.index >= HOLDOUT])
base.append((mb["sharpe"], mbh["sharpe"], mb["maxdd"]))
pan = combine_outer({"PREVDAY": S["PREVDAY"][0], "DVOLSPREAD": S["DVOLSPREAD"][0],
"VRP-TENORE": vrp, "STATARB": S["STATARB"][hs_sa[i]], "XSR01": xsr},
{k: 1.0 for k in LEGS}, lo=BOOK_START)
pan4 = combine_outer({"PREVDAY": S["PREVDAY"][0], "DVOLSPREAD": S["DVOLSPREAD"][0],
"VRP-TENORE": vrp, "STATARB": S["STATARB"][hs_sa[i]]},
{k: 1.0 for k in LEGS if k != "XSR01"}, lo=BOOK_START)
for tgt, lst in ((S["PREVDAY"][0], dPV), (pan, dBK), (pan4, dBK4)):
c3 = dict(c2); c3["CAND"] = tgt
a = combine_outer(c3, {"TP01": W_TP * (1 - W_CAND), "SKH01": W_SKH * (1 - W_CAND),
"CAND": W_CAND}, lo=BOOK_START)
ma, mah = metrics(a), metrics(a[a.index >= HOLDOUT])
lst.append((ma["sharpe"] - mb["sharpe"], mah["sharpe"] - mbh["sharpe"],
ma["maxdd"] - mb["maxdd"]))
Bs = np.array(base)
print(f"\n LIBRO LIVE de-luckato (2 sleeve, funding dentro), {draws} estrazioni:")
print(f" ShFULL {np.median(Bs[:,0]):.3f} ShHOLD {np.median(Bs[:,1]):.3f} "
f"maxDD {100*np.median(Bs[:,2]):.2f}%")
print(" §50 pubblicava 1,813 / 1,437 / 9,42% -> ✅ replica (estrazioni diverse, "
"stessa cache)")
print(f"\n peso del candidato = {W_CAND:.0%}. Statistica = MEDIANA DELLE DIFFERENZE APPAIATE.")
print(f"\n {'candidato':<34}{'dShFULL':>11}{'>0':>7}{'dShHOLD':>11}{'>0':>7}"
f"{'d maxDD pp':>13}")
rows = [("PREVDAY da sola (§50: +0,192/+0,363)", np.array(dPV)),
("PANIERE 5 gambe (quasi-passati)", np.array(dBK)),
("PANIERE 4 gambe (senza XSR01, eseguibile)", np.array(dBK4))]
for nm, a in rows:
print(f" {nm:<34}{np.median(a[:,0]):>+11.4f}{100*(a[:,0]>0).mean():>6.0f}%"
f"{np.median(a[:,1]):>+11.4f}{100*(a[:,1]>0).mean():>6.0f}%"
f"{100*np.median(a[:,2]):>+13.2f}")
d5 = np.array(dBK)[:, 0] - np.array(dPV)[:, 0]
d5h = np.array(dBK)[:, 1] - np.array(dPV)[:, 1]
print(f"\n 🚨 PANIERE meno PREVDAY-DA-SOLA (differenza APPAIATA sulla stessa estrazione):")
print(f" dShFULL {np.median(d5):+.4f} (>0 nel {100*(d5>0).mean():.0f}%) "
f"dShHOLD {np.median(d5h):+.4f} (>0 nel {100*(d5h>0).mean():.0f}%)")
return dict(base=Bs, dPV=np.array(dPV), dBK=np.array(dBK), dBK4=np.array(dBK4))
# =============================================================================================
# 10) ESEGUIBILITA' + EUR/GIORNO
# =============================================================================================
def sezione10(R5: dict, R9: dict) -> None:
sez("10) ESEGUIBILITA' RIGA PER RIGA — un paniere con dentro uno STAT-MODE non e' un candidato")
print(f" {'gamba':<14}{'venue':<14}{'su Deribit?':<14}{'ticket a $635 (peso 15%/5)':<30}"
f"{'stato'}")
tick = CAPITAL_TODAY * 0.15 / len(LEGS)
righe = [
("PREVDAY", "Deribit", "SI'", f"${tick:.2f} netta col libro", "eseguibile"),
("DVOLSPREAD", "Deribit", "SI'", f"${tick:.2f} netta col libro", "eseguibile"),
("STATARB", "Deribit", "SI'", f"${tick:.2f} netta col libro", "eseguibile"),
("VRP-TENORE", "Deribit opz.", "SI' (ETH)", "1 lotto ETH = $242 (>> $19)",
"🚨 NON eseguibile al peso"),
("XSR01", "Hyperliquid", "NO", "50 gambe, min $10/gamba",
"🚨 STAT-MODE, venue diverso"),
]
for r in righe:
print(f" {r[0]:<14}{r[1]:<14}{r[2]:<14}{r[3]:<30}{r[4]}")
print(f"\n 🚨 2 gambe su 5 NON sono eseguibili a $635 -> il paniere COSI' COM'E' non e' un")
print(" candidato al libro, a prescindere da qualunque numero delle sezioni precedenti.")
print(" VRP-TENORE cade sul LOTTO (regola gia' scritta: 'niente short-vol da modello in")
print(" deploy' — il lotto non e' nemmeno il vincolo principale). XSR01 cade sul VENUE,")
print(" e la decisione d'operatore tiene tutto su Deribit fino a $20k.")
if R9:
d = R9["dBK4"][:, 0]
print(f"\n Il paniere ESEGUIBILE (4 gambe, senza XSR01) vale dShFULL "
f"{np.median(d):+.4f} di libro. Per convertirlo in reddito serve la LEVA, che "
f"a $635 non c'e'.")
def eur_al_giorno(R9: dict) -> None:
sez("11) IN EURO AL GIORNO — l'unita' che il progetto usa per non mentirsi")
cagr_base = 0.1519 # L3 congiunta (fisco + funding), CLAUDE.md §36
perp = 0.0635 # rendita perpetua L3
print(f" Conto reale $635. Rendita perpetua della lente congiunta L3 = {100*perp:.2f}%/anno")
print(f" -> oggi il libro vale ${635*perp/365.25:.3f}/giorno = "
f"€{635*perp/365.25*0.92:.3f}/giorno.")
if not R9:
return
d = np.median(R9["dBK4"][:, 0])
dPV = np.median(R9["dPV"][:, 0])
print(f"\n Il paniere eseguibile aggiunge dShFULL {d:+.4f} al libro; PREVDAY DA SOLA "
f"{dPV:+.4f}.")
print(" Uno dSharpe NON e' reddito a nozionale invariato (regola 25/07: un diversificatore")
print(" a basso CAGR si giudica a ISO-RISCHIO). Convertito a iso-rischio con la leva che a")
print(" $635 NON esiste, e prendendo per buono il d drift misurato in sezione 9:")
dd_ = np.median(R9["dBK4"][:, 2])
print(f" d maxDD {100*dd_:+.2f}pp -> a iso-DD si potrebbe alzare la scala di un fattore")
print(f" ~{(np.median(R9['base'][:,2])/max(1e-9, np.median(R9['base'][:,2])+dd_)):.3f}, "
f"cioe' ~{100*((np.median(R9['base'][:,2])/max(1e-9,np.median(R9['base'][:,2])+dd_))-1):.1f}% "
f"di reddito in piu'.")
v = 635 * perp / 365.25 * 0.92
k = np.median(R9['base'][:, 2]) / max(1e-9, np.median(R9['base'][:, 2]) + dd_)
print(f"\n 🚨 IN EURO: €{v:.3f}/g -> €{v*k:.3f}/g. Guadagno = "
f"€{v*(k-1):.4f}/GIORNO, cioe' €{v*(k-1)*365:.2f}/anno su un conto da $635.")
print(f" Versare €500/mese vale €6.000/anno. Il rapporto e' "
f"~{6000/max(1e-9, abs(v*(k-1)*365)):.0f}x.")
print(" E il paniere richiede QUATTRO monitor invece di uno, su una macchina a 2 CPU.")
# =============================================================================================
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--draws", type=int, default=1000)
ap.add_argument("--bookdraws", type=int, default=200)
ap.add_argument("--force", action="store_true")
args = ap.parse_args()
sez("r0823b_quasi_passati.py — §68 | i candidati morti PER POCO, presi insieme, passano?")
print(f" avvio {dt.datetime.now(dt.timezone.utc):%Y-%m-%d %H:%M UTC} · "
f"estrazioni {args.draws} · seed {SEED} · SOLA LETTURA, 0 ordini, 0 chiamate di rete")
print(__doc__.split("DOMANDA")[1].split("REGOLA DI AMMISSIONE")[0].rstrip())
sez("0) ATTESE A PRIORI — dichiarate nel docstring PRIMA di misurare")
print(__doc__.split("=====\n")[2].split("METODO")[0].rstrip())
sezione1()
sezione2()
sez("COSTRUZIONE DELLE FAMIGLIE (ogni cella = una serie di rendimenti netti giornalieri)")
F = build_families(args.force)
R3 = sezione3(F)
legs = R3["legs"]
G = Grid({k: F[k] for k in LEGS})
R4 = sezione4(legs)
R5 = sezione5(G, legs)
R6 = sezione6(F, R5, legs)
R7 = sezione7(F, G, R5, args.draws)
R8 = sezione8(G, R5)
R9 = sezione9(R5, legs, args.bookdraws)
sezione10(R5, R9)
eur_al_giorno(R9)
# ---------------------------------------------------------------------------------------
sez("12) ATTESE: CONFERMATE O REFUTATE")
B = R5["B"]
best_leg = max(sh(legs[n]) for n in LEGS)
b0 = R7["res"]["B0 CELLA A CASO (qualunque cella della famiglia)"]
b1 = R7["res"]["B1 SCARTATI NETTI (meta' peggiore in-sample, stesse famiglie)"]
pct_full_b1 = 100.0 * float((b1[:, 0] < sh(B)).mean())
pct_hold_b1 = 100.0 * float((b1[:, 2] < shH(B)).mean())
a1 = sh(B) > best_leg
a2 = (max(R6.values()) >= 0.95) and (min(R6.values()) < 0.95)
a3 = (pct_full_b1 > 50) and (pct_hold_b1 < pct_full_b1)
a4 = R4["neff"] > 0.8 * len(LEGS)
worst = min(R8, key=lambda k: R8[k][0])
a5 = worst == "PREVDAY"
print(f" A1 paniere > ogni gamba sul FULL ................. "
f"{'CONFERMATA' if a1 else 'REFUTATA'} ({sh(B):.3f} vs {best_leg:.3f})")
print(f" A2 il DSR si ribalta con la partizione ........... "
f"{'CONFERMATA' if a2 else 'REFUTATA'} (range {min(R6.values()):.3f}-{max(R6.values()):.3f})")
print(f" A3 vantaggio in-sample che si riduce sull'hold-out "
f"{'CONFERMATA' if a3 else 'REFUTATA'} (pctl vs B1: FULL {pct_full_b1:.0f}° / "
f"HOLD {pct_hold_b1:.0f}°)")
print(f" A4 ampiezza effettiva ~ K ....................... "
f"{'CONFERMATA' if a4 else 'REFUTATA'} ({R4['neff']:.2f} su {len(LEGS)})")
print(f" A5 dipende da UNA gamba (PREVDAY) ............... "
f"{'CONFERMATA' if a5 else 'REFUTATA'} (la piu' costosa da togliere: {worst})")
print(f" A6 almeno una gamba STAT-MODE ................... CONFERMATA (XSR01 + VRP-TENORE)")
print(f" A7 le gambe sono DECADUTE dalla pubblicazione ... vedi sezione 3b")
sez(f"VERDETTO {clock()}")
print(f" Sharpe del paniere: FULL {sh(B):.3f} / IS {shI(B):.3f} / HOLD {shH(B):.3f}, "
f"maxDD {100*dd(B):.2f}%, ampiezza effettiva {R4['neff']:.2f}/5.")
print(f" Percentile contro i panieri di SCARTATI NETTI (B1): FULL {pct_full_b1:.1f}° / "
f"HOLD {pct_hold_b1:.1f}°.")
print(f" Percentile contro i panieri a CELLA CASUALE (B0): FULL "
f"{100.0*float((b0[:,0] < sh(B)).mean()):.1f}° / HOLD "
f"{100.0*float((b0[:,2] < shH(B)).mean()):.1f}°.")
print(f" DSR del paniere: {min(R6.values()):.3f} - {max(R6.values()):.3f} secondo la "
f"partizione dei trial.")
print("\n La riga per il registro e' nel messaggio finale.")
if __name__ == "__main__":
main()