Files
PythagorasGoal/scripts/research/r0726_tabella_anni.py
T
Adriano Dal Pastro bdd9e60355 research: tabella anno per anno del piano (EUR 5.000 + 500/mese)
Mette in forma leggibile le misure di r0726_piano_5k500.py, anno per anno e con gli anni
di calendario, piu' tre colonne che mancavano e che servono a leggerla onestamente:
quanto hai VERSATO fino a quel punto (senza, il capitale sembra rendimento), la banda
p10-p90 (meta' dei percorsi sta fuori dalla mediana) e la soglia attraversata.

Traguardo EUR 50/g al capitale mediano: anno 12 (2038). P(traguardo) 16% a 10 anni,
53% a 12, 92% a 15, 99.9% a 20.

Il pezzo che conta: la quota di capitale che viene dal RENDIMENTO invece che dai
versamenti e' 10% al primo anno, 39% al quinto, 63% al decimo, 88% al ventesimo. I primi
anni si giudicano sui versamenti, non sui risultati — e' il motivo per cui il piano e'
fragile all'interruzione precoce (misurato: i primi 5 anni sono il 25% dei soldi e il 58%
del risultato).

Regola del progetto rispettata: un numero pubblicato deve avere uno script committato che
lo riproduce.

Ipotesi dichiarate in testa allo script: x0.89 misurato, book live TP01+SKH01, fisco 33%,
NESSUN rischio di venue e NESSUN decadimento dell'edge (misurati in r0726_venue_risk.py e
r0726_decadimento.py, da leggere insieme a questa).

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

119 lines
4.7 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
"""r0726_tabella_anni.py — la tabella anno per anno del piano dichiarato (€5.000 + €500/mese).
Non aggiunge misure: mette in forma leggibile quelle di `r0726_piano_5k500.py`, anno per anno e
con gli anni di CALENDARIO, piu' tre colonne che nelle tabelle precedenti mancavano e che servono
a leggerla onestamente:
* QUANTO HAI VERSATO fino a quel punto — senza, il capitale sembra un rendimento;
* la BANDA p10-p90, non solo la mediana — meta' dei percorsi sta fuori dalla colonna centrale;
* la SOGLIA attraversata, quando ce n'e' una (GTAA01, decisione venue, traguardo).
Ipotesi dichiarate (le stesse di tutto il filone): fattore d'ancora ×0.89 MISURATO, book live
TP01+SKH01 sul path reale, fisco 33%, EURUSD 1.09, NESSUN rischio di venue e NESSUN decadimento
dell'edge — i due scenari peggiori sono misurati altrove (`r0726_venue_risk`, `r0726_decadimento`)
e vanno letti insieme a questa.
uv run python scripts/research/r0726_tabella_anni.py
"""
from __future__ import annotations
import sys
from pathlib import Path
import numpy as np
import pandas as pd
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "scripts" / "research"))
import r0725_capcurve as CC # noqa: E402
import r0726_capwall_refresh as WR # noqa: E402
import r0726_deposits as DP # noqa: E402
OGGI = pd.Timestamp("2026-07-26")
CONTO = 596.92
LUMP_EUR, MENSILE_EUR = 5_000.0, 500.0
N_PATHS, BLOCK, YEARS, SEED = 6000, 20, 20, 20260726
SOGLIE = [(13_000, "GTAA01 entra nel book"),
(20_000, "si riapre la decisione venue"),
(117_000, "XS01 eseguibile")]
def main() -> None:
r = DP.deluck_returns()
gross = CC.TARGET_EUR_DAY * 365 * CC.EURUSD / (1 - CC.TAX_RATE)
_, perp, wall = WR.perp_and_wall(r, 1.0, gross)
start = CONTO + LUMP_EUR * CC.EURUSD
dep = MENSILE_EUR * CC.EURUSD
rng = np.random.default_rng(SEED)
n_days = 365 * YEARS
paths = CC._boot_paths(r, N_PATHS, n_days, BLOCK, rng)
cap = np.full(N_PATHS, start)
paid = start
snaps, paid_at = {}, {}
for t in range(n_days):
cap = cap * (1.0 + paths[:, t])
if t % 30 == 0 and t > 0:
cap += dep
paid += dep
if (t + 1) % 365 == 0:
y = (t + 1) // 365
snaps[y], paid_at[y] = cap.copy(), paid
print("=" * 104)
print(" PIANO €5.000 SUBITO + €500/MESE — anno per anno")
print("=" * 104)
print(f" partenza ${start:,.0f} · bersaglio €{CC.TARGET_EUR_DAY:.0f}/g = ${wall:,.0f} "
f"· rendita perpetua {perp:.2%} · fattore d'ancora ×{DP.DELUCK}")
print(f" {N_PATHS:,} percorsi bootstrap · SENZA rischio di venue e SENZA decadimento "
f"dell'edge (misurati a parte)")
print(f"\n {'anno':>5}{'':>7}{'versato':>11}{'p10':>12}{'MEDIANO':>13}{'p90':>13}"
f"{'rendita med.':>15}{'P(traguardo)':>14} soglia")
print(" " + "-" * 100)
viste = set()
for y in range(1, YEARS + 1):
s = snaps[y]
med = float(np.median(s))
rent = med * perp * (1 - CC.TAX_RATE) / 365.0 / CC.EURUSD
p_wall = float((s >= wall).mean())
nota = ""
for lv, txt in SOGLIE:
if lv not in viste and med >= lv:
viste.add(lv)
nota = f"<- {txt}"
if wall not in viste and med >= wall:
viste.add(wall)
nota = "<- ⭐ TRAGUARDO (capitale mediano)"
anno_cal = (OGGI + pd.DateOffset(years=y)).year
print(f" {y:>5}{anno_cal:>7}{paid_at[y]:>10,.0f}${np.percentile(s,10):>11,.0f}"
f"${med:>12,.0f}${np.percentile(s,90):>12,.0f}"
f"{rent:>12.2f} €/g{p_wall:>13.1%} {nota}")
# da dove viene il capitale
print("\n" + "=" * 104)
print(" DA DOVE VIENE IL CAPITALE (mediano)")
print("=" * 104)
print(f"\n {'anno':>5}{'versato':>12}{'rendimento':>14}{'quota da rendimento':>22}")
for y in (1, 3, 5, 10, 15, 20):
med = float(np.median(snaps[y]))
ret = med - paid_at[y]
print(f" {y:>5}{paid_at[y]:>11,.0f}${ret:>13,.0f}${ret/med:>21.0%}")
print("\n All'inizio il capitale E' quello che hai versato; il rendimento diventa la parte")
print(" principale solo dopo ~8-10 anni. E' la ragione per cui i primi anni si giudicano")
print(" sui VERSAMENTI e non sui risultati.")
print("\n ⚠️ La colonna MEDIANA non e' una previsione: meta' dei percorsi sta sotto. La banda")
print(" p10-p90 e' larga per costruzione (vol ~8%/anno composta per 20 anni), e i due")
print(" scenari che la tabella NON contiene — fallimento del venue e morte dell'edge —")
print(" sono misurati in r0726_venue_risk.py e r0726_decadimento.py.")
if __name__ == "__main__":
main()