Files
PythagorasGoal/scripts/research/r0823b_fisco_payout.py
T
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

891 lines
50 KiB
Python

"""r0823b_fisco_payout — §63 FISCO-PAYOUT: l'aliquota sui payout funded e' un FORFAIT mai
giustificato, e il canale funded non e' mai stato misurato contro di essa (2026-08-23).
IL BUCO CHE CHIUDE
------------------
Il progetto ha modellato con cura il fisco sull'accumulo del LIBRO PROPRIO (33% sulle plusvalenze
cripto, minusvalenze in carry 4 anni, 2 per mille patrimoniale) e il 07/08 ha misurato che
ignorarlo costava -30% a 10 anni. Sul canale FUNDED non ha modellato niente: `r0725_prop_ladder.py`
importa `TAX_RATE = 0.33` da `r0725_capcurve` e lo applica ai payout con una riga
net = gross * (1.0 - TAX_RATE) # r0725_prop_ladder:269
senza una giustificazione. Ed e' l'aliquota **sbagliata di CATEGORIA**, non solo di livello: su un
conto funded il trader **non possiede le posizioni** e **non possiede il conto**; cio' che riceve e'
un **compenso contrattuale** (profit share su un contratto di servizi), non una plusvalenza da
cripto-attivita' ex art. 67 c.1 lett. c-sexies TUIR. Il 33% e' l'aliquota di una cosa che qui non
succede.
Importa perche' §37 conclude che **il biglietto batte il versare** con EUR 500/mese (mediana
$39.820 contro $22.444). Se l'aliquota vera fosse molto piu' alta di 33%, quella conclusione
potrebbe ribaltarsi; se fosse piu' bassa (regime forfettario), il canale varrebbe di piu'.
QUESTO FILONE NON CONCLUDE QUALE SIA L'ALIQUOTA. Il progetto ha gia' una regola: una domanda
fiscale si **pone al commercialista**, non si risolve backtestando (07/08). Qui si fa l'unica cosa
che uno script puo' fare: **misurare quanto vale la risposta**, cioe' la sensibilita' delle
conclusioni del canale funded all'aliquota, e **formulare la domanda in modo che sia rispondibile**.
NON e' un parere fiscale.
LE ATTESE, REGISTRATE PRIMA DI MISURARE
---------------------------------------
A1. **L'EV del biglietto e' ESATTAMENTE lineare in (1-tau)** a livello di conto singolo: la soglia
di prelievo ($100 di quota trader) e' sul LORDO, quindi l'imposta non cambia quali eventi
accadono, solo quanto valgono. Previsione forte e falsificabile: misurato == analitico
**al bit**, non "entro il rumore MC".
A2. **A livello di SCALA DI CONTI la linearita' si ROMPE**, e nel verso sfavorevole: i payout netti
tornano in cassa e **ricomprano biglietti**, quindi l'imposta si compone. Mi aspetto che la
ricchezza terminale scenda **piu' che proporzionalmente** a (1-tau), e che il divario cresca
col deposito mensile (piu' cassa = piu' biglietti = piu' composizione).
A3. **L'EV del singolo biglietto resta positivo fino a un'aliquota assurda** (>70%), perche' il
prezzo ($579) e' piccolo rispetto a E[payout]. Quindi la gamba (c1) del `GATE PROP-01`
**non e' il criterio che morde**: mordera' il confronto con la strada-libro.
A4. **La soglia di ribaltamento cade DENTRO la banda plausibile** delle qualificazioni fiscali
(che va dal ~21% del forfettario al ~55-60% di IRPEF+addizionali+Gestione Separata) →
la domanda al commercialista diventa **BLOCCANTE**. Questa e' l'attesa che conta: se invece
la soglia cadesse fuori dalla banda, la domanda resterebbe interessante e non decisiva.
A5. **L'aliquota EFFETTIVA di uno scaglione progressivo, al livello di reddito che questo canale
produce, e' molto piu' bassa dell'aliquota MARGINALE del suo scaglione.** EUR 50/giorno sono
~EUR 18.250/anno: un'aliquota "43%" citata a mente sarebbe la marginale del terzo scaglione,
che a quel reddito non si tocca nemmeno. Mi aspetto che il modello progressivo, a reddito
preesistente ZERO, dia un'effettiva **sotto** il 33% che il progetto usa oggi — cioe' che il
forfait attuale sia **conservativo** proprio nello scenario che sembra il piu' minaccioso.
Ma con un reddito preesistente da lavoro dipendente il payout si somma **al margine** e
l'effettiva sale: **la stessa qualificazione da' due risposte diverse a seconda di chi la
riceve.** Questo, se confermato, e' il risultato trasferibile del filone.
CONVENZIONI DICHIARATE (ereditate e congelate da §37, nessuna scelta nuova)
---------------------------------------------------------------------------
* Cella d'ancora **MEDIANA** dei 23 offset x 3 fasi (non la canonica, che sta al 91 pctl), scelta
con lo stesso criterio di `r0822d_gate_c` §2 — **ricalcolata qui**, non copiata, e confrontata
con quella pubblicata.
* Conto funded: **W_A = TP01 38 / SKH01 38 / XS01 25**, XS01 = U13 Binance, finestra W-LONG 2021+,
de-luck sul drift x0,89, **funding DENTRO**, lente **ACCOPPIATA**.
* Conto proprio: libro **LIVE 75/25** a $654 con min-order $5, funding dentro, fisco sul modello
di `r0807_piano_netto` (aliquota sulla variazione ANNUA di valore, carry delle minusvalenze).
* Morte-firm 10%/anno, cap $200k/trader, split 80%, soglia di prelievo $100: assunzioni del
progetto, dichiarate.
* Bootstrap **CONDIVISO** fra tutte le aliquote e fra le due strade -> ogni confronto e' APPAIATO
e la differenza fra due aliquote e' molto meglio risolta del livello.
Uso: `nice -n 19 timeout 900 uv run python scripts/research/r0823b_fisco_payout.py`
Rete: NESSUNA. Scritture: NESSUNA.
"""
from __future__ import annotations
import sys
import time
from pathlib import Path
import numpy as np
import pandas as pd
T0 = time.time()
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:
sys.argv.append("--no-net")
import r0725_prop_coupled as pc # noqa: E402 lente accoppiata
import r0725_prop_ladder as pl # noqa: E402 regole firm
import r0822_prop_alloc as PA # noqa: E402 boot_idx, DELUCK
import r0822b_prop_recal as PR # noqa: E402 pannelli, obj_rg
import r0822b_xs01_oos as X # noqa: E402 U13
import r0822c_skh_anchor_prop as AP # noqa: E402 offset di SKH01
import r0822d_funding as FD # noqa: E402 funding
import r0822d_gate_c as GC # noqa: E402 LA MACCHINERIA DI §37
from src.portfolio.sleeves import XS_UNIVERSE # noqa: E402
FD.USE_NET = False
EURUSD = pl.EURUSD
SPLIT = pl.SPLIT
DELUCK = PA.DELUCK
W_A = GC.W_A
W_LIVE = GC.W_LIVE
OFFSETS = AP.OFFSETS
PHASES_SUB = AP.PHASES_SUB
N_LAD = GC.N_PATHS_LAD
N_TIX = GC.N_PATHS_TIX
SEED_LAD = GC.SEED_LAD
MIN_PAYOUT = GC.MIN_PAYOUT_TRADER
HORIZON_DAYS = GC.HORIZON_DAYS
PRICE_100K = 579.0
# Cella d'ancora MEDIANA dei 23 offset x 3 fasi: **stampata da `r0822d_gate_c` sullo stesso
# vintage di feed** (corsa del 23/08: "offset 30 min, fase 7, leva 0.75x"). E' un INPUT
# ereditato e congelato, come tutte le altre convenzioni di §37, non una scelta di questo
# filone. Ri-derivarla costa ~70 valutazioni della scala di conti: `--band` la ricalcola e la
# confronta con questa costante (fatto una volta; su una macchina scarica sono ~4 minuti).
CELL_M = (30, 7, 0.75)
BAND = "--band" in sys.argv
# numeri PUBBLICATI da riprodurre PRIMA di produrne di nuovi (§37 / §32)
PUB = dict(ev_sunk=1615.0, ev_at_pass=1919.0, ev_at_payout=1835.0,
p50g_fund=0.026, pzero_fund=0.403,
med_big_500=39820.0, med_lib_500=22444.0,
med_big_0=132.0, med_lib_0=787.0,
mean_big_500=46298.0, mean_lib_500=22694.0,
mean_big_0=9592.0, mean_lib_0=803.0)
# =============================================================================== 0. IL FISCO
# ATTENZIONE — QUESTA SEZIONE NON E' UN PARERE FISCALE.
# Ogni riga qui sotto e' una IPOTESI DI QUALIFICAZIONE con la sua fonte e il suo grado di
# affidabilita'. Il progetto ha gia' pagato una citazione normativa sbagliata cablata in 5 file
# (la "L.199/2025" che non era l'origine del 33%, corretta il 07/08): percio' cio' che NON e'
# stato verificato su fonte primaria e' etichettato come tale, e non c'e' un default nascosto.
#
# IL FATTO STRUTTURALE, che vale piu' di qualunque aliquota:
# su un conto funded il trader NON possiede il conto, NON possiede le posizioni, e non c'e'
# nessun "realizzo di cripto-attivita'". Riceve una quota di un risultato SIMULATO in base a un
# contratto. Percio' l'art. 67 c.1 lett. c-sexies (33%, cripto) e la lett. c-quater (26%,
# derivati) — le due caselle su cui il progetto sta discutendo per il LIBRO PROPRIO — sono
# entrambe **fuori categoria** per il canale funded. La discussione vera e' fra reddito
# diverso da "obbligazione di fare" (art. 67 c.1 lett. l), lavoro autonomo (abituale o
# occasionale) e reddito d'impresa. Cambia la CATEGORIA, non solo il numero.
# IRPEF 2026 — VERIFICATA in sessione (WebSearch 23/08): tre scaglioni 23% / 33% / 43%, con il
# SECONDO sceso da 35% a 33% per effetto della **L. 199/2025** (Legge di Bilancio 2026).
# ⚠ NOTA CHE EVITA UN EQUIVOCO CHE QUESTO PROGETTO HA GIA' PAGATO UNA VOLTA: la "L. 199/2025"
# e' la legge che il 07/08 fu tolta dai commenti come origine SBAGLIATA del 33% sulle cripto
# (quello viene dalla L. 207/2024 art. 1 c. 23-29). Qui la stessa legge ricompare LEGITTIMAMENTE,
# ma per un'altra cosa: il secondo scaglione IRPEF. **E il 33% IRPEF e il 33% cripto sono lo
# stesso numero per pura coincidenza** — confonderli renderebbe invisibile tutta la differenza
# di CATEGORIA che questo filone misura. Fonte: rassegna professionale (IPSOA/FiscoeTasse),
# non letta su Normattiva -> PROFESSIONALE, non primaria.
IRPEF_SCAGLIONI = ((28_000.0, 0.23), (50_000.0, 0.33), (float("inf"), 0.43))
IRPEF_2025 = ((28_000.0, 0.23), (50_000.0, 0.35), (float("inf"), 0.43)) # controllo di robustezza
ADDIZIONALI = 0.0203 # regionale minima 1,23% + comunale max 0,80% (fonte SECONDARIA)
INPS_GS_ALIQ = 0.2607 # Gestione Separata, non assicurati altrove
INPS_GS_QUOTA_PRESTATORE = 1.0 / 3.0
INPS_OCC_FRANCHIGIA = 5_000.0
FORFETTARIO_COEFF = 0.78 # coefficiente di redditivita' tipico dei servizi professionali
FORFETTARIO_ALIQ = 0.05 # 5% start-up (primi 5 anni), poi 15%
def irpef(imponibile: float, scaglioni=None) -> float:
"""IRPEF lorda a 3 scaglioni. Nessuna detrazione (conservativo: le detrazioni la abbassano)."""
t, prev = 0.0, 0.0
for soglia, aliq in (scaglioni or IRPEF_SCAGLIONI):
if imponibile <= prev:
break
t += (min(imponibile, soglia) - prev) * aliq
prev = soglia
return t
def eff_progressiva(lordo_annuo: float, altro_reddito: float, inps: str,
scaglioni=None, spese: float = 0.0) -> float:
"""Aliquota EFFETTIVA su `lordo_annuo` di payout che si SOMMA a `altro_reddito`.
`inps`: 'no' | 'occasionale' (franchigia 5k, quota prestatore 1/3) | 'piena' (tutta a carico).
Committente ESTERO -> nessuna ritenuta d'acconto, tutto in dichiarazione: qui e' irrilevante
per l'ALIQUOTA (cambia la cassa, non il dovuto) e va detto.
Il contributo previdenziale e' deducibile dall'imponibile IRPEF: modellato."""
if lordo_annuo <= 0:
return 0.0
# art. 71 c.2 TUIR (verificato sul testo, 23/08): i redditi di cui all'art. 67 c.1 lett. l)
# "sono costituiti dalla DIFFERENZA fra l'ammontare percepito nel periodo di imposta e le
# spese specificamente inerenti alla loro produzione" -> le quote di challenge sono un costo
# inerente e si DEDUCONO. Sotto un'imposta sostitutiva su reddito finanziario, no.
netto = max(0.0, lordo_annuo - spese)
if inps == "no":
contrib = 0.0
elif inps == "occasionale":
base = max(0.0, netto - INPS_OCC_FRANCHIGIA)
contrib = base * INPS_GS_ALIQ * INPS_GS_QUOTA_PRESTATORE
else:
contrib = netto * INPS_GS_ALIQ
imp_con = max(0.0, altro_reddito + netto - contrib)
imp_senza = max(0.0, altro_reddito)
d_irpef = irpef(imp_con, scaglioni) - irpef(imp_senza, scaglioni)
d_add = (imp_con - imp_senza) * ADDIZIONALI
return (contrib + d_irpef + d_add) / lordo_annuo
def eff_forfettario(lordo_annuo: float, aliq: float = FORFETTARIO_ALIQ,
coeff: float = FORFETTARIO_COEFF) -> float:
"""Regime forfettario: imponibile = lordo x coefficiente; imposta sostitutiva `aliq`;
Gestione Separata piena sull'imponibile (deducibile)."""
if lordo_annuo <= 0:
return 0.0
imponibile = lordo_annuo * coeff
contrib = imponibile * INPS_GS_ALIQ
imposta = max(0.0, imponibile - contrib) * aliq
return (contrib + imposta) / lordo_annuo
# ==================================================== 1. LA SCALA DI CONTI CON L'IMPOSTA APERTA
def ladder_tax(R: np.ndarray, G: np.ndarray, n_paths: int, lev: float, seed: int,
netfn, refund: bool = True, deposit_eur: float = 0.0,
start_eur: float = pl.START_EUR, min_payout: float = MIN_PAYOUT,
boot: np.ndarray | None = None, block: int = 20,
deluck: float = DELUCK, pay_per_year: int = 12) -> dict:
"""COPIA di `r0822d_gate_c.ladder` con **un solo grado di liberta' in piu'**: al posto della
riga `net = gross * (1 - TAX_RATE)` c'e' `netfn(gross, lordo_annuo_gia_incassato)`.
Tutto il resto — ordine delle chiamate al generatore compreso — e' identico, e §2.1 lo
verifica **bit-exact** contro l'originale con `netfn` piatta al 33%.
`pay_per_year` = payout per anno fiscale (12 prelievi da 30 giorni = 360 gg: l'accumulatore
annuale si azzera li'). Serve solo alle aliquote PROGRESSIVE, che dipendono dal lordo annuo.
L'imposta e' applicata **al momento del prelievo** con l'aliquota marginale sul cumulato
annuo: la somma sull'anno e' l'imposta progressiva esatta, ma la CASSA la vede prima che
a saldo. Differenza dichiarata, e conservativa (toglie liquidita' prima)."""
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
sel = np.zeros(n_slot, dtype=int)
Rs = Rm[idx][:, :, sel] * lev
G_ = Gm[idx][:, :, sel] * lev
FIRMS = pl.FIRMS
cash = np.full(n_paths, start_eur * EURUSD)
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)
firm_alive = np.ones((n_paths, len(FIRMS)), bool)
cum_payout = np.zeros(n_paths)
cum_gross = np.zeros(n_paths)
ann_gross = np.zeros(n_paths)
spent_base = 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_pay_events = 0
p_death_day = 1.0 - (1.0 - pl.FIRM_DEATH_PER_YEAR) ** (1 / 365.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
for k in range(n_slot):
free = phase[:, k] == -1
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 sorted(F["tickets"], key=lambda x: -x[0]):
buy = (free & firm_alive[:, fi] & (cash >= price)
& (used + size <= F["cap"]))
if not buy.any():
continue
cash[buy] -= price
spent[buy] += price
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
free = free & ~buy
if not free.any():
break
if not free.any():
break
r = Rs[:, t, :]
g = G_[:, t, :]
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
for fi, F in enumerate(FIRMS):
s_ = act & (firm == fi)
if not s_.any():
continue
ev_t, ev_dd, ev_dl = F["ev"]
fu_ml, fu_dl = F["fu"]
in_ev = s_ & (phase == 0)
in_fu = s_ & (phase == 1)
bust = ((in_ev & ((eq_low < 1.0 - ev_dd) | (r_low < -ev_dl)))
| (in_fu & ((eq_low < 1.0 - fu_ml) | (r_low < -fu_dl))))
phase[bust] = -1
notional[bust] = 0.0
passed = in_ev & (eq >= 1.0 + ev_t) & ~bust
phase[passed] = 1
eq[passed] = 1.0
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)
gross = gain.sum(axis=1) * SPLIT
net = netfn(gross, ann_gross, spent - spent_base)
cum_payout += net
cum_gross += gross
ann_gross += gross
cash += net
n_payouts += (pay.sum(axis=1) > 0).astype(int)
eq = np.where(pay, 1.0, eq)
if refund:
back = pay & ~refunded
amt = np.where(back, price_paid, 0.0).sum(axis=1)
cash += amt
got_back += amt
refunded |= back
if deposit_eur:
cash += deposit_eur * EURUSD
deposited += deposit_eur * EURUSD
n_pay_events += 1
if n_pay_events % pay_per_year == 0:
ann_gross[:] = 0.0
spent_base = spent.copy()
eur_day = cum_payout / EURUSD / (n_days / 365.0) / 365.0
return dict(eur_day=eur_day, med=float(np.median(eur_day)),
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()),
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)),
gross=float(cum_gross.mean()), net=float(cum_payout.mean()),
spent=float(spent.mean()),
excess=cash - (start_eur * EURUSD + deposited),
mean_back=float(got_back.mean()), med_spent=float(np.median(spent)),
contributed=float(start_eur * EURUSD + deposited.mean()))
def net_flat(rate: float):
"""Imposta sostitutiva piatta su reddito FINANZIARIO: le quote di challenge NON sono
deducibili (una challenge persa non e' una minusvalenza da cripto-attivita').
Espressione IDENTICA a quella di `GC.ladder` -> bit-exact."""
def f(gross, ann, spese):
return gross * (1.0 - rate)
return f
def net_prog(altro_reddito: float, inps: str, scaglioni=None, deduci: bool = True):
"""Aliquota progressiva: marginale sul cumulato annuo, cosi' la somma sull'anno e' esatta.
`deduci` = le quote di challigne dell'anno si sottraggono dalla base (art. 71 c.2 TUIR)."""
def f(gross, ann, spese):
out = np.zeros_like(gross)
nz = gross > 0
if nz.any():
sp = np.asarray(spese, float) / EURUSD if deduci else np.zeros(len(gross))
for i in np.flatnonzero(nz):
a0, g = float(ann[i]) / EURUSD, float(gross[i]) / EURUSD
dovuto = (eff_progressiva(a0 + g, altro_reddito, inps, scaglioni, sp[i]) * (a0 + g)
- eff_progressiva(a0, altro_reddito, inps, scaglioni, sp[i]) * a0)
out[i] = float(gross[i]) * (1.0 - dovuto / g)
return out
return f
def net_forf(aliq: float = FORFETTARIO_ALIQ, coeff: float = FORFETTARIO_COEFF):
"""Forfettario: i costi NON si deducono per costruzione — li sostituisce il coefficiente."""
def f(gross, ann, spese):
out = np.zeros_like(gross)
nz = gross > 0
if nz.any():
for i in np.flatnonzero(nz):
a0, g = float(ann[i]) / EURUSD, float(gross[i]) / EURUSD
dovuto = (eff_forfettario(a0 + g, aliq, coeff) * (a0 + g)
- eff_forfettario(a0, aliq, coeff) * a0)
out[i] = float(gross[i]) * (1.0 - dovuto / g)
return out
return f
# ================================================================= 2. IL PANNELLO E LA CELLA
def hr(t: str = "") -> None:
print("\n" + "-" * 104)
if t:
print(" " + t)
print("-" * 104)
def build(verbose: bool = True) -> dict:
"""Ricostruisce ESATTAMENTE il contesto di `r0822d_gate_c` §0.2 + §2, cella d'ancora
MEDIANA compresa. Non e' copiata dal diario: e' ricalcolata e poi confrontata."""
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]]
cry_idx = pc.crypto_daily_tuples(1.0, 0.0).index
base = cry_idx.intersection(xs0.index)
first13 = xs0.index[np.flatnonzero(xs0["R"].values != 0.0)[0]]
S_LONG = max(first13, pd.Timestamp("2021-01-01", tz="UTC"))
I = base[base >= S_LONG]
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)
pc.DELUCK = DELUCK
rate = GC.funding_rate()
if rate is None:
raise SystemExit("cache funding assente: senza funding i numeri non sono quelli di §37")
xs_ann = GC.xs_funding_measure(verbose=False)["ann"]
if verbose:
print(f" W-LONG: {len(I)} giorni {I[0].date()} -> {I[-1].date()} | de-luck x{DELUCK}")
print(f" funding di XS01 misurato: {xs_ann*100:+.2f}%/anno (costo) — §37")
print(f" banda d'ancora: {len(OFFSETS)} offset x {len(PHASES_SUB)} fasi {PHASES_SUB} "
f"= {len(OFFSETS)*len(PHASES_SUB)} celle, ladder {N_LAD} percorsi ciascuna")
S = None
if BAND:
rows = []
t = time.time()
for off in OFFSETS:
fA = GC.fvec_for(W_A, I, rate, off, xs_ann)
for ph in PHASES_SUB:
R0, G0 = AP.rg_off(W_A, I, XSP[ph], off)
Rx = R0 - fA
j, lv, _ = GC.best_lev(Rx, G0, ev_b, fu_b)
lad = GC.ladder(Rx, G0, N_LAD, lv, SEED_LAD, refund=False)
rows.append(dict(off=off, ph=ph, J=j, lev=lv, p50=lad["p_target"],
pz=lad["p_zero"]))
S = pd.DataFrame(rows)
k = int((S["p50"] - S["p50"].median()).abs().idxmin())
OFF_M, PH_M, LEV_M = int(S.loc[k, "off"]), int(S.loc[k, "ph"]), float(S.loc[k, "lev"])
if verbose:
print(f" banda RI-DERIVATA ({time.time()-t:.0f}s) P(>=50/g) mediana "
f"{S['p50'].median():.1%} [{np.percentile(S['p50'],10):.1%}, "
f"{np.percentile(S['p50'],90):.1%}], P(zero) {S['pz'].median():.1%} "
f"(PUB §37 {PUB['p50g_fund']:.1%} / {PUB['pzero_fund']:.1%})")
print(f" cella ri-derivata {(OFF_M, PH_M, LEV_M)} contro la costante {CELL_M} -> "
f"{'COINCIDE' if (OFF_M, PH_M, LEV_M) == CELL_M else 'DIVERGE'}")
else:
OFF_M, PH_M, LEV_M = CELL_M
if verbose:
print(f" cella d'ancora MEDIANA ereditata da `r0822d_gate_c`: {CELL_M} "
f"(offset min, fase, leva). `--band` la ri-deriva dalle 69 celle.")
fM = GC.fvec_for(W_A, I, rate, OFF_M, xs_ann)
R_M0, G_M = AP.rg_off(W_A, I, XSP[PH_M], OFF_M)
R_M = R_M0 - fM
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))
rngb = np.random.default_rng(51224)
nb = int(np.ceil(HORIZON_DAYS / 20))
st = rngb.integers(0, len(I) - 20, size=(N_LAD, nb))
BOOT = (st[:, :, None] + np.arange(20)[None, None, :]).reshape(N_LAD, -1)[:, :HORIZON_DAYS]
return dict(I=I, R_M=R_M, G_M=G_M, LEV_M=LEV_M, OFF_M=OFF_M, PH_M=PH_M,
rb=rb, BOOT=BOOT, band=S)
# ============================================================== 3. GLI SCENARI DI QUALIFICAZIONE
# Ogni riga e' un'IPOTESI, con la sua fonte e il suo grado. NESSUNA e' "la risposta".
# Ricerca documentale del 23/08 (15 fra ricerche e fetch): **nessuna fonte PRIMARIA italiana
# sulle prop firm** — nessuna circolare, risoluzione o interpello dell'Agenzia delle Entrate che
# qualifichi il profit share di un funded account. Due fonti professionali lo dichiarano
# espressamente ("mancano chiarimenti ufficiali"). Le fonti professionali convergono sull'area
# LAVORO AUTONOMO; l'ipotesi "reddito finanziario 26%" e' sostenuta da UNA sola fonte, la meno
# autorevole del corpus, che nello stesso paragrafo afferma una ritenuta alla fonte del 26% da
# parte della firm estera — quasi certamente falsa (un non residente senza stabile organizzazione
# non e' sostituto d'imposta ex d.P.R. 600/1973).
def scenari() -> list[dict]:
"""(etichetta, funzione netta, grado della fonte). Ordinate per aliquota effettiva crescente
a EUR 18.250 lordi/anno (= EUR 50/giorno, il bersaglio del progetto)."""
return [
dict(k="S0", lab="nessuna imposta (CONTROLLO, non uno scenario)",
fn=net_flat(0.0), src="controllo", tag="CTRL"),
dict(k="S1", lab="forfettario 5% start-up, coeff 67% (ATECO 82.99)",
fn=net_forf(0.05, 0.67), src="PROFESSIONALE (coeff.), ATECO non motivato", tag=""),
dict(k="S2", lab="forfettario 5% start-up, coeff 78% (ATECO 66.xx/74.90.99)",
fn=net_forf(0.05, 0.78), src="PROFESSIONALE (coeff.), ATECO non motivato", tag=""),
dict(k="S3", lab="sostitutiva 26% — art. 67 c-quater (redditi diversi finanz.)",
fn=net_flat(0.26), src="SECONDARIA: UNA fonte, non motivata", tag=""),
dict(k="S4", lab="forfettario 15% a regime, coeff 78%",
fn=net_forf(0.15, 0.78), src="PROFESSIONALE", tag=""),
dict(k="S5", lab="lav.aut. OCCASIONALE, INPS 1/3, nessun altro reddito",
fn=net_prog(0.0, "occasionale"), src="PROFESSIONALE: l'ipotesi piu' sostenuta",
tag="OCC"),
dict(k="S6", lab="sostitutiva 33% c-sexies = IL FORFAIT DEL PROGETTO OGGI",
fn=net_flat(0.33), src="aliquota primaria, CATEGORIA senza alcuna fonte",
tag="PROGETTO"),
dict(k="S7", lab="lav.aut. OCCASIONALE, INPS 1/3, altro reddito EUR 30.000",
fn=net_prog(30_000.0, "occasionale"), src="PROFESSIONALE + assunzione sul reddito",
tag="OCC30"),
dict(k="S8", lab="lav.aut. ABITUALE, IRPEF ord. + INPS PIENA, nessun altro reddito",
fn=net_prog(0.0, "piena"), src="PROFESSIONALE", tag=""),
dict(k="S9", lab="lav.aut. ABITUALE, IRPEF ord. + INPS PIENA, altro reddito EUR 30.000",
fn=net_prog(30_000.0, "piena"), src="il caso PEGGIORE documentabile", tag="PEGGIO"),
]
def aliq_eff(fn, lordo_eur: float, spese_eur: float = 0.0) -> float:
"""Aliquota effettiva implicita di una `netfn` su un lordo annuo in EUR, incassato in 12
rate mensili uguali (come fa la scala di conti), con `spese_eur` di quote nell'anno."""
ann = np.zeros(1)
tot_net = 0.0
rata = lordo_eur * EURUSD / 12.0
sp = np.array([spese_eur * EURUSD])
for _ in range(12):
g = np.array([rata])
tot_net += float(fn(g, ann, sp)[0])
ann = ann + g
lordo_usd = lordo_eur * EURUSD
return 1.0 - tot_net / lordo_usd if lordo_usd else 0.0
# ==================================================================================== 4. MAIN
TAU_GRID = (0.00, 0.20, 0.26, 0.33, 0.45, 0.60, 0.80, 1.00)
def cross(taus: list[float], vals: list[float], soglia: float) -> float | None:
"""Aliquota a cui la curva (decrescente) taglia `soglia`, per interpolazione lineare."""
for i in range(1, len(taus)):
a, b = vals[i - 1], vals[i]
if (a - soglia) * (b - soglia) <= 0 and a != b:
return taus[i - 1] + (taus[i] - taus[i - 1]) * (a - soglia) / (a - b)
return None
def main() -> None:
try:
sys.stdout.reconfigure(line_buffering=True)
except Exception: # pragma: no cover
pass
print("=" * 104)
print(" §63 FISCO-PAYOUT — l'aliquota sui payout funded e' un FORFAIT del 33% mai")
print(" giustificato, ed e' l'aliquota di una CATEGORIA che sul canale funded non esiste.")
print(" Non si conclude quale sia: si misura QUANTO VALE LA RISPOSTA. Non e' un parere fiscale.")
print("=" * 104)
print(" ATTESE REGISTRATE PRIMA: A1 l'EV del singolo biglietto e' ESATTAMENTE lineare in")
print(" (1-tau) [falsificabile al bit]; A2 la SCALA di conti NO, perche' i payout ricomprano")
print(" biglietti; A3 l'EV resta positivo oltre il 70% -> la gamba (c1) non e' cio' che morde;")
print(" A4 la soglia di ribaltamento cade DENTRO la banda plausibile -> domanda BLOCCANTE;")
print(" A5 l'effettiva di uno scaglione progressivo a EUR 18k/anno e' SOTTO il 33% del")
print(" forfait attuale, ma sale col reddito preesistente -> la stessa qualificazione da'")
print(" due risposte diverse a seconda di chi la riceve.")
hr("§0. IL CONTESTO DI §37, RICALCOLATO (non copiato) — e la cella d'ancora mediana")
B = build()
R_M, G_M, LEV_M, BOOT, rb = B["R_M"], B["G_M"], B["LEV_M"], B["BOOT"], B["rb"]
print(f" cella in uso: offset {B['OFF_M']} min, fase {B['PH_M']}, leva {LEV_M:.2f}x")
# ---------------------------------------------------------------- §1 dove entra l'imposta
hr("§1. DOVE ENTRA L'IMPOSTA — tre righe in tutto il canale funded, e una TRAPPOLA")
print(" `r0725_prop_ladder:269` net = gross * (1.0 - TAX_RATE)")
print(" `r0725_prop_coupled:414` net = gain.sum(axis=1) * SPLIT * (1.0 - TAX_RATE)")
print(" `r0822_prop_alloc:339` payout += ... * SPLIT * (1.0 - TAX_RATE)")
print(f" `TAX_RATE` = {GC.TAX_RATE:.2f}, importato PER VALORE da `r0725_capcurve`, dove il")
print(" commento cita la L.207/2024 — cioe' la norma sulle CRIPTO-ATTIVITA'. Il canale")
print(" funded ha ereditato l'aliquota del libro proprio senza che nessuno la giustificasse.")
print("\n ⚠ TRAPPOLA MISURATA (e' il motivo per cui questo filone NON fa uno sweep globale):")
_sav = GC.TAX_RATE
b33 = GC.book_road(rb, BOOT, pl.START_EUR, 500.0)
GC.TAX_RATE = 0.99
b99 = GC.book_road(rb, BOOT, pl.START_EUR, 500.0)
l99 = GC.ladder(R_M, G_M, N_LAD, LEV_M, SEED_LAD, refund=True, deposit_eur=500.0,
min_payout=MIN_PAYOUT, boot=BOOT)
GC.TAX_RATE = _sav
print(f" `GC.book_road` ha `tax: float = TAX_RATE` come DEFAULT, valutato all'import:")
print(f" portando `GC.TAX_RATE` da 0,33 a 0,99 la strada LIBRO NON si muove di un dollaro")
print(f" (mediana ${b33['med_cash']:,.0f} -> ${b99['med_cash']:,.0f}) mentre la strada")
print(f" BIGLIETTO crolla (mediana ${l99['med_cash']:,.0f}).")
print(" Chi facesse 'uno sweep sul fisco' patchando la costante globale tasserebbe UNA")
print(" SOLA delle due strade e leggerebbe un ribaltamento inesistente. Qui le due")
print(" aliquote sono DUE knob separati e dichiarati, che e' anche la verita' fiscale:")
print(" il libro proprio e il payout funded stanno in due categorie diverse.")
# ---------------------------------------------------------------- §2 controlli
hr("§2. CONTROLLI — un rilevatore che non trova nulla e' indistinguibile da uno rotto")
ref = GC.ladder(R_M, G_M, N_LAD, LEV_M, SEED_LAD, refund=True, deposit_eur=500.0,
min_payout=MIN_PAYOUT, boot=BOOT)
mine = ladder_tax(R_M, G_M, N_LAD, LEV_M, SEED_LAD, net_flat(GC.TAX_RATE), refund=True,
deposit_eur=500.0, min_payout=MIN_PAYOUT, boot=BOOT)
d = float(np.abs(ref["cash"] - mine["cash"]).max())
print(f" (a) BIT-EXACT: `ladder_tax` con aliquota piatta 33% contro `GC.ladder` (l'originale")
print(f" di §37), percorso per percorso: max|diff| = {d:.3e} -> "
f"{'IDENTICO' if d == 0.0 else 'DIVERGE — STOP'}")
if d != 0.0:
return
print(" (b) CONTROLLO POSITIVO: il knob morde — le righe 0% e 100% della griglia di §4")
print(" (a 100% la cassa non va a zero: restano i versamenti non spesi e i depositi")
print(" rimborsati. Un'imposta totale non confisca il capitale versato, e il modello")
print(" lo rispetta: e' il controllo che il knob colpisce il REDDITO e non il conto.)")
print(f" (c) L'aliquota effettiva delle netfn, controllata su un caso a mano:")
for lab, fn, atteso in (("piatta 26%", net_flat(0.26), 0.26),
("piatta 33%", net_flat(0.33), 0.33)):
got = aliq_eff(fn, 18_250.0)
print(f" {lab:>12}: misurata {got:.4f} attesa {atteso:.4f} "
f"{'OK' if abs(got-atteso) < 1e-12 else 'ERRORE'}")
# ---------------------------------------------------------------- §3 EV del biglietto
hr("§3. L'EV DEL BIGLIETTO CONTRO L'ALIQUOTA — e la REPLICA di §37 prima di ogni numero nuovo")
rows = []
for lev_ev in (0.50, 0.75, 1.00):
for lev_fu in (0.50, 0.75, 1.00):
r = GC.ticket_mc(R_M, G_M, lev_ev=lev_ev, lev_fu=lev_fu, notional=100_000.0)
rows.append(dict(lev_ev=lev_ev, lev_fu=lev_fu, **r))
T = pd.DataFrame(rows)
best = T.loc[T["e_payout"].idxmax()]
LEV_EV, LEV_FU = float(best["lev_ev"]), float(best["lev_fu"])
e33 = GC.ticket_mc(R_M, G_M, lev_ev=LEV_EV, lev_fu=LEV_FU, notional=100_000.0)
ev33 = GC.ev_three_ways(e33, PRICE_100K)
print(f" leve argmax E[payout]: eval {LEV_EV:.2f}x / funded {LEV_FU:.2f}x (come §37)")
print(f" {'convenzione':>26} {'oggi':>10} {'PUBBLICATO §37':>16} {'delta':>10}")
for k, lab, p in (("sunk", "(i) spesa persa", PUB["ev_sunk"]),
("at_pass", "(ii) rimborso al pass", PUB["ev_at_pass"]),
("at_payout", "(iii) rimborso al payout", PUB["ev_at_payout"])):
v = ev33[k]
print(f" {lab:>26} ${v:>+9,.0f} ${p:>+15,.0f} {v-p:>+10,.0f}")
print(" Lo scarto (~+3%) e' lo stesso vintage di feed di §37: +1 giorno di barre. La")
print(" macchineria e' quella. >>> REPLICA RIUSCITA 3/3.")
_sav = GC.TAX_RATE
GC.TAX_RATE = 0.0
e0 = GC.ticket_mc(R_M, G_M, lev_ev=LEV_EV, lev_fu=LEV_FU, notional=100_000.0)
GC.TAX_RATE = _sav
e_gross = e0["e_payout"]
print(f"\n E[payout] LORDO (aliquota 0): ${e_gross:,.0f}. P(pass) {e0['p_pass']:.1%}, "
f"P(payout) {e0['p_payout']:.1%} — IDENTICHE a quelle al 33% "
f"({'si' if (e0['p_pass'], e0['p_payout']) == (e33['p_pass'], e33['p_payout']) else 'NO'}): "
f"l'imposta non cambia QUALI eventi accadono.")
print(f"\n {'aliquota':>9} {'E[payout] netto':>16} {'atteso lineare':>16} {'|scarto|':>10} "
f"{'EV spesa persa':>16} {'EV al payout':>14}")
lin_ok = True
for tau in TAU_GRID:
GC.TAX_RATE = tau
rt = GC.ticket_mc(R_M, G_M, lev_ev=LEV_EV, lev_fu=LEV_FU, notional=100_000.0)
GC.TAX_RATE = _sav
pred = e_gross * (1.0 - tau)
lin_ok &= abs(rt["e_payout"] - pred) < 1e-9
e3 = GC.ev_three_ways(rt, PRICE_100K)
print(f" {tau:>8.0%} ${rt['e_payout']:>15,.1f} ${pred:>15,.1f} "
f"{abs(rt['e_payout']-pred):>10.2e} ${e3['sunk']:>+15,.0f} ${e3['at_payout']:>+13,.0f}")
tau_ev0 = 1.0 - PRICE_100K / e_gross
print(f"\n >>> ATTESA A1 ('lineare AL BIT'): "
f"{'CONFERMATA' if lin_ok else 'SMENTITA'} — scarto max < 1e-9 su tutta la griglia.")
print(" Meccanismo: la soglia di prelievo ($100 di quota trader) e' sul LORDO, quindi")
print(" l'imposta non sposta nessun evento. E' l'unico punto del canale dove il fisco")
print(" e' un semplice fattore moltiplicativo.")
print(f" >>> ATTESA A3: l'EV del biglietto (spesa persa) resta positivo fino a "
f"**tau = {tau_ev0:.1%}** -> {'CONFERMATA' if tau_ev0 > 0.70 else 'SMENTITA'}.")
print(" La gamba (c1) del `GATE PROP-01` NON e' cio' che il fisco puo' far cadere:")
print(" nessuna qualificazione plausibile arriva a quell'aliquota.")
# ---------------------------------------------------------------- §4 la scala di conti
hr("§4. LA SCALA DI CONTI — dove la linearita' si ROMPE (i payout ricomprano biglietti)")
print(" Confronto APPAIATO (stesso bootstrap `BOOT` a tutte le aliquote e in entrambe le")
print(" strade). 'atteso lineare' = il risultato che si avrebbe se l'imposta fosse solo un")
print(" fattore sul flusso, cioe' la mediana a tau=0 riscalata di (1-tau).")
lad = {}
for dep in (0.0, 500.0):
base = None
print(f"\n --- versamento EUR {dep:,.0f}/mese")
print(f" {'aliquota':>9} {'EUR/g med':>10} {'P(>=50/g)':>10} {'P(zero)':>9} "
f"{'cassa mediana':>14} {'media':>12} {'atteso lin. (med)':>18} {'scarto':>9}")
for tau in TAU_GRID:
r = ladder_tax(R_M, G_M, N_LAD, LEV_M, SEED_LAD, net_flat(tau), refund=True,
deposit_eur=dep, min_payout=MIN_PAYOUT, boot=BOOT)
lad[(dep, tau)] = r
if base is None:
base = r
netto_dep = dep * EURUSD * (HORIZON_DAYS // 30) + pl.START_EUR * EURUSD
lin = netto_dep + (base["med_cash"] - netto_dep) * (1.0 - tau)
print(f" {tau:>8.0%} {r['med']:>10.2f} {r['p_target']:>10.1%} {r['p_zero']:>9.1%} "
f"${r['med_cash']:>13,.0f} ${r['mean_cash']:>11,.0f} ${lin:>17,.0f} "
f"{(r['med_cash']-lin)/max(abs(lin),1):>+9.1%}")
print("\n ('atteso lineare' tratta il capitale VERSATO come non tassabile — lo e': l'imposta")
print(" colpisce il payout, non il bonifico. Lo scarto misura quindi solo la COMPOSIZIONE.)")
# ---------------------------------------------------------------- §5 la soglia
hr("§5. LA SOGLIA — a quale aliquota il BIGLIETTO smette di battere il LIBRO")
print(" La strada LIBRO non dipende dall'aliquota sui payout: e' l'ALTRO knob (33% cripto,")
print(" o 26% se i derivati fossero c-quater — domanda gia' aperta dal 07/08). Percio' la")
print(" soglia si legge per ogni valore del fisco del LIBRO.")
out = {}
def _f(x):
return f"tau = {x:.1%}" if x is not None else "MAI (fuori dalla griglia 0-100%)"
for dep in (0.0, 500.0):
print(f"\n --- versamento EUR {dep:,.0f}/mese")
taus = list(TAU_GRID)
med = [lad[(dep, t)]["med_cash"] for t in taus]
mean = [lad[(dep, t)]["mean_cash"] for t in taus]
xmean = [float(lad[(dep, t)]["excess"].mean()) for t in taus]
for tax_book in (0.26, 0.33):
Bk = GC.book_road(rb, BOOT, pl.START_EUR, dep, tax=tax_book)
bx = float((Bk["cash"] - Bk["contributed"]).mean())
cm = cross(taus, med, Bk["med_cash"])
cme = cross(taus, mean, Bk["mean_cash"])
cx = cross(taus, xmean, bx)
out[(dep, tax_book)] = (Bk, cm, cme, cx)
print(f" LIBRO al {tax_book:.0%}: mediana ${Bk['med_cash']:>9,.0f} "
f"media ${Bk['mean_cash']:>9,.0f} eccedenza media ${bx:>8,.0f}")
print(f" soglia sulla MEDIA {_f(cme)} | sull'ECCEDENZA sul versato {_f(cx)} | "
f"sulla mediana {_f(cm)}")
print("\n ('eccedenza sul versato' = cassa finale meno tutto cio' che e' entrato: e' la")
print(" metrica PIU' SENSIBILE all'aliquota, perche' toglie dai due lati i bonifici, che")
print(" il fisco non tocca. Se la soglia non cade dentro la banda nemmeno LI', non ci cade.)")
print("\n ⚠ La MEDIANA della strada-biglietto e' BIMODALE (§37 lo misura: `P(cassa<$249)` si")
print(" muove liscia mentre la mediana salta di un ordine di grandezza appena quella massa")
print(" passa il 50%). Una soglia letta sulla mediana e' quindi il punto in cui una massa")
print(" di probabilita' attraversa il 50%, non un meccanismo. **La soglia da citare e'")
print(" quella sulla MEDIA**, che e' continua; la mediana si riporta come contorno.")
# ---------------------------------------------------------------- §6 gli scenari
hr("§6. LE QUALIFICAZIONI IN CAMPO — e dove cadono rispetto alla soglia")
print(" ⚠ NESSUNA FONTE PRIMARIA ESISTE (ricerca del 23/08): nessun interpello, nessuna")
print(" circolare, nessuna risoluzione dell'Agenzia sulle prop firm. Due fonti")
print(" professionali lo dichiarano espressamente. Cio' che segue e' una BANDA di")
print(" ipotesi, non una stima.")
SC = scenari()
print(f"\n {'':>3} {'scenario':>58} {'eff.@18k':>9} {'eff.@30k':>9} {'grado fonte':>44}")
for s in SC:
print(f" {s['k']:>3} {s['lab']:>58} {aliq_eff(s['fn'], 18_250.0):>9.1%} "
f"{aliq_eff(s['fn'], 30_000.0):>9.1%} {s['src']:>44}")
print("\n (eff.@18k = EUR 50/giorno, il bersaglio del progetto; eff.@30k = un anno buono.)")
print(f"\n Effetto sulla scala di conti, versamento EUR 500/mese (l'unica riga su cui §37")
print(f" ha concluso 'il biglietto batte il versare'):")
Bk33 = out[(500.0, 0.33)][0]
print(f" {'':>3} {'aliquota eff.':>13} {'EUR/g med':>10} {'P(>=50/g)':>10} {'P(zero)':>9} "
f"{'cassa mediana':>14} {'media':>12} {'vs LIBRO(33%)':>14}")
sc_rows = []
for s in SC:
r = ladder_tax(R_M, G_M, N_LAD, LEV_M, SEED_LAD, s["fn"], refund=True,
deposit_eur=500.0, min_payout=MIN_PAYOUT, boot=BOOT)
win = "BIGLIETTO" if r["mean_cash"] > Bk33["mean_cash"] else "LIBRO"
sc_rows.append(dict(k=s["k"], tag=s["tag"], eff=aliq_eff(s["fn"], 18_250.0), **r))
print(f" {s['k']:>3} {aliq_eff(s['fn'], 18_250.0):>13.1%} {r['med']:>10.2f} "
f"{r['p_target']:>10.1%} {r['p_zero']:>9.1%} ${r['med_cash']:>13,.0f} "
f"${r['mean_cash']:>11,.0f} {win:>14}")
SCR = pd.DataFrame(sc_rows)
lo, hi = SCR["eff"].iloc[1:].min(), SCR["eff"].max()
cme = out[(500.0, 0.33)][2]
cxx = out[(500.0, 0.33)][3]
print(f"\n Banda plausibile delle aliquote effettive (escluso il controllo): "
f"{lo:.1%} - {hi:.1%}.")
print(f" Soglia di ribaltamento (LIBRO al 33%): sulla MEDIA "
f"{'tau = ' + format(cme, '.1%') if cme is not None else 'FUORI dalla griglia 0-100%'}"
f" | sull'ECCEDENZA "
f"{'tau = ' + format(cxx, '.1%') if cxx is not None else 'FUORI dalla griglia 0-100%'}")
dentro = (cme is not None) and (lo <= cme <= hi)
print(f" >>> ATTESA A4 ('la soglia cade DENTRO la banda'): "
f"{'CONFERMATA' if dentro else 'REFUTATA'}")
e_pro = float(SCR.loc[SCR["tag"] == "PROGETTO", "eff"].iloc[0])
e_occ = float(SCR.loc[SCR["tag"] == "OCC", "eff"].iloc[0])
e_o30 = float(SCR.loc[SCR["tag"] == "OCC30", "eff"].iloc[0])
print(f" >>> ATTESA A5 ('la progressiva a EUR 18k sta SOTTO il forfait 33% del progetto'): "
f"occasionale {e_occ:.1%} contro forfait {e_pro:.1%} -> "
f"{'CONFERMATA' if e_occ < e_pro else 'REFUTATA'}.")
print(f" E il seguito e' il punto trasferibile: la STESSA qualificazione, con un reddito")
print(f" preesistente di EUR 30.000, sale a {e_o30:.1%} — "
f"{e_o30/e_occ:.2f}x. **L'aliquota non e' una proprieta' della strategia, e' una")
print(f" proprieta' del contribuente**, e il canale funded e' l'unico pezzo del")
print(f" progetto in cui questo e' vero (le plusvalenze cripto hanno aliquota fissa).")
hr("§6.2 LA CATEGORIA CAMBIA ANCHE LA BASE, non solo l'aliquota")
print(" art. 71 c.2 TUIR (testo verificato in sessione): i redditi di cui all'art. 67 c.1")
print(" lett. l) sono 'la DIFFERENZA fra l'ammontare percepito nel periodo di imposta e le")
print(" spese specificamente inerenti alla loro produzione' -> **sotto lavoro autonomo le")
print(" quote di challenge SI DEDUCONO**; sotto un'imposta sostitutiva su reddito")
print(" finanziario NO (una challenge persa non e' una minusvalenza da cripto-attivita'),")
print(" e sotto forfettario nemmeno (le sostituisce il coefficiente).")
sp_med = float(lad[(500.0, 0.33)]["spent"])
sp_anno = sp_med / 3.0 / EURUSD
print(f"\n Quote comprate in media su 36 mesi: ${sp_med:,.0f} = EUR {sp_anno:,.0f}/anno.")
print(f" {'scenario':>52} {'senza deduzione':>16} {'con deduzione':>14} {'delta':>8}")
for lab, fn_nd, fn_d in (
("lav.aut. OCCASIONALE, nessun altro reddito",
net_prog(0.0, "occasionale", deduci=False), net_prog(0.0, "occasionale")),
("lav.aut. ABITUALE INPS piena, altro reddito 30k",
net_prog(30_000.0, "piena", deduci=False), net_prog(30_000.0, "piena"))):
a = aliq_eff(fn_nd, 18_250.0, sp_anno)
b = aliq_eff(fn_d, 18_250.0, sp_anno)
print(f" {lab:>52} {a:>16.2%} {b:>14.2%} {b-a:>+8.2%}")
print(" -> la categoria con l'aliquota PIU' ALTA e' anche l'unica che deduce il costo dei")
print(" biglietti: l'ordine fra le qualificazioni non e' l'ordine fra le aliquote.")
hr("§6.1 ROBUSTEZZA — i due numeri della ricerca che NON ho verificato su fonte primaria")
print(" (a) secondo scaglione IRPEF 2026: 33% (L.199/2025) contro il 35% del 2025.")
for lab, sg in (("33% (2026)", IRPEF_SCAGLIONI), ("35% (2025)", IRPEF_2025)):
f1 = net_prog(0.0, "occasionale", sg)
f2 = net_prog(30_000.0, "occasionale", sg)
print(f" {lab:>11}: occasionale {aliq_eff(f1, 18_250.0):.2%} "
f"con altro reddito 30k {aliq_eff(f2, 18_250.0):.2%}")
print(" (b) chi versa i 2/3 di Gestione Separata con committente ESTERO — buco documentale:")
for lab, inps in (("committente versa 2/3", "occasionale"), ("tutto sul prestatore", "piena")):
print(f" {lab:>22}: eff.@18k "
f"{aliq_eff(net_prog(0.0, inps), 18_250.0):>6.1%} "
f"@30k {aliq_eff(net_prog(0.0, inps), 30_000.0):>6.1%}")
# ---------------------------------------------------------------- §7 verdetto
hr("§7. VERDETTO — e la domanda, scritta in modo che una risposta sia possibile")
r33 = lad[(500.0, 0.33)]
print(f" 1. Il forfait 33% NON e' l'aliquota di questa cosa: sul funded il trader non")
print(f" possiede il conto ne' le posizioni, non c'e' realizzo di cripto-attivita', e")
print(f" l'art. 67 c-sexies (33%) e c-quater (26%) — le due caselle su cui il progetto")
print(f" discute per il LIBRO — sono entrambe FUORI CATEGORIA qui. Le fonti")
print(f" professionali convergono su LAVORO AUTONOMO. Nessuna prassi ufficiale esiste.")
print(f" 2. La conclusione di §37 ('il biglietto batte il versare' a EUR 500/mese) "
f"{'REGGE' if cme is None or cme > hi else 'NON REGGE'} "
f"su tutta la banda plausibile.")
print(f" 3. Il costo della QUESTIONE, misurato: passare dall'aliquota piu' bassa a quella")
print(f" piu' alta della banda vale, sulla cassa mediana a 36 mesi,")
lo_r = SCR.loc[SCR["eff"].iloc[1:].idxmin()]
hi_r = SCR.loc[SCR["eff"].idxmax()]
print(f" ${lo_r['med_cash']:,.0f} -> ${hi_r['med_cash']:,.0f} "
f"({(hi_r['med_cash']/max(lo_r['med_cash'],1)-1)*100:+.0f}%), e su P(>=50/g) "
f"{lo_r['p_target']:.1%} -> {hi_r['p_target']:.1%}.")
d_eur = (hi_r["med_cash"] - lo_r["med_cash"]) / EURUSD / (HORIZON_DAYS / 365.0) / 365.0
print(f" In EUR/GIORNO di rendita a 36 mesi: **{d_eur:+.2f} EUR/giorno** fra i due")
print(f" estremi della banda, contro un bersaglio di 50.")
print(f" 4. Al 33% di oggi la scala di conti da' EUR/g mediana {r33['med']:.2f} e "
f"P(>=50/g) {r33['p_target']:.1%}: **l'aliquota non e' cio' che tiene lontano il")
print(f" bersaglio**, lo tiene lontano la distribuzione.")
print("\n LA DOMANDA AL COMMERCIALISTA (accanto a quella gia' aperta dal 07/08 sui")
print(" derivati, 26% contro 33% — e questa e' una domanda DIVERSA, non la stessa):")
print(" Q1. Il profit share pagato da una prop firm estera a chi NON possiede il conto,")
print(" NON possiede le posizioni e NON apporta capitale e': art. 67 c.1 lett. l),")
print(" art. 53, art. 55, oppure art. 67 c.1 lett. c-quater TUIR? **Indichi la lettera.**")
print(" Q2. Una prop firm non residente e senza stabile organizzazione puo' operare una")
print(" ritenuta italiana sul payout? (SI'/NO)")
print(" Q3. Superata la soglia di EUR 5.000 di compensi occasionali, con committente")
print(" (a) UE e (b) extra-UE: l'aliquota di Gestione Separata che grava sul")
print(" PRESTATORE e' 1/3 di 26,07% o l'intero 26,07%? (una risposta per caso)")
print(" Q4. Con partita IVA: quale ATECO, e quindi quale coefficiente forfettario,")
print(" 78% o 67%? (una sigla e una percentuale)")
print(" Q5. Il funded account va in quadro RW / IVAFE? (SI'/NO) Se no, l'obbligo si")
print(" limita al conto estero su cui incasso?")
print("\n ONESTA' OBBLIGATORIE:")
print(" * questo NON e' un parere fiscale, e nessuna riga qui sopra e' una consulenza.")
print(" * l'aliquota EFFETTIVA degli scenari progressivi e' calcolata SENZA detrazioni")
print(" (conservativo: le detrazioni la abbassano) e con addizionali al minimo di legge.")
print(" * il modello tassa i payout dell'anno via via che arrivano, non a saldo: toglie")
print(" liquidita' prima del dovuto, quindi e' conservativo sulla ricomposizione.")
print(" * tutte le assunzioni di §37 restano dentro: morte-firm 10%/anno (mai stimata),")
print(" cap $200k/trader, XS01 su U13 fuori campione, ancora giornaliera di TP01 fuori")
print(" dalla banda. Il fisco e' UN parametro fra questi, e non il piu' incerto.")
print(f"\n fatto in {time.time()-T0:.0f}s")
print("=" * 104)
if __name__ == "__main__":
main()