# 2026-08-07 — La crescita del capitale, il fisco che nessuno aveva contato, e se invece fosse un ETF **Richieste dell'operatore, in sequenza:** *«stato progetto»* → *«riepiloga piano»* → *«grafico della crescita per anno con versamento e con guadagno»* → *«con 800 al mese»* → *«sistema dinamico dove imposti valore iniziale, mensile e durata, e calcola la best curva fissando il tempo»* → *«il guadagno come viene calcolato? e se mettessi in MSCI World o ETF SP500?»* → *«quale è la miglior strategia?»*. **Esito: book, pesi, cron, config INVARIATI.** Nessuna decisione operativa cambia. Cambiano tre numeri pubblicati e cade un'affermazione su GTAA01. --- ## 0. Il buco trovato per primo: quattro risultati mai registrati Ricostruendo il piano per l'operatore ho scoperto che **quattro commit del 27/07 sera non sono né in CLAUDE.md né in un diario**: vivono solo nei messaggi di commit e negli script (`r0727_3k_vs_5k.py`, `r0727_orizzonte10.py`, `r0727_tasse.py`). Uno di questi cambia il numero di testa del piano — vedi §2. È il motivo per cui questo diario esiste prima ancora del lavoro nuovo. --- ## 1. Come si calcola il «guadagno» — la domanda che andava fatta Nessuna traiettoria del progetto ipotizza un rendimento. Il meccanismo, ora scritto: 1. si parte dai ritorni giornalieri **veri** del book live (TP01 75% + SKH01 25%), 2.692 giorni dal 2019-03-14, già netti di commissioni; 2. si toglie la fortuna d'ancora: `r − (1−0.89)·media(r)`; 3. si **rimescolano a blocchi di 20 giorni** (block bootstrap): blocchi, non giorni singoli, per non distruggere il raggruppamento della volatilità; 4. si compone: `cap *= (1+r)` ogni giorno, deposito ogni 30, imposta a fine anno, su 4.000 percorsi; 5. **`guadagno = mediana(capitale) − versato`**. Drift implicito: **17,1% annuo, vol 10,9%**. Non è un'assunzione sul rendimento — è l'assunzione che *il futuro somigli a quei 7 anni*. Che è esattamente ciò che §3 mette alla prova. Script: `scripts/research/r0807_growth_yearly.py` (`--lump`, `--dep`, `--anni`, `--json`). --- ## 2. ⚠️ Il fisco durante l'ACCUMULO — la voce mai contata `TAX_RATE` compariva in **un solo punto** di tutto il progetto: la lordizzazione del bersaglio in fase di *prelievo*. L'accumulo componeva al lordo per dieci o vent'anni. Misurato il 27/07 (`r0727_tasse.py`) e riprodotto oggi su lump €5.000 + €500/mese: | | 5 anni | 10 anni | 15 anni | |---|---|---|---| | costo del fisco d'accumulo | **−15,7%** | **−29,8%** | **−42,6%** | (27/07, lump €10k: −16,8% / −31% / −44% → replica coerente su lump diverso.) **L'errore è composto, non una tantum.** Conseguenza da tenere presente: *tutte* le tabelle a 15-20 anni pubblicate in CLAUDE.md sono al lordo del fisco d'accumulo e vanno lette con questo sconto sopra. Assunzioni dichiarate (33% plusvalenze, minusvalenze in carry 4 anni, 0,2% annuo sul valore), **non un parere fiscale**. Piano a €800/mese, 15 anni: capitale mediano **$450.107** netto contro $776.366 lordo. 📌 **Risultato contro-intuitivo:** versare di più **ritarda il sorpasso** (l'anno in cui il guadagno cumulato supera tutto il versato): 7º anno a €500/mese, 8º a €800, perché si alza l'asticella che il guadagno deve superare. I €300 in più non comprano il sorpasso, comprano il **traguardo**: la mediana tocca il bersaglio al 12º anno invece che al 15º, e P(bersaglio) a 15 anni passa da 73,2% a 99,0%. ⚠️ **€800/mese non bastano per il vincolo dei 10 anni**: P(entro 10 anni) col fisco = **25,5%**. Servono ~€880-1.050/mese (27/07), e a quel punto si versano oltre $119.000 per arrivare a $272.061. --- ## 3. E se invece fosse un ETF S&P 500 o MSCI World Script `scripts/research/r0807_asset_compare.py`. Tre cose andavano rese comparabili: - **la griglia** — le azioni hanno ~252 barre/anno, il book 365: portate su calendario con **0,0 a borsa chiusa** (convenzione GTAA01). Senza, il Sharpe esce ×1,20 (lezione 25/07); - **il fisco** — il book realizza ogni anno al 33%; un UCITS ad accumulazione paga il 26% **alla vendita**. Il differimento è un vantaggio strutturale dell'ETF, ora nel modello (le curve ETF sono valori di *liquidazione*, già al netto dell'imposta latente); - **il bersaglio** — $272.061 vale per la rendita perpetua *del book* e per il 33%. Ricalcolato per ciascuno. | a 15 anni, €5.000 + €500/mese | book | S&P 500 | MSCI World (proxy) | |---|---|---|---| | rendita perpetua | 11,67% | 4,16% | 3,09% | | capitale-rendita necessario | $254.524 | $646.172 | $869.729 | | **lente A** — storia piena di ciascuno | $293.823 → **115%** | $204.663 → **32%** | $188.417 → 22% | | **lente B** — stessa finestra 2019-26 | $295.540 → **118%** | $343.805 → **110%** | $296.707 → 82% | **Il risultato che conta non è quale vince, è che le due lenti danno risposte opposte.** Sulla storia piena il book stravince; sulla stessa finestra **l'S&P 500 accumula più del book**. Il divario della lente A viene interamente dal fatto che i 30 anni dell'indice contengono il 2000 e il 2008, crolli che la strategia non ha mai vissuto. 📌 **E in una riga della tabella delle serie c'è il fatto più importante:** sulla stessa finestra il rendimento è quasi identico — **17,4% contro 16,8%**. Tutta la differenza è nel rischio: vol 11,0% contro 19,6%, maxDD 10,5% contro 33,7%. **Il book non guadagna di più, perde di meno** — che è precisamente ciò che il progetto scrive di TP01 dal 19/06, qui misurato contro un'alternativa vera. E la rendita perpetua vive sul drawdown: per questo il book ha bisogno di **2,5× meno capitale**. ⚠️ MSCI World è un **proxy** (70% SPY + 30% EFA): URTH/ACWI/VT non sono nell'abbonamento dati del conto IB. Fra 50% e 80% di quota USA il drift si muove di 0,7 punti e il Sharpe di 0,05. --- ## 4. Quale strategia: book, ETF o un mix Script `scripts/research/r0807_best_strategy.py`. ⚠️ **Difetto della prima stesura, corretto: un mix esiste solo dove esistono ENTRAMBE le serie.** Confrontavo «storia piena» contro «stessa finestra» come due lenti, ma calcolavo i bersagli del mix sull'intersezione in entrambe — quindi la lente «storia piena» dichiarava trent'anni e ne usava sette (per l'ETF puro dava rendita 8,63% invece del 4,16% vero). **Il confronto fra finestre non è disponibile per un portafoglio misto.** Rifatto su una finestra sola, con gli scenari espressi come spostamento del **drift**, applicabile simmetricamente ai due lati. | quota sul book | base | equity a 30 anni | book dimezzato | entrambi cauti | peggiore | **rimpianto max** | |---|---|---|---|---|---|---| | solo ETF | 68% | 23% | 68% | 23% | 23% | 53% | | 25% book | 80% | 41% | 60% | 27% | 27% | 34% | | **50% book** | **86%** | 58% | 48% | 27% | 27% | **20%** | | 75% book | 84% | 69% | 32% | 23% | 23% | 35% | | solo book | 75% | **75%** | 16% | 16% | 16% | 52% | **Risposta: 50/50**, non perché vinca (vince solo nello scenario base) ma perché ha il **rimpianto massimo più basso**. ⚠️ Il criterio del solo caso peggiore **non** distingue 25% da 50% (27,09% contro 26,99% = pareggio dentro il rumore): a separarli è il rimpianto. 📌 **L'asimmetria fra i due stress È il risultato.** Quello sull'equity è **misurato** — trent'anni esistono e dicono 11,3% invece di 16,5%. Quello sul book è **giudiziale** — metà del drift, scelto a mano, perché 7,4 anni sono tutta la storia che ha e *non c'è nulla con cui stressarlo*. Si può discutere la taglia del taglio, non lo si può togliere. La sua conseguenza è brutale: col drift dimezzato il capitale-rendita del book puro passa da $254k a **$771.646** (rendita 11,67% → 3,85%). **Perché il mix non è un compromesso:** correlazione book↔S&P **+0,082** nei giorni di borsa aperta, **+0,046** nei ribassi; nel 5% di giornate peggiori dell'indice (media −2,94%) il book fa **−0,11%**. Il capitale-rendita del 50/50 è **$235.769**, più basso sia del solo ETF ($311.567) sia del solo book ($254.524): due motori scorrelati *abbassano l'asticella*. ⚠️ Non c'è il rischio di venue (spingerebbe ancora verso il mix), e la decisione del 26/07 tiene tutto su Deribit fino a $20k: questa analisi è **materiale per quella soglia**, non un'indicazione di agire adesso. --- ## 5. Il simulatore nel browser, e la sua verifica `scripts/web/` — motore di accumulo in JavaScript (`engine.js`), serie esportata da `export_series.py`, pagine assemblate da `build.py`. **Il motore JS deve dare la stessa risposta del Python, e lo si prova:** `test_engine.js` confronta mediane e probabilità su due configurazioni già calcolate, verifica che il *versato* (deterministico) coincida al centesimo, e include un **controllo positivo** (un motore col fisco spento dev'essere rilevato fuori tolleranza — un test che non sa fallire non è un test). Il risolutore («quanto serve al mese per centrare il bersaglio in N anni») è validato contro `dep_necessario` di `r0727_tasse.py`: scarti −0,4% / −0,6% / −1,1% su tre configurazioni. Misura che ha cambiato una scelta: la banda del versamento suggerito resta **±1% da 1.200 a 3.000 percorsi** → non domina il Monte Carlo ma la granularità della bisezione (~€5). Percorsi tenuti bassi e **incertezza dichiarata**, invece di pagare tempo per una precisione che non arriva. --- ## 6. Quattro errori miei, tutti trovati da un controllo e non a occhio Sono la parte riutilizzabile del diario. **(a) Dati inventati in un grafico.** Le righe degli anni 1-2 di una serie erano scritte *a memoria* perché l'output del terminale era troncato da `tail`. Le ha trovate il confronto riga-per-riga fra il JSON e i dati incollati nella pagina. **Regola: i dati di una pagina si INIETTANO da un file, mai si trascrivono** — ora è `build.py` a farlo, e il passaggio manuale non esiste più. **(b) «Distorsione sistematica» che non esisteva.** Il motore JS sembrava +0,75% sopra il Python su 8 semi, tutti positivi. Ma erano **8 estrazioni contro UN solo punto Python** (seme 807), che stava in basso nella propria distribuzione: 8 segni concordi rispetto a un punto rumoroso non sono 8 osservazioni indipendenti. Misurato bene (8 semi per parte): **−0,01%, t = −0,04**; e i due campionatori cadono entrambi entro 1,7 SE dall'**atteso analitico** della media di blocco. **Regola: un confronto punto-contro-distribuzione non produce evidenza di distorsione.** **(c) Un confronto impossibile per costruzione** — §4, il mix sull'intersezione. **(d) Una pagina pubblicata rotta.** Python scrive le chiavi dei pesi come `"0.0"`/`"1.0"`, la pagina le ricostruiva con `String(0)` → `"0"`: ogni lookup `undefined`, script morto alla prima riga utile. I pesi intermedi funzionavano *per caso*. **Il controllo che usavo (`node --check`) valida solo la SINTASSI**: ora c'è `smoke.js`, che esegue le pagine con un DOM finto e segnala sia le eccezioni sia gli elementi riempiti con `"undefined"`. **Regola: le chiavi di un dizionario Python si LEGGONO dal JSON, non si ricostruiscono.** --- ## 7. ⚠️ Effetto collaterale del check: un gate di GTAA01 ora FALLISCE `tests/test_gtaa_band_gate.py::test_la_proposta_non_e_selezionata_sull_hold_out` — la proposta (banda 25%, cadenza 5g) risulta **9ª/30 in-sample e 8ª/30 sull'hold-out**: migliora passando all'hold-out, cioè la firma che il test intercetta. CLAUDE.md registra **4/30 e 5/30** (27/07). Caratterizzato prima di riportarlo: - i due ranghi sono separati da **0,00116 di Sharpe** su un'ampiezza di griglia di 0,3124 = lo **0,4%**: il criterio non ha mai avuto margine, era una differenza di un rango; - il calcolo è **deterministico** (due corse, `max|diff| = 0.0`) e il codice del gate è **invariato** dal 27/07 (nessun commit su `r0727_gtaa_band_gate.py`, `gtaa.py`, `eqlib.py`, `eq_splits.py`); - quindi è cambiato **il dato**: `data/raw/` è gitignored e i parquet equity vengono riscritti ogni giorno dal cron con `ADJUSTED_LAST` di IB, che è retroattivo. 📌 **La lezione vale più del test: un gate validato su dati sovrascritti ogni giorno non è ri-verificabile.** Il lato cripto non ha questo problema (`rebuild_history.py` ricostruisce da una sorgente deterministica); il lato equity sì. **Il test NON è stato toccato** — allentare una soglia perché ha smesso di passare è ciò che questo progetto vieta, e un `xfail` silenzierebbe esattamente il segnale. Nulla di operativo dipende da questo (GTAA01 non è deployabile per il blocco PRIIPs e non è nel book live), ma l'affermazione *«il rango NON migliora sull'hold-out»* oggi è falsa: **decisione dell'operatore** se correggere l'affermazione, ripensare il gate, o congelare uno snapshot dei parquet equity per renderlo riproducibile. --- ## Cosa NON cambia Book, pesi, cron, `config/live.json`, i gate pre-registrati (STATARB 27/09, XSR01 23/10, DVOLSPREAD 24/10), la decisione di venue (100% Deribit fino a $20k), il muro pubblicato di $272.061. Gli script di questo diario non toccano la produzione.