Files
PythagorasGoal/scripts/research/r0727_orizzonte10.py
T
Adriano Dal Pastro 067c89fc16 research(capitale): aggiunta la riga 10k al filone orizzonte-10
10.000 EUR + 500/mese: P(entro 10 anni) 33.9% (contro 19.7% con 5k), mediana 10.7 anni,
rendita a 10 anni 42.25 EUR/g. Raddoppia quasi la probabilita' ma resta fuori dal vincolo.

Versamento richiesto con lump 10k: P=50% -> 604 EUR/m, P=75% -> 793, P=90% -> 975.
Cioe' 5.000 EUR in piu' oggi valgono 77 EUR/mese per 10 anni (~9.240): meno del 2.45x
misurato su 20 anni, perche' a orizzonte corto il lump compone meno.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 19:37:34 +00:00

167 lines
8.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
"""r0727_orizzonte10.py — €50/giorno entro 10 anni: cosa serve, e cosa si ottiene se non c'e'.
IL VINCOLO NUOVO. L'operatore ha 49 anni e non vuole arrivare al capitale-rendita in piu' di
**10 anni**. Le tabelle del 26/07 avevano l'orizzonte come variabile libera e il versamento come
incognita, ma partivano da `START = 600` senza versamento iniziale; quelle del 27/07 hanno il
versamento iniziale ma orizzonte 20 anni. Questa e' l'intersezione: **lump + 10 anni**.
Il fatto gia' misurato che governa tutto (26/07): comprimere l'orizzonte da 20 a 10 anni costa
**2.5× al mese E 2.5× in totale**, perche' a orizzonte corto il rendimento fa il 43% del lavoro
invece del 77%. **A orizzonti corti non si fa lavorare la strategia: si COMPRA il capitale coi
bonifici.** Questo script mette il prezzo su quella frase.
TRE DOMANDE, IN ORDINE DI UTILITA'
(1) Con il piano attuale (€5.000 + €500/mese), che probabilita' c'e' di farcela in 10 anni?
(2) Quanto servirebbe al mese per farcela in 10 anni, a diversi livelli di confidenza?
(3) Se quel numero non e' disponibile: **che rendita si compra in 10 anni con cio' che c'e'?**
(la "domanda inversa" gia' codificata il 26/07: quando l'obiettivo dichiarato non e'
raggiungibile, la tabella utile e' l'altra)
uv run python scripts/research/r0727_orizzonte10.py
"""
from __future__ import annotations
import sys
from pathlib import Path
import numpy as np
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "scripts" / "research"))
import r0725_capcurve as CC # noqa: E402
import r0726_capwall_refresh as WR # noqa: E402
import r0726_venue_risk as VR # noqa: E402
import r0727_lumpsum_split as LS # noqa: E402
ETA = 49
ORIZZONTE = 10
LUMPS = (3_000.0, 5_000.0, 6_043.0, 10_000.0) # 10k = oltre XEON: tocca VWCE/SPYM/PPFB
DEPS = (500.0, 800.0, 1_000.0, 1_500.0, 2_000.0)
CONFIDENZE = (0.50, 0.75, 0.90)
CONC = {"Deribit": 1.0}
def p_entro(series: dict, lump_eur: float, dep_eur: float, years: int = ORIZZONTE,
target: float | None = None) -> dict:
old = LS.TARGET
if target is not None:
LS.TARGET = target
try:
return LS.simulate(CONC, series, 0.0, lump_usd=lump_eur * CC.EURUSD,
dep_eur=dep_eur, years=years)
finally:
LS.TARGET = old
def dep_per_confidenza(series: dict, lump_eur: float, p_target: float,
target: float | None = None) -> float:
"""Versamento mensile minimo perche' P(traguardo entro l'orizzonte) >= p_target."""
lo, hi = 0.0, 12_000.0
for _ in range(16):
mid = 0.5 * (lo + hi)
if p_entro(series, lump_eur, mid, target=target)["p_reach"] >= p_target:
hi = mid
else:
lo = mid
return 0.5 * (lo + hi)
def main() -> None:
series = VR.venue_series()
r = series["Deribit"].values.astype(float)
gross = CC.TARGET_EUR_DAY * 365 * CC.EURUSD / (1 - CC.TAX_RATE)
_, perp_loc, muro_loc = WR.perp_and_wall(r, 1.0, gross)
# ⚠️ Si usa il muro PUBBLICATO ($272.061), non quello ricalcolato qui ($254.524): le due
# costruzioni del "book live" (CC.book_series in r0726_capwall_refresh vs le repliche
# ancorate combinate 75/25 di venue_series) danno rendite perpetue 10.91% e 11.67%. La
# differenza e' del 6%; usare la piu' generosa renderebbe il piano piu' facile di quanto
# ogni altra tabella data all'operatore dica. Si tiene la conservativa e si dichiara.
muro = LS.TARGET
perp = gross / muro
print("=" * 100)
print(f" r0727 — €{CC.TARGET_EUR_DAY:.0f}/GIORNO ENTRO {ORIZZONTE} ANNI "
f"(da {ETA} a {ETA + ORIZZONTE} anni)")
print("=" * 100)
print(f" bersaglio ${muro:,.0f} · rendita perpetua {perp:.2%} · book live de-luckato "
f"×{LS.DELUCK} · tutto su Deribit")
print(f" (ricalcolando il muro dalle serie di QUESTO script uscirebbe ${muro_loc:,.0f} / "
f"{perp_loc:.2%}: si tiene il valore")
print(" pubblicato, che e' il piu' conservativo e il solo confrontabile con le altre tabelle)")
# ------------------------------------------------------------ (1) il piano attuale
print("\n" + "=" * 100)
print(" (1) IL PIANO ATTUALE REGGE IL VINCOLO?")
print("=" * 100)
print(f"\n {'lump':>9}{'dep/mese':>11}{'P(entro 10a)':>15}{'mediana SE ce la fa':>22}"
f"{'rendita a 10a':>17}")
for lump in LUMPS:
for dep in (500.0,):
x = p_entro(series, lump, dep)
rend = x["median_end"] * perp * (1 - CC.TAX_RATE) / 365.0 / CC.EURUSD
yrs = f"{x['median_yrs']:.1f}a" if not np.isnan(x["median_yrs"]) else "n.d."
print(f" €{lump:>8,.0f}{dep:>11,.0f}{x['p_reach']:>15.1%}{yrs:>22}"
f"{rend:>14.2f} €/g")
print("\n ⚠️ La colonna 'mediana SE ce la fa' e' CONDIZIONATA ai percorsi che arrivano:")
print(" con P(entro 10a) del 15-23% quei 9.2-9.4 anni sono la mediana di una minoranza")
print(" fortunata, NON il tempo atteso. La mediana incondizionata e' ~11.3-11.7 anni")
print(" (misura del 27/07), cioe' FUORI dal vincolo.")
# ------------------------------------------------------------ (2) quanto serve
print("\n" + "=" * 100)
print(f" (2) QUANTO SERVE AL MESE PER FARCELA IN {ORIZZONTE} ANNI")
print("=" * 100)
print(f"\n {'lump':>9}" + "".join(f"{f'P={c:.0%}':>13}" for c in CONFIDENZE)
+ f"{'totale versato @P=75%':>25}")
for lump in LUMPS:
row = [dep_per_confidenza(series, lump, c) for c in CONFIDENZE]
tot = lump * CC.EURUSD + row[1] * CC.EURUSD * 12 * ORIZZONTE
print(f" €{lump:>8,.0f}" + "".join(f"{d:>12,.0f}€" for d in row) + f"{tot:>24,.0f}$")
print(f"\n ⚠️ Confronto col bersaglio (${muro:,.0f}): a P=75% si VERSA la maggior parte di")
print(" cio' che si vuole avere. E' la frase del 26/07 col prezzo attaccato:")
print(" a orizzonte corto non fai lavorare la strategia, COMPRI il capitale coi bonifici.")
# ------------------------------------------------------------ (3) la domanda inversa
print("\n" + "=" * 100)
print(f" (3) SE QUEL NUMERO NON C'E': CHE RENDITA SI COMPRA IN {ORIZZONTE} ANNI")
print("=" * 100)
print(f"\n (lump €10.000; rendita NETTA mediana a {ORIZZONTE} anni, e in quanti anni")
print(" si arriverebbe invece ai €50/g)")
print(f"\n {'dep/mese':>10}{'cap. mediano a 10a':>21}{'rendita a 10a':>16}"
f"{'anni per €50/g':>17}{'eta a quel punto':>19}")
for dep in DEPS:
a = p_entro(series, 10_000.0, dep, years=ORIZZONTE)
b = LS.simulate(CONC, series, 0.0, lump_usd=10_000.0 * CC.EURUSD, dep_eur=dep, years=25)
rend = a["median_end"] * perp * (1 - CC.TAX_RATE) / 365.0 / CC.EURUSD
yrs = b["median_yrs"]
print(f" {dep:>9,.0f}{a['median_end']:>20,.0f}${rend:>13.2f} €/g"
f"{yrs:>16.1f}a{ETA + yrs:>18.0f}")
# ------------------------------------------------------------ le altre leve
print("\n" + "=" * 100)
print(" LE ALTRE DUE LEVE, PER COMPLETEZZA (misurate altrove, non qui)")
print("=" * 100)
# ⚠️ Le righe di leva si confrontano fra loro (stessa serie, stesso stimatore), NON col
# muro pubblicato: mescolare i due stimatori attribuirebbe alla leva un 6% che e' solo
# differenza di costruzione della serie.
for k in (1.0, 1.25, 1.5):
_, pk, mk = WR.perp_and_wall(r, k, gross)
print(f" leva {k:.2f}x -> rendita perpetua {pk:.2%}, bersaglio ${mk:,.0f} "
f"({mk / muro_loc - 1:+.0%} vs la stessa serie a leva 1)")
print(" ⚠️ La leva abbassa il muro perche' alza il drift, ma alza il drawdown nella")
print(" stessa proporzione, e `config/live.json` e' oggi cappato a leva lorda <=1x")
print(" (con un test che si rompe se qualcuno lo alza). E' una decisione di RISCHIO,")
print(" non una scorciatoia: il 25/07 ha misurato che la curva Sharpe del book e'")
print(" PIATTA da $600 a $200k, quindi la leva non compra qualita', compra varianza.")
print("\n Canale PROP (25/07): €600 come BIGLIETTO invece che come capitale —")
print(" P(≥€50/g entro 3 anni) ≈ 6%, P(perdere tutto) 52-65%. E' l'unico percorso")
print(" misurato che arriva a €50/g in meno di 10 anni senza capitale, ed e' una")
print(" lotteria con probabilita' note, non un piano.")
if __name__ == "__main__":
main()