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

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

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

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

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

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

910 lines
51 KiB
Python

"""r0823b_retry — §61 RETRY: la POLITICA DI RI-ACQUISTO del biglietto funded (2026-08-23).
IL BUCO CHE CHIUDE
------------------
Un conto funded che rompe una regola muore. Il progetto ha modellato tutto il resto del ciclo
(prezzo, regole, leva, lente accoppiata, funding, morte-firm, fisco) e **mai la politica di
RI-ACQUISTO**: quando ricomprare dopo un bust, con quali soldi, e con quale leva sul conto nuovo.
Nei simulatori esistenti (`r0725_prop_ladder.simulate`, `r0725_prop_coupled.simulate`,
`r0822d_gate_c.ladder`) la politica c'e' — e' **cablata**: *compra sempre, subito, il biglietto
piu' GRANDE che la cassa permette, in tutti e 6 gli slot*. E' la politica piu' aggressiva della
famiglia, non e' mai stata dichiarata come scelta, e **tutti i numeri operativi del canale funded
escono da li'** (42% -> 7,8% -> 4,4% -> 2,6%).
E' diventata una domanda vera solo ieri, per due misure:
(a) §30: la quota d'ingresso e' un **deposito RIMBORSABILE** ("Refundable Challenge Deposit,
returned in full alongside your first funded payout") -> un tentativo fallito costa la
quota, uno riuscito no. E' una struttura a OPZIONE, e le opzioni si comprano piu' volte.
(b) §37: il biglietto batte il libro **solo perche' il piano di versamento c'e'**, cioe'
**perche' si puo' giocare piu' di una volta** ("una lotteria a EV positivo che un conto da
$654 puo' giocare UNA VOLTA SOLA").
Se il valore sta nel NUMERO DI TENTATIVI, la politica di ri-acquisto e' la variabile principale
e non e' mai stata ottimizzata.
LE ATTESE, REGISTRATE PRIMA DI MISURARE (poi riportate confermate/refutate)
--------------------------------------------------------------------------
A1. **Compromesso monotono.** IMMEDIATA massimizza sia il numero di giocate sia P(cassa a zero);
MAI li minimizza entrambi. Nessuna politica dovrebbe dominare su tutte e due le colonne.
A2. **La dose-risposta di §37 dovrebbe essere ripida.** Se il meccanismo e' "quante volte si
gioca", passare da max 1 biglietto a illimitati deve muovere P(>=50 EUR/g) di molto. Se non
lo muove, il meccanismo dichiarato da §37 e' sbagliato (o e' un'altra cosa).
A3. **Il biglietto PICCOLO ($249/$25k) compra piu' giocate e perde sul bersaglio.** 50 EUR/g netti
sono ~$59k di payout netti in 3 anni: con nozionale $25k servono troppi cicli. Mi aspetto
P(zero) piu' bassa e P(>=50/g) piu' bassa. Dominato sul bersaglio, non sulla sopravvivenza.
A4. **SOLO-PAYOUT ~= MAI senza versamenti** (senza payout non c'e' cassa per ricomprare) e
molto piu' vicina a IMMEDIATA con versamenti.
A5. **Il RIMBORSO alza i livelli di ~1-3pp (§37) ma NON cambia l'ordine delle politiche.**
Previsione forte: l'ottimo e' lo stesso nelle tre convenzioni.
A6. 🚨 **Le regole di leva condizionate all'esito passato sono NULL DEL DE-LEVERING.** In un
bootstrap a blocchi il passato non porta informazione sul futuro: una regola "riduci la leva
dopo un bust" puo' agire SOLO cambiando la leva MEDIA. Il controllo obbligatorio e' la leva
COSTANTE alla stessa media realizzata. Mi aspetto REFUTED 3/3 (8ª occorrenza).
A7. **La politica conta meno del versamento.** Mi aspetto uno spread fra politiche di pochi punti
percentuali contro i ~+10pp del passaggio EUR 0 -> EUR 500/mese misurato da §37.
CONVENZIONI (tutte EREDITATE e congelate — nessuna scelta di strategia in questo file)
--------------------------------------------------------------------------------------
* Lente **ACCOPPIATA** (`r0725_prop_coupled`): su una regola a UN GIORNO la close-only e' cieca.
* Conto funded = **W_A TP01 38 / SKH01 38 / XS01 25** (centro della regione robusta di §29),
XS01 = **U13 Binance** fuori campione, finestra **W-LONG 2021+**, de-luck sul drift **x0,89**.
* **Funding dentro** (§35/§37), morte-firm **10%/anno** (assunzione del progetto), cap
**$200k/trader**, fisco **33%**, split **80%**, soglia di prelievo **$100** di quota trader.
* Banda d'ancora: **23 offset x 3 fasi (0,3,7)** = lo stesso sottocampione dichiarato da §32/§37.
La cella di riferimento e' la **MEDIANA** della banda, non la canonica (91° pctl).
* Cassa non spesa: **FERMA** per default (convenzione di §37) e **SUL LIBRO** come sensibilita'
dichiarata in §7 — perche' la convenzione "ferma" penalizza per costruzione le politiche
prudenti, che sono esattamente quelle sotto esame.
* Bootstrap **CONDIVISO** fra tutte le politiche di una stessa tabella -> confronti **APPAIATI**.
COSA NON E' QUESTO FILE: non e' una selezione di strategia (meccanismo, pesi, leva ottima, lente
e soglie sono tutti ereditati); e' la mappatura di una politica OPERATIVA che finora era cablata.
L'argmax su ~30 politiche resta pero' una selezione: si riportano il PLATEAU e la risoluzione MC.
Uso: `nice -n 19 timeout 900 uv run python scripts/research/r0823b_retry.py`
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 (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
import r0822c_skh_anchor_prop as AP # noqa: E402 offset di SKH01 (gamba b)
import r0822d_funding as FD # noqa: E402 il funding (22/08)
import r0822d_gate_c as GC # noqa: E402 ladder di riferimento (§37)
from src.portfolio.sleeves import XS_UNIVERSE # noqa: E402
FD.USE_NET = False
EURUSD = pl.EURUSD
TAX_RATE = pl.TAX_RATE
SPLIT = pl.SPLIT
DELUCK = PA.DELUCK
W_A = GC.W_A
OFFSETS = AP.OFFSETS
PHASES_SUB = AP.PHASES_SUB
MIN_PAYOUT = GC.MIN_PAYOUT_TRADER
HORIZON_DAYS = GC.HORIZON_DAYS
SEED_LAD = GC.SEED_LAD
XS_FUND_ANN = 0.0145 # §37: XS01 PAGA +1,45%/anno di funding (misurato)
N_BAND = 1000 # percorsi per la banda d'ancora (riproduzione §32/§37)
N_MAIN = 2000 # percorsi per la griglia di politiche (cella di rif.)
N_ROB = 1000 # percorsi per la robustezza fra celle
# Sottocampione di offset dichiarato A PRIORI: gli stessi 8 uniformi di `r0726_skh_live_book`
# (la griglia piena e' 23; su 2 CPU condivise con altri 5 processi la piena non sta nel budget,
# e un sottocampione uniforme dichiarato prima e' l'unica forma onesta di ridurla).
BAND_OFFSETS = tuple(range(0, 690, 90))
# numeri PUBBLICATI da riprodurre prima di produrne di nuovi
PUB = dict(anchor_p50g=0.044, anchor_p10=0.025, anchor_p90=0.082, anchor_pzero=0.353,
gatec_p50g=0.026, gatec_p10=0.015, gatec_p90=0.047, gatec_pzero=0.403,
refund_pp_lo=0.01, refund_pp_hi=0.03)
TRIALS = 0
T0 = time.time()
CHEAPEST = min(t[1] for F in pl.FIRMS for t in F["tickets"]) # $249
def bump(n: int = 1) -> None:
global TRIALS
TRIALS += n
def hr(t: str = "") -> None:
print("\n" + "-" * 104)
if t:
print(f" {t}")
print("-" * 104)
def tick(lab: str) -> None:
print(f" [{time.time() - T0:6.0f}s] {lab}", flush=True)
# ============================================================================ LE POLITICHE
def POL(when="immediate", k_reserve=1.0, cadence=0, max_tickets=10 ** 9, size="largest",
lev_rule="const", lev_dn=1.0, lev_up=1.0, lev_lo=0.25, lev_hi=1.50,
max_open=pl.MAX_CONCURRENT) -> dict:
"""Una politica di ri-acquisto. `when`:
immediate — compra appena uno slot e' libero e la cassa basta (= il CABLATO di oggi)
threshold — compra solo se la cassa e' >= k_reserve x il prezzo (tiene una riserva)
earned — il PRIMO biglietto dai propri soldi, i successivi SOLO dai payout/rimborsi
cadence — al piu' un acquisto ogni `cadence` giorni
none — non compra MAI (controllo positivo: deve dare P(>=50/g)=0)
`size`: 'largest' (cablato) o 'cheapest' (piu' giocate, nozionale minore).
`max_open`: quanti conti al MASSIMO possono essere aperti insieme (cablato: 6 = tutti gli
slot). E' l'altra faccia del ri-acquisto: giocare in SERIE invece che in PARALLELO.
`lev_rule`: 'const' | 'down_on_bust' (x lev_dn a ogni bust) | 'up_on_pass' (x lev_up a ogni
pass). La leva di un conto e' fissata all'ACQUISTO e non cambia piu'."""
return dict(when=when, k_reserve=k_reserve, cadence=cadence, max_tickets=max_tickets,
size=size, lev_rule=lev_rule, lev_dn=lev_dn, lev_up=lev_up,
lev_lo=lev_lo, lev_hi=lev_hi, max_open=max_open)
P_BASE = POL() # il cablato, bit-exact vs §37
# ============================================================================ IL SIMULATORE
def ladder_rt(R, G, n_paths, lev, seed, *, pol=None, refund_mode="none", deposit_eur=0.0,
start_eur=pl.START_EUR, min_payout=0.0, boot=None, block=20, deluck=DELUCK,
rb_boot=None, tax=TAX_RATE) -> dict:
"""`r0822d_gate_c.ladder` generalizzato alla POLITICA DI RI-ACQUISTO. Tre aggiunte:
1. `pol` — quando/quale biglietto/con quali soldi/a che leva (sopra);
2. `refund_mode` — 'none' (spesa persa, `pc.simulate`) | 'pass' (`r0725_hyro:200`) |
'payout' (la regola vera della firm);
3. `rb_boot` — se dato, la cassa NON spesa gira sul LIBRO LIVE invece di restare
ferma, con lo STESSO sorteggio di bootstrap (stesso mercato) e lo
stesso fisco annuale di `GC.book_road`.
Con `pol=P_BASE, refund_mode='none', deposit_eur=0, min_payout=0, rb_boot=None` dev'essere
**BIT-EXACT** rispetto a `GC.ladder(..., refund=False)` e quindi a `pc.simulate`: e' §1.
🚨 Zero e' ASSORBENTE ed e' modellato come tale: senza conti vivi e con cassa sotto il
biglietto piu' economico ($249) non si gioca piu'; solo un versamento puo' riaprire il gioco.
"""
pol = pol or P_BASE
rng = np.random.default_rng(seed)
n_days = HORIZON_DAYS
L = len(R)
Rm = R.astype(float).reshape(-1, 1).copy()
Gm = G.astype(float).reshape(-1, 1).copy()
Rm = Rm - (1.0 - deluck) * Rm.mean(axis=0, keepdims=True)
if boot is None:
n_blocks = int(np.ceil(n_days / block))
starts = rng.integers(0, L - block, size=(n_paths, n_blocks))
idx = (starts[:, :, None] + np.arange(block)[None, None, :]).reshape(n_paths, -1)[:, :n_days]
else:
idx = boot
n_slot = pl.MAX_CONCURRENT
# (paths, days): tutti gli slot girano lo STESSO libro -> una colonna basta. La leva
# moltiplica per-slot (serve alle regole di leva) invece che globalmente: `x*lev` e' la
# stessa moltiplicazione in virgola mobile, quindi il bit-exact regge (verificato in §1).
Rb = Rm[idx][:, :, 0]
Gb = Gm[idx][:, :, 0]
FIRMS = pl.FIRMS
cash = np.full(n_paths, start_eur * EURUSD)
basis = cash.copy()
carry = np.zeros(n_paths)
earned = np.zeros(n_paths) # borsellino dei soli payout/rimborsi
phase = np.full((n_paths, n_slot), -1, np.int8)
eq = np.ones((n_paths, n_slot))
firm = np.full((n_paths, n_slot), -1, np.int8)
notional = np.zeros((n_paths, n_slot))
price_paid = np.zeros((n_paths, n_slot))
refunded = np.zeros((n_paths, n_slot), bool)
lev_slot = np.full((n_paths, n_slot), lev)
# soglie della firm materializzate PER SLOT all'acquisto: la dinamica diventa una sola
# espressione vettoriale invece di un loop sulle firm. Le maschere per firm sono disgiunte,
# quindi il risultato e' identico (verificato bit-exact in §1).
TH_TGT = np.zeros((n_paths, n_slot))
TH_DD = np.ones((n_paths, n_slot))
TH_DL = np.ones((n_paths, n_slot))
TH_ML = np.ones((n_paths, n_slot))
TH_DLF = np.ones((n_paths, n_slot))
mult = np.ones(n_paths)
firm_alive = np.ones((n_paths, len(FIRMS)), bool)
cum_payout = np.zeros(n_paths)
spent = np.zeros(n_paths)
got_back = np.zeros(n_paths)
deposited = np.zeros(n_paths)
n_payouts = np.zeros(n_paths, int)
n_tickets = np.zeros(n_paths, int)
lev_sum = np.zeros(n_paths)
last_buy = np.full(n_paths, -10 ** 9)
days_out = np.zeros(n_paths, int)
ever_passed = np.zeros(n_paths, bool)
p_death_day = 1.0 - (1.0 - pl.FIRM_DEATH_PER_YEAR) ** (1 / 365.0)
tickets_order = {}
for fi, F in enumerate(FIRMS):
tickets_order[fi] = sorted(F["tickets"], key=(lambda x: x[0]) if pol["size"] == "cheapest"
else (lambda x: -x[0]))
for t in range(n_days):
died = rng.random((n_paths, len(FIRMS))) < p_death_day
newly_dead = died & firm_alive
firm_alive &= ~died
if newly_dead.any():
for fi in range(len(FIRMS)):
kill = newly_dead[:, fi]
if kill.any():
hit = (firm == fi) & kill[:, None]
phase[hit] = -1
notional[hit] = 0.0
# ---------------------------------------------------------------- acquisti
if pol["when"] == "none":
budget = np.zeros(n_paths, int)
elif pol["when"] == "cadence":
budget = ((t - last_buy) >= pol["cadence"]).astype(int)
else:
budget = np.full(n_paths, n_slot, int)
budget = np.minimum(budget, np.maximum(pol["max_tickets"] - n_tickets, 0))
if pol["max_open"] < n_slot:
budget = np.minimum(budget, np.maximum(pol["max_open"] - (phase >= 0).sum(axis=1), 0))
if budget.any() and (cash >= CHEAPEST).any():
for k in range(n_slot):
free = (phase[:, k] == -1) & (budget > 0)
if not free.any():
continue
for fi, F in enumerate(FIRMS):
used = np.where(firm == fi, notional, 0.0).sum(axis=1)
for (size, price) in tickets_order[fi]:
buy = (free & firm_alive[:, fi] & (cash >= price)
& (used + size <= F["cap"]))
if pol["when"] == "threshold":
buy &= cash >= pol["k_reserve"] * price
elif pol["when"] == "earned":
buy &= (n_tickets == 0) | (earned >= price)
if not buy.any():
continue
cash[buy] -= price
basis[buy] -= price
if pol["when"] == "earned":
take = buy & (n_tickets > 0)
earned[take] -= price
spent[buy] += price
n_tickets[buy] += 1
budget[buy] -= 1
last_buy[buy] = t
phase[buy, k] = 0
eq[buy, k] = 1.0
firm[buy, k] = fi
notional[buy, k] = size
price_paid[buy, k] = price
refunded[buy, k] = False
lv = np.clip(lev * mult, pol["lev_lo"], pol["lev_hi"])
lev_slot[buy, k] = lv[buy]
TH_TGT[buy, k], TH_DD[buy, k], TH_DL[buy, k] = F["ev"]
TH_ML[buy, k], TH_DLF[buy, k] = F["fu"]
lev_sum[buy] += lv[buy]
free = free & ~buy
if not free.any():
break
if not free.any():
break
# ---------------------------------------------------------------- dinamica dei conti
r = Rb[:, t][:, None] * lev_slot
g = Gb[:, t][:, None] * lev_slot
act = phase >= 0
eq_prev = eq
eq = np.where(act, eq * (1.0 + r), eq)
eq_low = np.where(act, eq_prev * (1.0 + r + g), eq)
r_low = r + g
in_ev = act & (phase == 0)
in_fu = act & (phase == 1)
bust = ((in_ev & ((eq_low < 1.0 - TH_DD) | (r_low < -TH_DL)))
| (in_fu & ((eq_low < 1.0 - TH_ML) | (r_low < -TH_DLF))))
phase[bust] = -1
notional[bust] = 0.0
passed = in_ev & (eq >= 1.0 + TH_TGT) & ~bust
phase[passed] = 1
eq[passed] = 1.0
if pol["lev_rule"] == "down_on_bust":
mult *= pol["lev_dn"] ** bust.sum(axis=1)
elif pol["lev_rule"] == "up_on_pass":
mult *= pol["lev_up"] ** passed.sum(axis=1)
if refund_mode == "pass" and passed.any():
back = passed & ~refunded
amt = np.where(back, price_paid, 0.0).sum(axis=1)
cash += amt
basis += amt
earned += amt
got_back += amt
refunded |= back
ever_passed |= passed.any(axis=1)
# ---------------------------------------------------------------- la cassa propria
if rb_boot is not None:
cash = np.maximum(cash * (1.0 + rb_boot[:, t]), 0.0)
# ---------------------------------------------------------------- mensile
if (t + 1) % 30 == 0:
fu = phase == 1
pay = fu & (eq > 1.0) & (((eq - 1.0) * notional * SPLIT) >= min_payout)
gain = np.where(pay, (eq - 1.0) * notional, 0.0)
net = gain.sum(axis=1) * SPLIT * (1.0 - TAX_RATE)
cum_payout += net
cash += net
basis += net
earned += net
n_payouts += (pay.sum(axis=1) > 0).astype(int)
eq = np.where(pay, 1.0, eq)
if refund_mode == "payout":
back = pay & ~refunded
amt = np.where(back, price_paid, 0.0).sum(axis=1)
cash += amt
basis += amt
earned += amt
got_back += amt
refunded |= back
if deposit_eur:
cash += deposit_eur * EURUSD
basis += deposit_eur * EURUSD
deposited += deposit_eur * EURUSD
# fisco annuale sulla sola cassa propria (i payout sono gia' netti)
if rb_boot is not None and (t + 1) % 365 == 0:
gtax = (cash - basis) + carry
due = np.where(gtax > 0, tax * gtax, 0.0)
carry = np.where(gtax > 0, 0.0, gtax)
cash = cash - due
basis = cash.copy()
out = (~(phase >= 0).any(axis=1)) & (cash < CHEAPEST)
days_out += out
eur_day = cum_payout / EURUSD / (n_days / 365.0) / 365.0
stuck = (~(phase >= 0).any(axis=1)) & (cash < CHEAPEST)
return dict(eur_day=eur_day, med=float(np.median(eur_day)),
p10=float(np.percentile(eur_day, 10)), p90=float(np.percentile(eur_day, 90)),
mean_eur=float(eur_day.mean()),
p_ge10=float((eur_day >= 10.0).mean()),
p_target=float((eur_day >= pl.TARGET_EUR_DAY).mean()),
p_zero=float((cum_payout <= 0).mean()),
p_payout=float((n_payouts > 0).mean()),
p_pass=float(ever_passed.mean()),
p_stuck=float(stuck.mean()),
n_tix=n_tickets, med_tix=float(np.median(n_tickets)),
mean_tix=float(n_tickets.mean()),
lev_mean=float(lev_sum.sum() / max(n_tickets.sum(), 1)),
days_out=float(np.median(days_out)),
cash=cash, med_cash=float(np.median(cash)), mean_cash=float(cash.mean()),
p10_cash=float(np.percentile(cash, 10)),
p90_cash=float(np.percentile(cash, 90)),
med_spent=float(np.median(spent)), mean_back=float(got_back.mean()),
contributed=float(start_eur * EURUSD + deposited.mean()))
def se_pair(a: np.ndarray, b: np.ndarray, thr: float = pl.TARGET_EUR_DAY) -> float:
"""SE della DIFFERENZA fra due proporzioni APPAIATE (stessi sorteggi): McNemar.
Con bootstrap condiviso la parte comune si cancella e la risoluzione e' molto migliore
di quella dei livelli — ma non e' zero, e va stampata."""
A = a >= thr
B = b >= thr
n01 = float((A & ~B).sum())
n10 = float((~A & B).sum())
n = len(a)
return float(np.sqrt(max(n01 + n10 - (n01 - n10) ** 2 / n, 0.0)) / n)
# ==================================================================================== main
def main() -> None:
try:
sys.stdout.reconfigure(line_buffering=True)
except Exception: # pragma: no cover
pass
print("=" * 104)
print(" §61 RETRY — la POLITICA DI RI-ACQUISTO del biglietto funded, mappata invece che")
print(" cablata. Quando ricomprare, con quali soldi, a che leva — e quanto conta.")
print("=" * 104)
print(" ATTESE REGISTRATE PRIMA: A1 compromesso monotono giocate/rovina; A2 dose-risposta")
print(" RIPIDA se il meccanismo di §37 e' 'il numero di volte che si gioca'; A3 biglietto")
print(" piccolo = piu' giocate, meno bersaglio; A4 SOLO-PAYOUT ~= MAI senza versamenti;")
print(" A5 il rimborso NON cambia l'ottimo; A6 le regole di leva sono null del de-levering")
print(" (REFUTED 3/3 atteso); A7 la politica conta meno del versamento.")
# ============================================================== §0 pannello
hr("§0. IL PANNELLO — le stesse serie di §29/§37 (U13 Binance, W-LONG 2021+, funding dentro)")
rate = GC.funding_rate()
if rate is None:
print(" !! cache funding assente: il filone si ferma. Un numero senza funding NON e'")
print(" confrontabile con §37, e confrontarlo sarebbe l'errore che §35 ha appena")
print(" pagato. 'non misurabile' e' un risultato.")
return
Cb, Ob, Hb, Lb = PR.ohlc_panels(PR.bin_loader, XS_UNIVERSE)
p13 = Cb[X.U13].dropna()
o13 = Ob.reindex(p13.index)[X.U13]
h13 = Hb.reindex(p13.index)[X.U13]
l13 = Lb.reindex(p13.index)[X.U13]
XSP = {ph: PR.xs_tuples(p13, o13, h13, l13, phase=ph) for ph in PHASES_SUB}
xs0 = XSP[PHASES_SUB[0]]
base = pc.crypto_daily_tuples(1.0, 0.0).index.intersection(xs0.index)
first13 = xs0.index[np.flatnonzero(xs0["R"].values != 0.0)[0]]
I = base[base >= max(first13, pd.Timestamp("2021-01-01", tz="UTC"))]
pc.DELUCK = DELUCK
print(f" W-LONG: {len(I)} giorni {I[0].date()} -> {I[-1].date()} | de-luck x{DELUCK} | "
f"cassa iniziale EUR {pl.START_EUR:.0f} = ${pl.START_EUR*EURUSD:,.0f}")
print(f" orizzonte {HORIZON_DAYS} giorni ({HORIZON_DAYS/30:.0f} versamenti da 30 giorni: "
f"§57 avverte che 'EUR X/mese' qui vuol dire ogni 30 giorni — su 36 mesi torna esatto)")
print(f" biglietti disponibili: " + " | ".join(
f"{F['name']} " + ", ".join(f"${s/1000:.0f}k@${p:.0f}" for s, p in F['tickets'])
for F in pl.FIRMS))
print(f" biglietto piu' economico ${CHEAPEST:.0f} -> sotto questa cassa e senza conti vivi")
print(f" il percorso e' FUORI GIOCO (zero assorbente).")
tick("§0")
# ============================================================== §1 controlli
hr("§1. CONTROLLI — bit-exact contro il simulatore pubblicato, e il controllo POSITIVO")
R0, G0 = AP.rg_off(W_A, I, XSP[0], 0)
f0 = GC.fvec_for(W_A, I, rate, 0, XS_FUND_ANN)
Rc0 = R0 - f0
print(" §1.1 la mia `ladder_rt` col cablato (immediate/largest/const, nessun rimborso,")
print(" nessun versamento, soglia 0, cassa ferma) contro `GC.ladder` di §37:")
a = GC.ladder(Rc0, G0, N_BAND, 0.75, SEED_LAD, refund=False)
b = ladder_rt(Rc0, G0, N_BAND, 0.75, SEED_LAD, pol=P_BASE)
d1 = float(np.abs(a["eur_day"] - b["eur_day"]).max())
print(f" max|diff| percorso per percorso = {d1:.3e} -> "
f"{'IDENTICO' if d1 < 1e-15 else 'DIVERGE — STOP'}")
if d1 >= 1e-15:
print(" Senza questo controllo i numeri sotto sarebbero di un'altra macchina.")
return
bump(2)
print("\n §1.2 e `GC.ladder` e' a sua volta bit-exact contro `pc.simulate` (§37 §4.1);")
print(" la catena e' quindi: ladder_rt == GC.ladder == pc.simulate.")
cfg = tuple(W_A.get(n, 0.0) for n in PA.CRYPTO_PROP)
key = (cfg[0], cfg[1], cfg[2], "shared")
saved = pc._TUP_CACHE.pop(key, None)
pc._TUP_CACHE[key] = (Rc0, G0, I)
ref = pc.simulate([cfg], [0] * pl.MAX_CONCURRENT, n_paths=N_BAND, lev=0.75,
seed=SEED_LAD, lens="coupled", start=str(I[0].date()))
pc._TUP_CACHE.pop(key, None)
if saved is not None:
pc._TUP_CACHE[key] = saved
d2 = float(np.abs(ref["eur_day"] - b["eur_day"]).max())
print(f" max|diff| ladder_rt vs pc.simulate = {d2:.3e} -> "
f"{'IDENTICO' if d2 < 1e-15 else 'DIVERGE'}")
bump(1)
print("\n §1.3 CONTROLLO POSITIVO del selettore di politica — un interruttore che non")
print(" cambia niente e' indistinguibile da un interruttore rotto.")
rngb = np.random.default_rng(51224)
nb = int(np.ceil(HORIZON_DAYS / 20))
st = rngb.integers(0, len(I) - 20, size=(N_MAIN, nb))
BOOT = (st[:, :, None] + np.arange(20)[None, None, :]).reshape(N_MAIN, -1)[:, :HORIZON_DAYS]
rb_full = FD.book_75_25(rate, alloc=654.0)
if rb_full.index.tz is None:
rb_full.index = rb_full.index.tz_localize("UTC")
rb = np.nan_to_num(rb_full.reindex(I).values.astype(float))
rb_dl = rb - (1.0 - DELUCK) * rb.mean()
RB_BOOT = rb_dl[BOOT]
none_pol = ladder_rt(Rc0, G0, N_MAIN, 0.75, SEED_LAD, pol=POL(when="none"), boot=BOOT)
bump(1)
print(f" politica 'MAI COMPRARE': biglietti mediani {none_pol['med_tix']:.0f}, "
f"P(>=50/g) {none_pol['p_target']:.1%}, P(zero payout) {none_pol['p_zero']:.1%} -> "
f"{'OK' if none_pol['p_target'] == 0 and none_pol['p_zero'] == 1 else 'ROTTO'}")
print("\n §1.4 CONTROLLO POSITIVO della cassa-sul-libro: 'MAI COMPRARE' + cassa sul libro")
print(" dev'essere la strada LIBRO di §37 (`GC.book_road`), stessi sorteggi.")
nb_book = ladder_rt(Rc0, G0, N_MAIN, 0.75, SEED_LAD, pol=POL(when="none"), boot=BOOT,
rb_boot=RB_BOOT)
road = GC.book_road(rb, BOOT, pl.START_EUR, 0.0)
d3 = float(np.abs(nb_book["cash"] - road["cash"]).max())
bump(2)
print(f" max|diff| sulla cassa finale = {d3:.3e} -> "
f"{'IDENTICO' if d3 < 1e-9 else 'DIVERGE'} | mediana ${nb_book['med_cash']:,.0f} "
f"(GC.book_road ${road['med_cash']:,.0f})")
tick("§1")
# ============================================================== §2 banda d'ancora
hr("§2. LA BANDA D'ANCORA — riproduzione di §32/§37 e scelta della cella MEDIANA")
print(f" {len(BAND_OFFSETS)} offset (sottocampione uniforme a priori di r0726, la griglia")
print(f" piena e' 23) x {len(PHASES_SUB)} fasi {PHASES_SUB} = "
f"{len(BAND_OFFSETS)*len(PHASES_SUB)} celle, funding DENTRO, politica CABLATA (quella")
print(f" con cui i numeri sono stati pubblicati), {N_BAND} percorsi per cella.")
ev_b = PA.boot_idx(len(I), GC.EV_H, PA.N_PATHS, seed=GC.SEED_EV)
fu_b = PA.boot_idx(len(I), GC.FU_H, PA.N_PATHS, seed=GC.SEED_FU)
cells = []
for off in BAND_OFFSETS:
fA = GC.fvec_for(W_A, I, rate, off, XS_FUND_ANN)
for ph in PHASES_SUB:
Rx, Gx = AP.rg_off(W_A, I, XSP[ph], off)
Rf = Rx - fA
j, lv, _ = GC.best_lev(Rf, Gx, ev_b, fu_b)
lad = ladder_rt(Rf, Gx, N_BAND, lv, SEED_LAD, pol=P_BASE)
cells.append(dict(off=off, ph=ph, J=j, lev=lv, p50=lad["p_target"],
pz=lad["p_zero"], med=lad["med"]))
bump(1)
C = pd.DataFrame(cells)
print(f"\n P(>=50 EUR/g) mediana {C['p50'].median():.1%} (PUB §37 {PUB['gatec_p50g']:.1%}) | "
f"banda [{np.percentile(C['p50'],10):.1%}, {np.percentile(C['p50'],90):.1%}] "
f"(PUB [{PUB['gatec_p10']:.1%}, {PUB['gatec_p90']:.1%}]) | "
f"P(zero) {C['pz'].median():.1%} (PUB {PUB['gatec_pzero']:.1%})")
can = C[(C["off"] == 0) & (C["ph"] == 0)].iloc[0]
pct_can = float((C["p50"] <= can["p50"]).mean())
print(f" cella CANONICA (off 0, fase 0): P(>=50/g) {can['p50']:.1%} = {pct_can:.0%}° pctl "
f"della banda -> il gia' noto: la canonica e' la cella FORTUNATA, non la stima.")
k_med = int((C["p50"] - C["p50"].median()).abs().idxmin())
OFF_M, PH_M, LEV_M = int(C.loc[k_med, "off"]), int(C.loc[k_med, "ph"]), float(C.loc[k_med, "lev"])
print(f" CELLA DI RIFERIMENTO (mediana della banda): offset {OFF_M} min, fase {PH_M}, "
f"leva {LEV_M:.2f}x, P(>=50/g) {C.loc[k_med,'p50']:.1%}")
fM = GC.fvec_for(W_A, I, rate, OFF_M, XS_FUND_ANN)
RxM, G_M = AP.rg_off(W_A, I, XSP[PH_M], OFF_M)
R_M = RxM - fM
tick("§2")
# ============================================================== §3 dose-risposta
hr("§3. QUANTE VOLTE SI GIOCA — la dose-risposta che §37 dichiara come IL meccanismo")
print(" Politica IMMEDIATA (il cablato) con un tetto DURO al numero di biglietti mai")
print(" comprati. E' l'esperimento pulito: cambia SOLO quante volte si puo' giocare.")
print(f" Cella di riferimento, {N_MAIN} percorsi, bootstrap condiviso, deposito rimborsato")
print(" al primo payout (la regola vera), soglia di prelievo $100, nessun versamento.")
print(f"\n {'tetto':>8} {'giocate med':>12} {'giocate medie':>14} {'P(>=50/g)':>10} "
f"{'P(>=10/g)':>10} {'P(zero payout)':>15} {'P(fuori gioco)':>15} {'EUR/g medio':>12}")
dose = {}
for mt in (1, 2, 3, 5, 8, 10 ** 9):
r = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=POL(max_tickets=mt),
refund_mode="payout", min_payout=MIN_PAYOUT, boot=BOOT)
dose[mt] = r
bump(1)
lab = "illim." if mt > 100 else str(mt)
print(f" {lab:>8} {r['med_tix']:>12.0f} {r['mean_tix']:>14.2f} {r['p_target']:>10.1%} "
f"{r['p_ge10']:>10.1%} {r['p_zero']:>15.1%} {r['p_stuck']:>15.1%} "
f"{r['mean_eur']:>12.2f}")
d1_, dinf = dose[1], dose[10 ** 9]
se = se_pair(dinf["eur_day"], d1_["eur_day"])
print(f"\n DA 1 GIOCATA A ILLIMITATE: P(>=50/g) {d1_['p_target']:.1%} -> "
f"{dinf['p_target']:.1%} ({(dinf['p_target']-d1_['p_target'])*100:+.2f}pp, "
f"SE appaiata {se*100:.2f}pp) | giocate mediane {d1_['med_tix']:.0f} -> "
f"{dinf['med_tix']:.0f} | P(zero) {d1_['p_zero']:.1%} -> {dinf['p_zero']:.1%}")
ripida = (dinf["p_target"] - d1_["p_target"]) > 3 * se
print(f" >>> ATTESA A2 ('dose-risposta RIPIDA se il meccanismo e' il numero di giocate'): "
f"{'CONFERMATA' if ripida else 'REFUTATA'}")
tick("§3")
# ============================================================== §4 le politiche
hr("§4. LE POLITICHE DI RI-ACQUISTO — 7 regole di TEMPO x 2 di TAGLIA, senza versamenti")
print(" Le due colonne che vanno SEMPRE lette insieme: 'giocate' e 'P(fuori gioco)'. Una")
print(" politica aggressiva aumenta entrambe, ed e' esattamente la trappola dichiarata.")
print("\n Prima di misurare, l'ARITMETICA del listino — prezzo per $1.000 di nozionale:")
for F in pl.FIRMS:
print(" " + f"{F['name']:>5} " + " ".join(
f"${s_/1000:.0f}k: ${p_/(s_/1000):.2f}/k" for s_, p_ in F["tickets"]))
print(" -> il biglietto GRANDE costa MENO per unita' di nozionale (HYRO $5,79/k contro")
print(" $9,96/k). Piu' giocate piccole NON sono piu' esposizione: sono meno.")
POLS = [
("IMMEDIATA (il cablato)", POL()),
("SOGLIA 2x il prezzo", POL(when="threshold", k_reserve=2.0)),
("SOGLIA 3x il prezzo", POL(when="threshold", k_reserve=3.0)),
("SOLO DAI PAYOUT", POL(when="earned")),
("CADENZA 90 giorni", POL(when="cadence", cadence=90)),
("CADENZA 180 giorni", POL(when="cadence", cadence=180)),
("UN CONTO ALLA VOLTA", POL(max_open=1)),
("DUE CONTI ALLA VOLTA", POL(max_open=2)),
("MAI (1 biglietto)", POL(max_tickets=1)),
]
res4 = {}
for size in ("largest", "cheapest"):
lab_s = "biglietto PIU' GRANDE ($100k)" if size == "largest" else "biglietto PIU' ECONOMICO ($25k)"
print(f"\n --- {lab_s} ---")
print(f" {'politica':>26} {'giocate med':>12} {'P(>=50/g)':>10} {'P(>=10/g)':>10} "
f"{'P(zero)':>9} {'P(fuori gioco)':>15} {'EUR/g med':>10} {'cassa fin. med':>15}")
for name, p in POLS:
pp = dict(p)
pp["size"] = size
r = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=pp, refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT)
res4[(size, name)] = r
bump(1)
print(f" {name:>26} {r['med_tix']:>12.0f} {r['p_target']:>10.1%} "
f"{r['p_ge10']:>10.1%} {r['p_zero']:>9.1%} {r['p_stuck']:>15.1%} "
f"{r['med']:>10.2f} ${r['med_cash']:>14,.0f}")
base_r = res4[("largest", "IMMEDIATA (il cablato)")]
print(f"\n DIFFERENZE APPAIATE contro il cablato (stessi sorteggi), su P(>=50 EUR/g):")
print(f" {'politica':>26} {'dP(>=50/g)':>12} {'SE appaiata':>13} {'dP(fuori gioco)':>17} "
f"{'d giocate med':>14}")
rows4 = []
for size in ("largest", "cheapest"):
for name, _ in POLS:
r = res4[(size, name)]
if (size, name) == ("largest", "IMMEDIATA (il cablato)"):
continue
s = se_pair(r["eur_day"], base_r["eur_day"])
tag = name if size == "largest" else "[pic] " + name
rows4.append(dict(tag=tag, d=r["p_target"] - base_r["p_target"], se=s,
dz=r["p_stuck"] - base_r["p_stuck"],
dt=r["med_tix"] - base_r["med_tix"], p50=r["p_target"],
pstuck=r["p_stuck"]))
print(f" {tag:>26} {(r['p_target']-base_r['p_target'])*100:>11.2f}pp "
f"{s*100:>12.2f}pp {(r['p_stuck']-base_r['p_stuck'])*100:>16.2f}pp "
f"{r['med_tix']-base_r['med_tix']:>14.0f}")
R4 = pd.DataFrame(rows4)
sig = R4[R4["d"].abs() > 2 * R4["se"]]
print(f"\n Politiche che si distinguono dal cablato oltre 2 SE appaiate: "
f"{len(sig)}/{len(R4)}"
+ (f" (fra cui {', '.join(list(sig['tag'].str.strip())[:4])}...)" if len(sig) else ""))
allp = pd.concat([R4[["tag", "p50", "pstuck"]],
pd.DataFrame([dict(tag="IMMEDIATA (il cablato)", p50=base_r["p_target"],
pstuck=base_r["p_stuck"])])], ignore_index=True)
print(f" Spread fra la politica migliore e la peggiore su P(>=50/g): "
f"{(allp['p50'].max()-allp['p50'].min())*100:.2f}pp "
f"(max {allp.loc[allp['p50'].idxmax(),'tag'].strip()} {allp['p50'].max():.1%}, "
f"min {allp.loc[allp['p50'].idxmin(),'tag'].strip()} {allp['p50'].min():.1%})")
s3 = res4[("largest", "SOGLIA 3x il prezzo")]
print(f"\n ⚠ A $654 la SOGLIA 3x e' degenere: il biglietto piu' economico costa ${CHEAPEST:.0f}")
print(f" e 3x sono ${3*CHEAPEST:.0f} > ${pl.START_EUR*EURUSD:,.0f} -> giocate mediane "
f"{s3['med_tix']:.0f}. Non e' una politica prudente, e' 'non giocare' scritta")
print(f" con un'altra sintassi. La soglia in VALUTA ASSOLUTA dipende dal capitale:")
print(f" stessa lezione della banda di GTAA01 (27/07), su un altro parametro.")
pic = res4[("cheapest", "IMMEDIATA (il cablato)")]
a3a = pic["p_target"] < base_r["p_target"]
a3b = pic["p_stuck"] < base_r["p_stuck"]
print(f"\n >>> ATTESA A3: il biglietto piccolo perde sul bersaglio "
f"({pic['p_target']:.1%} contro {base_r['p_target']:.1%}) -> "
f"{'confermata' if a3a else 'REFUTATA'}; e sulla ROVINA "
f"({pic['p_stuck']:.1%} contro {base_r['p_stuck']:.1%}) -> "
f"{'confermata' if a3b else 'REFUTATA'}. Verdetto A3: "
f"{'CONFERMATA' if (a3a and a3b) else 'PARZIALE/REFUTATA'}")
tick("§4")
# ============================================================== §5 la leva
hr("§5. LA LEVA DEL CONTO NUOVO — e il NULL DEL DE-LEVERING, dichiarato PRIMA")
print(" 🚨 In un bootstrap a blocchi il passato NON porta informazione sul futuro: una")
print(" regola 'riduci la leva dopo un bust' puo' agire SOLO cambiando la leva MEDIA. Il")
print(" controllo obbligatorio e' la leva COSTANTE alla stessa media realizzata. Se la")
print(" regola non la batte, e' de-levering travestito (sarebbe l'8ª occorrenza).")
lev_rules = [
("costante (il cablato)", POL()),
("RIDOTTA x0,80 a ogni bust", POL(lev_rule="down_on_bust", lev_dn=0.80)),
("RIDOTTA x0,60 a ogni bust", POL(lev_rule="down_on_bust", lev_dn=0.60)),
("CRESCENTE x1,25 a ogni pass", POL(lev_rule="up_on_pass", lev_up=1.25)),
]
print(f"\n {'regola di leva':>30} {'leva media':>11} {'P(>=50/g)':>10} {'P(zero)':>9} "
f"{'P(fuori gioco)':>15} {'EUR/g medio':>12}")
lev_res = {}
for name, p in lev_rules:
r = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=p, refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT)
lev_res[name] = r
bump(1)
print(f" {name:>30} {r['lev_mean']:>11.3f} {r['p_target']:>10.1%} {r['p_zero']:>9.1%} "
f"{r['p_stuck']:>15.1%} {r['mean_eur']:>12.2f}")
print(f"\n IL NULL: leva COSTANTE alla stessa media realizzata di ciascuna regola")
print(f" {'regola':>30} {'leva cost.':>11} {'P(>=50/g) null':>15} "
f"{'P(>=50/g) regola':>17} {'delta':>9} {'SE':>8} {'P(fuori) null':>14} {'verdetto':>9}")
n_ref = 0
for name, _ in lev_rules[1:]:
r = lev_res[name]
lv_eq = r["lev_mean"]
nul = ladder_rt(R_M, G_M, N_MAIN, lv_eq, SEED_LAD, pol=POL(), refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT)
bump(1)
d = r["p_target"] - nul["p_target"]
s = se_pair(r["eur_day"], nul["eur_day"])
ok = d > 2 * s
n_ref += 0 if ok else 1
print(f" {name:>30} {lv_eq:>11.3f} {nul['p_target']:>15.1%} {r['p_target']:>17.1%} "
f"{d*100:>8.2f}pp {s*100:>7.2f}pp {nul['p_stuck']:>14.1%} "
f"{'BATTE' if ok else 'REFUTED':>9}")
print(f"\n >>> ATTESA A6 ('null del de-levering, REFUTED 3/3'): "
f"{'CONFERMATA' if n_ref == 3 else f'PARZIALE ({n_ref}/3 refutate)'}")
print(" Lettura: la leva del conto nuovo non e' una politica, e' un LIVELLO — e il livello")
print(" ottimo e' gia' cercato simmetricamente da `best_lev` in ogni cella (§29).")
print("\n §5.1 DIAGNOSTICO (non una proposta): il LIVELLO di leva, costante, spazzato sulla")
print(" stessa griglia LEVS di §29. `best_lev` massimizza J = P(pass) x P(vivo), NON")
print(" P(>=50 EUR/g): §29 lo dichiara ('J e P(>=50/g) hanno argmax diversi'). Sceglierla")
print(" qui sul bersaglio sarebbe selezione sulla metrica d'uscita — si mostra il PREZZO.")
print(f"\n {'leva':>8} {'P(>=50/g)':>10} {'P(>=10/g)':>10} {'P(zero payout)':>15} "
f"{'P(fuori gioco)':>15} {'EUR/g medio':>12} {'EUR/g mediano':>14}")
for lv in PR.LEVS:
r = ladder_rt(R_M, G_M, N_MAIN, lv, SEED_LAD, pol=POL(), refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT)
bump(1)
star = " <- best_lev (J)" if abs(lv - LEV_M) < 1e-9 else ""
print(f" {lv:>8.3f} {r['p_target']:>10.1%} {r['p_ge10']:>10.1%} {r['p_zero']:>15.1%} "
f"{r['p_stuck']:>15.1%} {r['mean_eur']:>12.2f} {r['med']:>14.2f}{star}")
tick("§5")
# ============================================================== §6 le tre convenzioni
hr("§6. LE TRE CONVENZIONI SUL DEPOSITO — cambia l'OTTIMO, o solo il livello?")
print(" (i) SPESA PERSA `pc.simulate` — da cui esce il numero operativo del progetto;")
print(" (ii) RIMBORSO AL PASS `r0725_hyro:200` — l'altro modello, contraddittorio;")
print(" (iii) RIMBORSO AL PRIMO PAYOUT — la regola dichiarata dalla firm (§30).")
sel6 = ["IMMEDIATA (il cablato)", "SOGLIA 2x il prezzo", "SOLO DAI PAYOUT",
"CADENZA 180 giorni", "MAI (1 biglietto)"]
conv = [("(i) spesa persa", "none"), ("(ii) al pass", "pass"), ("(iii) al primo payout", "payout")]
tab6 = {}
print(f"\n {'politica':>26} " + " ".join(f"{c[0]:>22}" for c in conv))
for name in sel6:
p = dict([x for x in POLS if x[0] == name][0][1])
line = f" {name:>26} "
for lab, rm in conv:
r = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=p, refund_mode=rm,
min_payout=MIN_PAYOUT, boot=BOOT)
tab6[(name, rm)] = r
bump(1)
line += f"{r['p_target']:>10.1%}/{r['p_stuck']:>9.1%} "
print(line + " <- P(>=50/g) / P(fuori gioco)")
print("\n ARGMAX per convenzione (su P(>=50 EUR/g)):")
same = True
arg0 = None
for lab, rm in conv:
vals = {n: tab6[(n, rm)]["p_target"] for n in sel6}
arg = max(vals, key=vals.get)
if arg0 is None:
arg0 = arg
same &= (arg == arg0)
print(f" {lab:>22}: {arg:>26} ({vals[arg]:.1%})")
dpp = np.median([tab6[(n, "payout")]["p_target"] - tab6[(n, "none")]["p_target"] for n in sel6])
print(f"\n Valore del rimborso (mediana su {len(sel6)} politiche, da 'spesa persa' a")
print(f" 'rimborso al primo payout'): {dpp*100:+.2f}pp su P(>=50/g) "
f"(PUB §37: +1-3pp atteso, misurato {'dentro' if PUB['refund_pp_lo'] <= dpp <= PUB['refund_pp_hi'] else 'FUORI'} banda)")
print(f" Quota media restituita: ${tab6[(sel6[0],'payout')]['mean_back']:,.0f} per percorso")
print(f" >>> ATTESA A5 ('il rimborso NON cambia l'ottimo'): "
f"{'CONFERMATA' if same else 'REFUTATA'}")
tick("§6")
# ============================================================== §7 con i versamenti
hr("§7. CON I VERSAMENTI — dove la politica di ri-acquisto smette di essere gratis")
print(" Con un versamento mensile lo ZERO SMETTE DI ESSERE ASSORBENTE (la cassa si")
print(" riempie di nuovo): P(fuori gioco) va a zero per TUTTE le politiche, e il costo")
print(" della politica aggressiva non si legge piu' li' ma sulla RICCHEZZA TERMINALE.")
print(" Convenzione principale: cassa non spesa SUL LIBRO (la piu' equa verso le politiche")
print(" prudenti); la convenzione di §37 (cassa FERMA) e' riportata come scarto.")
dep_rows = []
for dep in (0.0, 250.0, 500.0):
print(f"\n --- versamento EUR {dep:,.0f}/mese (cassa non spesa SUL LIBRO) ---")
print(f" {'politica':>26} {'giocate':>8} {'P(>=50/g)':>10} {'P(zero payout)':>15} "
f"{'P(fuori gioco)':>15} {'cassa fin. med':>15} {'P(<versato)':>12} "
f"{'speso/entrato':>14}")
for name in sel6:
p_ = dict([x for x in POLS if x[0] == name][0][1])
a_ = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=p_, refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT, deposit_eur=dep)
b_ = ladder_rt(R_M, G_M, N_MAIN, LEV_M, SEED_LAD, pol=p_, refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT, deposit_eur=dep, rb_boot=RB_BOOT)
bump(2)
ploss = float((b_["cash"] < b_["contributed"]).mean())
dep_rows.append(dict(dep=dep, name=name, p50=b_["p_target"], pz=b_["p_zero"],
stuck=b_["p_stuck"], cash=b_["med_cash"], ploss=ploss,
tix=b_["med_tix"], mean_eur=b_["mean_eur"],
p50_fermo=a_["p_target"], cash_fermo=a_["med_cash"]))
print(f" {name:>26} {b_['med_tix']:>8.0f} {b_['p_target']:>10.1%} "
f"{b_['p_zero']:>15.1%} {b_['p_stuck']:>15.1%} ${b_['med_cash']:>14,.0f} "
f"{ploss:>12.1%} {b_['med_spent']/b_['contributed']:>14.1%}")
if dep == 500.0 and name == sel6[0]:
dep500 = b_
if dep == 0.0 and name == sel6[0]:
dep0 = b_
if dep == 500.0 and name == "SOLO DAI PAYOUT":
dep500_safe = b_
D7 = pd.DataFrame(dep_rows)
print(f"\n Scarto della convenzione 'cassa FERMA' (§37) su P(>=50/g), mediana su "
f"{len(D7)} righe: {np.median(D7['p50_fermo']-D7['p50'])*100:+.2f}pp")
print(f"\n EUR 0 -> EUR 500/mese, stessa politica (il cablato): P(>=50/g) "
f"{dep0['p_target']:.1%} -> {dep500['p_target']:.1%} "
f"({(dep500['p_target']-dep0['p_target'])*100:+.2f}pp)")
print(f" Spread fra POLITICHE (§4, senza versamenti): "
f"{(allp['p50'].max()-allp['p50'].min())*100:.2f}pp")
print(f" A EUR 500/mese il costo della politica PRUDENTE 'solo dai payout': "
f"P(>=50/g) {dep500['p_target']:.1%} -> {dep500_safe['p_target']:.1%} "
f"({(dep500_safe['p_target']-dep500['p_target'])*100:+.2f}pp), cassa mediana "
f"${dep500['med_cash']:,.0f} -> ${dep500_safe['med_cash']:,.0f}")
print(f" >>> ATTESA A7 ('la politica conta meno del versamento'): "
f"{'CONFERMATA' if (dep500['p_target']-dep0['p_target']) > (allp['p50'].max()-allp['p50'].min()) else 'REFUTATA'}")
tick("§7")
# ============================================================== §8 robustezza fra celle
hr("§8. ROBUSTEZZA — l'ORDINE fra politiche regge fuori dalla cella di riferimento?")
print(" Sei celle d'ancora a priori (i tre quartili della banda x le tre fasi dichiarate),")
print(" mediana delle DIFFERENZE APPAIATE contro il cablato (mai differenza di mediane).")
Cs = C.sort_values("p50").reset_index(drop=True)
picks = [Cs.iloc[int(q * (len(Cs) - 1))] for q in (0.15, 0.35, 0.50, 0.65, 0.85)]
sel8 = ["SOGLIA 2x il prezzo", "SOLO DAI PAYOUT", "MAI (1 biglietto)"]
st2 = np.random.default_rng(7761).integers(0, len(I) - 20, size=(N_ROB, nb))
BOOT2 = (st2[:, :, None] + np.arange(20)[None, None, :]).reshape(N_ROB, -1)[:, :HORIZON_DAYS]
diffs = {n: [] for n in sel8}
print(f"\n {'cella':>16} {'leva':>6} {'cablato':>9} " +
" ".join(f"{n[:16]:>18}" for n in sel8))
for row in picks:
off, ph = int(row["off"]), int(row["ph"])
fX = GC.fvec_for(W_A, I, rate, off, XS_FUND_ANN)
Rx, Gx = AP.rg_off(W_A, I, XSP[ph], off)
Rf = Rx - fX
lv = float(row["lev"])
b0 = ladder_rt(Rf, Gx, N_ROB, lv, SEED_LAD, pol=POL(), refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT2)
bump(1)
line = f" off{off:>4} fase{ph:>2} {lv:>6.2f} {b0['p_target']:>9.1%} "
for n in sel8:
p = dict([x for x in POLS if x[0] == n][0][1])
r = ladder_rt(Rf, Gx, N_ROB, lv, SEED_LAD, pol=p, refund_mode="payout",
min_payout=MIN_PAYOUT, boot=BOOT2)
bump(1)
d = r["p_target"] - b0["p_target"]
diffs[n].append(d)
line += f"{d*100:>+17.2f}pp"
print(line)
print(f"\n {'politica':>26} {'mediana delle diff. appaiate':>30} {'celle > 0':>11}")
for n in sel8:
v = np.array(diffs[n])
print(f" {n:>26} {np.median(v)*100:>29.2f}pp {int((v > 0).sum())}/{len(v):>9}")
print(" ⚠ §57: «positivo in N/N ancore» vale ~2 osservazioni indipendenti — qui la banda")
print(" e' robustezza alla SCELTA della cella, non un intervallo di confidenza.")
tick("§8")
# ============================================================== §9 verdetto
hr("§9. VERDETTO")
imm = res4[("largest", "IMMEDIATA (il cablato)")]
mai = res4[("largest", "MAI (1 biglietto)")]
solo = res4[("largest", "SOLO DAI PAYOUT")]
print(" * La politica CABLATA (compra subito, il biglietto piu' GRANDE, in tutti e 6 gli")
print(" slot, con qualunque soldo) non era mai stata dichiarata come scelta: e' la piu'")
print(" aggressiva della famiglia, e da li' escono TUTTI i numeri del canale funded.")
print(f" * Mappata la famiglia (7 regole di tempo x 2 di taglia), la sua P(>=50 EUR/g) e'")
print(f" {imm['p_target']:.1%}; massimo di famiglia {allp['p50'].max():.1%} "
f"({allp.loc[allp['p50'].idxmax(),'tag'].strip()}), minimo {allp['p50'].min():.1%}, "
f"spread {(allp['p50'].max()-allp['p50'].min())*100:.2f}pp.")
print(f" * LE DUE COLONNE INSIEME, senza versamenti: cablato {imm['med_tix']:.0f} giocate e "
f"P(fuori gioco) {imm['p_stuck']:.1%};")
print(f" una giocata sola {mai['med_tix']:.0f} e {mai['p_stuck']:.1%}. Il prezzo della "
f"prudenza e' {(imm['p_target']-mai['p_target'])*100:.2f}pp di bersaglio per "
f"{(imm['p_stuck']-mai['p_stuck'])*100:.2f}pp di rovina.")
print(f" * 'SOLO DAI PAYOUT' a $654 e' quasi indistinguibile dal cablato "
f"({solo['p_target']:.1%} contro {imm['p_target']:.1%}): dopo il primo biglietto da "
f"${579:.0f}")
print(f" restano ${pl.START_EUR*EURUSD-579:.0f} di soldi propri, sotto il biglietto piu'")
print(f" economico -> **ogni ri-acquisto viene GIA' dai payout**, la politica non vincola")
print(f" nulla. Vincola solo quando c'e' un versamento (§7).")
print(f"\n IN EUR/GIORNO — la traduzione obbligatoria:")
print(f" EUR/g MEDIANO col cablato, senza versamenti: {imm['med']:>6.2f} EUR/g")
print(f" EUR/g MEDIO col cablato, senza versamenti: {imm['mean_eur']:>6.2f} EUR/g")
fam = {n: tab6[(n, 'payout')]['mean_eur'] for n in sel6}
bn = max(fam, key=fam.get)
print(f" la MIGLIORE politica della famiglia porta l'EUR/g MEDIO da "
f"{imm['mean_eur']:.2f} a {fam[bn]:.2f} ({fam[bn]-imm['mean_eur']:+.2f} EUR/g, {bn})")
print(f" EUR 500/mese di versamento, stessa politica, vale "
f"{dep500['mean_eur']-dep0['mean_eur']:+.2f} EUR/g sulla stessa metrica.")
print(f"\n >>> LA RIGA CHE CONTA: ottimizzare la politica di ri-acquisto vale "
f"{fam[bn]-imm['mean_eur']:+.2f} EUR/g;")
print(f" versare EUR 500/mese ne vale {dep500['mean_eur']-dep0['mean_eur']:+.2f}. "
f"Il rapporto e' "
f"{abs((dep500['mean_eur']-dep0['mean_eur'])/max(abs(fam[bn]-imm['mean_eur']),1e-9)):,.0f}x.")
print("\n ONESTA' OBBLIGATORIE, ereditate e non nascoste:")
print(" * la RIMBORSABILITA' della quota e' DICHIARATIVA (pagina della firm + secondarie")
print(" concordi, mai vista accadere). §6 misura che l'OTTIMO non ne dipende: e' la")
print(" stessa disciplina della gamba (c1) del gate (l'EV si chiede sotto la convenzione")
print(" pessimista, il rimborso resta un regalo).")
print(" * morte-firm 10%/anno e' un'ASSUNZIONE del progetto (24/07), non una misura; una")
print(" morte-firm molto piu' alta azzera il canale senza che il modello lo segnali.")
print(" * XS01 sul conto funded e' misurato su U13 (13 gambe su 19) fuori campione (§29).")
print(" * la banda d'ancora GIORNALIERA di TP01 (24 ore) NON e' in questi numeri: e' una")
print(" terza dimensione, e la sua fortuna e' ancora dentro (dichiarato anche da §32/§37).")
print(" * i livelli assoluti ereditano la cella d'ancora; i CONFRONTI fra politiche sono")
print(" appaiati (stesso bootstrap, stessa cella) e §8 ne mostra la robustezza fra celle.")
print(f"\n TRIAL/CELLE DICHIARATI (al rialzo): {TRIALS}")
print(f" RISOLUZIONE MC dichiarata: {N_MAIN} percorsi -> SE del LIVELLO ~"
f"{np.sqrt(max(imm['p_target'],1e-9)*(1-imm['p_target'])/N_MAIN)*100:.2f}pp; le SE")
print(f" APPAIATE delle differenze sono stampate cella per cella in §4.")
print(f" fatto in {time.time()-T0:.0f}s")
print("=" * 104)
if __name__ == "__main__":
main()