Vai al contenuto
PAPER SIAT 2026Apri la pagina della ricerca
Cryptoverso

Calcolatore del libro · C02

C02 — Costi cumulati su un anno di operatività, al variare della frequenza

Calcolatore 2 — I costi, sui tuoi numeri

Quaderno del capitolo «I costi che ti mangiano vivo» di La matematica di chi perde.

Tre risposte, con i tuoi parametri: quanto ti costano i costi in un anno, quale rendimento lordo ti serve solo per pareggiarli, e quanto ti sarebbe rimasto operando a quella frequenza su una serie reale.

Il numero che quasi nessuno conosce è il secondo.

Le righe marcate PROVA sono quelle da cambiare: cambiale e riesegui per vedere l'effetto. Il resto — comprese le righe marcate NON TOCCARE — serve a mantenere il risultato confrontabile con quello stampato nel libro.

Espandi lo script di questo passo
calc_02_costi.py
python
import matplotlib.pyplot as plt
import numpy as np

from cvbook.dati import carica
from cvbook.lingua import t
from cvbook.metriche import equity, rendimenti

1. I tuoi tre numeri

Se non conosci il tuo costo per giro, il capitolo spiega come misurarlo: prendi dieci operazioni chiuse, confronta il prezzo che avevi visto con quello ottenuto, somma le commissioni. Quasi tutti scoprono di stare più vicini allo 0,25% che allo 0,06%.

Output

in un anno paghi:            624.00 euro
cioe' il:                     6.24% del capitale
rendimento lordo per
NON perdere nulla:            6.43%
Espandi lo script di questo passo
calc_02_costi.py
python
CAPITALE = 10_000.0   # ← il capitale impegnato, in euro
                      # PROVA / TRY: il tuo capitale reale — cambia solo la
                      # scala, non le percentuali qui sotto
COSTO_GIRO = 0.0012   # ← costo tutto compreso di un giro completo (0,12%)
                      # PROVA / TRY: 0,0006 (scontato) · 0,0012 · 0,0025 (al dettaglio)
OPERAZIONI_ANNO = 52  # ← quanti giri completi fai in un anno
                      # PROVA / TRY: la tua frequenza reale, contata sull'estratto conto

speso = CAPITALE * COSTO_GIRO * OPERAZIONI_ANNO
pareggio = (1 + COSTO_GIRO) ** OPERAZIONI_ANNO - 1

print(t("in un anno paghi:        ", "in a year you pay:       ") + f"{speso:10,.2f}"
      + t(" euro", " euros"))
print(t("cioe' il:                ", "that is:                 ") + f"{speso / CAPITALE:10.2%}"
      + t(" del capitale", " of capital"))
print(t("rendimento lordo per     ", "gross return to          "))
print(t("NON perdere nulla:       ", "lose NOTHING:            ") + f"{pareggio:10.2%}")

2. La soglia, al variare della frequenza

La riga tratteggiata è, come nel libro, il rendimento medio storico di lungo periodo di un indice azionario ampio. Tutto ciò che sta sopra è territorio in cui il costo si mangia più di quanto un mercato intero abbia mai reso.

Tre curve crescenti su un asse orizzontale logaritmico con sei tacche — 12, 26, 52, 125, 250 e 500 operazioni complete all'anno — e in verticale quanto occorre guadagnare lordo per pareggiare i soli costi, graduato fino a 200%. Con 0,06% a giro la curva resta sotto il 35%, con 0,12% arriva a circa 82%, con 0,25% supera 86% gia' a 250 operazioni e esce dalla scala a 500. Una riga tratteggiata grigia a 10% segna la media storica di lungo periodo di un indice azionario ampio.

Quanto serve guadagnare per pareggiare i costi, al variare della frequenza delle operazioni.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Costo per operazione completa composto per il numero di operazioni all'anno, tre costi a confronto; la riga tratteggiata e' la media storica di lungo periodo di un indice azionario ampio.

Output

costo 0.06%: 12op→0.7%  26op→1.6%  52op→3.2%  125op→7.8%  250op→16.2%  500op→35.0%
costo 0.12%: 12op→1.4%  26op→3.2%  52op→6.4%  125op→16.2%  250op→35.0%  500op→82.1%
costo 0.25%: 12op→3.0%  26op→6.7%  52op→13.9%  125op→36.6%  250op→86.7%  500op→248.5%
Espandi lo script di questo passo
calc_02_costi.py
python
FREQUENZE = np.array([12, 26, 52, 125, 250, 500])
COSTI = [0.0006, 0.0012, 0.0025]

with avvio.figura("schermo"):
    fig, ax = plt.subplots(figsize=(9, 5))
    for c in COSTI:
        soglia = ((1 + c) ** FREQUENZE - 1) * 100
        ax.plot(FREQUENZE, soglia, marker="o", label=t(f"costo {c:.2%} a giro", f"cost {c:.2%} per round trip"))

    # Riferimento in grigio, con l'etichetta in legenda invece che sul grafico:
    # una scritta appoggiata sulle curve e' il modo piu' rapido di rendere
    # illeggibile una figura che dice una cosa semplice.
    # Grey reference, labelled in the legend rather than on the chart: text
    # sitting on top of the curves is the fastest way to make an otherwise
    # simple figure unreadable.
    ax.axhline(
        10,
        linestyle="--",
        linewidth=1.2,
        color="#8C8C8C",
        zorder=0,
        label=t("~10% annuo: media storica di un indice azionario",
                 "~10% a year: historical average of an equity index"),
    )

    ax.set_xscale("log")
    ax.set_xticks(FREQUENZE)
    ax.set_xticklabels([str(f) for f in FREQUENZE])
    ax.set_xlabel(t("Operazioni complete all'anno", "Round trips per year"))
    ax.set_ylabel(t("Rendimento lordo necessario per pareggiare (%)", "Gross return needed to break even (%)"))
    ax.set_ylim(0, None)
    ax.legend(loc="upper left")
    plt.show()

for c in COSTI:
    print(t(f"costo {c:.2%}: ", f"cost {c:.2%}: ") + "  ".join(
        f"{f}op→{((1 + c) ** f - 1):.1%}" for f in FREQUENZE))

3. Cosa sarebbe rimasto, su dati reali

Stessa esposizione, stesso asset, stesso periodo. L'unica cosa che cambia è quante volte si chiude e si riapre la stessa posizione. Nessuna previsione diversa, nessuna decisione diversa.

Output

btcusdt · 3239 giorni

             frequenza      0.06%      0.12%      0.25%
  mai (compra e tieni)     13.673x     13.664x     13.645x
      una volta l'anno     13.606x     13.532x     13.372x
     una volta al mese     12.824x     12.020x     10.445x
 una volta a settimana     10.365x      7.852x      4.299x
           ogni giorno      1.959x      0.280x      0.004x
Espandi lo script di questo passo
calc_02_costi.py
python
SERIE = "btcusdt"  # ← PROVA / TRY: "ethusdt" · "solusdt" (le tre preparate nel setup)
                   # per un'altra delle 11 serie in codice/dati/registro.json
                   # aggiungila anche a avvio.prepara([...]) qui sopra

r = rendimenti(carica(SERIE).sort("data")["chiusura"].to_numpy())
n = len(r)


def con_frequenza(rend: np.ndarray, ogni_n_giorni: int | None, costo: float) -> float:
    """Capitale finale restando sempre investiti ma rientrando ogni N giorni."""
    operazioni = np.zeros(len(rend))
    # L'ingresso del primo giorno si paga sempre, anche a chi non rientrera'
    # mai piu': e' un'operazione. Senza questa riga il compra-e-tieni era
    # l'unica riga della tabella a viaggiare gratis, e il confronto con le
    # altre frequenze partiva gia' truccato di dodici centesimi per mille euro.
    # The first day's entry is always paid, even by whoever never re-enters.
    operazioni[0] = 1.0
    if ogni_n_giorni is not None:
        operazioni[::ogni_n_giorni] = 1.0
    return float(equity(rend - operazioni * costo)[-1])


print(f"{SERIE} · {n}" + t(" giorni\n", " days\n"))
print(f"{t('frequenza', 'frequency'):>22s} " + " ".join(f"{c:>10.2%}" for c in COSTI))
for ogni, etichetta in [
    (None, t("mai (compra e tieni)", "never (buy and hold)")),
    (365, t("una volta l'anno", "once a year")),
    (30, t("una volta al mese", "once a month")),
    (7, t("una volta a settimana", "once a week")),
    (1, t("ogni giorno", "every day")),
]:
    valori = " ".join(f"{con_frequenza(r, ogni, c):10.3f}x" for c in COSTI)
    print(f"{etichetta:>22s} {valori}")

Esercizi

  1. Metti la tua frequenza reale in OPERAZIONI_ANNO: contale sull'estratto conto dell'ultimo anno, non a memoria. Poi confronta la soglia di pareggio con quello che pensavi di poter ottenere.
  2. Raddoppia COSTO_GIRO e riesegui tutto. Se una strategia sopravvive solo al costo ottimistico, quel vantaggio appartiene a chi ha costi bassi, non a te.
  3. Nella terza cella cambia serie. La colonna del compra-e-tieni cambia molto; il rapporto fra le righe quasi per niente: il costo della frequenza non dipende da quale asset hai scelto.

Riproducibilità e download

Eseguito il 2026-08-27 dal quaderno del repository

Il quaderno

  • calc_02_costi.ipynb11,7 KB

    sha256 4210a85bb1b4ad856ce6f94cbde408f64623d1da3ca4cdebcfc0a29ca0a41d18

  • calc_02_costi.py9,0 KB

    sha256 58d906d189a4efb9c5e4cefa66630b2fb09b3cc10c4f33d472e2a61504cdb2d1

I dati

  • btcusdt.parquet93,2 KB

    sha256 ea75ad84e6e981507054df5c622c6b0ec3c8849c1f4dd007721878d4e4c8a329

    Fonte: Binance Data Vision · Periodo: 2017-08-17 → 2026-06-30 · 3240 righe · estratto 2026-08-16

  • ethusdt.parquet87,0 KB

    sha256 c2bd0259da905e0fec87235d7a62295532433fb89657726dd2d19558db7c072a

    Fonte: Binance Data Vision · Periodo: 2017-08-17 → 2026-06-30 · 3240 righe · estratto 2026-08-16

  • solusdt.parquet57,5 KB

    sha256 c7ba2368a3e419b898fb31ec6d5345b7212b74784b69079d3d43571c2ac63657

    Fonte: Binance Data Vision · Periodo: 2020-08-11 → 2026-06-30 · 2150 righe · estratto 2026-08-16

Torna all’indice dei lab