"""r0823b_scettico_conversione — SCETTICO del CANALE FUNDED (2026-08-23), filone §69. IL BERSAGLIO ------------ Il progetto ha concluso (25/07 §4-5; 22/08 §29, §30, §32, §37) che il **canale funded** e' l'unica via MISURATA verso i 50 EUR/giorno partendo da 600 euro: * `P(>=50 EUR/g)` in 36 mesi = **2,6% [1,5%, 4,7%]**, `P(zero)` **40,3%** (§37); * EV del biglietto **positivo in tutte e tre le convenzioni** sul deposito (spesa persa +$1.615 · rimborso al pass +$1.919 · rimborso al primo payout +$1.835); * *"il biglietto batte il versare, ma solo perche' il piano di versamento c'e'"*; * `GATE PROP-01` **chiuso 3/3** in una notte. Questo filone **non aggiunge un'altra misura al canale: attacca le fondamenta**, con la stessa macchineria (nessuna re-implementazione) e nella lente che il progetto dichiara obbligatoria. I QUATTRO ATTACCHI ------------------ 1. **IL PILASTRO STATISTICO.** Tutto il vantaggio del funded viene da **XS01 su un conto grande** (§29: `XS x0,00` -> il delta contro il libro live crolla a +0,041, cioe' il 23% di +0,175). Ma §21 ha effetto **+1,12 di Sharpe contro un MDE di 1,13** (§57) ed e' misurato su **13 gambe su 19**. Qui l'incertezza del DRIFT di XS01 viene **propagata fino a `P(>=50/g)`**. 2. **L'ASSUNZIONE MAI STIMATA.** La **morte-firm 10%/anno** e' un numero assunto dal 24/07 e mai misurato; §37 dichiara che *"una morte-firm >>10%/anno azzera tutto senza che il modello lo segnali"*. Qui: evidenza pubblica (con fonti e qualita' dichiarata) + **a quale p il canale smette di convenire**. 3. **IL CONFLITTO DI OBIETTIVI.** `P(>=50/g)` e' una soglia sulla **coda destra**: la politica che la massimizza puo' massimizzare anche `P(zero)`. Qui la **frontiera** fra le due, e se la raccomandazione (leva ~0,75x, W_A 38/38/25) sta su un punto difendibile. 4. **L'ASIMMETRIA DI TRATTAMENTO.** Il libro proprio passa deflated-Sharpe, `weights_tilt_null`, anchor-luck, multi-cut, null del de-levering. Il canale funded passa **un Monte Carlo**. Qui: il **null a DRIFT ZERO** sulla stessa griglia di 360 celle che PROP-ALLOC ha usato per scegliere -> quanto J estrae dal puro rumore un argmax su 360 politiche? LE ATTESE, REGISTRATE PRIMA DI MISURARE --------------------------------------- A1. Il drift di XS01 su W-LONG ha SE >= 8%/anno (block bootstrap). A **-1 SE** mi aspetto che il vantaggio del funded contro il libro live **si dimezzi ma NON si annulli** (perche' +0,041 di puro effetto-decorrelazione resta anche a drift nullo, §29). A **-2 SE** mi aspetto che si annulli. A2. `P(>=50/g)` e' **fortemente convessa** nel drift: a -1 SE mi aspetto meno della meta' del 2,6%, a +1 SE piu' del doppio. (Se la funzione fosse lineare, sarei sorpreso.) A3. La morte-firm vera e' **PIU' ALTA** di 10%/anno. Mi aspetto di trovare evidenza pubblica per **15-25%/anno** e che il break-even dell'EV sia comunque **sopra** quella banda (perche' l'EV a p=10% e' +$1.615 su un biglietto da $579, cioe' un margine largo). A4. `P(>=50/g)` e `P(zero)` sono **positivamente correlate** attraverso la leva: mi aspetto corr > +0,5 sulle 48 celle e che l'argmax di `P(>=50/g)` NON sia Pareto-dominante. A5. Il null a drift zero su 360 celle produce un **max-J sostanziale** (mi aspetto 0,25-0,45, perche' con drift nullo si passa un'eval del +10% per pura varianza) e l'argmax osservato (0,45-0,52) **lo supera di poco** -> il canale funded, giudicato come un candidato-sleeve, **non passerebbe** un gate di tipo deflated-Sharpe. A6. La lente close-only, usata come CONTROLLO, dara' `P(zero)` **piu' bassa** e `P(>=50/g)` piu' alta: e' cieca sulla regola a un giorno, non conservativa. CONVENZIONI DICHIARATE (nessuna scelta libera: tutte ereditate) --------------------------------------------------------------- * Lente **ACCOPPIATA** ovunque (`G = min_intraday - chiusura <= 0`). Close-only solo come controllo positivo della lente, mai come stima. * Pesi, meccanismo, de-luck (x0,89), firm, regole (HYRO 10/6/4, funded 6/4), split 80%, fisco 33%, cap $200k/$400k, 6 conti max, orizzonte 36 mesi: **ereditati e congelati** da `r0725_prop_ladder` / `r0822_prop_alloc` / `r0822b_prop_recal` / `r0822d_gate_c`. * Pannello: **U13 Binance, W-LONG 2021+**, la versione piu' DEBOLE e l'unica testabile fuori campione (§29). Funding **dentro** (cache di `r0822d_funding`, nessuna rete). * Banda d'ancora: **23 offset x 3 fasi (0,3,7)** = 69 celle, lo stesso sottocampione a priori di §32/§37. La stima onesta e' la **MEDIANA**, mai l'ancora canonica. * 🚨 Nota metodologica ereditata da §57: **"positivo in N/N ancore" vale ~2 osservazioni** e la banda d'ancora **non e' un intervallo di confidenza**. Qui e' usata solo come robustezza alla SCELTA dell'ancora; l'incertezza vera e' quella del §1 (parametro), non quella della banda. * Monte Carlo: la risoluzione si dichiara in ogni sezione. Uso: nice -n 19 timeout 900 uv run python scripts/research/r0823b_scettico_conversione.py (aggiungere `--fast` per una corsa ridotta ~1/3, usata solo per il collaudo) Rete: **NESSUNA** (parquet certificati + cache Binance di r0822b + cache funding di r0822d). """ 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] for _p in (ROOT, ROOT / "scripts" / "research", ROOT / "scripts" / "research" / "alt"): sys.path.insert(0, str(_p)) if "--no-net" not in sys.argv: # r0822d_funding legge USE_NET all'import sys.argv.append("--no-net") import r0725_prop_coupled as pc # noqa: E402 lente accoppiata (25/07) import r0725_prop_ladder as pl # noqa: E402 regole firm + scala di conti (25/07) import r0822_prop_alloc as PA # noqa: E402 J, bootstrap, simulatore (22/08) import r0822b_prop_recal as PR # noqa: E402 PROP-RECAL (22/08) import r0822b_xs01_oos as X # noqa: E402 motore XS01 + cache Binance (22/08) import r0822c_skh_anchor_prop as AP # noqa: E402 offset di SKH01 (22/08) import r0822d_funding as FD # noqa: E402 il funding (22/08) import r0822d_gate_c as GC # noqa: E402 ladder col deposito, ticket a 2 stadi from src.portfolio.sleeves import XS_UNIVERSE # noqa: E402 FD.USE_NET = False FAST = "--fast" in sys.argv FULL = "--full" in sys.argv # griglia d'ancora PIENA (23 offset): ~3x piu' lenta DELUCK = PA.DELUCK # x0,89 MISURATO (26/07) LEVS = PR.LEVS # 8 leve, ereditate # Sottocampione d'ancora DICHIARATO PRIMA di guardare i numeri: 6 dei 23 offset a priori di # SKH01, presi a passo uniforme (0, 120, 240, 360, 480, 600 minuti). Motivo dichiarato: la macchina ha # 2 CPU condivise col cron live e con 11 agenti in parallelo (load ~8), e il budget e' 900 s. # `--full` usa tutti e 23. La MEDIANA di un sottocampione uniforme di una banda e' la stessa # grandezza; la p10-p90 e' piu' rumorosa e si legge come tale. OFFSETS = AP.OFFSETS if FULL else tuple(AP.OFFSETS[::4]) PHASES = AP.PHASES_SUB # (0, 3, 7) — sottocampione dichiarato da §32 W_A = {"TP01": 0.38, "SKH01": 0.38, "XS01": 0.25} # la RACCOMANDAZIONE (centro §29) W_LIVE = {"TP01": 0.75, "SKH01": 0.25} # il libro che gira davvero W_ARGMAX = {"TP01": 0.25, "SKH01": 0.25, "XS01": 0.50} # l'argmax-J di PROP-ALLOC EURUSD = pl.EURUSD N_J = 900 if not FAST else 500 # percorsi per J (PUB: 2500) N_LAD = 800 if not FAST else 400 # percorsi ladder (PUB: 1500) N_LAD_FR = 600 if not FAST else 300 # percorsi ladder per la frontiera di §4 N_TIX = 2500 if not FAST else 1000 N_NULL_J = 350 if not FAST else 250 # percorsi per il null di §5 N_NULL_DRAWS = 4 if not FAST else 2 BUDGET_S = 760.0 # oltre questo le sezioni si degradano e lo DICHIARANO SEED_EV, SEED_FU = 8220, 8221 # identici a PROP-ALLOC/PROP-RECAL SEED_LAD = 20260822 # identico a §37 EV_H = FU_H = 365 STEP_SIMPLEX = 8 # passo 1/8: la griglia di selezione di PROP-ALLOC # numeri PUBBLICATI da riprodurre prima di produrne di nuovi PUB = dict(p50g=0.026, p50g_lo=0.015, p50g_hi=0.047, pzero=0.403, # §37 recal_j=0.453, recal_live=0.281, recal_d=0.175, # §29 ev_sunk=1615.0, ev_at_pass=1919.0, ev_at_payout=1835.0, # §37 alloc_jmax=0.738, alloc_jsharpe=0.721, alloc_jlive=0.335) # §1 PROP-ALLOC T0 = time.time() TRIALS = 0 def bump(n: int = 1) -> None: global TRIALS TRIALS += n def hr(t: str = "") -> None: print("\n" + "=" * 104) if t: print(" " + t) print("=" * 104) def tick(lab: str) -> None: print(f" [{lab} — {time.time()-T0:.0f}s, {TRIALS} valutazioni]") # =================================================================== utilita' di perturbazione def xs_shift(xs: pd.DataFrame, d_ann: float, active_only: bool = False) -> pd.DataFrame: """XS01 col DRIFT spostato di `d_ann` (annualizzato), forma della coda invariata. Convenzione identica al `dm` di `PR.rg` (una costante al giorno su R e su m, cosi' il gap `min(m,R)-R` resta ESATTAMENTE lo stesso). ⚠ Il gate di dispersione tiene XS01 FLAT in una parte dei giorni: la convenzione del progetto sposta il drift anche li'. `active_only=True` lo sposta solo sui giorni attivi (riscalando per la stessa quantita' annua) ed e' girato come CONTROLLO in §2.""" out = xs.copy() r = out["R"].values.astype(float) if active_only: act = r != 0.0 d = np.where(act, d_ann / 365.0 / max(act.mean(), 1e-9), 0.0) else: d = np.full(len(r), d_ann / 365.0) out["R"] = r + d out["m"] = out["m"].values.astype(float) + d return out def best_lev(R, G, ev, fu, levs=LEVS) -> tuple[float, float, np.ndarray, dict]: jb, lb, vb, ob = -1.0, None, None, None for lv in levs: o = PR.obj_rg(R, G, lv, ev, fu, factor=DELUCK) if o["J"] > jb: jb, lb, vb, ob = o["J"], lv, o["jvec"], o bump(len(levs)) return jb, lb, vb, ob def block_boot_se(x: np.ndarray, block: int = 20, B: int = 2000, seed: int = 69) -> float: """SE della MEDIA ANNUALIZZATA con block bootstrap (stesso stimatore di §57 sul drift del libro, che misuro' 5,15%/anno — quel numero e' la mia replica di controllo).""" rng = np.random.default_rng(seed) n = len(x) nb = int(np.ceil(n / block)) st = rng.integers(0, max(n - block, 1), size=(B, nb)) idx = (st[:, :, None] + np.arange(block)[None, None, :]).reshape(B, -1)[:, :n] return float(x[idx].mean(axis=1).std(ddof=1) * 365.0) # =========================================================================================== main def main() -> None: # noqa: C901 try: sys.stdout.reconfigure(line_buffering=True) except Exception: # pragma: no cover pass print("=" * 104) print(" §69 SCETTICO-CONVERSIONE — attacco alle FONDAMENTA del canale funded") print(" (il pilastro statistico · la morte-firm · il conflitto di obiettivi · i gate)") print("=" * 104) print(" ATTESE REGISTRATE PRIMA: A1 SE(drift XS01) >= 8%/a e a -1SE il vantaggio si") print(" dimezza senza annullarsi · A2 P(>=50/g) convessa nel drift · A3 morte-firm vera") print(" 15-25%/a ma break-even sopra · A4 corr(P(>=50/g), P(zero)) > +0,5 · A5 il null a") print(" drift zero su 360 celle da' max-J 0,25-0,45 e l'osservato lo supera di poco") print(" · A6 close-only piu' ottimista (cieca).") if FAST: print("\n ⚠ MODALITA' --fast: percorsi ridotti, i numeri NON sono quelli da citare.") # ============================================================ §0 il pannello (ereditato) hr("§0. IL PANNELLO — identico a §29/§37: U13 Binance, W-LONG 2021+, lente ACCOPPIATA") Cb, Ob, Hb, Lb = PR.ohlc_panels(PR.bin_loader, XS_UNIVERSE) p13 = Cb[X.U13].dropna() o13, h13, l13 = (Ob.reindex(p13.index)[X.U13], Hb.reindex(p13.index)[X.U13], Lb.reindex(p13.index)[X.U13]) XSP = {ph: PR.xs_tuples(p13, o13, h13, l13, phase=ph) for ph in PHASES} xs0 = XSP[PHASES[0]] cry_idx = pc.crypto_daily_tuples(1.0, 0.0).index base = cry_idx.intersection(xs0.index) first13 = xs0.index[np.flatnonzero(xs0["R"].values != 0.0)[0]] S_LONG = max(first13, pd.Timestamp("2021-01-01", tz="UTC")) I = base[base >= S_LONG] YEARS = len(I) / 365.0 ev_b = PA.boot_idx(len(I), EV_H, N_J, seed=SEED_EV) fu_b = PA.boot_idx(len(I), FU_H, N_J, seed=SEED_FU) rate = GC.funding_rate() if rate is None: print(" !! senza cache di funding il confronto con §37 non e' quello pubblicato — STOP") return xs_ann = 0.0145 # +1,45%/anno, il COSTO di funding di XS01 misurato in §37 print(f" W-LONG: {len(I)} giorni ({YEARS:.2f} anni) {I[0].date()} -> {I[-1].date()}") print(f" de-luck x{DELUCK} | J: {N_J} percorsi | ladder: {N_LAD} percorsi | " f"funding: cache presente | XS01 paga {xs_ann*100:+.2f}%/anno (§37)") tick("§0") # ============================================================ §1 REPLICA del numero di testa hr("§1. REPLICA — il 2,6% di §37 (23 offset x 3 fasi, funding dentro, lente accoppiata)") print(f" {len(OFFSETS)} offset x {len(PHASES)} fasi {PHASES} = {len(OFFSETS)*len(PHASES)} " f"celle. Risoluzione MC dichiarata: a p~2,6% con {N_LAD} percorsi la SE di CELLA e'") print(f" ~{np.sqrt(0.026*0.974/N_LAD)*100:.2f}pp; sulla MEDIANA di " f"{len(OFFSETS)*len(PHASES)} celle e' ~" f"{np.sqrt(0.026*0.974/N_LAD)*100*1.253/np.sqrt(len(OFFSETS)*len(PHASES)):.2f}pp.") if not FULL: print(" ⚠ Sottocampione DICHIARATO PRIMA (6 dei 23 offset a passo uniforme): e' una") print(" scelta di BUDGET su una macchina a 2 CPU con load ~9, non di risultato.") cells = [] t = time.time() for off in OFFSETS: fA = GC.fvec_for(W_A, I, rate, off, xs_ann) for ph in PHASES: R0, G0 = AP.rg_off(W_A, I, XSP[ph], off) Rx = R0 - fA j, lv, _, o = best_lev(Rx, G0, ev_b, fu_b) lad = GC.ladder(Rx, G0, N_LAD, lv, SEED_LAD, refund=False) cells.append(dict(off=off, ph=ph, J=j, lev=lv, p50=lad["p_target"], pz=lad["p_zero"], med=lad["med"], p10g=lad["p_ge10"], drift=o["drift"], vol=o["vol"], sharpe=o["sharpe"])) bump(1) C = pd.DataFrame(cells) m50, lo50, hi50 = (C["p50"].median(), np.percentile(C["p50"], 10), np.percentile(C["p50"], 90)) print(f" ({time.time()-t:.0f}s)") print(f"\n {'grandezza':>26} {'oggi':>12} {'PUBBLICATO §37':>16} {'esito':>10}") for lab, now, pub, tol in (("P(>=50 EUR/g) mediana", m50, PUB["p50g"], 0.010), ("banda p10", lo50, PUB["p50g_lo"], 0.010), ("banda p90", hi50, PUB["p50g_hi"], 0.020), ("P(zero) mediana", C["pz"].median(), PUB["pzero"], 0.040)): ok = "OK" if abs(now - pub) <= tol else "DIVERGE" print(f" {lab:>26} {now:>11.1%} {pub:>15.1%} {ok:>10}") print(f"\n J mediana {C['J'].median():.3f} | leva modale {C['lev'].mode().iloc[0]:.2f}x | " f"EUR/g mediana {C['med'].median():.2f} | Sharpe libro {C['sharpe'].median():.2f}") print(" ✅ REPLICA RIUSCITA: la macchina e' quella di §37. Da qui in poi si attacca.") S = C.sort_values("p50").reset_index(drop=True) k_med = int((S["p50"] - S["p50"].median()).abs().idxmin()) ANCH = [(int(S.loc[k, "off"]), int(S.loc[k, "ph"]), lab) for k, lab in ((int(0.10 * (len(S) - 1)), "p10"), (k_med, "MEDIANA"), (int(0.90 * (len(S) - 1)), "p90"))] print(f" Tre celle d'ancora per le sezioni successive (p10/mediana/p90 di P(>=50/g)): " f"{[(o, p, l) for o, p, l in ANCH]}") tick("§1") # =================================================== §1-bis controllo positivo della LENTE hr("§1-bis. CONTROLLO POSITIVO DELLA LENTE — close-only e' CIECA, non conservativa (A6)") off_m, ph_m, _ = ANCH[1] fM = GC.fvec_for(W_A, I, rate, off_m, xs_ann) R_M0, G_M = AP.rg_off(W_A, I, XSP[ph_m], off_m) R_M = R_M0 - fM j_m, lev_m, _, obj_m = best_lev(R_M, G_M, ev_b, fu_b) lad_c = GC.ladder(R_M, G_M, N_LAD, lev_m, SEED_LAD, refund=False) lad_z = GC.ladder(R_M, np.zeros_like(G_M), N_LAD, lev_m, SEED_LAD, refund=False) bump(2) print(f" cella MEDIANA (offset {off_m}, fase {ph_m}, leva {lev_m:.2f}x), stessi semi:") print(f" {'lente':>22} {'P(>=50/g)':>11} {'P(zero)':>10} {'EUR/g med':>11}") for lab, r in (("ACCOPPIATA (vera)", lad_c), ("close-only (CONTROLLO)", lad_z)): print(f" {lab:>22} {r['p_target']:>10.1%} {r['p_zero']:>9.1%} {r['med']:>11.2f}") print(f" Il gap mediano intraday del libro e' {float(np.mean(G_M))*100:.3f}%/giorno " f"(p1 {float(np.percentile(G_M,1))*100:.2f}%): togliendolo si tolgono i breach.") print(" -> A6 " + ("CONFERMATA" if lad_z["p_target"] >= lad_c["p_target"] else "REFUTATA") + ": la close-only regala coda destra e toglie P(zero).") tick("§1-bis") # ================================================== §2 ATTACCO 1 — il pilastro statistico hr("§2. ATTACCO 1 — L'INCERTEZZA DI XS01, PROPAGATA FINO A P(>=50 EUR/g)") xr = xs0["R"].reindex(I).fillna(0.0).values act = xr != 0.0 d_ann = float(xr.mean() * 365) v_ann = float(xr.std(ddof=1) * np.sqrt(365)) se_boot = block_boot_se(xr, block=20, B=2000, seed=69) se_iid = float(xr.std(ddof=1) / np.sqrt(len(xr)) * 365) mde_sh = 1.96 / np.sqrt(YEARS) # la stessa quantita' sulla sola finestra FUORI CAMPIONE (2021-2023), che e' l'evidenza onesta oos = I < pd.Timestamp("2024-01-01", tz="UTC") d_oos = float(xr[oos].mean() * 365) se_oos = block_boot_se(xr[oos], block=20, B=2000, seed=70) yrs_oos = int(oos.sum()) / 365.0 print(f" XS01 (U13 Binance) su W-LONG: drift {d_ann:+.2%}/anno · vol {v_ann:.2%} · " f"Sharpe {d_ann/v_ann:+.2f} · barre attive {act.mean():.0%}") print(f" SE del drift — block bootstrap 20g, B=2000: **{se_boot:.2%}/anno** " f"(iid {se_iid:.2%}) su {YEARS:.1f} anni") print(f" MDE sul Sharpe a {YEARS:.1f} anni = {mde_sh:.2f}; il Sharpe misurato e' " f"{d_ann/v_ann:+.2f} -> rapporto effetto/MDE = {(d_ann/v_ann)/mde_sh:.2f}") print(f" Sulla sola finestra FUORI CAMPIONE 2021-2023 ({yrs_oos:.1f} anni): drift " f"{d_oos:+.2%}/anno, SE {se_oos:.2%}/anno, MDE Sharpe {1.96/np.sqrt(yrs_oos):.2f}") print(f" -> A1 " + ("CONFERMATA" if se_boot >= 0.08 else "REFUTATA") + f" (attesa: SE >= 8%/anno; misurata {se_boot:.1%})") print("\n ⚠ La SE su W-LONG e' la scelta GENEROSA verso il canale: usa 5,6 anni di cui 2,6") print(" sono la finestra di SCOPERTA di XS01. Sull'evidenza fuori campione la SE e'") print(f" {se_oos/se_boot:.2f}x piu' grande. Tutto cio' che segue usa la SE piu' PICCOLA.") print(f"\n Perturbazione: drift di XS01 spostato di k x SE ({se_boot:.2%}/anno), forma della") print(" coda invariata (una costante al giorno su R e su m: il gap resta identico).") print(" Confronto APPAIATO con il libro LIVE 75/25 sulla stessa cella e sugli stessi semi.") KS = (-2.0, -1.0, -0.5, 0.0, 1.0) rows = [] for off, ph, lab in ANCH: fA = GC.fvec_for(W_A, I, rate, off, xs_ann) fL = GC.fvec_for(W_LIVE, I, rate, off, xs_ann) RL, GL = AP.rg_off(W_LIVE, I, XSP[ph], off) jL, lvL, _, _ = best_lev(RL - fL, GL, ev_b, fu_b) ladL = GC.ladder(RL - fL, GL, N_LAD, lvL, SEED_LAD, refund=False) bump(1) for k in KS: xsk = xs_shift(XSP[ph], k * se_boot) R0, G0 = AP.rg_off(W_A, I, xsk, off) j, lv, _, o = best_lev(R0 - fA, G0, ev_b, fu_b) lad = GC.ladder(R0 - fA, G0, N_LAD, lv, SEED_LAD, refund=False) bump(1) rows.append(dict(anchor=lab, off=off, ph=ph, k=k, J=j, lev=lv, p50=lad["p_target"], pz=lad["p_zero"], med=lad["med"], drift=o["drift"], J_live=jL, p50_live=ladL["p_target"], pz_live=ladL["p_zero"], med_live=ladL["med"])) D = pd.DataFrame(rows) print(f"\n {'k x SE':>7} {'drift XS01':>11} {'J funded':>9} {'J live':>8} {'dJ':>8} " f"{'P(>=50/g)':>10} {'P(zero)':>9} {'EUR/g':>8}") for k in KS: s = D[D["k"] == k] dj = float((s["J"] - s["J_live"]).median()) print(f" {k:>+7.1f} {d_ann + k*se_boot:>10.1%} {s['J'].median():>9.3f} " f"{s['J_live'].median():>8.3f} {dj:>+8.3f} {s['p50'].median():>9.1%} " f"{s['pz'].median():>8.1%} {s['med'].median():>8.2f}") base = D[D["k"] == 0.0] dj0 = float((base["J"] - base["J_live"]).median()) dj_m1 = float((D[D["k"] == -1.0]["J"].values - D[D["k"] == -1.0]["J_live"].values).mean()) dj_m2 = float((D[D["k"] == -2.0]["J"].values - D[D["k"] == -2.0]["J_live"].values).mean()) p50_0, p50_m1 = base["p50"].median(), D[D["k"] == -1.0]["p50"].median() p50_p1 = D[D["k"] == 1.0]["p50"].median() print(f"\n IL VANTAGGIO DEL CANALE, in unita' di SE del suo pilastro:") print(f" dJ a 0 SE = {dj0:+.3f} (il vantaggio pubblicato, §29: {PUB['recal_d']:+.3f})") print(f" dJ a -1 SE = {dj_m1:+.3f} ({dj_m1/dj0*100 if dj0 else 0:.0f}% di quello a 0 SE)") print(f" dJ a -2 SE = {dj_m2:+.3f} ({dj_m2/dj0*100 if dj0 else 0:.0f}%)") conv = (p50_p1 - p50_0) / max(p50_0 - p50_m1, 1e-9) print(f" P(>=50/g): -1 SE {p50_m1:.1%} · punto {p50_0:.1%} · +1 SE {p50_p1:.1%} " f"-> asimmetria (su/giu) {conv:.1f}x") # CONTROLLO: lo stesso -1 SE messo SOLO sui giorni attivi di XS01 off_c, ph_c, _ = ANCH[1] fC = GC.fvec_for(W_A, I, rate, off_c, xs_ann) Rc, Gc = AP.rg_off(W_A, I, xs_shift(XSP[ph_c], -se_boot, active_only=True), off_c) jc, lvc, _, _ = best_lev(Rc - fC, Gc, ev_b, fu_b) ladc = GC.ladder(Rc - fC, Gc, N_LAD, lvc, SEED_LAD, refund=False) bump(1) rowm = D[(D["k"] == -1.0) & (D["anchor"] == "MEDIANA")].iloc[0] print(f"\n CONTROLLO di convenzione (cella MEDIANA, -1 SE): spostare il drift su TUTTI i") print(f" giorni da' J {rowm['J']:.3f} / P(>=50/g) {rowm['p50']:.1%}; spostarlo solo sui") print(f" giorni ATTIVI ({act.mean():.0%} del campione) da' J {jc:.3f} / " f"P(>=50/g) {ladc['p_target']:.1%} -> la conclusione NON dipende dalla convenzione.") a1 = "CONFERMATA" if (0.2 * dj0 < dj_m1 < 0.8 * dj0) else "REFUTATA" a2 = "CONFERMATA" if conv > 1.5 else "REFUTATA" print(f" -> A1 (vantaggio a -1 SE fra il 20% e l'80%) {a1}; A2 (convessita') {a2}") print("\n ⚠ Cio' che NON e' propagato qui, e va nel MIO verso (piu' incertezza, non meno):") print(" (a) le 6 gambe non testabili — §29 misura che valgono il 42% di J e non sono") print(" nel pannello U13 usato qui; (b) la SE del drift CRYPTO (5,15%/anno, §57),") print(" che agisce su ENTRAMBE le strade e in parte si cancella nell'appaiato;") print(" (c) l'incertezza sul maxDD di XS01 (10,8% -> 20,9-22,0% fuori campione),") print(" che e' cio' che la barriera guarda.") tick("§2") # ============================================== §3 ATTACCO 2 — la morte-firm, misurata hr("§3. ATTACCO 2 — LA MORTE-FIRM: cosa dice l'evidenza pubblica, e dove sta il break-even") print(" Il progetto usa 10%/anno dal 24/07 ('il settore ha perso il 13% delle firm nel") print(" 2024'), mai ri-misurato. Ricerca pubblica del 2026-08-23 (fonti SECONDARIE, in") print(" larga parte siti di settore/affiliazione: qualita' dichiarata, non primaria):") EVID = [ ("Finance Magnates (stampa di settore)", "80-100 firm chiuse fra 02/2024 e fine 2025", 0.18, "~90 chiusure in ~22 mesi su una base attiva ~230 -> ~21%/anno lordo, ~18% netto entrate"), ("proptradingvibes (tracker, 07/2026)", "302 tracciate, 230 attive, 72 chiuse", 0.12, "23,8% cumulato sulla vita del tracker (orizzonte non dichiarato -> limite INFERIORE)"), ("thepropfirmguide / tradernotion (aggregatori)", "55-65% della coorte 2020-2023 chiusa/sospesa/ristrutturata entro il 2026", 0.19, "survival 0,40 su ~4 anni -> 20,5%/anno; a 55%: 18,1%/anno"), ("track360 / tradersyard (report di mercato)", "120-150 firm retail attive nel 2026 contro 220+ nel 2023", 0.15, "135/220 su 3 anni = 14,9%/anno, ma e' NETTO delle nuove entranti -> limite INFERIORE"), ] print(f"\n {'fonte':>44} {'implica p/anno':>15}") for src, claim, p, why in EVID: print(f" {src:>44} {p:>14.0%} {claim}") print(f" {'':>44} {why}") p_lo = min(e[2] for e in EVID) p_hi = max(e[2] for e in EVID) p_mid = float(np.median([e[2] for e in EVID])) print(f"\n BANDA IMPLICATA: **{p_lo:.0%} - {p_hi:.0%}/anno, mediana {p_mid:.0%}** contro il " f"**{pl.FIRM_DEATH_PER_YEAR:.0%}** assunto.") print(" ⚠ Tre riserve, tutte a favore del canale e tutte dichiarate: (i) 'chiusa/sospesa/") print(" ristrutturata' e' piu' largo di 'sparita col saldo dentro'; (ii) i denominatori") print(" delle fonti non coincidono (2.000 / 302 / 135 firm) e nessuna e' primaria;") print(" (iii) FTMO (2015) e HyroTrader (2022) sono SOPRAVVISSUTE — condizionarsi su una") print(" firm gia' vecchia abbassa il suo hazard, ma e' esattamente il survivorship bias") print(" che non si puo' rivendicare a priori su un orizzonte di 36 mesi.") PS = (0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.40, 0.55) print(f"\n SWEEP su p (cella d'ancora MEDIANA, leva {lev_m:.2f}x, {N_LAD} percorsi ladder,") print(f" {N_TIX} percorsi biglietto; tutto il resto CONGELATO):") print(f" {'p/anno':>7} {'P(>=50/g)':>10} {'P(zero)':>9} {'EUR/g med':>10} " f"{'EV spesa persa':>15} {'EV rimb.payout':>15} {'P(pass)':>8} {'P(payout)':>10}") p_saved = pl.FIRM_DEATH_PER_YEAR sw = [] for p in PS: pl.FIRM_DEATH_PER_YEAR = p lad = GC.ladder(R_M, G_M, N_LAD, lev_m, SEED_LAD, refund=True) tix = GC.ticket_mc(R_M, G_M, lev_m, lev_m, 100_000.0, n_paths=N_TIX) ev3 = GC.ev_three_ways(tix, 579.0) bump(2) sw.append(dict(p=p, p50=lad["p_target"], pz=lad["p_zero"], med=lad["med"], sunk=ev3["sunk"], at_payout=ev3["at_payout"], p_pass=tix["p_pass"], p_pay=tix["p_payout"])) print(f" {p:>7.0%} {lad['p_target']:>9.1%} {lad['p_zero']:>8.1%} {lad['med']:>10.2f} " f"${ev3['sunk']:>14,.0f} ${ev3['at_payout']:>14,.0f} {tix['p_pass']:>7.1%} " f"{tix['p_payout']:>9.1%}") pl.FIRM_DEATH_PER_YEAR = p_saved SW = pd.DataFrame(sw) neg = SW[SW["sunk"] <= 0] if len(neg): i1 = SW.index[SW["sunk"] <= 0][0] x0, x1 = SW.loc[i1 - 1, "p"], SW.loc[i1, "p"] y0, y1 = SW.loc[i1 - 1, "sunk"], SW.loc[i1, "sunk"] p_be = x0 + (x1 - x0) * y0 / (y0 - y1) print(f"\n BREAK-EVEN dell'EV (spesa persa, la convenzione conservativa): " f"p* = **{p_be:.0%}/anno**") else: p_be = float("nan") print(f"\n BREAK-EVEN dell'EV: **oltre {max(PS):.0%}/anno** (EV positivo su tutto lo sweep)") p50_at_mid = float(np.interp(p_mid, SW["p"], SW["p50"])) print(f" A p = {p_mid:.0%} (mediana dell'evidenza) P(>=50/g) scende " f"{SW.loc[SW['p']==0.10,'p50'].iloc[0]:.1%} -> {p50_at_mid:.1%} " f"({p50_at_mid/max(SW.loc[SW['p']==0.10,'p50'].iloc[0],1e-9)-1:+.0%})") a3 = "CONFERMATA" if (0.15 <= p_mid <= 0.25 and (np.isnan(p_be) or p_be > p_hi)) else "PARZIALE" print(f" -> A3 {a3}: la morte-firm vera e' plausibilmente {p_lo:.0%}-{p_hi:.0%}/anno, e il") print(f" break-even dell'EV sta {'sopra' if (np.isnan(p_be) or p_be > p_hi) else 'DENTRO'} " f"quella banda.") print(" 📌 La lettura che conta NON e' l'EV (che regge): e' che P(>=50/g) e' gia' 2,6% e") print(" l'errore sulla morte-firm la muove del ~{:.0f}% senza toccare nulla d'altro." .format(abs(p50_at_mid / max(SW.loc[SW['p'] == 0.10, 'p50'].iloc[0], 1e-9) - 1) * 100)) tick("§3") # ================================= §4 ATTACCO 3 — la frontiera P(>=50/g) contro P(zero) hr("§4. ATTACCO 3 — LA FRONTIERA: P(>=50/g) e' una soglia sulla CODA DESTRA") POL = [("LIVE 75/25/0", W_LIVE), ("W_A 38/38/25 (racc.)", W_A), ("38/25/38", {"TP01": 0.38, "SKH01": 0.25, "XS01": 0.38}), ("argmaxJ 25/25/50", W_ARGMAX), ("55/20/25 (book div 25/07)", {"TP01": 0.55, "SKH01": 0.20, "XS01": 0.25})] LEVS_FR = LEVS if time.time() - T0 > 0.45 * BUDGET_S: LEVS_FR = LEVS[::2] print(f" ⚠ BUDGET: leve della frontiera ridotte da {len(LEVS)} a {len(LEVS_FR)} " f"(dichiarato).") fr = [] for nm, w in POL: fw = GC.fvec_for(w, I, rate, off_m, xs_ann) Rw, Gw = AP.rg_off(w, I, XSP[ph_m], off_m) Rw = Rw - fw for lv in LEVS_FR: lad = GC.ladder(Rw, Gw, N_LAD_FR, lv, SEED_LAD, refund=False) bump(1) fr.append(dict(pol=nm, lev=lv, p50=lad["p_target"], pz=lad["p_zero"], med=lad["med"], p10g=lad["p_ge10"])) F = pd.DataFrame(fr) rho = float(np.corrcoef(F["p50"], F["pz"])[0, 1]) print(f" {len(POL)} politiche x {len(LEVS_FR)} leve = {len(F)} celle, cella d'ancora MEDIANA.") print(f"\n corr( P(>=50/g) , P(zero) ) sulle {len(F)} celle = **{rho:+.3f}** -> A4 " + ("CONFERMATA" if rho > 0.5 else "REFUTATA")) b50 = F.loc[F["p50"].idxmax()] bz = F.loc[F["pz"].idxmin()] bmed = F.loc[F["med"].idxmax()] b10 = F.loc[F["p10g"].idxmax()] print(f"\n {'obiettivo massimizzato':>28} {'politica':>26} {'leva':>6} {'P(>=50/g)':>10} " f"{'P(zero)':>9} {'EUR/g med':>10}") for lab, r in (("P(>=50 EUR/g) <- il citato", b50), ("P(zero) minima", bz), ("EUR/g mediana", bmed), ("P(>=10 EUR/g)", b10)): print(f" {lab:>28} {r['pol']:>26} {r['lev']:>6.2f} {r['p50']:>9.1%} " f"{r['pz']:>8.1%} {r['med']:>10.2f}") rec = F[(F["pol"] == "W_A 38/38/25 (racc.)")] rr = rec.loc[rec["p50"].idxmax()] print(f"\n LA RACCOMANDAZIONE ({rr['pol']} @ {rr['lev']:.2f}x): P(>=50/g) {rr['p50']:.1%}, " f"P(zero) {rr['pz']:.1%}, EUR/g {rr['med']:.2f}") dom = F[(F["p50"] >= rr["p50"]) & (F["pz"] <= rr["pz"]) & ((F["p50"] > rr["p50"]) | (F["pz"] < rr["pz"]))] print(f" Celle che la DOMINANO (>= su P(>=50/g) e <= su P(zero)): **{len(dom)}** su {len(F)}") if len(dom): d0 = dom.loc[dom["p50"].idxmax()] print(f" la migliore: {d0['pol']} @ {d0['lev']:.2f}x -> {d0['p50']:.1%} / {d0['pz']:.1%}") # frontiera di Pareto pts = F.sort_values("pz") par, best = [], -1.0 for _, r in pts.iterrows(): if r["p50"] > best: par.append(r) best = r["p50"] P = pd.DataFrame(par) print(f"\n FRONTIERA DI PARETO ({len(P)} punti non dominati su {len(F)}):") print(f" {'P(zero)':>9} {'P(>=50/g)':>10} {'EUR/g med':>10} {'politica':>26} {'leva':>6}") for _, r in P.iterrows(): star = " <== raccomandazione" if (r["pol"] == rr["pol"] and r["lev"] == rr["lev"]) else "" print(f" {r['pz']:>8.1%} {r['p50']:>9.1%} {r['med']:>10.2f} {r['pol']:>26} " f"{r['lev']:>6.2f}{star}") print("\n 📌 Il prezzo del punto scelto, in unita' comprensibili: passare dal punto a") print(" P(zero) minima a quello a P(>=50/g) massima costa " f"{(F['pz'].max()-F['pz'].min())*100:.0f}pp di probabilita' di finire a ZERO per " f"comprare {(F['p50'].max()-F['p50'].min())*100:.1f}pp di probabilita' di 50 EUR/g.") tick("§4") # ============================== §5 ATTACCO 4 — il gate che il canale non ha mai passato hr("§5. ATTACCO 4 — IL NULL A DRIFT ZERO sulla griglia di 360 celle di PROP-ALLOC") grid = PA.simplex_grid(("TP01", "SKH01", "XS01"), STEP_SIMPLEX) n_cells = len(grid) * len(LEVS) print(f" Griglia di SELEZIONE dichiarata da PROP-ALLOC: {len(grid)} vettori di peso " f"(passo 1/{STEP_SIMPLEX}) x {len(LEVS)} leve = **{n_cells} celle**.") print(" Conteggio dei trial al RIALZO, come vuole il progetto: PROP-ALLOC 360 di selezione") print(" + la seconda firm (360) + PROP-RECAL su 3 finestre + le politiche del 25/07") print(" -> l'ordine di grandezza del multiple testing sul CANALE e' ~1.000-2.000 celle,") print(" e nessuno di questi filoni ha mai calcolato un deflated-Sharpe sul canale.") print("\n IL NULL: stesso pannello, stessa lente, stesse regole, stessa griglia — ma il") print(" DRIFT del libro azzerato (`R - mean(R)` per ogni vettore di peso). Domanda: quanto") print(" J estrae un argmax su 360 politiche quando NON c'e' edge? (Con drift zero si passa") print(" un'eval del +10% per pura varianza: il null NON e' zero.)") ev_n = PA.boot_idx(len(I), EV_H, N_NULL_J, seed=SEED_EV) fu_n = PA.boot_idx(len(I), FU_H, N_NULL_J, seed=SEED_FU) RG = {} for w in grid: key = PA.wkey(w) fw = GC.fvec_for(w, I, rate, off_m, xs_ann) Rw, Gw = AP.rg_off(w, I, XSP[ph_m], off_m) RG[key] = (Rw - fw, Gw) def scan_grid(shift_to_zero: bool, ev_i, fu_i) -> np.ndarray: out = np.empty(n_cells) i = 0 for w in grid: Rw, Gw = RG[PA.wkey(w)] Rz = Rw - Rw.mean() if shift_to_zero else Rw for lv in LEVS: out[i] = PR.obj_rg(Rz, Gw, lv, ev_i, fu_i, factor=DELUCK)["J"] i += 1 bump(n_cells) return out t = time.time() J_real = scan_grid(False, ev_n, fu_n) print(f"\n OSSERVATO ({time.time()-t:.0f}s): max-J su {n_cells} celle = **{J_real.max():.3f}** " f"| mediana {np.median(J_real):.3f} | p90 {np.percentile(J_real,90):.3f}") el = time.time() - T0 per_scan = max(time.time() - t, 1.0) n_draws = N_NULL_DRAWS while n_draws > 2 and el + (n_draws + 1) * per_scan > BUDGET_S: n_draws -= 1 if n_draws != N_NULL_DRAWS: print(f" ⚠ BUDGET: a {el:.0f}s con {per_scan:.0f}s a scansione, le estrazioni di null") print(f" scendono da {N_NULL_DRAWS} a {n_draws}. Dichiarato, non nascosto: la MEDIA") print(f" del max-J del null e' piu' rumorosa, la sua TAGLIA no.") nulls = [] for b in range(n_draws): ev_i = PA.boot_idx(len(I), EV_H, N_NULL_J, seed=9000 + 2 * b) fu_i = PA.boot_idx(len(I), FU_H, N_NULL_J, seed=9001 + 2 * b) Jn = scan_grid(True, ev_i, fu_i) nulls.append(Jn) print(f" null #{b+1}: max-J {Jn.max():.3f} · mediana {np.median(Jn):.3f} " f"({time.time()-t:.0f}s)") N = np.vstack(nulls) nmax = N.max(axis=1) print(f"\n NULL A DRIFT ZERO ({n_draws} estrazioni, {N_NULL_J} percorsi ciascuna):") print(f" max-J atteso dal PURO RUMORE = **{nmax.mean():.3f}** " f"[min {nmax.min():.3f}, max {nmax.max():.3f}]") print(f" OSSERVATO {J_real.max():.3f} -> eccesso **{J_real.max()-nmax.mean():+.3f}** " f"({(J_real.max()/max(nmax.mean(),1e-9)-1)*100:+.0f}%)") print(f" estrazioni di null che BATTONO l'osservato: {int((nmax>=J_real.max()).sum())}" f"/{n_draws}") a5 = "CONFERMATA" if (0.25 <= nmax.mean() <= 0.45) else "REFUTATA" print(f" -> A5 (max-J del null fra 0,25 e 0,45) {a5}") # crescita del massimo col numero di celle: la sensibilita' del verdetto al CONTEGGIO print(f"\n Sensibilita' al CONTEGGIO dei trial (max-J del null su sottoinsiemi casuali):") rng = np.random.default_rng(4242) print(f" {'k celle':>9} {'max-J null':>11} {'osservato':>11} {'eccesso':>9}") for k in (45, 90, 180, 360): mk = np.array([N[b, rng.choice(n_cells, size=min(k, n_cells), replace=False)].max() for b in range(n_draws) for _ in range(4)]) ok = np.array([J_real[rng.choice(n_cells, size=min(k, n_cells), replace=False)].max() for _ in range(20)]).mean() print(f" {k:>9} {mk.mean():>11.3f} {ok:>11.3f} {ok-mk.mean():>+9.3f}") # il gate STANDARD del progetto, puntato sul canale — e la sua CECITA' alla leva import altlib as AL # noqa: E402 sh_w, ret_w = {}, {} for w in grid: Rw, Gw = RG[PA.wkey(w)] Rd = PA.deluck(Rw, DELUCK) v = float(Rd.std(ddof=1) * np.sqrt(365)) sh_w[PA.wkey(w)] = float(Rd.mean() * 365 / v) if v > 0 else 0.0 ret_w[PA.wkey(w)] = Rd kb = max(sh_w, key=sh_w.get) dsr, sr0 = AL.deflated_sharpe(sh_w[kb], list(sh_w.values()), ret_w[kb]) print(f"\n IL GATE STANDARD, per confronto — `altlib.deflated_sharpe` sulla stessa griglia:") print(f" Sharpe migliore {sh_w[kb]:.3f} ({kb}) · attesa dal rumore su N={len(sh_w)} " f"trial {sr0:.3f} · **DSR {dsr:.3f} {'PASS' if dsr >= 0.95 else 'FAIL'}**") print(f" 🚨 Ma N e' **{len(sh_w)}, non {n_cells}**: lo Sharpe e' INVARIANTE ALLA LEVA") print(f" (`obj_rg` lo calcola su `Rd`, non su `Rd*lev`), quindi le {n_cells-len(sh_w)}") print(" celle che differiscono SOLO per la leva sono **invisibili** al gate standard.") print(" E' esattamente la lezione di §33/§53: la leva non la vede nessun gate del") print(" progetto. Su un conto a BARRIERA la leva e' la variabile che decide.") # il libro LIVE, che NON e' stato selezionato, come incumbent fL = GC.fvec_for(W_LIVE, I, rate, off_m, xs_ann) RL, GL = AP.rg_off(W_LIVE, I, XSP[ph_m], off_m) jL_all = [PR.obj_rg(RL - fL, GL, lv, ev_n, fu_n, factor=DELUCK)["J"] for lv in LEVS] bump(len(LEVS)) print(f"\n L'INCUMBENT (libro LIVE 75/25, che NON e' stato selezionato su questa griglia):") print(f" J max sulle 8 leve = {max(jL_all):.3f} -> anche l'incumbent " f"{'SUPERA' if max(jL_all) > nmax.mean() else 'NON supera'} il max del null.") print(" ⚠ CONTROLLO NEGATIVO obbligatorio: una estrazione di null trattata come se fosse") print(" il candidato deve dare eccesso ~0 contro le altre.") held = nmax[0] rest = nmax[1:] print(f" null #1 come candidato: max-J {held:.3f} contro media delle altre " f"{rest.mean():.3f} -> eccesso {held-rest.mean():+.3f} " f"({'OK, ~0' if abs(held-rest.mean()) < 0.05 else 'ATTENZIONE'})") print("\n 📌 Cosa dice e cosa NON dice: **non** dice che il canale sia rumore — l'eccesso") print(" e' misurato e positivo. Dice che **una parte non piccola del J pubblicato la") print(" produce la varianza attraverso una barriera**, e che nessuno l'aveva sottratta.") tick("§5") # ================================================================== §6 il verdetto hr("§6. LA DOMANDA FINALE — se il canale funded fosse un CANDIDATO-SLEEVE, passerebbe?") ded = J_real.max() - nmax.mean() checks = [ ("edge in-sample (J > incumbent)", dj0 > 0.05, f"dJ {dj0:+.3f} contro il libro live"), ("deflated / null di selezione", ded > 0.10, f"eccesso sul max del null a drift zero {ded:+.3f} su {n_cells} celle"), ("robustezza al PARAMETRO (-1 SE)", dj_m1 > 0.05, f"dJ a -1 SE del drift di XS01 = {dj_m1:+.3f}"), ("robustezza a -2 SE", dj_m2 > 0.05, f"dJ a -2 SE = {dj_m2:+.3f}"), ("assunzione esogena stimata", (not np.isnan(p_be)) and p_be > p_hi, f"morte-firm: assunta {p_saved:.0%}, evidenza {p_lo:.0%}-{p_hi:.0%}, " f"break-even {p_be:.0%}" if not np.isnan(p_be) else f"morte-firm: assunta {p_saved:.0%}, evidenza {p_lo:.0%}-{p_hi:.0%}, break-even >55%"), ("obiettivo non degenere", len(dom) == 0, f"{len(dom)} celle dominano la raccomandazione su (P(>=50/g), P(zero))"), ("deflated-Sharpe standard (cieco alla leva)", dsr >= 0.95, f"DSR {dsr:.3f} su N={len(sh_w)} trial visibili di {n_cells} reali"), ("fuori dalla finestra di scoperta", True, "§21: XS01 regge fuori campione (+1,12), MA a 13 gambe su 19 e a effetto/MDE ~1,0"), ("eseguibilita' verificata al venue", True, "§30: 13/13 gambe `Trading` su Bybit, min notional $5 — PASS misurato"), ] print(f" {'gate':>36} {'esito':>8} dettaglio") npass = 0 for nm, ok, det in checks: npass += int(ok) print(f" {nm:>36} {'PASS' if ok else 'FAIL':>8} {det}") print(f"\n {npass}/{len(checks)} gate superati.") hr("VERDETTO") print(f" 1. REPLICA: P(>=50 EUR/g) {m50:.1%} contro il pubblicato {PUB['p50g']:.1%}, " f"P(zero) {C['pz'].median():.1%} contro {PUB['pzero']:.1%} -> **la macchina e' quella**.") print(f" 2. IL PILASTRO: SE del drift di XS01 = {se_boot:.1%}/anno. A -1 SE il vantaggio " f"del canale passa da {dj0:+.3f} a {dj_m1:+.3f} di J e P(>=50/g) da {p50_0:.1%} a " f"{p50_m1:.1%}.") print(f" 3. LA MORTE-FIRM: evidenza pubblica {p_lo:.0%}-{p_hi:.0%}/anno contro il " f"{p_saved:.0%} assunto; l'EV regge (break-even " f"{'>' + f'{max(PS):.0%}' if np.isnan(p_be) else f'{p_be:.0%}'}), " f"ma P(>=50/g) scende a {p50_at_mid:.1%}.") print(f" 4. LA FRONTIERA: corr(P(>=50/g), P(zero)) = {rho:+.3f}; " f"{len(dom)} celle dominano il punto raccomandato.") print(f" 5. IL GATE MANCANTE: max-J dal puro rumore su {n_cells} celle = {nmax.mean():.3f}, " f"osservato {J_real.max():.3f}, eccesso {ded:+.3f}.") eur_pt = float(C["med"].median()) eur_m1 = float(D[D["k"] == -1.0]["med"].median()) eur_live = float(D[D["k"] == 0.0]["med_live"].median()) print(f"\n IN EUR/GIORNO (mediana, 36 mesi, da 600 euro, funding e fisco dentro):") print(f" canale funded al drift misurato ... {eur_pt:>6.2f} EUR/g") print(f" canale funded a -1 SE ............ {eur_m1:>6.2f} EUR/g") print(f" libro LIVE sullo stesso conto .... {eur_live:>6.2f} EUR/g") print(f" obiettivo dichiarato ............. {pl.TARGET_EUR_DAY:>6.2f} EUR/g") print(f"\n Questo filone NON avvicina i 50 EUR/giorno: non produce ritorno, " f"riduce la fiducia") print(f" nel numero gia' pubblicato. Il suo effetto sulla rendita attesa e' " f"**{eur_m1-eur_pt:+.2f} EUR/g**") print(f" se si crede a -1 SE, e **0,00 EUR/g** se non si cambia nulla (ed e' cio' che " f"raccomanda).") print(f"\n [{TRIALS} valutazioni, {time.time()-T0:.0f}s]") print("=" * 104) if __name__ == "__main__": main()