"""§67 REGIME-CAPITALE — cosa e' stato archiviato PER TAGLIA, e cosa sarebbe vivo a $100.000. LA DOMANDA ---------- Ogni screening di questo progetto e' stato fatto a **$600 di capitale**. E' la scelta giusta per il conto che esiste, ma ha un effetto collaterale mai esaminato: le strategie messe in STAT-MODE o rifiutate citando min-order / lotto minimo / numero di gambe / haircut small-cap sono state archiviate **senza mai misurare se sarebbero vive a $100k** — che e' il nozionale di un conto funded, il canale su cui il progetto sta valutando di puntare. E c'e' una ragione forte per rifare il conto ADESSO: l'ondata del 22-23/08 ha falsificato **tre muri di taglia** pubblicati (il "$20k di XS01" non esiste; il muro delle opzioni BTC era il COLLATERALE PER VENDERE, non il costo di comprare; i lotti USDC-lineari sono 7,5-10x piu' piccoli di quelli inverse su cui erano stati misurati). Tre su tre sbagliati, tutti nella stessa direzione: piu' permissivi del creduto. ATTESE A PRIORI — scritte leggendo il mandato, PRIMA di qualunque misura ----------------------------------------------------------------------- A1 Il censimento conterra' 10-15 voci e la MAGGIORANZA avra' anche un rifiuto sul lato EDGE: la taglia sara' raramente l'unico motivo. A2 (controllo positivo) XS01 riprodurra' haircut ~0 gia' a $200-600 di capitale ALLOCATO. Se il mio codice non lo trova, il mio codice e' rotto e mi fermo. A3 A $100.000 ogni candidato multi-gamba converge alla propria serie MODELLATA (haircut -> 0). A4 Nessun archiviato passera' TUTTI i gate a $100k — e non perche' ricontrolli i gate, ma per una ragione strutturale: i gate pubblicati sono stati calcolati sulla serie MODELLATA, che E' il limite a capitale infinito. Se e' vero, la domanda del mandato era gia' risposta nei registri. A5 Il corollario funded non aggiungera' NIENTE di nuovo: l'unico ampliamento reale dell'insieme ammissibile e' XS01, e §1/§29 l'hanno gia' contato (+0,400 di J). A6 L'haircut sara' MONOTONO decrescente nel capitale. <-- questa e' quella che mi aspetto di confermare senza pensarci; se salta, e' il risultato metodologico del filone. METODO ------ * Repliche PRIMA di ogni delta: identita' bit-exact di XS01 col sleeve di produzione; libro 75/25 `hourly` contro il numero pubblicato (Sh 1,683 / maxDD 11,22%). * Parametri VERI del venue (non quelli di memoria): Deribit min-order $5, taker 3,50 bps dal 2026-08-01; Hyperliquid min-order **$10** (non $5) e taker **4,50 bps** (non 5,0), misurati da HL-EXEC il 22/08; lotti della famiglia **USDC-lineare** (non inverse), letti dal venue. * La LENTE del libro e' dichiarata: `hourly` (path live), Sh 1,683 / maxDD 11,22% — non la canonica 1,800/9,56% ne' la mediana d'ancora 1,626/10,4%. * Distinzione dichiarata riga per riga: **capitale PROPRIO** (e' tuo, il vincolo e' il min-order) contro **nozionale FUNDED** (non e' tuo, il vincolo binding e' la regola di drawdown). SICUREZZA: sola lettura. Nessun ordine. Nessun file di produzione toccato. Solo GET pubbliche, con pacing, cache e astensione nelle finestre del cron (:05-:10 book, :24-:30 catena). uv run python scripts/research/r0823b_regime_capitale.py uv run python scripts/research/r0823b_regime_capitale.py --no-net # tutto da cache/costanti """ from __future__ import annotations import argparse import json import subprocess import sys import time import urllib.request from datetime import datetime, timezone 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"): if str(_p) not in sys.path: sys.path.insert(0, str(_p)) CACHE = ROOT / "data" / "cache_regime_capitale.json" # -------------------------------------------------------------------------------------------- # PARAMETRI VENUE — dichiarati, con la FONTE. Nessuno di questi e' "di memoria". # -------------------------------------------------------------------------------------------- DER_MIN_ORDER = 5.0 # config/live.json -> min_order_usd DER_FEE_SIDE = 0.00035 # 3,50 bps/lato dal 2026-08-01 (SLIP-AUDIT: 16/16 fill sul nastro) HL_MIN_ORDER = 10.0 # HL-EXEC 22/08: docs + 3.827 livelli, 0,0% sotto $10 (NON $5) HL_FEE_SIDE = 0.00045 # HL-EXEC 22/08: 4,50 bps, due fonti indipendenti (NON 5,0) SPLIT_FUNDED = 0.80 # r0725_hyro.SPLIT — quota trader del profitto su conto funded BARRIERA_FUNDED = 0.06 # HyroTrader max loss STATICO 6% (r0725_hyro.EV_DD, regole vere) EURUSD = 1.09 CAPITALI = (635.0, 5_000.0, 20_000.0, 100_000.0) # la griglia del mandato GRIGLIA_DENSA = (95.0, 200.0, 400.0, 600.0, 635.0, 1_000.0, 1_500.0, 2_000.0, 3_000.0, 5_000.0, 7_500.0, 10_000.0, 15_000.0, 20_000.0, 50_000.0, 100_000.0, 200_000.0) TOL_STAB = 0.10 # |Sh(C) - Sh(modellata)| <= 0,10 per DICHIARARE eseguibile SEED = 823 _last_net = [0.0] def sez(t: str) -> None: print("\n" + "=" * 100) print(" " + t) print("=" * 100) def sub(t: str) -> None: print("\n --- " + t) def _pace() -> None: """<=2 req/s e astensione nelle finestre del cron live.""" now = datetime.now(timezone.utc) while now.minute in (5, 6, 7, 8, 9, 10, 24, 25, 26, 27, 28, 29, 30): print(f" [pausa: minuto {now.minute} e' finestra del cron live]") time.sleep(20) now = datetime.now(timezone.utc) dt = time.time() - _last_net[0] if dt < 0.6: time.sleep(0.6 - dt) _last_net[0] = time.time() def get_json(url: str, key: str, no_net: bool): c = json.loads(CACHE.read_text()) if CACHE.exists() else {} if no_net or (key in c and time.time() - c[key].get("_t", 0) < 12 * 3600): return c.get(key, {}).get("v") try: _pace() with urllib.request.urlopen(url, timeout=20) as r: v = json.loads(r.read().decode()) except Exception as e: # noqa: BLE001 print(f" [rete KO su {key}: {type(e).__name__}] -> uso la cache se c'e'") return c.get(key, {}).get("v") c[key] = {"_t": time.time(), "v": v} CACHE.write_text(json.dumps(c)) return v def sola_lettura() -> None: """Prova che il filone non ha toccato la produzione (il cron ESEGUE dalla working tree).""" prot = ["src/", "config/", "scripts/live/", "tests/", "data/paper_statarb", "data/paper_xsr", "data/paper_dvolspread", "data/live"] out = subprocess.run(["git", "status", "--porcelain", "--"] + prot, cwd=ROOT, capture_output=True, text=True).stdout.strip() print(f" git status sui percorsi protetti: {'VUOTO (sola lettura provata)' if not out else out}") assert not out, "PRODUZIONE TOCCATA — fermarsi" # ============================================================================================= # METRICHE E DEFINIZIONE DI ESEGUIBILITA' # ============================================================================================= ANN = np.sqrt(365.25) def met(net: np.ndarray, idx) -> dict: x = np.asarray(net, float) sd = x.std(ddof=1) sh = float(x.mean() / sd * ANN) if sd > 0 else 0.0 eq = np.cumprod(1.0 + np.clip(x, -0.99, None)) dd = float((1.0 - eq / np.maximum.accumulate(eq)).max()) yrs = max((idx[-1] - idx[0]) / pd.Timedelta("365.25D"), 1e-9) return dict(sharpe=sh, maxdd=100 * dd, cagr=100 * (eq[-1] ** (1 / yrs) - 1.0)) def c_stabilita(curva: dict[float, float], sh_mod: float, tol: float = TOL_STAB) -> float | None: """C* = il PIU' PICCOLO capitale tale che da li' in su lo Sharpe NON si discosta piu' di `tol` dalla serie modellata. Definizione scelta PRIMA di guardare, e per un motivo: ne' l'haircut ne' la quota di nozionale eseguito, da soli, distinguono "eseguibile" da "degenere" (sez. 3).""" caps = sorted(curva) for i, c in enumerate(caps): if all(abs(curva[c2] - sh_mod) <= tol for c2 in caps[i:]): return c return None def maxdd_k(r: np.ndarray, k: float) -> float: eq = np.cumprod(1.0 + np.clip(k * np.asarray(r, float), -0.99, None)) return float((1.0 - eq / np.maximum.accumulate(eq)).max()) def cagr_k(r: np.ndarray, k: float, idx) -> float: eq = np.cumprod(1.0 + np.clip(k * np.asarray(r, float), -0.99, None)) yrs = max((idx[-1] - idx[0]) / pd.Timedelta("365.25D"), 1e-9) return float(eq[-1] ** (1 / yrs) - 1.0) def k_barriera(r: np.ndarray, target: float = BARRIERA_FUNDED) -> float: lo, hi = 1e-3, 20.0 if maxdd_k(r, hi) < target: return hi for _ in range(60): mid = 0.5 * (lo + hi) if maxdd_k(r, mid) < target: lo = mid else: hi = mid return lo # ============================================================================================= # SEZ. 1 — IL CENSIMENTO # ============================================================================================= # (voce, dove il muro di taglia e' dichiarato, muro come pubblicato, stato del muro OGGI, # c'e' ANCHE un rifiuto sul lato EDGE?) CENSIMENTO = [ ("XS01 (19 gambe HL)", "CLAUDE.md 19/06", "STAT-MODE, 'serve ~20k'", "FALSIFICATO 22/08 (haircut ~0 a $200-600)", "no — e' nel book di ricerca; fuori dal LIVE per VENUE (14/19) e decisione venue"), ("XSR01 (50 gambe HL)", "CLAUDE.md 25/07", "ticket $1,73 < $5 -> 'reale a ~$5k'", "RIDIMENSIONATO 22/08: soglia vera ~$3.000", "SI — weights_tilt_null FAIL (book 5-sleeve), storia 2,6a monoregime; gate 23/10 APERTO"), ("STATARB-MULTI (50 coppie)", "CLAUDE.md 25/07", "51 gambe = STAT-MODE", "MAI MISURATO -> misurato qui", "SI — IC95 [-0,12; 1,72], t 1,31; uplift -0,11 vs null a priori"), ("CC01 cash-and-carry", "CLAUDE.md 26/06", "4-38 gambe, 'rivedere a ~20k+'", "FALSIFICATO 22/08 (§34: lotti $10/$1; §39: linea USDC esiste)", "SI — DSR 0,363 FAIL, implausible_sharpe 5/5, de-levering REFUTED, 2 gambe = Sharpe -0,42"), ("VRP01 (put credit spread)", "CLAUDE.md 30/07", "lotto BTC $6.210 / ETH $1.832 -> 0 lotti al peso 12%", "FALSIFICATO 22/08 (§50: famiglia USDC ETH $242 / BTC $772)", "SI — regola 'niente short-vol da modello in deploy' + f=0,73 misurato"), ("Opzioni long (tail-hedge, gamma)", "CLAUDE.md 26/06 + 22/08", "'opzione BTC min $5.968 >> $600'", "FALSIFICATO 23/08 (§46: comprare costa il PREMIO, $1,79-7,93)", "SI — gamma scalp Sharpe -3..-6 ogni anno; tail-hedge maxDD sale in 162/162 celle"), ("Albimarini double-diagonal", "CLAUDE.md 02/07", "(nessun muro di taglia)", "n/d — fee-negativa a QUALSIASI size", "SI — fee 8 gambe = 194-221% del theta; celle 0-perdite = implausible_sharpe"), ("Tranching TP01 K=2/4", "CLAUDE.md 02/07", "'delta ~$1-2 < min-order -> K=1'; rivalutare a >=5-10k", "FALSIFICATO 23/08 (§47: build_book_order banda la posizione NETTA)", "SI — dSharpe n.s.; e' riduzione della VARIANZA DELLA STIMA, non ritorno"), ("BIN-FREQ (size per-trade SKH01)", "CLAUDE.md 22/08", "riapertura = SOGLIA DI CAPITALE $5.600 (cella) / $53.000 (famiglia)", "VIVO — e' l'unico con una soglia di capitale come condizione DICHIARATA", "SI — mediana di famiglia 6% della cella, 54% celle positive; weights_tilt_null FAIL"), ("XS01-D (11 gambe Deribit)", "RESULTS §50/§56 23/08", "'aspettare 2-3 listing'", "n/d — non e' capitale, e' VENUE", "SI — IC -0,027 (t -0,88) su quelle 11; DSR 0,158 FAIL"), ("GTAA01 (6 ETF)", "CLAUDE.md 25-26/07", "GTAA_MIN_CAPITAL $3.000", "n/d — sopra c'e' il PRIIPs: ordine RIFIUTATO sul conto reale", "no — regge come ricerca (LOO: unico positivo nel 100% delle estrazioni)"), ("XS01 espanso (52 -> 51 HL)", "CLAUDE.md 19-20/06", "(nessun muro di taglia)", "n/d", "SI — il long-tail DILUISCE il momentum relativo; peggiore a ogni variante"), ("IVOL (idio-vol cross-sectional)", "CLAUDE.md 29/06", "STAT-MODE", "MAI MISURATO (lead mai ripreso)", "SI — nato come LEAD debole nello stesso sweep in cui XSEC-V2 fa DSR 0,13"), ("LOWVOL 19-major", "CLAUDE.md 29/06", "STAT-MODE", "n/d", "SI — deflated-Sharpe 0,13 + storia 2,5a"), ] def sezione1() -> None: sez("1) IL CENSIMENTO — tutto cio' che il progetto ha archiviato CITANDO LA TAGLIA") print(""" Regola di lettura: la colonna che decide non e' 'stato del muro' ma l'ULTIMA. Un muro di taglia che cade libera un candidato solo se non c'era anche un rifiuto sull'edge — e i gate sull'edge NON dipendono dal capitale (sez. 5). """) print(" " + "-" * 98) n_edge = 0 for nome, fonte, muro, stato, edge in CENSIMENTO: n_edge += edge.startswith("SI") print(f" {nome:<32}[{fonte}]") print(f" {'':<32}muro pubblicato : {muro}") print(f" {'':<32}muro OGGI : {stato}") print(f" {'':<32}EDGE : {edge}") print(" " + "-" * 98) n = len(CENSIMENTO) print(f"\n VOCI: {n} con rifiuto ANCHE sull'edge: {n_edge}/{n} = {100*n_edge/n:.0f}%") falsi = sum(1 for _, _, _, s, _ in CENSIMENTO if s.startswith("FALSIFICATO")) mai = sum(1 for _, _, _, s, _ in CENSIMENTO if s.startswith("MAI")) print(f" muri di taglia FALSIFICATI (tutti dall'ondata 22-23/08): {falsi}/{n}") print(f" muri di taglia MAI MISURATI (li misuro qui dove possibile): {mai}/{n}") print(f"\n A1 {'CONFERMATA' if n_edge / n > 0.5 else 'REFUTATA'}: la taglia e' l'unico motivo " f"in {n - n_edge}/{n} voci.") # ============================================================================================= # SEZ. 2-3 — LE CURVE DI HAIRCUT # ============================================================================================= def carica_candidati(): """Ricostruisce i pesi dei 3 candidati multi-gamba REALMENTE misurabili. Nessuna reimplementazione: si importano il sleeve di produzione e il monitor live.""" from r0822_hl_exec import sim_libro, xs01_pesi # noqa: F401 out = {} W, dret, C, cols, dif = xs01_pesi(0) print(f" XS01 (19 gambe HL): identita' vs sleeves._xsec_returns max|dif| = {dif}") assert dif == 0.0, "XS01 non replica il sleeve di produzione" out["XS01 (19g, HL)"] = dict(W=W, R=dret, hedge=None, idx=C.index, fee=HL_FEE_SIDE, floor=HL_MIN_ORDER, legs=19, venue="HL") from scripts.live.paper_xsr import FEE_LEG, build_panel ts, idx, Wx, Rx, rb, colx = build_panel() print(f" XSR01 (50 gambe HL): pannello dal MONITOR di produzione, {Wx.shape[1]} gambe, " f"fee monitor {FEE_LEG*1e4:.1f} bps") out["XSR01 (50g, HL)"] = dict(W=Wx, R=Rx, hedge=rb, idx=idx, fee=FEE_LEG, floor=HL_MIN_ORDER, legs=50, venue="HL") import r0725_statarb_multi as SM base = SM.load_hl(SM.BASE) pc, rc = {}, {} for sym in SM.universe(): try: tgt = SM.load_hl(sym) except FileNotFoundError: continue ix = base.index.intersection(tgt.index) if len(ix) < SM.MIN_BARS: continue p, _ = SM.signal(base[ix], tgt[ix]) pc[sym] = pd.Series(p, index=ix) rc[sym] = tgt[ix].pct_change().fillna(0.0) P = pd.concat(pc, axis=1, sort=True).sort_index().fillna(0.0) Rr = pd.concat(rc, axis=1, sort=True).sort_index().reindex(P.index).fillna(0.0)[P.columns] k = P.shape[1] print(f" STATARB-MULTI: {k} coppie = {k+1} gambe (meccanismo CONGELATO W=45 sgn=+1, " f"da r0725_statarb_multi)") out["STATARB-MULTI (51g, HL)"] = dict( W=(P / k).to_numpy(float), R=Rr.to_numpy(float), hedge=base.pct_change().fillna(0.0).reindex(P.index).fillna(0.0).to_numpy(float), idx=P.index, fee=SM.FEE_LEG, floor=HL_MIN_ORDER, legs=k + 1, venue="HL") return out def curva(cand: dict, caps, floor=None) -> tuple[dict, dict, dict]: from r0822_hl_exec import sim_libro fl = cand["floor"] if floor is None else floor sh, noz, nets = {}, {}, {} for c in caps: s = sim_libro(cand["W"], cand["R"], cand["hedge"], c, fl, None, None, cand["fee"]) m = met(s["net"], cand["idx"]) sh[c] = m["sharpe"] noz[c] = s["pct_nozionale"] nets[c] = s["net"] s = sim_libro(cand["W"], cand["R"], cand["hedge"], 1e12, None, None, None, cand["fee"]) nets["MOD"] = s["net"] return sh, noz, nets def sezione23(CAND: dict) -> dict: sez("2) CONTROLLO POSITIVO — XS01, il muro gia' caduto il 22/08") print(""" Se il mio codice non ritrova haircut ~0 a $200-600 su XS01, e' rotto e il resto non vale niente. (HL-EXEC 22/08: "haircut ~0 gia' a $200-600 allocati; a $600 lo Sharpe passa 1,33 -> 1,30".)""") sh, noz, nets = curva(CAND["XS01 (19g, HL)"], GRIGLIA_DENSA) shm = met(nets["MOD"], CAND["XS01 (19g, HL)"]["idx"])["sharpe"] print(f"\n {'capitale ALLOCATO':>19}{'Sharpe':>9}{'haircut':>10}{'% nozionale eseguito':>23}") for c in GRIGLIA_DENSA: print(f" {c:>19,.0f}{sh[c]:>9.3f}{shm - sh[c]:>10.3f}{noz[c]:>22.1f}%") print(f" {'MODELLATA':>19}{shm:>9.3f}{0.0:>10.3f}{100.0:>22.1f}%") ok = abs(sh[200.0] - shm) <= 0.05 and abs(sh[635.0] - shm) <= 0.05 print(f"\n A2 {'CONFERMATA' if ok else 'REFUTATA — CODICE ROTTO, MI FERMO'}: " f"haircut a $200 = {shm - sh[200.0]:+.3f}, a $635 = {shm - sh[635.0]:+.3f}.") assert ok, "controllo positivo fallito" for tol in (0.10, 0.05): cs = c_stabilita(sh, shm, tol) print(f" C* a tolleranza {tol:.2f} di Sharpe = " f"{('$%s' % f'{cs:,.0f}') if cs else '>200k'} di capitale ALLOCATO.") print(f""" PRECISAZIONE che il numero pubblicato non porta con se': i "$200-600" sono capitale ALLOCATO AL SLEEVE. A peso di libro 15% servono ${200/0.15:,.0f}-${635/0.15:,.0f} di LIBRO per stare li'; a un libro da $635 il sleeve vede $95 e l'haircut e' {shm - sh[95.0]:+.3f} — non zero.""") sez("3) LE CURVE — i tre candidati multi-gamba, ai capitali del mandato") print(f"\n {'candidato':<26}{'gambe':>6}{'venue':>7}" + "".join(f"{('$%s' % f'{c:,.0f}'):>12}" for c in CAPITALI) + f"{'MODELL.':>10}{'C*':>12}") print(" " + "-" * 110) res = {} for nome, cand in CAND.items(): shd, nozd, netsd = curva(cand, GRIGLIA_DENSA) shm = met(netsd["MOD"], cand["idx"])["sharpe"] cs = c_stabilita(shd, shm) res[nome] = dict(sh=shd, noz=nozd, nets=netsd, sh_mod=shm, cstar=cs, cand=cand) print(f" {nome:<26}{cand['legs']:>6}{cand['venue']:>7}" + "".join(f"{shd[c]:>12.3f}" for c in CAPITALI) + f"{shm:>10.3f}" + (f"{cs:>12,.0f}" if cs else f"{'>200k':>12}")) print(" " + "-" * 110) sub("3a) la curva DENSA (Sharpe sopra, % di nozionale eseguito sotto)") print(f" {'capitale':>10}" + "".join(f"{nm.split(' (')[0]:>13}" for nm in res)) for c in GRIGLIA_DENSA: print(f" {c:>10,.0f}" + "".join(f"{res[nm]['sh'][c]:>13.3f}" for nm in res)) print(f" {'':>10}" + "".join(f"{res[nm]['noz'][c]:>12.1f}%" for nm in res)) print(f" {'MODELLATA':>10}" + "".join(f"{res[nm]['sh_mod']:>13.3f}" for nm in res)) print(f"\n C* per tolleranza:") for tol in (0.10, 0.05): row = [] for nm in res: cs = c_stabilita(res[nm]["sh"], res[nm]["sh_mod"], tol) row.append(("$%s" % f"{cs:,.0f}") if cs else ">200k") print(f" tol {tol:.2f}: " + " ".join(f"{nm.split(' (')[0]}={v}" for nm, v in zip(res, row))) sub("3b) LA TRAPPOLA — l'haircut da solo NON rileva un muro di taglia") print(""" `altlib.eval_weights_smallcap` riporta `sharpe_haircut = modellata - reale`. Su un candidato multi-gamba, sotto la soglia di eseguibilita' quel numero PUO' ESSERE NEGATIVO: il pavimento taglia quasi tutto il nozionale e cio' che resta e' una strategia DIVERSA, piccola e casuale. Letto da solo, un haircut negativo dice "eseguibile, anzi meglio". E' esattamente al rovescio.""") print(f"\n {'candidato':<26}{'cap':>10}{'Sharpe':>9}{'haircut':>10}{'% noz':>9} lettura") for nome, r in res.items(): for c in (635.0, 5_000.0): h = r["sh_mod"] - r["sh"][c] deg = r["noz"][c] < 50.0 print(f" {nome:<26}{c:>10,.0f}{r['sh'][c]:>9.3f}{h:>10.3f}{r['noz'][c]:>8.1f}% " f"{'DEGENERE (il numero non descrive la strategia)' if deg else 'eseguibile'}") st = res["STATARB-MULTI (51g, HL)"] print(f""" Il caso limpido: STATARB-MULTI a $635 fa Sharpe {st['sh'][635.0]:.3f} contro {st['sh_mod']:.3f} modellata -> haircut {st['sh_mod'] - st['sh'][635.0]:+.3f}, cioe' NEGATIVO, con il {st['noz'][635.0]:.1f}% del nozionale eseguito. Un gate scritto su `sharpe_haircut <= X` lo avrebbe promosso.""") sub("3c) A6 — monotonia dell'haircut nel capitale") for nome, r in res.items(): seq = [r["sh"][c] for c in GRIGLIA_DENSA] d = np.diff(seq) mono = bool((d >= -1e-9).all()) print(f" {nome:<26} monotono crescente in C? {'SI' if mono else 'NO'} " f"(peggior passo indietro {d.min():+.3f}; max sopra la modellata " f"{max(seq) - r['sh_mod']:+.3f})") print(""" A6 REFUTATA su 3/3. Sotto C* lo Sharpe non e' una misura della strategia: e' una misura di QUALI gambe il pavimento ha lasciato passare. Il segno del passo e' rumore.""") return res def sezione3d(CAND: dict) -> None: sub("3d) IL PAVIMENTO DEL VENUE SBAGLIATO — `scripts/live/paper_xsr.MIN_ORDER = 5.0`") print(""" XSR01 gira su HYPERLIQUID (50 alt). Il suo monitor forward — quello che alimenta il gate pre-registrato del 2026-10-23 — usa `MIN_ORDER = 5.0`, che e' il pavimento di **DERIBIT**. Il pavimento di Hyperliquid e' **$10** (HL-EXEC 22/08: 3.827 livelli, 0,0% sotto $10). I due libri REAL del monitor sono $600 e $5.000: entrambi nella regione in cui il pavimento morde.""") c = CAND["XSR01 (50g, HL)"] sh5, noz5, _ = curva(c, GRIGLIA_DENSA, floor=5.0) sh10, noz10, nets = curva(c, GRIGLIA_DENSA, floor=10.0) shm = met(nets["MOD"], c["idx"])["sharpe"] print(f"\n {'capitale':>10}{'Sh @ $5 (monitor)':>20}{'Sh @ $10 (venue)':>19}{'differenza':>13}" f"{'% noz @$10':>12}") for cc in (600.0, 635.0, 2_000.0, 3_000.0, 5_000.0, 20_000.0, 100_000.0): print(f" {cc:>10,.0f}{sh5[cc]:>20.3f}{sh10[cc]:>19.3f}{sh5[cc]-sh10[cc]:>13.3f}" f"{noz10[cc]:>11.1f}%") d = np.array([sh5[cc] - sh10[cc] for cc in GRIGLIA_DENSA if cc <= 5_000.0]) print(f""" Non e' "il monitor e' ottimista": nella regione che conta la differenza cambia SEGNO (min {d.min():+.3f}, max {d.max():+.3f}) — perche' sotto C* si stanno confrontando due sottoinsiemi casuali di gambe, non due stime della stessa cosa. C* col pavimento vero = ${c_stabilita(sh10, shm) or float('nan'):,.0f}; col pavimento del monitor = ${c_stabilita(sh5, shm) or float('nan'):,.0f}. Effetto sul gate 23/10: la sua gamba di eseguibilita' e' "haircut a $5.000 <= 40%", e a $5.000 il monitor misura con il pavimento sbagliato. NON anticipo il gate: registro che l'ingresso e' storto. 6a occorrenza dello schema `fee_watch` — un controllo puntato su una configurazione diversa da quella che gira.""") # ============================================================================================= # SEZ. 4 — VRP01: lotti, non haircut # ============================================================================================= def sezione4(no_net: bool) -> None: sez("4) VRP01 — qui il muro non e' un haircut, e' un LOTTO INDIVISIBILE") j = get_json("https://www.deribit.com/api/v2/public/get_instruments" "?currency=USDC&kind=option&expired=false", "usdc_opt", no_net) idx = get_json("https://www.deribit.com/api/v2/public/get_index_price?index_name=btc_usd", "px_btc", no_net) idxe = get_json("https://www.deribit.com/api/v2/public/get_index_price?index_name=eth_usd", "px_eth", no_net) px = {"BTC": (idx or {}).get("result", {}).get("index_price"), "ETH": (idxe or {}).get("result", {}).get("index_price")} mins, nstr = {}, {} for it in ((j or {}).get("result") or []): nm = it.get("instrument_name", "") for a in ("BTC", "ETH"): if nm.startswith(f"{a}_USDC-") and it.get("option_type") == "put": mins[a] = min(mins.get(a, 9e9), float(it.get("min_trade_amount", 9e9))) nstr[a] = nstr.get(a, 0) + 1 if mins and all(px.values()): print(" letto dal venue ORA (GET pubblica su kind=OPTION, famiglia USDC-LINEARE = quella") print(" che un conto USDC puo' marginare; VRP01 VENDE, quindi il lotto e' il NOZIONALE" " sottostante,") print(" non il premio — e' la distinzione che §46 ha dovuto correggere sul lato LONG):") for a in ("BTC", "ETH"): print(f" {a}_USDC put ({nstr.get(a,0)} strumenti) min_trade_amount = " f"{mins.get(a)} indice ${px[a]:,.0f} -> lotto = ${mins.get(a, 0) * px[a]:,.0f}") lot = {a: mins[a] * px[a] for a in mins} else: print(" [venue non letto -> uso i valori verificati dal coordinatore il 22/08 (§50)]") lot = {"BTC": 772.0, "ETH": 242.0} print(f""" Il sleeve VRP01 e' 50/50 BTC+ETH al peso di libro 12%. Un lotto NON si divide: sotto un lotto la gamba non esiste, e la meta' BTC del sleeve cade prima della meta' ETH.""") print(f" (memoria: $242 ETH / $772 BTC, §50 22/08 — e $1.832/$6.210 sulla famiglia INVERSE," f" che un conto USDC non puo' marginare)") print(f"\n {'capitale PROPRIO':>18}{'quota 12%':>12}{'lotti ETH':>11}{'lotti BTC':>11} sleeve") soglia_eth, soglia_btc = lot["ETH"] / 0.06, lot["BTC"] / 0.06 for c in (635.0, 2_000.0, soglia_eth, 5_000.0, 6_440.0, soglia_btc, 20_000.0, 100_000.0): q = 0.12 * c ne, nb = int(q / 2 / lot["ETH"]), int(q / 2 / lot["BTC"]) stato = ("assente" if ne + nb == 0 else "ETH-only (meta' del sleeve)" if nb == 0 else "50/50 come modellato") print(f" {c:>18,.0f}{q:>12,.0f}{ne:>11}{nb:>11} {stato}") print(f""" A $100.000 il sleeve e' 50/50 con {int(0.06*100000/lot['ETH'])} lotti ETH e {int(0.06*100000/lot['BTC'])} BTC: il muro di taglia di VRP01 CADE del tutto. CORREZIONE A UN NUMERO PUBBLICATO IERI (§50 / CLAUDE.md): "1 lotto ETH copre il peso di book 12% gia' da ~$2.000, e il BTC da ~$6.440" divide il lotto per 0,12 — cioe' mette TUTTO il peso del sleeve su UNA gamba. VRP01 e' 50/50: la gamba ETH vede il 6% del libro, non il 12%. Soglie vere: prima gamba (ETH) da ${soglia_eth:,.0f}; sleeve 50/50 completo da ${soglia_btc:,.0f} — cioe' il DOPPIO di quanto pubblicato, su entrambe. Non cambia nessuna decisione (VRP01 e' fermo per una regola), ma e' lo stesso errore di un fattore 2 in due punti. E non serve a niente: VRP01 e' fuori dal libro live per una REGOLA ("niente short-vol da modello in deploy") e per un `f` misurato 0,73 sulle quote vere — nessuna delle due dipende dal capitale. E' la forma piu' pulita del risultato di questo filone: il muro cade, la porta resta chiusa.""") # ============================================================================================= # SEZ. 5 — I GATE SONO INVARIANTI AL CAPITALE # ============================================================================================= def sezione5(res: dict) -> dict: sez("5) IL PUNTO STRUTTURALE — un gate calcolato sulla serie MODELLATA E' GIA' il gate a $100k") print(""" La serie modellata e' il limite a capitale infinito della serie eseguita (nessun ordine viene mai saltato). Quindi: se a $100k l'eseguita converge alla modellata, il verdetto dei gate a $100k E' gia' quello pubblicato — non serve rifarli, e soprattutto NON SI PUO' sperare che cambino. Verifico la premessa (convergenza) e poi la conseguenza (il verdetto non si muove).""") import altlib as al sub("5a) convergenza a $100k: max|differenza| giornaliera contro la serie modellata") for nome, r in res.items(): d = np.abs(r["nets"][100_000.0] - r["nets"]["MOD"]).max() print(f" {nome:<26} max|dif| = {d:.3e} dSharpe = " f"{r['sh'][100_000.0] - r['sh_mod']:+.4f} % noz = {r['noz'][100_000.0]:.1f}%") print(f" A3 CONFERMATA: a $100k tutti e tre stanno entro {TOL_STAB} di Sharpe dalla modellata.") sub("5b) `marginal_vs_tp01` a ogni capitale — il verdetto si muove col capitale?") print(f"\n {'candidato':<26}" + "".join(f"{('$%s' % f'{c:,.0f}'):>13}" for c in CAPITALI) + f"{'MODELLATA':>13}") ver = {} for nome, r in res.items(): row, vv = [], [] for c in list(CAPITALI) + ["MOD"]: s = pd.Series(r["nets"][c], index=r["cand"]["idx"]) m = al.marginal_vs_tp01(s) v = m.get("marginal_verdict", "?") row.append(v) vv.append(v) ver[nome] = vv print(f" {nome:<26}" + "".join(f"{v:>13}" for v in row)) print(""" Lettura: dove il verdetto cambia fra $635 e $100k, NON e' che la taglia sblocchi l'edge — e' che sotto C* la serie non e' la strategia (sez. 3b). Il verdetto che conta e' quello sulla MODELLATA, ed e' quello che i registri hanno gia' pubblicato.""") sub("5c) `weights_tilt_null` a ogni capitale — libro LIVE 75/25, lente `hourly`, candidato 15%") import r0724_skh_live_weight as skl import r0725_capcurve as CC from src.portfolio.portfolio import combine_outer, metrics, weights_tilt_null skh = skl.skh_book(0, "hourly") if skh.index.tz is None: skh.index = skh.index.tz_localize("UTC") lo = pd.Timestamp("2019-03-14", tz="UTC") tp = CC.tp01_realistic(635.0 * 0.75) base = combine_outer({"TP01": tp, "SKH01": skh}, {"TP01": 0.75, "SKH01": 0.25}, lo=lo) mb = metrics(base) print(f" REPLICA del libro pubblicato (lente `hourly`): Sharpe {mb['sharpe']:.3f} " f"(pubblicato 1,683) maxDD {100*mb['maxdd']:.2f}% (pubblicato 11,22%) " f"-> {'OK' if abs(mb['sharpe']-1.683) < 0.02 else 'DIVERGE'}") print(f"\n {'candidato':<26}{'capitale':>10}{'d_insample':>12}{'pctl_hold':>11}" f"{'frac_rand':>11}{'gate_pass':>11}") for nome, r in res.items(): for c in CAPITALI: s = pd.Series(r["nets"][c], index=r["cand"]["idx"]) # TP01 va valutato allo STESSO capitale del candidato (altrimenti si confronta un # candidato a $100k con un TP01 a $635): e' l'errore che il progetto chiama # "un controllo puntato su una configurazione diversa da quella che gira". tpc = CC.tp01_realistic(c * 0.6375) g = weights_tilt_null({"TP01": tpc, "SKH01": skh, "C": s}, {"TP01": 0.75, "SKH01": 0.25, "C": 0.0}, {"TP01": 0.6375, "SKH01": 0.2125, "C": 0.15}, n=300, seed=SEED) print(f" {nome:<26}{c:>10,.0f}{g['delta_insample']:>12.4f}{g['pctl_hold']:>11.1f}" f"{g['frac_random_beat_hold']:>11.2f}{str(g['gate_pass']):>11}") print(""" ATTENZIONE, e vale piu' del PASS: `frac_random_beat_hold` sta a 0,8-0,9 — cioe' 8-9 tilt CASUALI su 10 battono i pesi correnti sull'hold-out. Dove vale cosi', "questo candidato migliora l'hold-out" e' un claim GENERICO (§50 lo dice sullo stesso gate). E il libro di riferimento non e' quello su cui XSR01 fu bocciato: CLAUDE.md riporta FAIL sul book di RICERCA a 5 sleeve, qui il libro e' quello LIVE a 2. Due libri, due verdetti — si dichiara quale.""") return ver # ============================================================================================= # SEZ. 6 — BIN-FREQ # ============================================================================================= def sezione6() -> None: sez("6) BIN-FREQ — l'UNICO archiviato la cui condizione di riapertura E' una soglia di capitale") eur_635 = 0.0113 # RESULTS §25: taglia misurata a $635 rapporto_fam = 0.007 / 0.112 # mediana di famiglia / argmax print(f""" §25 (22/08) chiude BIN-FREQ con quattro gambe, e la quarta e' esplicitamente di TAGLIA: (1) mediana di famiglia >= meta' della cella e >65% celle positive -> FAIL (6%, 54%) (2) weights_tilt_null -> FAIL / vacuo (3) marginale + null con potenza -> PASS (4) taglia >= EUR 0,10/giorno -> FAIL: EUR {eur_635:.4f}/g a $635 La (4) e' lineare nel capitale. Le altre tre NON lo sono: sono statistiche sulla serie.""") print(f"\n {'capitale':>10}{'EUR/g (cella)':>16}{'EUR/g (famiglia)':>19}{'gate (4)?':>12}") for c in (635.0, 5_600.0, 20_000.0, 53_000.0, 100_000.0, 200_000.0): ec = eur_635 * c / 635.0 ef = ec * rapporto_fam print(f" {c:>10,.0f}{ec:>16.4f}{ef:>19.4f}{('PASS' if ef >= 0.10 else 'PASS(cella)' if ec >= 0.10 else 'FAIL'):>12}") print(f""" A $100.000 la gamba (4) PASSA anche con la stima ONESTA di famiglia (EUR {eur_635*100000/635*rapporto_fam:.3f}/giorno > 0,10) — e' l'unica voce del censimento per cui il capitale cambia davvero un verdetto pre-registrato. MA le gambe (1) e (2) restano FAIL, e sono invarianti al capitale: la mediana di famiglia e' il 6% dell'argmax e il 54% delle celle e' positivo comunque si finanzi il conto. -> BIN-FREQ a $100k: 1 gate su 4 si sblocca, 2 restano chiusi. RESTA UN LEAD.""") # ============================================================================================= # SEZ. 7 — IL COROLLARIO FUNDED # ============================================================================================= def sezione7(res: dict) -> None: sez("7) IL COROLLARIO FUNDED — il canale e' mai stato accreditato di AMPLIARE l'insieme?") print(""" Distinzione obbligatoria: fin qui la colonna 'capitale' era CAPITALE PROPRIO. Un conto funded da $100k non e' capitale proprio: il nozionale e' della firm, il vincolo binding e' la regola di drawdown (max loss 6% STATICO), e il trader incassa una quota del profitto (0,80). Domanda: quali voci del censimento diventano ESEGUIBILI a $100k di nozionale funded e non lo sono a $635 di capitale proprio? E quanto vale, in Sharpe di libro e in EUR/giorno?""") import r0724_skh_live_weight as skl import r0725_capcurve as CC from src.portfolio.portfolio import combine_outer, metrics skh = skl.skh_book(0, "hourly") if skh.index.tz is None: skh.index = skh.index.tz_localize("UTC") lo = pd.Timestamp("2019-03-14", tz="UTC") tp = CC.tp01_realistic(100_000.0 * 0.6375) # libro funded $100k, non $635 base = combine_outer({"TP01": tp, "SKH01": skh}, {"TP01": 0.75, "SKH01": 0.25}, lo=lo) sub("7a) chi si aggiunge davvero (capitale PROPRIO $635 -> nozionale FUNDED $100k)") print(f" {'voce':<26}{'C* (proprio)':>14}{'a $635?':>10}{'a $100k?':>10} perche' non basta") righe = [ ("XS01 (19g, HL)", "SI", "SI", "gia' eseguibile a $635 -> NON e' un ampliamento di taglia; " "sul funded e' un ampliamento di VENUE (§30: Bybit 13/13), gia' contato da §1 (+0,400 J)"), ("XSR01 (50g, HL)", "NO", "SI", "AMPLIAMENTO VERO — ma gate 23/10 aperto e blocchi invarianti al capitale"), ("STATARB-MULTI (51g, HL)", "NO", "SI", "AMPLIAMENTO VERO — ma t 1,31, IC95 contiene lo zero"), ] for nome, a, b, why in righe: cs = res[nome]["cstar"] print(f" {nome:<26}{(f'${cs:,.0f}' if cs else '>200k'):>14}{a:>10}{b:>10}") print(f" {'':<26}{why}") print(""" A5: l'insieme AMMISSIBILE non si amplia (entrambi hanno un blocco che il capitale non tocca). L'insieme ESEGUIBILE si amplia di due voci, ed e' un fatto nuovo: nessun filone del progetto aveva mai misurato che a $100k STATARB-MULTI e XSR01 girano al 99,6% del nozionale.""") sub("7b) quanto varrebbe, se fossero ammissibili — ISO-BARRIERA, su FINESTRA COMUNE") print(""" A ISO-NOZIONALE un diversificatore a basso CAGR toglie reddito (regola 25/07 §3). Su un conto funded la lente giusta e' la BARRIERA: si cerca la leva k che porta il maxDD alla regola dei -6% e si legge il drift a quella leva. E' un LIMITE SUPERIORE, non una simulazione (breach a un giorno, lente wick accoppiata e morte-firm sono §37). FINESTRA COMUNE 2024+ obbligatoria: i candidati esistono solo da li'. Con la finestra piena `combine_outer` rinormalizza per riga, il maxDD del libro cade PRIMA del 2024 e le tre righe danno la STESSA k -> il confronto non misura niente (errore commesso e corretto in sessione).""") lo2 = pd.Timestamp("2024-01-01", tz="UTC") print(f"\n {'libro (finestra comune 2024+)':<34}{'Sharpe':>8}{'maxDD':>8}{'k@-6%':>8}" f"{'drift@k':>9}{'EUR/g $100k funded':>21}") base_rows = {} for lab, nome in [("LIVE 75/25 (TP01+SKH01)", None), ("+ XSR01 @15%", "XSR01 (50g, HL)"), ("+ STATARB-MULTI @15%", "STATARB-MULTI (51g, HL)")]: if nome is None: b = combine_outer({"TP01": tp, "SKH01": skh}, {"TP01": 0.75, "SKH01": 0.25}, lo=lo2) else: s_ = pd.Series(res[nome]["nets"][100_000.0], index=res[nome]["cand"]["idx"]) b = combine_outer({"TP01": tp, "SKH01": skh, "C": s_}, {"TP01": 0.6375, "SKH01": 0.2125, "C": 0.15}, lo=lo2) b = b[b.index >= lo2] r = b.values m = metrics(b) k = k_barriera(r) g = cagr_k(r, k, b.index) eur = SPLIT_FUNDED * g * 100_000.0 / 365.0 / EURUSD base_rows[lab] = eur print(f" {lab:<34}{m['sharpe']:>8.3f}{100*m['maxdd']:>7.1f}%{k:>8.2f}{100*g:>8.1f}%" f"{eur:>21.2f}") d1 = base_rows["+ XSR01 @15%"] - base_rows["LIVE 75/25 (TP01+SKH01)"] d2 = base_rows["+ STATARB-MULTI @15%"] - base_rows["LIVE 75/25 (TP01+SKH01)"] print(f""" L'AMPLIAMENTO VALE, come LIMITE SUPERIORE: XSR01 {d1:+.2f} EUR/giorno, STATARB-MULTI {d2:+.2f} EUR/giorno su $100.000 di nozionale funded — e ZERO oggi, perche' nessuno dei due e' ammissibile. ⚠️ La finestra 2024+ NON contiene un sinistro: il maxDD del libro li' e' molto piu' piccolo che sulla storia piena, quindi k e' gonfiata per TUTTE le righe. Il numero da leggere e' la DIFFERENZA, non il livello — e resta un tetto, perche' il funding dei candidati non e' contato. ✅ REPLICA D'ORDINE DI GRANDEZZA: la riga LIVE da' {base_rows['LIVE 75/25 (TP01+SKH01)']:.0f} EUR/giorno su un conto funded da $100k, contro i "~EUR 15-30/g max" che il progetto pubblica dal 25/07 per UN conto con cap $200k/trader. Macchineria diversa (qui una k iso-barriera, li' un MC con breach), stesso ordine di grandezza. 📌 E IL CONFRONTO CHE CONTA: la somma di TUTTI i lead dell'ondata 22-23/08 vale +0,036 EUR/giorno (§57). Il solo AMPLIAMENTO DELL'INSIEME su un conto funded vale, come tetto, {d1:+.2f} / {d2:+.2f} EUR/giorno — cioe' 40-100x. Non e' un argomento per aprire un funded: e' un argomento per smettere di valutare il canale funded SOLO sul nozionale.""") # ============================================================================================= # SEZ. 8 — MDE E VERDETTO # ============================================================================================= def sezione8(res: dict) -> None: sez("8) MDE, LIMITI, VERDETTO") for nome, r in res.items(): idx = r["cand"]["idx"] yrs = (idx[-1] - idx[0]) / pd.Timedelta("365.25D") print(f" {nome:<26} {yrs:.2f} anni -> SE(Sharpe) ~ {1/np.sqrt(yrs):.2f}, " f"MDE(95%) ~ {1.96/np.sqrt(yrs):.2f} di Sharpe") print(""" Cio' che questo filone PUO' dire con questi dati: dove sta la soglia di eseguibilita' (e' una misura deterministica sul pavimento del venue, non una stima statistica, e non ha MDE). Cio' che NON puo' dire: se uno di questi candidati abbia un edge — su 2,6 anni l'MDE e' ~1,2 di Sharpe, cioe' meta' del loro Sharpe modellato. Non lo dico: lo dicono i gate gia' pubblicati. LIMITI DICHIARATI - I 3 candidati misurati vivono su HYPERLIQUID. Che un conto funded (Bybit, §30) listi le 50 gambe di XSR01 NON e' verificato: §30 ha verificato le 13 di U13. E' una GET pubblica: costa zero e va fatta prima di credere alla sez. 7. - `sim_libro` applica il pavimento per gamba e non modella il lotto minimo per-strumento HL (lotti $0,01-7,72 sui 19 major, sotto il pavimento $10 -> non binding). Sui 50 alt della coda non e' verificato strumento per strumento. - Lo slippage NON e' nel conto: HL-EXEC lo ha refutato come rischio #1 con margine 21x, ma su UNA fotografia di 172 secondi, e SLIP-AUDIT ha scritto che la partecipazione scala lineare -> a $100k la misura di attrito a $635 NON si estrapola. La sez. 7 va riletta a quella taglia. - Il funding NON e' nel conto per i 3 candidati (§35 lo ha prezzato per il libro, non per loro): XS01 paga +1,45%/anno (§37) e i due panieri dollar-neutral hanno la stessa esposizione al prezzo cross-sezionale del funding. Ogni EUR/giorno della sez. 7 e' quindi OTTIMISTA.""") def main() -> None: ap = argparse.ArgumentParser() ap.add_argument("--no-net", action="store_true") a = ap.parse_args() t0 = time.time() sez("§67 REGIME-CAPITALE — gli SCARTATI PER TAGLIA, rimisurati a $635 / $5k / $20k / $100k") print(f" avvio {datetime.now(timezone.utc):%Y-%m-%d %H:%M:%S} UTC seed {SEED}") sola_lettura() print(f" parametri venue: Deribit min ${DER_MIN_ORDER:.0f} / {DER_FEE_SIDE*1e4:.2f} bps ; " f"Hyperliquid min ${HL_MIN_ORDER:.0f} / {HL_FEE_SIDE*1e4:.2f} bps " f"(i due HL sono i valori MISURATI il 22/08, non i $5/5,0 bps di memoria)") print(f" lente del libro: `hourly` (path live) — Sh 1,683 / maxDD 11,22%") sezione1() print("\n ricostruzione dei candidati misurabili (repliche prima di ogni delta):") CAND = carica_candidati() res = sezione23(CAND) sezione3d(CAND) sezione4(a.no_net) sezione5(res) sezione6() sezione7(res) sezione8(res) sez("VERDETTO") n = len(CENSIMENTO) n_edge = sum(1 for *_, e in CENSIMENTO if e.startswith("SI")) nf = sum(1 for _, _, _, st, _ in CENSIMENTO if st.startswith("FALSIFICATO")) print(f""" `A $100.000 NESSUN ARCHIVIATO PASSA TUTTI I GATE — E NON PERCHE' LI ABBIA RICONTROLLATI: I GATE PUBBLICATI ERANO GIA' CALCOLATI SULLA SERIE MODELLATA, CHE E' IL LIMITE A CAPITALE INFINITO. IL MURO DI TAGLIA NON NASCONDEVA NIENTE.` Il censimento ha {n} voci; {n_edge} hanno ANCHE un rifiuto sull'edge. Delle {n - n_edge} in cui la taglia era l'unico motivo, nessuna e' una strategia (sono XS01 — gia' sbloccato e fermo per la decisione di venue — e GTAA01, fermo per il PRIIPs). Muri di taglia caduti: {nf} su {n}, tutti nell'ondata 22-23/08, tutti nella stessa direzione. Muri di taglia MISURATI QUI per la prima volta: STATARB-MULTI (C* $2.000-$7.500 secondo la tolleranza) e la curva completa di XSR01 col pavimento del venue GIUSTO (C* $15.000-$20.000, contro i ~$3.000 che HL-EXEC riportava con un criterio piu' permissivo). IN EUR/GIORNO — la domanda del progetto: Questo filone NON avvicina i 50 EUR/giorno. Non aggiunge NIENTE al conto di oggi: tutto cio' che sblocca vive a capitali che il conto non ha, e a quei capitali resta bloccato sull'edge. Il suo contributo e' +0,000 EUR/giorno. Cio' che TOGLIE e' reale ma non e' reddito: il gate XSR01 del 23/10 legge un monitor tarato sul pavimento del venue sbagliato. Per confronto, sullo stesso motore: EUR 250 -> 500 al mese porta P(20 anni) dal 14% all'85%. Libro, pesi, cron, config INVARIATI. Nessun ordine. durata {time.time()-t0:.0f} s""") if __name__ == "__main__": main()