b1c3ff1bb8
Verificato sulle fonti (Fisco Oggi dell'Agenzia, Eutekne, Fiscomania, Circolare AdE 30/E del 27/10/2023, guide professionali) cio' che il progetto assumeva senza averlo mai controllato. NON e' un parere fiscale. CONFERMATO, e nessun numero del piano cambia: 33% sulle plusvalenze cripto realizzate dal 1/1/2026 (art. 67 c.1 lett. c-sexies TUIR); franchigia EUR 2.000 abolita dal 2025; minusvalenze riportabili 4 periodi ma solo contro plusvalenze cripto (art. 68 c. 9-bis); patrimoniale 2 per mille sul valore al 31/12; regime dichiarativo per gli exchange esteri. CORRETTO: il progetto citava «L.199/2025» come origine del 33% in 5 punti (r0725_capcurve, r0725_ib10k x2, r0727_tasse, r0807_asset_compare, diario 24/07). E' falso. Il 33% dal 2026 e l'abolizione della franchigia vengono dalla L. 207/2024 art. 1 c. 23-29. La L. 199/2025 art. 1 c. 28 ritaglia il 26% per i soli token e-money denominati in EURO: BTC/ETH e le stablecoin in dollari restano al 33%. RESTA APERTA la domanda che vale $22k di muro: la Circolare 30/E non tratta i derivati, e le fonti professionali collocano i derivati su cripto fuori dalle cripto-attivita' (c-quater, RT Sez. II, 26%) — ma parlando di CFD di broker UE regolati in euro, non di contratti inverse marginati e regolati IN CRIPTO su sede extra-UE. Registrata la domanda da porre al commercialista nei termini esatti. Trovata per strada una conseguenza modellistica: se i derivati sono c-quater, sono un comparto di compensazione separato → il buffer di carry UNICO di r0807_piano_netto e r0727_tasse e' ottimistico sulla coda (non sull'aliquota). REGOLA: una fonte normativa citata in un commento di codice si verifica come un numero — questa era sbagliata da settimane in 5 file e nessun test poteva accorgersene. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
201 lines
10 KiB
Python
201 lines
10 KiB
Python
#!/usr/bin/env python
|
||
"""r0727_tasse.py — il fisco durante l'ACCUMULO: la voce che nessuna traiettoria ha mai contato.
|
||
|
||
IL BUCO. `TAX_RATE = 0.33` compare in tutto il progetto in UN SOLO punto: la lordizzazione del
|
||
bersaglio (per netto €50/giorno servono €74.6/giorno lordi, da cui il muro di $272.061) e la
|
||
conversione capitale->rendita. **L'accumulo compone al LORDO**: `cap *= (1 + r)` ogni giorno, per
|
||
dieci o vent'anni, senza che il fisco tocchi mai il capitale in crescita.
|
||
|
||
Non e' un dettaglio contabile. Un book che apre e chiude posizioni ogni giorno **realizza** i
|
||
guadagni in continuazione: in Italia le plusvalenze si tassano per CASSA, anno per anno, non
|
||
alla fine. Quindi il modello sta capitalizzando soldi che ogni anno andrebbero versati, e
|
||
l'effetto composto di quell'errore cresce col tempo — proprio sull'orizzonte in cui si sta
|
||
decidendo.
|
||
|
||
COSA SI MISURA QUI
|
||
(1) quanto costa la tassazione annua sulle plusvalenze realizzate;
|
||
(2) quanto costa in piu' l'imposta patrimoniale sul valore delle cripto-attivita';
|
||
(3) di quanto si sposta il versamento mensile necessario per l'obiettivo a 10 anni.
|
||
|
||
⚠️ ASSUNZIONI FISCALI DICHIARATE — NON SONO UN PARERE FISCALE, e vanno confermate:
|
||
* aliquota **33%** sulle plusvalenze cripto realizzate dal **1/1/2026**: fissata dalla
|
||
**L. 207/2024 art. 1 c. 23-29** (che ha anche abolito la franchigia di EUR 2.000 gia' dal
|
||
2025), su `art. 67 c. 1 lett. c-sexies` TUIR. La **L. 199/2025 art. 1 c. 28** (Bilancio 2026)
|
||
NON l'ha toccata: ha solo ritagliato il 26% per i token di moneta elettronica denominati in
|
||
**euro** — BTC/ETH e le stablecoin in dollari restano al 33%. *(Verificato 2026-08-07; il
|
||
progetto citava erroneamente la L.199/2025 come fonte del 33%.)*
|
||
Si misura anche a **26%** perche' resta aperta — e NON risolta da alcun documento
|
||
dell'Agenzia — la qualificazione dei **DERIVATI su cripto**: le fonti professionali li
|
||
collocano fuori dalle cripto-attivita' (`lett. c-quater`, quadro RT Sezione II, 26%) ma
|
||
trattano CFD di broker UE regolati in euro, non contratti *inverse* marginati e regolati IN
|
||
CRIPTO su sede extra-UE. La differenza vale piu' di molte decisioni prese qui.
|
||
* **minusvalenze compensabili nei 4 periodi d'imposta successivi** (`art. 68 c. 9-bis` TUIR;
|
||
modellato: buffer a 4 anni). ⚠️ Le minusvalenze cripto compensano SOLO plusvalenze cripto:
|
||
se i derivati Deribit fossero `c-quater`, sarebbero un comparto SEPARATO e il buffer unico
|
||
di questo modello sarebbe ottimistico sulla coda (non sull'aliquota).
|
||
* imposta **0.2% annua sul valore** delle cripto-attivita' detenute al 31/12 (dovuta sopra
|
||
EUR 12/anno, quadro RW/W).
|
||
* ⚠️ **il modello tassa la variazione ANNUA di valore** (fine anno − inizio anno − versamenti),
|
||
cioe' anche la parte NON realizzata di una posizione aperta a cavallo del 31 dicembre. E'
|
||
quindi un **LIMITE SUPERIORE** rispetto a una tassazione per pura realizzazione. Quanto sia
|
||
superiore dipende dal turnover: TP01 ribilancia ogni giorno e SKH01 chiude round-trip
|
||
discreti, quindi la quasi totalita' del risultato annuo E' realizzata entro l'anno — il vero
|
||
numero sta fra la riga senza imposte e questa, molto piu' vicino a questa.
|
||
|
||
uv run python scripts/research/r0727_tasse.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_venue_risk as VR # noqa: E402
|
||
import r0727_lumpsum_split as LS # noqa: E402
|
||
|
||
ALIQUOTE = (0.0, 0.26, 0.33)
|
||
PATRIMONIALE = 0.002 # 0.2% annuo sul valore (analoga IVAFE)
|
||
CARRY_ANNI = 4 # minusvalenze riportabili
|
||
N_PATHS = 4000
|
||
BLOCK = 20
|
||
SEED = 727
|
||
|
||
|
||
def accumula(r: np.ndarray, lump_eur: float, dep_eur: float, years: int,
|
||
aliquota: float, patrimoniale: float = 0.0,
|
||
n_paths: int = N_PATHS, seed: int = SEED) -> dict:
|
||
"""Accumulo con imposta ANNUA sulle plusvalenze realizzate + patrimoniale sul valore.
|
||
|
||
La plusvalenza dell'anno e' `capitale_fine - capitale_inizio - versamenti_dell_anno`
|
||
(i versamenti non sono reddito). Le minusvalenze vanno in un buffer che scade dopo
|
||
`CARRY_ANNI` anni, come le minusvalenze da redditi diversi.
|
||
"""
|
||
rng = np.random.default_rng(seed)
|
||
n_days = years * 365
|
||
paths = CC._boot_paths(r, n_paths, n_days, BLOCK, rng)
|
||
dep = dep_eur * CC.EURUSD
|
||
cap = np.full(n_paths, LS.START + lump_eur * CC.EURUSD)
|
||
hit = np.zeros(n_paths, bool) # traguardo toccato in QUALUNQUE momento
|
||
carry = np.zeros((n_paths, CARRY_ANNI)) # minusvalenze per anno di formazione
|
||
imposte = np.zeros(n_paths)
|
||
anno_start = cap.copy()
|
||
versato_anno = np.zeros(n_paths)
|
||
|
||
for t in range(n_days):
|
||
cap *= (1.0 + paths[:, t])
|
||
hit |= cap >= LS.TARGET
|
||
if t % 30 == 0 and t > 0 and dep > 0:
|
||
cap += dep
|
||
versato_anno += dep
|
||
if (t + 1) % 365 == 0:
|
||
plus = cap - anno_start - versato_anno
|
||
if aliquota > 0:
|
||
disponibili = carry.sum(axis=1)
|
||
usate = np.minimum(np.maximum(plus, 0.0), disponibili)
|
||
imponibile = np.maximum(plus, 0.0) - usate
|
||
# consuma il carry dal piu' vecchio
|
||
resid = usate.copy()
|
||
for k in range(CARRY_ANNI - 1, -1, -1): # dalla PIU' VECCHIA, che scade prima
|
||
presa = np.minimum(carry[:, k], resid)
|
||
carry[:, k] -= presa
|
||
resid -= presa
|
||
dovuta = imponibile * aliquota
|
||
cap -= np.minimum(dovuta, cap)
|
||
imposte += dovuta
|
||
carry = np.roll(carry, 1, axis=1) # invecchia: l'ultimo scade
|
||
carry[:, 0] = np.maximum(-plus, 0.0)
|
||
if patrimoniale > 0:
|
||
p = cap * patrimoniale
|
||
cap -= np.minimum(p, cap)
|
||
imposte += p
|
||
anno_start = cap.copy()
|
||
versato_anno[:] = 0.0
|
||
|
||
# stessa definizione delle altre tabelle: traguardo toccato in qualunque momento
|
||
return dict(median_end=float(np.median(cap)), p_reach=float(hit.mean()),
|
||
imposte=float(np.median(imposte)),
|
||
versato=LS.START + lump_eur * CC.EURUSD + dep * (n_days // 30))
|
||
|
||
|
||
def dep_necessario(r: np.ndarray, lump_eur: float, years: int, aliquota: float,
|
||
patrimoniale: float, p_target: float = 0.50) -> float:
|
||
lo, hi = 0.0, 15_000.0
|
||
for _ in range(14):
|
||
mid = 0.5 * (lo + hi)
|
||
if accumula(r, lump_eur, mid, years, aliquota, patrimoniale)["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)
|
||
|
||
print("=" * 100)
|
||
print(" r0727 — IL FISCO DURANTE L'ACCUMULO (mai contato in nessuna traiettoria)")
|
||
print("=" * 100)
|
||
print(f" bersaglio ${LS.TARGET:,.0f} (gia' lordizzato al {CC.TAX_RATE:.0%} per il PRELIEVO) · "
|
||
f"book de-luckato ×{LS.DELUCK}")
|
||
print(f" ⚠️ il {CC.TAX_RATE:.0%} nel bersaglio riguarda la fase di RENDITA; qui si misura "
|
||
"cio' che manca: l'imposta")
|
||
print(" annua durante i 10 anni di crescita. Le due NON si sovrappongono.")
|
||
|
||
# ------------------------------------------------------ (1) il costo, a 10 anni
|
||
print("\n" + "=" * 100)
|
||
print(" (1) QUANTO COSTA — €10.000 + €500/mese, orizzonte 10 anni")
|
||
print("=" * 100)
|
||
print(f"\n {'regime':<44}{'cap. mediano':>16}{'P(entro 10a)':>15}{'imposte pagate':>18}")
|
||
base = None
|
||
for al in ALIQUOTE:
|
||
for patr in ((0.0, PATRIMONIALE) if al > 0 else (0.0,)):
|
||
x = accumula(r, 10_000.0, 500.0, 10, al, patr)
|
||
base = base if base is not None else x["median_end"]
|
||
et = "nessuna imposta (il modello pubblicato)" if al == 0 else (
|
||
f"plus {al:.0%}" + (f" + patrimoniale {patr:.1%}" if patr else ""))
|
||
print(f" {et:<44}{x['median_end']:>15,.0f}${x['p_reach']:>15.1%}"
|
||
f"{x['imposte']:>17,.0f}$")
|
||
x33 = accumula(r, 10_000.0, 500.0, 10, 0.33, PATRIMONIALE)
|
||
print(f"\n Costo del regime piu' severo vs il modello pubblicato: "
|
||
f"{x33['median_end'] / base - 1:+.1%} di capitale a 10 anni")
|
||
|
||
# ------------------------------------------------------ (2) il versamento necessario
|
||
print("\n" + "=" * 100)
|
||
print(" (2) DI QUANTO SI SPOSTA IL VERSAMENTO NECESSARIO (P=50%, 10 anni)")
|
||
print("=" * 100)
|
||
for pt in (0.50, 0.75):
|
||
print(f"\n a P={pt:.0%}")
|
||
print(f" {'lump':>9}{'senza imposte':>16}{'plus 26%':>13}{'plus 33%':>13}"
|
||
f"{'33% + patrim.':>16}")
|
||
for lump in (5_000.0, 10_000.0):
|
||
cells = [dep_necessario(r, lump, 10, 0.0, 0.0, pt),
|
||
dep_necessario(r, lump, 10, 0.26, PATRIMONIALE, pt),
|
||
dep_necessario(r, lump, 10, 0.33, 0.0, pt),
|
||
dep_necessario(r, lump, 10, 0.33, PATRIMONIALE, pt)]
|
||
print(f" €{lump:>8,.0f}" + "".join(f"{c:>12,.0f}€" for c in cells))
|
||
|
||
# ------------------------------------------------------ (3) l'orizzonte
|
||
print("\n" + "=" * 100)
|
||
print(" (3) LO STESSO PIANO, PIU' AVANTI NEL TEMPO (€10.000 + €500/mese)")
|
||
print("=" * 100)
|
||
print(f"\n {'anni':>6}{'senza imposte':>17}{'con 33% + patrim.':>21}{'differenza':>14}")
|
||
for yrs in (5, 10, 15, 20):
|
||
a = accumula(r, 10_000.0, 500.0, yrs, 0.0, 0.0)["median_end"]
|
||
b = accumula(r, 10_000.0, 500.0, yrs, 0.33, PATRIMONIALE)["median_end"]
|
||
print(f" {yrs:>5}a{a:>16,.0f}${b:>20,.0f}${b / a - 1:>13.1%}")
|
||
print("\n ⚠️ Il divario si allarga col tempo: e' un errore COMPOSTO, non una tassa una tantum.")
|
||
print(" Ed e' il motivo per cui va corretto adesso e non 'quando ci arriviamo'.")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|