From 37c83c11c9b828dd832e4c0625191bc79a040b90 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Sun, 23 Aug 2026 04:06:28 +0000 Subject: [PATCH] =?UTF-8?q?critico=20di=20chiusura:=20il=20muro=20$313k=20?= =?UTF-8?q?e'=20una=20mediana=20con=20banda=20[$187k,=20$1,14M],=20e=20?= =?UTF-8?q?=C2=ABN/N=20ancore=C2=BB=20vale=20~2=20osservazioni?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ultimo agente dell'ondata 2026-08-22/23. Sola lettura, nessun file di produzione toccato. Attese a priori dichiarate nel docstring: A1/A4/A5/A6 confermate, A2 e A3 REFUTATE. REPLICHE (prima di ogni accusa, tutte riuscite): - libro 75/25 path live: drift 19,23%/17,07%, Sharpe 1,692/1,513, funding -2,1597%/anno - i quattro muri L0/L1/L2/L3 riprodotti al dollaro: $278.033 / $264.373 / $327.617 / $313.143, e il muro E' esattamente `prelievo / perpetua` - §42 dShFULL(floor=-1) all'ancora 0 = -0,4502 (pubblicato -0,450) - TP01 canonico ShFULL 1,305; XS01 fase 0 == sleeve di produzione a max|diff| 0,0 - funding ri-misurato da implementazione indipendente: TP01 2,138%/anno, rapporto condizionale 1,93x (BTC) / 2,58x (ETH) contro il pubblicato 1,86-2,55x TROVATO: 1. Il muro $313k non ha mai avuto una banda. Propagando SOLO la SE del drift (5,151%/anno, block bootstrap; §53 la misura 5,09 su altra lente) va da $204k (+1 SE) a $707k (-1 SE), p10-p90 [$187k, $1,14M], e a -2 SE il traguardo NON esiste a nessun capitale. La riga «EUR500/mese -> P(20a) 85%» diventa ~0% a -1 SE. L'ondata ha pubblicato la risoluzione Monte Carlo del muro (0,7%) e mai quella del suo input, che e' 100x piu' grande. 2. «positivo in N/N ancore/fasi» non e' N osservazioni: N_eff misurato 1,6-2,1 (24 ancore TP01, corr 0,63) e 1,2-1,5 (10 fasi XS01, corr 0,79), con controllo positivo 24,5 / 1,00. La componente comune NON si cancella nella differenza appaiata (corr 0,59) -> A3 refutata. E la banda d'ancora non e' un IC: per la stessa grandezza l'IC95 bootstrap e' 4,3x piu' largo e contiene lo zero. I verdetti reggono, la precisione dei numeri no. 3. Tre baseline diverse sotto lo stesso nome «libro 75/25»: 1,68 (hourly, tutti i muri), 1,80 (canonical, §41/42/49/50/54), 1,63 (mediana d'ancora, §8/25) — spread 0,12 di Sharpe e 1,7pp di maxDD, piu' grande di quasi tutti gli effetti misurati. 4. «Soffitto direzionale ~1,15» contro 1,639 (§23) e 1,621 (§54) nella stessa ondata: seconda refutazione indipendente dell'argomento aritmetico di §12. 5. «EUR X/mese» versa ogni 30 GIORNI (12,17 versamenti/anno, +0,8-1,4%); e il contatore `versato` non si ferma al traguardo -> a 10 anni i bonifici fanno il 61%, non il 73%. 6. MDE: la catena opzioni misurata da me da' 77 giorni di superficie (registro 74-75, ok) = MDE 4,3 di Sharpe -> ogni SCARTATO di §4/§5/§7/§11 che poggia su uno Sharpe e' un non-risultato su quell'asse. §21 XS01-OOS, pilastro del canale funded, ha effetto +1,12 contro un MDE di 1,13. 7. Errore mio catturato in sessione: la prima stesura de-luckava una serie gia' de-luckata (0,89^2) e stampava un finto +31,5% sul muro; il valore vero della scelta di modello e' +4,0%. RISPOSTA AL MANDATO: no. La somma di TUTTI i lead positivi dell'ondata, se fossero autorizzati e additivi (non lo sono), vale +0,036 EUR/giorno a $635. EUR250 -> EUR500 al mese porta P(20a) dal 14% all'85%. Il valore dell'ondata e' difensivo ed e' reale; il mandato «arrivare ai 50 giornalieri velocemente» ha risposta negativa. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_018M8Ncho6QV9FWLdyy4VyQf --- scripts/research/r0823_critico_chiusura.py | 821 +++++++++++++++++++++ 1 file changed, 821 insertions(+) create mode 100644 scripts/research/r0823_critico_chiusura.py diff --git a/scripts/research/r0823_critico_chiusura.py b/scripts/research/r0823_critico_chiusura.py new file mode 100644 index 0000000..f5a9c44 --- /dev/null +++ b/scripts/research/r0823_critico_chiusura.py @@ -0,0 +1,821 @@ +"""r0823 — CRITICO DI CHIUSURA dell'ondata 2026-08-22/23 (55 filoni, `research/wave-0822`). + +Non cerca strategie: attacca cio' che l'ondata ha CONCLUSO, coordinatore incluso. +Sola lettura. Nessun ordine, nessuna rete, nessun file di produzione toccato. + +============================================================================================= +ATTESE A PRIORI — scritte PRIMA di misurare (un critico che ha sempre ragione non sta criticando) +============================================================================================= +A1 Le repliche dei numeri di testa RIUSCIRANNO (muri, funding, dShFULL della short di TP01): + l'ondata ha fatto molte repliche interne e i suoi script sono ripetibili. + -> attesa: CONFERMATA. Se fallisse, sarebbe il risultato piu' grosso del filone. +A2 Il muro di $313k sara' molto sensibile al drift, ma ci aspettiamo un fattore ~1,5x fra + +1SE e -1SE, cioe' una banda dell'ordine di [$230k, $430k]. + -> attesa: DA MISURARE. (esito: REFUTATA — misurato [$204k, $707k] a +/-1 SE, e a -2 SE + il traguardo NON esiste: la mia stima era ottimista di ~2x sull'ampiezza) +A3 Le 24 ancore / 10 fasi porteranno meno informazione di quanta ne sembri, ma su una + DIFFERENZA APPAIATA la componente comune si cancellera' e il numero effettivo di + osservazioni indipendenti sara' >= 5. + -> attesa: DA MISURARE. (esito: REFUTATA — non si cancella quasi nulla) +A4 La maggior parte degli SCARTATI dell'ondata sara' correttamente etichettata come + "non misurabile" quando lo e': l'ondata cita gli MDE spesso. + -> attesa: CONFERMATA in larga parte, con eccezioni nominate. +A5 L'aritmetica pubblicata (muri = prelievo/perpetua, tetti di leva) tornera'. + -> attesa: CONFERMATA. +A6 Nessuna misura dell'ondata battera' "versare": ce lo aspettiamo perche' l'ondata stessa + lo ha scritto due volte. Il valore e' nel METTERLE IN FILA con la stessa unita'. + -> attesa: CONFERMATA. + +METODO + * ogni accusa e' MISURATA, non argomentata; + * ogni rilevatore ha un controllo positivo (un rilevatore che non trova nulla e' + indistinguibile da uno rotto); + * le repliche vengono PRIMA di ogni numero nuovo. + +USO: uv run python scripts/research/r0823_critico_chiusura.py [--fast] +""" +from __future__ import annotations + +import sys +import time +from pathlib import Path + +import numpy as np +import pandas as pd + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +sys.path.insert(0, str(ROOT / "scripts" / "research")) + +from src.data.downloader import load_data # noqa: E402 +from src.strategies.trend_portfolio import ( # noqa: E402 + CANONICAL, TrendPortfolio, simple_returns) +from src.portfolio.sleeves import XS_CFG, XS_UNIVERSE, _HL_DIR, _xsec_returns # noqa: E402 + +import r0725_capcurve as CC # noqa: E402 EURUSD, TARGET_EUR_DAY, TAX_RATE, _boot_paths +import r0807_piano_netto as PN # noqa: E402 sopravvivenza / accumula +import r0727_tasse as TX # noqa: E402 PATRIMONIALE + +FAST = "--fast" in sys.argv +N_WALL = 2500 if FAST else 4000 +N_TRAJ = 2000 if FAST else 3000 +BLOCK = 20 +DELUCK = 0.89 +SEED = 725 +T0 = time.time() + +# La serie giornaliera del libro live 75/25, con e senza funding, prodotta da +# r0822d_piano_vero.costruisci_serie(). Se la cache non c'e' si rigenera (richiede rete). +CACHE = Path("/tmp/claude-1001/-opt-docker-PythagorasGoal/" + "b6cc75e7-14f8-4c32-bd07-ab8a0d2aaee6/scratchpad/pianovero/book.parquet") + + +def sez(t: str) -> None: + print("\n" + "=" * 102) + print(f" {t} [{time.time() - T0:5.0f}s]") + print("=" * 102) + + +def sh(r: np.ndarray) -> float: + r = np.asarray(r, float) + return float(r.mean() / r.std() * np.sqrt(365.25)) + + +def deluck(r: np.ndarray) -> np.ndarray: + """Toglie dal DRIFT la fortuna d'ancora misurata (r0726_deluck_factor). La vol resta.""" + r = np.asarray(r, float) + return r - (1.0 - DELUCK) * r.mean() + + +def boot_stat(x: np.ndarray, fn, n: int = 3000, block: int = BLOCK, seed: int = 7): + """Block bootstrap di una statistica scalare su una serie (o su una matrice n x k).""" + rng = np.random.default_rng(seed) + x = np.asarray(x, float) + N = x.shape[0] + nb = int(np.ceil(N / block)) + out = np.empty(n) + for i in range(n): + st = rng.integers(0, N - block, size=nb) + ix = (st[:, None] + np.arange(block)[None, :]).reshape(-1)[:N] + out[i] = fn(x[ix]) + return out + + +def n_eff(M: pd.DataFrame) -> tuple[float, float, float]: + """(corr media fuori diagonale, N_eff da rbar, participation ratio degli autovalori).""" + C = M.corr().values + k = C.shape[0] + iu = np.triu_indices(k, 1) + rbar = float(C[iu].mean()) + ev = np.linalg.eigvalsh(C) + pr = float(ev.sum() ** 2 / (ev ** 2).sum()) + return rbar, k / (1.0 + (k - 1) * rbar), pr + + +# ============================================================================================= +# 1) REPLICHE — i controlli positivi della MIA macchineria, prima di qualunque accusa +# ============================================================================================= +def resample_off(df: pd.DataFrame, h: int) -> pd.DataFrame: + """Daily con ancora all'ora h. Stessa convenzione di r0702_tp01_offset.resample_offset.""" + d = df.copy() + d["datetime"] = pd.to_datetime(d["datetime"]) + return (d.set_index("datetime") + .resample("24h", offset=pd.Timedelta(hours=h), label="left", closed="left") + .agg({"open": "first", "high": "max", "low": "min", + "close": "last", "volume": "sum"}) + .dropna().reset_index()) + + +_RAW: dict[str, pd.DataFrame] = {} + + +def tp01_at(h: int, long_only: bool = True) -> pd.Series: + """Serie giornaliera netta di TP01 50/50 all'ancora h (long-flat o long-short).""" + if not _RAW: + for a in ("BTC", "ETH"): + _RAW[a] = load_data(a, "1h") + tp = TrendPortfolio(**{**CANONICAL, "long_only": long_only}) + out = {} + for a in ("BTC", "ETH"): + df = resample_off(_RAW[a], h) + r = simple_returns(df["close"].values.astype(float)) + tgt = tp.target_series(df) + held = np.zeros(len(tgt)) + held[1:] = tgt[:-1] + net = held * r - tp.fee_side * np.abs(np.diff(held, prepend=0.0)) + net[0] = 0.0 + out[a] = pd.Series(np.clip(net, -0.99, None), + index=pd.to_datetime(df["datetime"]).dt.normalize()) + J = pd.concat(out, axis=1, join="inner").fillna(0.0) + return pd.Series(0.5 * J["BTC"].values + 0.5 * J["ETH"].values, index=J.index) + + +def xs01_phase(phase: int) -> pd.Series: + """XS01 col meccanismo CONGELATO, ribilanciato alla fase `phase` del ciclo H=10.""" + cols = {} + for sym in XS_UNIVERSE: + p = _HL_DIR / f"hl_{sym.lower()}_1d.parquet" + if p.exists(): + d = pd.read_parquet(p) + cols[sym] = pd.Series(d["close"].values.astype(float), + index=pd.to_datetime(d["timestamp"], unit="ms", utc=True)) + C = pd.concat(cols, axis=1, join="inner").sort_index().dropna() + px = C.values + n, A = px.shape + lbs, H, k, tv = XS_CFG["lookbacks"], XS_CFG["H"], XS_CFG["k"], XS_CFG["target_vol"] + dp, mh, mlb = XS_CFG["disp_pct"], XS_CFG["disp_minhist"], max(XS_CFG["lookbacks"]) + dret = np.vstack([np.zeros(A), px[1:] / px[:-1] - 1.0]) + W = np.zeros((n, A)) + w = np.zeros(A) + hist: list[float] = [] + for i in range(n): + if i >= mlb and i % H == phase: + rLs = [px[i] / px[i - L] - 1.0 for L in lbs] + disp = float(np.mean([r.std() for r in rLs])) + thr = np.percentile(hist, dp) if (dp > 0 and len(hist) >= mh) else -np.inf + if disp >= thr: + score = np.zeros(A) + cnt = 0 + for rL in rLs: + sd = rL.std() + if sd > 0: + score += (rL - rL.mean()) / sd + cnt += 1 + if cnt: + score /= cnt + o = np.argsort(score) + w = np.zeros(A) + w[o[-k:]] = 0.5 / k + w[o[:k]] = -0.5 / k + else: + w = np.zeros(A) + hist.append(disp) + W[i] = w + gross = np.zeros(n) + gross[1:] = np.sum(W[:-1] * dret[1:], axis=1) + turn = np.zeros(n) + turn[0] = np.abs(W[0]).sum() + turn[1:] = np.abs(np.diff(W, axis=0)).sum(axis=1) + s = pd.Series(gross - turn * (0.001 / 2.0), index=C.index) + rv = s.rolling(30, min_periods=15).std().shift(1) * np.sqrt(365.25) + scale = np.clip(np.nan_to_num(tv / rv.replace(0, np.nan).values, nan=0.0), 0, 3.0) + return pd.Series(s.values * scale, index=C.index) + + +def perpetua(r: np.ndarray, aliq: float, patr: float, + n_paths: int = N_WALL, seed: int = SEED) -> float: + """Prelievo annuo massimo (frazione) con P(capitale a 20a >= iniziale) >= 90%. + Stessa definizione e stessa bisezione di r0807_piano_netto.muro / r0822d_piano_vero.muro_di.""" + lo, hi = 0.0, 0.40 + for _ in range(13): + mid = (lo + hi) / 2 + s = PN.sopravvivenza(r, 1e6, 1e6 * mid, 20, aliq, patr, n_paths=n_paths, seed=seed) + if s["p10_end"] >= 1e6: + lo = mid + else: + hi = mid + return lo + + +PREL_NET = CC.TARGET_EUR_DAY * 365 * CC.EURUSD # 50 EUR/g netti, in $/anno +PREL_LORDO = PREL_NET / (1 - CC.TAX_RATE) + + +def sezione_repliche(B: pd.DataFrame) -> dict: + sez("1) REPLICHE — la mia macchineria riproduce l'ondata? (prima di ogni accusa)") + out = {} + A, F = B["nofund"].values, B["fund"].values + print(f" serie del libro live 75/25, {len(B)} giorni, {B.index[0].date()} -> {B.index[-1].date()}") + print(f" {'':22}{'drift':>10}{'vol':>10}{'Sharpe':>10} pubblicato (§35)") + print(f" {'senza funding':22}{A.mean()*365:9.2%}{A.std()*365**.5:10.2%}{sh(A):10.3f}" + f" 19,24% / 11,37% / 1,692") + print(f" {'con funding':22}{F.mean()*365:9.2%}{F.std()*365**.5:10.2%}{sh(F):10.3f}" + f" 17,08% / 11,29% / 1,513") + dfund = (F.mean() - A.mean()) * 365 + print(f" costo del funding {dfund:+.4%}/anno pubblicato -2,1597% " + f"{'OK' if abs(dfund + 0.021597) < 2e-4 else 'DIVERGE'}") + out["fund_ok"] = abs(dfund + 0.021597) < 2e-4 + + L0, L1, L3 = deluck(A), deluck(A), deluck(F) + rows = [("L0 LORDO (26/07)", L0, 0.0, 0.0, PREL_LORDO, 0.1068, 278_000), + ("L1 +FISCO (07/08)", L1, CC.TAX_RATE, TX.PATRIMONIALE, PREL_NET, 0.0752, 264_000), + ("L2 +FUNDING (22/08)", L3, 0.0, 0.0, PREL_LORDO, 0.0906, 328_000), + ("L3 CONGIUNTA (§36)", L3, CC.TAX_RATE, TX.PATRIMONIALE, PREL_NET, 0.0635, 313_000)] + print(f"\n {'lente':<22}{'drift':>9}{'perpetua':>10}{'muro':>13}{'pubbl.':>11}{'scarto':>9}") + for nome, r, al, pa, prel, p_pub, m_pub in rows: + p = perpetua(r, al, pa) + muro = prel / p + print(f" {nome:<22}{r.mean()*365:8.2%}{p:10.2%}{muro:13,.0f}{m_pub:11,.0f}" + f"{muro/m_pub-1:+9.1%}") + out[nome] = dict(perp=p, muro=muro, r=r, aliq=al, patr=pa, prel=prel) + out["_raw_nofund"] = A + print(" ✅ le quattro lenti si riproducono; il muro E' esattamente `prelievo / perpetua`.") + + # replica di §42 (la short del trend) con implementazione indipendente + d0 = sh(tp01_at(0, long_only=False).values) - sh(tp01_at(0, long_only=True).values) + print(f"\n §42 dShFULL(floor=-1) all'ancora 0: {d0:+.4f} pubblicato -0,450 (estremo p10)") + print(f" §41/§35 TP01 canonico ShFULL: {sh(tp01_at(0).values):.3f} pubblicato 1,305-1,314") + # replica di XS01 + x = _xsec_returns() + p0 = xs01_phase(0) + print(f" XS01 fase 0 == sleeve di produzione: max|diff| = " + f"{float(np.abs(p0.values - x.values).max()):.3e}") + return out + + +# ============================================================================================= +# 2) LA BANDA CHE NON E' STATA PUBBLICATA +# ============================================================================================= +def sezione_muro(L: dict) -> dict: + sez("2) IL MURO E' UNA FUNZIONE ESPLOSIVA DI UN DRIFT STIMATO SU 7,4 ANNI") + l3 = L["L3 CONGIUNTA (§36)"] + r = l3["r"] + d = boot_stat(r, lambda x: x.mean() * 365, n=4000, seed=11) + SE = float(d.std()) + print(f" drift L3 {r.mean()*365:.3%}/anno · SE block-bootstrap (blocchi 20g) {SE:.3%}" + f" · IC95 [{np.percentile(d,2.5):.2%}, {np.percentile(d,97.5):.2%}]") + print(f" (§53 misura SE 5,09% su un'altra lente: ✅ concorda)") + print("\n Muro e traiettoria propagando SOLO l'incertezza del drift (vol e forma invariate):") + print(f" {'':>10}{'drift':>9}{'perpetua':>10}{'muro':>14}{'x muro pubbl.':>15}") + band = {} + for lab, k in (("+2 SE", 2.0), ("+1 SE", 1.0), ("p90", 1.2816), ("PUNTO", 0.0), + ("p10", -1.2816), ("-1 SE", -1.0), ("-2 SE", -2.0)): + rr = r + k * SE / 365.0 + p = perpetua(rr, l3["aliq"], l3["patr"]) + muro = PREL_NET / p if p > 0.002 else float("inf") + band[lab] = (rr, p, muro) + m = f"${muro:,.0f}" if np.isfinite(muro) else "IRRAGGIUNGIBILE" + x = f"{muro/l3['muro']:.2f}x" if np.isfinite(muro) else "—" + print(f" {lab:>10}{rr.mean()*365:8.2%}{p:10.2%}{m:>14}{x:>15}") + lo = band["p10"][2] + hi = band["p90"][2] + print(f"\n 🚨 BANDA p10-p90 DEL MURO: [${hi:,.0f}, " + f"{('$%s' % f'{lo:,.0f}') if np.isfinite(lo) else 'IRRAGGIUNGIBILE'}]" + f" contro il punto pubblicato ${l3['muro']:,.0f}") + print(" Il muro e' `prelievo / perpetua` e la perpetua va a ZERO ben prima del drift:") + print(" e' un 1/x su una quantita' che si annulla, quindi l'errore NON e' simmetrico.") + print(" ⚠️ La SE del block-bootstrap e' una LIMITE INFERIORE dell'incertezza vera") + print(" (misura la variabilita' dentro gli stessi 7,4 anni, non il cambio di regime).") + + print("\n Traiettorie sotto la stessa banda (start $635, 25 anni, block bootstrap):") + print(f" {'drift':>8}{'muro':>13}" + "".join(f"{f'EUR{d}/m':>18}" for d in (250, 500, 1000))) + for lab in ("+1 SE", "PUNTO", "-1 SE"): + rr, p, muro = band[lab] + if not np.isfinite(muro): + continue + rng = np.random.default_rng(SEED) + paths = CC._boot_paths(rr, N_TRAJ, 25 * 365, BLOCK, rng) + cells = [] + for dep in (250, 500, 1000): + a = PN.accumula(paths, dep, muro, l3["aliq"], l3["patr"], start=635.0) + y = np.where(a["colpito"] >= 0, a["colpito"] / 365.0, np.inf) + med = np.median(y) + cells.append(f"{('>25a' if not np.isfinite(med) else f'{med:.1f}a')} P{float((y<=20).mean()):.0%}") + print(f" {rr.mean()*365:7.2%}{muro:13,.0f}" + "".join(f"{c:>18}" for c in cells)) + print("\n 📌 «EUR500/mese -> P(20a) 85%» e' il PUNTO. A -1 SE di drift la stessa riga e' ~0%.") + print(" L'ondata ha misurato la risoluzione MONTE CARLO del muro (0,7%) e mai quella") + print(" del suo INPUT. Le due differiscono di due ordini di grandezza.") + return band + + +# ============================================================================================= +# 3) «N/N ANCORE» NON E' N OSSERVAZIONI +# ============================================================================================= +def sezione_ancore() -> None: + sez("3) «0/24 ANCORE» E «10/10 FASI»: quante osservazioni indipendenti sono davvero?") + + # -- controllo positivo del rilevatore (obbligatorio) ------------------------------------- + rng = np.random.default_rng(1) + indip = pd.DataFrame(rng.normal(size=(2000, 24))) + uguali = pd.DataFrame(np.repeat(rng.normal(size=(2000, 1)), 24, axis=1) + + rng.normal(scale=1e-6, size=(2000, 24))) + for nome, M in (("24 serie INDIPENDENTI", indip), ("24 serie IDENTICHE", uguali)): + rb, ne, pr = n_eff(M) + print(f" [controllo positivo] {nome:<24} rbar {rb:+.3f} N_eff {ne:5.2f} PR {pr:5.2f}") + print(" -> il rilevatore distingue i due estremi: il suo «poco» vale.\n") + + # -- TP01: 24 ancore, LIVELLI -------------------------------------------------------------- + S = {h: tp01_at(h) for h in range(24)} + M = pd.DataFrame(S).dropna() + shs = np.array([sh(M[h].values) for h in range(24)]) + rb, ne, pr = n_eff(M) + print(f" TP01 — 24 ancore, LIVELLI: Sharpe da {shs.min():.2f} a {shs.max():.2f}" + f" (canonico {shs[0]:.2f})") + print(f" corr media fra ancore {rb:.3f} -> N_eff {ne:.2f} / participation ratio {pr:.2f}") + + # -- TP01: 24 ancore, DIFFERENZA APPAIATA (la forma che l'ondata usa di piu') ------------- + D, dsh = {}, [] + for h in range(24): + a, b = tp01_at(h, True), tp01_at(h, False) + ix = a.index.intersection(b.index) + D[h] = b.reindex(ix) - a.reindex(ix) + dsh.append(sh(b.reindex(ix).values) - sh(a.reindex(ix).values)) + dsh = np.array(dsh) + MD = pd.DataFrame(D).dropna() + rbd, ned, prd = n_eff(MD) + print(f"\n TP01 — 24 ancore, DIFFERENZA APPAIATA (§42, floor=-1 vs canonico):") + print(f" dShFULL mediana {np.median(dsh):+.3f} banda [{dsh.min():+.3f}, {dsh.max():+.3f}]" + f" >0 in {int((dsh>0).sum())}/24 (§42 pubblica -0,354 [-0,450,-0,251] 0/24)") + print(f" corr media delle serie-differenza {rbd:.3f} -> N_eff {ned:.2f} / PR {prd:.2f}") + print(" 🚨 A3 REFUTATA: nella differenza appaiata la componente comune NON si cancella" + f" ({rbd:.2f} contro {rb:.2f} dei livelli).") + + # -- la banda d'ancora NON e' un intervallo di confidenza --------------------------------- + a0, b0 = tp01_at(0, True), tp01_at(0, False) + ix = a0.index.intersection(b0.index) + A0, B0 = a0.reindex(ix).values, b0.reindex(ix).values + X = np.column_stack([A0, B0]) + bs = boot_stat(X, lambda z: sh(z[:, 1]) - sh(z[:, 0]), n=3000, seed=7) + ic = (float(np.percentile(bs, 2.5)), float(np.percentile(bs, 97.5))) + amp_mm = float(dsh.max() - dsh.min()) + amp_pp = float(np.percentile(dsh, 90) - np.percentile(dsh, 10)) + amp_ic = ic[1] - ic[0] + print(f"\n 🚨 Per la STESSA grandezza, all'ancora canonica:") + print(f" banda d'ANCORA min-max (quella che §42 pubblica) ampiezza {amp_mm:.3f}" + f" · p10-p90 {amp_pp:.3f}") + print(f" IC95 bootstrap a blocchi [{ic[0]:+.3f}, {ic[1]:+.3f}] ampiezza {amp_ic:.3f}" + f" -> {amp_ic/amp_mm:.1f}x la banda pubblicata ({amp_ic/amp_pp:.1f}x la p10-p90)," + f" e CONTIENE LO ZERO.") + print(" La DECISIONE di §42 (SCARTATO) regge lo stesso — poggia su iso-vol FAIL 3/3,") + print(" maxDD +8,80pp, selection-on-holdout e fee-zero, non su questo Δ. Ma il NUMERO") + print(" e la sua banda sono pubblicati con una precisione che il campione non ha.") + + # -- XS01: 10 fasi ------------------------------------------------------------------------- + P = {p: xs01_phase(p) for p in range(10)} + MP = pd.DataFrame(P).dropna() + shp = np.array([sh(MP[p].values) for p in range(10)]) + rbp, nep, prp = n_eff(MP) + bsp = boot_stat(MP[0].values, sh, n=3000, seed=3) + icp = (float(np.percentile(bsp, 2.5)), float(np.percentile(bsp, 97.5))) + amp_f = float(np.percentile(shp, 90) - np.percentile(shp, 10)) + anni = len(MP) / 365.25 + print(f"\n XS01 — 10 fasi del ciclo H=10 (universo 19, {anni:.2f} anni):") + print(f" Sharpe per fase da {shp.min():.2f} a {shp.max():.2f}, mediana {np.median(shp):.2f}") + print(f" corr media {rbp:.3f} -> N_eff {nep:.2f} / PR {prp:.2f}") + print(f" banda di FASE p10-p90 ampiezza {amp_f:.3f} contro IC95 bootstrap " + f"[{icp[0]:+.2f}, {icp[1]:+.2f}] ampiezza {icp[1]-icp[0]:.3f} = " + f"{(icp[1]-icp[0])/amp_f:.1f}x") + print(f" MDE sul LIVELLO (1,96/sqrt(anni)) = {1.96/np.sqrt(anni):.2f}" + f" contro Sharpe mediano {np.median(shp):.2f}") + print("\n 📌 CONSEGUENZA, e vale per TUTTA l'ondata: «positivo in N/N ancore o fasi» e' una") + print(" dichiarazione di ROBUSTEZZA ALLA SCELTA DELL'ANCORA, non un test. Il suo") + print(" equivalente in osservazioni indipendenti e' ~2 (ancore) e ~1,3 (fasi), quindi") + print(" NON vale 2^-24 ne' 2^-10; e la «banda» che l'accompagna e' ~4x piu' stretta") + print(" dell'intervallo di confidenza della stessa grandezza.") + print(" Dove l'ondata attacca un p-value a un conteggio del genere (§26, «test dei segni") + print(" 12/12, p=0,0005», su finestre 30g SOVRAPPOSTE e per giunta SELEZIONATE come le") + print(" peggiori) quel p-value non e' calcolabile cosi'.") + + +# ============================================================================================= +# 4) MDE — quali SCARTATI sono non-risultati +# ============================================================================================= +def sezione_mde() -> None: + sez("4) MDE — quanti SCARTATI dell'ondata sono «non misurabile» invece che «misurato e no»") + + # finestra reale della catena opzioni, misurata (non presa dal registro) + p = ROOT / "data" / "raw" / "cb_chain" / "bite_archive.parquet" + giorni_sup = np.nan + if p.exists(): + d = pd.read_parquet(p, columns=["asset", "ts", "exp"]) + g = d.groupby(["asset", d["ts"].dt.floor("D")])["exp"].nunique() + gg = min(int((g.loc[a] >= 2).sum()) for a in ("BTC", "ETH")) + prop = len(list((ROOT / "data" / "raw" / "cb_chain").glob("2026-*.parquet"))) + giorni_sup = gg + prop + print(f" [misurato] catena opzioni: archivio {d['ts'].dt.floor('D').nunique()} giorni di") + print(f" calendario, ma solo {gg} con >=2 scadenze; + {prop} di raccolta") + print(f" propria = {giorni_sup} giorni di SUPERFICIE (il registro dice 74-75 ✅)") + + ANNI_SUP = giorni_sup / 365.25 if np.isfinite(giorni_sup) else 75 / 365.25 + R = [ + # (filone, oggetto misurato, anni utili, effetto dichiarato, unita', tipo) + ("§4 DEALER-GAMMA", "Sharpe di cella", 90 / 365.25, 4.98, "Sharpe", "maxk:5.12"), + ("§5 SKEW Q1", "Sharpe direzionale", ANNI_SUP, 0.0, "Sharpe", "livello"), + ("§5 SKEW Q2", "gate de-risk su TP01", 5 / 365.25, 0.0, "Sharpe", "livello"), + ("§6 OI-PIN", "Sharpe max-pain", 75 / 365.25, 5.59, "Sharpe", "maxk:6.79"), + ("§7 TERM-STRUCTURE", "Sharpe di cella", 74 / 365.25, 0.14, "Sharpe", "livello"), + ("§10 FLOW-SQUEEZE", "Sharpe di cella", 114 / 365.25, 3.25, "Sharpe", "maxk:5.40"), + ("§11 VRP-QUOTE-VERE", "Sharpe (T=10)", 10 * 7 / 365.25, 0.0, "Sharpe", "rifiutato"), + ("§13 BASIS-CALENDAR", "premio a termine", 7.4, 0.0085, "ret/anno", "livello"), + ("§27 SURFACE-RV", "censimento 1,24M quote", ANNI_SUP, 0.0, "$", "censimento"), + ("§43 DATA-UNUSED", "Sharpe hold-out", 1.40, 0.951, "Sharpe", "maxk:1.009"), + ("§48 VOLVOL", "dSharpe vs TP01", 985 / 365.25, 0.034, "Sharpe", "livello"), + ("§21 XS01-OOS (LEAD)", "Sharpe fuori campione", 3.0, 1.12, "Sharpe", "livello"), + ("§50 PREVDAY (LEAD)", "Sharpe forward", 63 / 365.25, 2.04, "Sharpe", "livello"), + ("§25 BIN-FREQ (LEAD)", "dSharpe di libro", 7.4, 0.112, "Sharpe", "appaiato"), + ("§8 VOL-SIZE (LEAD)", "dSharpe di libro", 7.4, 0.070, "Sharpe", "appaiato"), + ("§42 TP01-LS", "dSharpe di libro", 7.4, -0.354, "Sharpe", "appaiato"), + ("§41 TP01-SIZE", "dSharpe di libro", 7.4, 0.0006, "Sharpe", "appaiato"), + ("§49 TP01-TWIN", "dSharpe hold-out", 7.4, -0.127, "Sharpe", "appaiato"), + ] + print(f"\n MDE sui LIVELLI = 1,96/sqrt(anni). Sugli APPAIATI l'MDE del livello NON si applica") + print(f" (la componente comune si cancella): li' serve l'IC bootstrap della DIFFERENZA,") + print(f" che per §42 ho misurato = {0.862:.3f} di ampiezza (sez. 3).\n") + print(f" {'filone':<24}{'anni':>7}{'MDE liv.':>10}{'effetto':>10}{'|eff|/MDE':>11} lettura") + for nome, _obj, anni, eff, unita, tipo in R: + mde = 1.96 / np.sqrt(anni) + if tipo == "censimento": + lett = "N di quote, non anni: potenza OK" + rap = float("nan") + elif tipo == "appaiato": + lett = "APPAIATO: l'MDE del livello non si applica" + rap = float("nan") + elif tipo == "rifiutato": + lett = "titolo 32,58 NON riportato dall'ondata: ✅ disciplina" + rap = float("nan") + elif tipo.startswith("maxk:"): + nmax = float(tipo.split(":")[1]) + rap = abs(eff) / mde + lett = (f"max-of-k: il rumore da' {nmax:.2f} -> il candidato " + f"{'STA SOTTO' if abs(eff) < nmax else 'sta sopra'} il proprio null") + elif unita != "Sharpe": + lett = "il registro dichiara SE 1,79pp -> non misurabile" + rap = float("nan") + else: + rap = abs(eff) / mde + lett = ("sotto il proprio MDE = NON MISURABILE" if rap < 1 + else "sopra l'MDE" if rap < 2 else "misurato con margine") + rs = " — " if not np.isfinite(rap) else f"{rap:9.2f}" + print(f" {nome:<24}{anni:7.2f}{mde:10.2f}{eff:10.3f}{rs} {lett}") + + print("\n 📌 A4 CONFERMATA IN LARGA PARTE: l'ondata dichiara il proprio MDE in §6, §10, §43,") + print(" §48, §56, e in §7 spiega perche' NON ha girato il deflated-Sharpe. E' disciplina") + print(" reale, e va detto.") + print(" ⚠️ MA restano tre etichette piu' forti della misura:") + print(" (a) §48 chiude un FILONE («quinto lato del DVOL chiuso») su una branca dove") + print(" dichiara esso stesso un fattore 44 sotto l'MDE. La parziale negativa e il") + print(" controllo non-causale hanno potenza; «filone chiuso» no.") + print(" (b) §4/§5/§7/§11 vivono su ~75-90 giorni: MDE 4,2-4,4 di Sharpe. Ogni loro") + print(" SCARTATO che poggia su un confronto di Sharpe e' un NON-RISULTATO su") + print(" quell'asse (le loro parti valide sono i lead-lag, i placebo e i censimenti,") + print(" non gli Sharpe).") + print(" (c) §21 XS01-OOS, che e' il PILASTRO del canale funded, ha effetto +1,12 contro") + print(f" un MDE di {1.96/np.sqrt(3.0):.2f} sui suoi 3 anni: il titolo sta esattamente al") + print(" proprio limite di rilevabilita', e la «banda 10 fasi» non e' un IC (sez. 3).") + print(" Nota di equita': §21 gira ANCHE un null di permutazione a fee zero (p=0,013),") + print(" che ha piu' potenza del t-stat sullo Sharpe -> il problema non e' «nessuna") + print(" evidenza», e' che il LIVELLO +1,12 viene poi propagato fino a P(>=50/g) e") + print(" al muro come se fosse noto a due cifre.") + + +# ============================================================================================= +# 4bis) CONTRADDIZIONI FRA SEZIONI — 55 sezioni scritte da agenti diversi +# ============================================================================================= +def sezione_contraddizioni() -> None: + sez("4bis) CONTRADDIZIONI FRA SEZIONI DELLO STESSO REGISTRO") + + print(" (A) 🚨 MISURATA — «il libro 75/25» ha TRE baseline diverse sotto LO STESSO NOME.") + out = {} + for lens in ("hourly", "canonical"): + s = CC.book_series(lens=lens, alloc=600.0) + r = s.values + eq = np.cumprod(1 + r) + dd = float((1 - eq / np.maximum.accumulate(eq)).max()) + out[lens] = (sh(r), r.mean() * 365, dd) + print(f" lente {lens:<10} ShFULL {sh(r):.3f} drift {r.mean()*365:.2%} maxDD {dd:.2%}") + print(" terza: §8 e §25 usano 1,626 / maxDD 10,4% = la MEDIANA della banda d'ancora.") + print(f" spread fra le tre: {abs(out['canonical'][0]-out['hourly'][0]):.3f} di Sharpe e " + f"{abs(out['canonical'][2]-out['hourly'][2])*100:.1f}pp di maxDD.") + print(" Chi usa quale: §35/§36/§39/§45/§52/§53 e OGNI muro e traiettoria -> `hourly`") + print(" (1,69); §41/§42/§49/§50/§54 -> `canonical` (1,81); §8/§25 -> 1,63.") + print(" 🚨 Lo spread e' PIU' GRANDE di quasi tutti gli effetti che l'ondata misura") + print(" (BIN-FREQ +0,112 · VOL-SIZE +0,070 · PREVDAY de-luckato +0,100): un Δ letto") + print(" accanto al baseline sbagliato cambia di piu' del Δ stesso. Ogni filone lo") + print(" dichiara nel proprio script; il REGISTRO no, e CLAUDE.md nemmeno.") + + print("\n (B) 🚨 IL «SOFFITTO DIREZIONALE» — §35 lo abbassa a ~1,15 (era ~1,31) per il") + print(" funding. Ma nella STESSA ondata, sulla STESSA coppia BTC/ETH e su lente netta") + print(" fee: §23 pubblica il miglior lookback COSTANTE a ShFULL 1,639 e §54 la cella") + print(" PREVDAY scelta al buio a 1,621 (che PASSA il deflated-Sharpe a N=336).") + print(" Le due cose non stanno insieme senza una DEFINIZIONE di «soffitto»:") + print(" «massimo osservabile» (>=1,64), «massimo che sopravvive a un DSR» (>=1,62),") + print(" o «Sharpe di TP01» (1,15 col funding)? Il registro usa la terza e la cita come") + print(" se fosse la prima.") + print(" ⚠️ E la cosa ha una conseguenza operativa: §12 costruisce un argomento") + print(" ARITMETICO («uno screen largo su BTC/ETH non puo' passare il proprio DSR") + print(" perche' il massimo dal rumore, 1,572, sta SOPRA il soffitto ~1,3»). Con") + print(" soffitto 1,62-1,64 quell'argomento si inverte — ed e' la SECONDA refutazione") + print(" dello stesso argomento, indipendente da quella di §24 (che lo ribalta sulla") + print(" partizione della griglia). Un argomento refutato due volte per due strade") + print(" diverse non va ereditato come regola.") + + print("\n (C) §50 chiama PREVDAY «il piu' forte misurato, robust_oos TRUE, ADDS» e §54") + print(" misura che la cella CHE GIRA fallisce il deflated-Sharpe (0,905) mentre quella") + print(" scelta onestamente lo passa (0,993) ma e' un'ALTRA strategia (4h, long-flat).") + print(" Non e' un errore di nessuno dei due — §50 valuta la cella congelata, §54 la") + print(" famiglia — ma le due righe finiscono nella stessa memoria e la prima e' quella") + print(" che suona come una promozione.") + + print("\n (D) ✅ CONTRADDIZIONI CHE L'ONDATA HA GIA' RISOLTO DA SOLA, e vanno a suo credito:") + print(" §45 «lo spot non si liquida» -> §52 lo falsifica (in_cross_collateral_pool);") + print(" §39 «non esiste una linea USDC datata» -> falsificato lo stesso giorno;") + print(" §8 «overlay non causale» -> RITIRATA dallo scettico in giornata;") + print(" §24 «dealer_net_gamma e' il GEX invertito» -> ritirata leggendo il sorgente.") + print(" Quattro auto-correzioni in 24 ore: e' il dato piu' sano dell'ondata.") + + +# ============================================================================================= +# 5) ARITMETICA: cosa torna, cosa no +# ============================================================================================= +def sezione_aritmetica(L: dict) -> None: + sez("5) ARITMETICA PUBBLICATA — verifica diretta") + + print(" (a) tetti di leva (§33/§38/§53) — aritmetica pura sul config che GIRA") + import json + cfg = json.loads((ROOT / "config" / "live.json").read_text()) + frac, dsl = cfg["max_notional_per_asset_frac"], cfg["disaster_sl_pct"] + n_asset = 2 + peggior_giorno_k1 = 0.1432 # §33, bound strutturale + print(f" config letto: frac={frac} · disaster_sl_pct={dsl} · n_asset={n_asset}") + print(f" leva lorda massima a k=1: {n_asset*frac:.2f}x (test di guardia: <=1x) " + f"{'OK' if n_asset*frac <= 1.0 else 'ROTTO'}") + for lab, tetto, pub in (("disaster-SL <= 50% equity", 0.50 / (n_asset * frac * dsl), 1.67), + ("peggior giorno <= 50%", 0.50 / peggior_giorno_k1, 3.49), + ("peggior giorno <= 20% (scettico)", 0.20 / peggior_giorno_k1, 1.40)): + print(f" {lab:<34} k <= {tetto:5.2f} pubblicato {pub:.2f} " + f"{'✅' if abs(tetto-pub) < 0.02 else '⚠️ DIVERGE'}") + print(f" 1,50x -> peggior giorno {1.50*peggior_giorno_k1:.2%} (>20% -> §53 lo boccia) ✅") + print(f" 1,25x -> costo di un disaster-SL {1.25*n_asset*frac*dsl:.1%} (§38 dice 37,5%) ✅") + + print("\n (b) muri = prelievo / perpetua — ✅ verificato in sez. 1 su 4 lenti su 4.") + print(f" prelievo netto = {CC.TARGET_EUR_DAY:.0f} EUR/g x 365 x {CC.EURUSD} = " + f"${PREL_NET:,.0f}/anno ; lordizzato ${PREL_LORDO:,.0f}") + + print("\n (c) 🚨 «EUR X/mese» NON e' al mese: `accumula` versa ogni 30 GIORNI.") + for anni in (10, 15, 20): + nd = anni * 365 + k = len([t for t in range(nd) if t % 30 == 0 and t > 0]) + print(f" {anni:>2} anni: {k} versamenti invece di {anni*12} " + f"({k/(anni*12)-1:+.2%} di denaro versato)") + print(" -> asintoticamente 365/30 = 12,17 versamenti l'anno invece di 12 (+1,39%).") + print(" Effetto piccolo (0,8-1,4%) ma SISTEMATICO e a FAVORE del piano, presente in") + print(" ogni tabella pubblicata dal 25/07 in poi. Va detto perche' l'ondata dichiara") + print(" la risoluzione del proprio Monte Carlo a 0,7% accanto agli stessi numeri.") + + print("\n (d) 🚨 «a 10 anni si versano $229k... i bonifici fanno il 73%» — il contatore") + print(" `versato` di r0807_piano_netto.accumula e' uno SCALARE che non si ferma al") + print(" traguardo (riga 157-167): conta i versamenti dell'INTERO orizzonte anche sui") + print(" percorsi che sono gia' arrivati. Misura del vero versato-fino-all'arrivo:") + l3 = L["L3 CONGIUNTA (§36)"] + rng = np.random.default_rng(SEED) + paths = CC._boot_paths(l3["r"], N_TRAJ, 10 * 365, BLOCK, rng) + dep_m = 1733.0 + dep = dep_m * CC.EURUSD + cap = np.full(N_TRAJ, 635.0) + versato = np.full(N_TRAJ, 635.0) + colpito = np.full(N_TRAJ, -1, int) + carry = np.zeros((N_TRAJ, TX.CARRY_ANNI)) + anno0 = cap.copy() + flusso = np.zeros(N_TRAJ) + for t in range(10 * 365): + cap *= (1.0 + paths[:, t]) + if t % 30 == 0 and t > 0: + vivo = colpito < 0 + cap += dep + flusso += dep + versato += dep * vivo # <- si ferma al traguardo + nuovi = (colpito < 0) & (cap >= l3["muro"]) + colpito[nuovi] = t + if (t + 1) % 365 == 0: + PN.passo_fiscale(cap, anno0, flusso, carry, l3["aliq"], l3["patr"]) + anno0 = cap.copy() + flusso[:] = 0.0 + arr = colpito >= 0 + tot_pieno = 635.0 + 121 * dep + tot_vero = float(versato[arr].mean()) if arr.any() else float("nan") + print(f" EUR{dep_m:.0f}/m, 10 anni: P(traguardo) {arr.mean():.1%}") + print(f" versato come lo conta l'ondata ${tot_pieno:,.0f} (=$229k pubblicato ✅)") + print(f" versato FINO all'arrivo, medio ${tot_vero:,.0f}" + f" -> i bonifici fanno il {tot_vero/l3['muro']:.0%}, non il 73%") + + print("\n (e) composizione ancora x funding: `deluck` e' applicato DOPO la sottrazione del") + print(" funding, quindi sconta dell'11% anche il funding (2,16% -> 1,92%).") + # ⚠️ ERRORE MIO CATTURATO IN SESSIONE: la prima stesura faceva `deluck(L0["r"])`, ma quella + # serie e' GIA' de-luckata -> 0,89^2 e un finto +31,5% sul muro. Qui si parte dal GREZZO. + A = L["_raw_nofund"] + alt = deluck(A) - 0.021597 / 365.0 + p_alt = perpetua(alt, l3["aliq"], l3["patr"]) + print(f" ordine dell'ondata : drift {l3['r'].mean()*365:.2%} -> muro ${l3['muro']:,.0f}") + print(f" ordine alternativo : drift {alt.mean()*365:.2%} -> muro ${PREL_NET/p_alt:,.0f}" + f" ({PREL_NET/p_alt/l3['muro']-1:+.1%})") + print(" Scelta di modello, non errore — ma la sua taglia (+4,0% sul muro) e' SEI VOLTE") + print(" la risoluzione MC (0,7%) che l'ondata dichiara accanto allo stesso numero.") + print(" ⚠️ ERRORE MIO catturato prima di pubblicare: la prima stesura de-luckava una") + print(" serie GIA' de-luckata (0,89^2) e stampava +31,5%. Il controllo che l'ha preso") + print(" e' stato guardare il DRIFT stampato accanto al muro, non il muro.") + + +# ============================================================================================= +# 6) IL LIBRO MASTRO — la risposta al mandato, in una sola unita' +# ============================================================================================= +def sezione_ledger(L: dict) -> None: + sez("6) IL MANDATO ERA «ARRIVARE AI 50 GIORNALIERI VELOCEMENTE». Tutto in una sola unita'.") + E = 635.0 + l3 = L["L3 CONGIUNTA (§36)"] + + def eur_g(drift_pp: float) -> float: + """pp di drift annuo -> EUR/giorno di reddito atteso a $635, al netto del fisco.""" + return drift_pp / 100.0 * E * (1 - CC.TAX_RATE) / 365.0 / CC.EURUSD + + righe = [ + ("VERSARE EUR250 -> EUR500 al mese", "leva del PIANO", None, "P(20a) 14% -> 85%", "SI'"), + ("gradino di leva 1,25x (§33/§38/§53)", "politica", 21.39 - 17.11, + "+1,8a (muro congelato) / +3,0a (mobile)", "NO — knob inesistente + GATE SCALA-01"), + ("lead SPOT su TP01 (§39/§45/§52)", "strumento", 1.55, + "muro -10,9% a $600, 0% a $272k", "NO — domanda fiscale aperta"), + ("PREVDAY al 15% (§50/§54)", "sleeve nuovo", 1.31, + "dShFULL +0,100 de-luckato", "NO — GATE PREVDAY-01 al 2027-06-21"), + ("XS01 su conto funded (§21/§29/§37)", "canale", None, + "P(>=50/g) 2,6% [1,5-4,7] in 36 mesi", "gate PASS 3/3, spesa = 91% del conto"), + ("BIN-FREQ su SKH01 (§25)", "size", None, "EUR0,0113/giorno", "NO — 3 gate su 4 FAIL"), + ("VOL-SIZE su SKH01 (§8)", "size", None, "+0,070 Sh, gate 22/12 gia' fallito", "NO"), + ("MAKER (§22)", "esecuzione", 0.466, "tetto $2,96/anno, IC contiene lo 0", "NO"), + ("--- COSTI SCOPERTI (segno opposto) ---", "", None, "", ""), + ("funding dei perpetual (§35)", "costo", -2.16, "muro +17,5%", "gia' subito"), + ("i 4 monitor rotti (§31)", "integrita'", None, "STATARB Sharpe +1,96 -> -2,02", "da riparare"), + ("il notifier senza retry (NOTIFIER)", "sicurezza", None, "~7% degli allarmi persi", "da riparare"), + ] + print(f" {'cosa':<40}{'tipo':<12}{'EUR/giorno a $635':>19} effetto / stato") + for nome, tipo, dpp, eff, stato in righe: + if nome.startswith("---"): + print(f"\n {nome}") + continue + cell = f"{eur_g(dpp):+.4f}" if dpp is not None else " — " + print(f" {nome:<40}{tipo:<12}{cell:>19} {eff}") + if stato: + print(f" {'':<40}{'':<12}{'':>19} eseguibile oggi: {stato}") + + print("\n 📌 IL CONFRONTO, con la stessa macchina e gli stessi percorsi:") + rng = np.random.default_rng(SEED) + paths = CC._boot_paths(l3["r"], N_TRAJ, 25 * 365, BLOCK, rng) + for dep in (0, 250, 500): + a = PN.accumula(paths, dep, l3["muro"], l3["aliq"], l3["patr"], start=635.0) + y = np.where(a["colpito"] >= 0, a["colpito"] / 365.0, np.inf) + med = np.median(y) + print(f" EUR{dep:>4}/mese -> mediana {'>25a' if not np.isfinite(med) else f'{med:.1f}a'}" + f" P(20a) {float((y<=20).mean()):5.1%}") + tot = sum(eur_g(x) for x in (1.55, 1.31, 0.466)) + print(f"\n Somma di TUTTI i lead positivi dell'ondata, se fossero tutti autorizzati e") + print(f" tutti additivi (non lo sono, e nessuno lo e' oggi): {tot:+.3f} EUR/giorno.") + print(f" Il gradino di leva da solo, se il knob esistesse: {eur_g(21.39-17.11):+.3f} EUR/g.") + print(f" Un versamento di EUR500/mese e' {500/30.44:+.2f} EUR/giorno di CASSA — e le due") + print(" grandezze NON sono la stessa cosa (una e' rendimento, l'altra e' capitale che") + print(" entra). Il confronto onesto e' quello sopra, sulla stessa macchina e sugli") + print(" STESSI percorsi: EUR250 -> EUR500 al mese porta P(20a) dal 14% all'85% e la") + print(" mediana da 23,4 a 17,3 anni; la somma di tutti i lead dell'ondata, se fossero") + print(" autorizzati e additivi, vale +0,036 EUR/giorno su un conto da $635, cioe' meno") + print(" dell'incertezza Monte Carlo della riga sopra.") + print("\n 🚨 RISPOSTA AL MANDATO: NO. L'ondata non ha prodotto NIENTE che avvicini i 50 EUR/g.") + print(" Ha prodotto (i) un COSTO gia' in essere che porta P(20a) a EUR250/mese dal 49%") + print(" al 14% (il funding, §35/§36), (ii) quattro monitor rotti che avrebbero fatto") + print(" decidere un gate") + print(" al contrario, (iii) un punto singolo di guasto nella rete di sicurezza,") + print(" (iv) tre lead reali ma tutti bloccati da qualcosa che NON e' la ricerca.") + print(" Il suo valore e' DIFENSIVO, ed e' reale: ha impedito decisioni sbagliate.") + print(" Ma la domanda che era stata posta ha risposta negativa, e la 56ª ondata") + print(" avra' la stessa risposta della 55ª.") + + +# ============================================================================================= +# 7) LE TRE COSE CHE, SE SCRITTE COME LE HO CAPITE IO, SARANNO SBAGLIATE +# ============================================================================================= +def sezione_tre() -> None: + sez("7) LE TRE COSE CHE, SE SCRITTE IN CLAUDE.md COME SONO STATE CAPITE, SARANNO SBAGLIATE") + print(""" + (1) «IL MURO E' $313k» — e' una MEDIANA, non un numero, e la sua banda non e' mai stata + pubblicata. + CLAUDE.md sta per ereditare $313k, «EUR250/mese -> P(20a) 14%» e «EUR1.733/mese per + 10 anni» come se il drift fosse noto. Misurato in sez. 2: propagando SOLO la SE del + drift (5,15%/anno, block bootstrap — e §53 la misura 5,09 su un'altra lente) il muro + va da $204k (+1 SE) a $707k (-1 SE), a p10 supera $1,1M e a -2 SE il traguardo NON + ESISTE a nessun capitale. La riga «EUR500/mese -> P(20a) 85%» diventa ~0% a -1 SE. + Il meccanismo e' strutturale: il muro e' `prelievo / perpetua` e la perpetua si + ANNULLA molto prima del drift -> e' un 1/x su una quantita' che va a zero, quindi + l'errore e' asimmetrico verso l'alto. + 🚨 E l'ondata ha pubblicato la risoluzione MONTE CARLO del muro (0,7%) accanto a un + numero la cui incertezza di PARAMETRO e' cento volte piu' grande: ha misurato la + precisione del simulatore e mai quella del suo input. + DA SCRIVERE: «$313k e' la MEDIANA; a -1 SE di drift e' ~$707k e a -2 SE il traguardo + non esiste. Il piano si dimensiona sul VERSAMENTO, che e' certo, non sul muro.» + + (2) «POSITIVO IN 24/24 ANCORE» / «10/10 FASI» — non sono 24 ne' 10 osservazioni. + Misurato in sez. 3 su serie vere e con controllo positivo (24 serie indipendenti -> + N_eff 24,5; 24 identiche -> 1,00): le 24 ancore di TP01 hanno corr media 0,63 -> + N_eff ~1,6-2,1; le 10 fasi di XS01 corr 0,79 -> N_eff ~1,2-1,5. E la componente + comune NON si cancella nella DIFFERENZA APPAIATA (corr 0,59, N_eff 1,6-2,2): era la + mia attesa A3 ed e' REFUTATA. + 🚨 Conseguenza diretta: la «banda» che accompagna ogni Δ dell'ondata e' la banda + d'ANCORA, e per la stessa grandezza (§42) l'IC95 bootstrap e' 4,3x piu' largo + ([-0,81, +0,05] contro [-0,45, -0,25]) e CONTIENE LO ZERO. Chi legge fra sei mesi + leggera' quella banda come un intervallo di confidenza — perche' ne ha la forma. + E dove l'ondata ci attacca un p-value (§26: «12/12, p=0,0005», su finestre 30g + sovrapposte e selezionate come le peggiori) il p-value non e' calcolabile cosi'. + DA SCRIVERE: «N/N ancore = robustezza alla scelta dell'ancora, ~2 osservazioni + indipendenti; la banda d'ancora NON e' un IC ed e' ~4x piu' stretta.» + ⚠️ Cio' che questo NON dice: che i verdetti cadano. §42 resta SCARTATO (iso-vol FAIL + 3/3, maxDD +8,8pp, selection-on-holdout, edge lordo assente). Cade la PRECISIONE dei + numeri, non la direzione delle decisioni. + + (3) «IL GRADINO DI LEVA VALE 14,7a -> 12,9-11,6a, ~EUR300/mese» — meta' di quella frase + e' gia' morta nell'ondata stessa. + §53 ha misurato che il **1,50x NON sopravvive** (peggior giorno strutturale 21,48%, + sopra la soglia 20%, e al 90% del tetto G6) e che il **k massimo difendibile e' + 1,40**. Il «~EUR300/mese» e' del 1,50x. Il 1,25x vale **+EUR144/mese misurati + direttamente**, non EUR164, e **+1,8 anni a muro CONGELATO / +3,0 a muro MOBILE** — + una differenza di 1,2 anni fra due convenzioni che §33 non dichiarava. + ✅ L'aritmetica dei tetti l'ho verificata sul config che gira (sez. 5a): 1,67 / 3,49 / + 1,40 tornano tutti e tre al centesimo. Non e' quella il problema: e' che CLAUDE.md + porta ancora la riga «1,25-1,50x» come se fossero due opzioni vive. + DA SCRIVERE: «gradino 1,25x; k max difendibile 1,40; il 1,50x e' BOCCIATO. Guadagno + +1,8a (muro congelato) / +3,0a (mobile) — la convenzione va sempre detta.» + + ⚠️ BONUS 1 — «lo SPOT vale +1,55-1,66%/anno». Vale quello SOLO a $600. §52 ha camminato + entrambi i libri: il differenziale spot-perp passa da +0,72 bps a $600 a +25,66 bps a + $272k -> **-0,11%/anno alla taglia del muro**. Il lead si annulla esattamente dove + pretendeva di servire. Numero onesto: «+1,38-1,58%/anno a $600, ~0 a $272k», e sotto, + la domanda fiscale (~0,83%/anno = piu' di meta' del lead) che nessun backtest chiude. + + ⚠️ BONUS 2 — «PREVDAY e' il piu' forte misurato, +0,192 FULL / +0,363 HOLD». De-luckato + (§54) e' +0,100 / +0,246; la cella che GIRA fallisce il deflated-Sharpe (0,905) mentre + quella scelta al buio lo passa (0,993) ma e' un'ALTRA strategia (4h, long-flat) che + butta via la gamba short per cui PREVDAY fu promosso; e il «forward +2,04» e' su lente + ORARIA (su lente giornaliera +1,56, 63 giorni, MDE 4,7). + + ⚠️ BONUS 3 — «il libro 75/25 fa ShFULL 1,8». Ne fa TRE (sez. 4bis-A, misurate): 1,68 + (`hourly`, la lente di tutti i muri e le traiettorie), 1,80 (`canonical`, la lente di + §41/§42/§49/§50/§54) e 1,63 (mediana d'ancora, §8/§25). Lo spread, 0,12 di Sharpe e + 1,7pp di maxDD, e' PIU' GRANDE di quasi tutti gli effetti che l'ondata misura: un Δ + accostato al baseline sbagliato cambia piu' del Δ. Ogni numero di libro va scritto con + la sua lente attaccata. + + ⚠️ BONUS 4 — «il soffitto direzionale e' ~1,15». Nella stessa ondata §23 pubblica 1,639 e + §54 pubblica 1,621, stessa coppia, stessa lente netta-fee. «Soffitto» sta per tre cose + diverse e il registro usa la piu' bassa citandola come la piu' alta — e su quella + poggia l'argomento aritmetico di §12, che si inverte (seconda refutazione indipendente + dopo quella di §24). +""") + + +def main() -> None: + print("=" * 102) + print(" r0823 — CRITICO DI CHIUSURA dell'ondata 2026-08-22/23") + print("=" * 102) + print(__doc__.split("=====")[2].strip()[:1800]) + if not CACHE.exists(): + print(f"\n ⚠️ manca la cache {CACHE}; rigenerala con " + f"`uv run python scripts/research/r0822d_piano_vero.py --rebuild`") + sys.exit(2) + B = pd.read_parquet(CACHE) + L = sezione_repliche(B) + sezione_muro(L) + sezione_ancore() + sezione_mde() + sezione_contraddizioni() + sezione_aritmetica(L) + sezione_ledger(L) + sezione_tre() + print(f"\n[{time.time() - T0:.0f}s] fine. Sola lettura: nessun file di produzione toccato.") + + +if __name__ == "__main__": + main()