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

Calcolatore del libro · C01

C01 — Quanto serve guadagnare per recuperare una perdita

Calcolatore 1 — Quanto serve per recuperare una perdita

Quaderno del capitolo «L'aritmetica che nessuno ti mostra» di La matematica di chi perde.

La perdita e il recupero non sono simmetrici, e la differenza cresce in fretta. Questo calcolatore mette i tuoi numeri dentro quell'asimmetria: quanto serve per tornare in pari, quanto costa la volatilità al capitale composto, e cosa succede aggiungendo la leva.

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_01_recupero_perdite.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 drawdown_massimo, equity, recupero_necessario, rendimenti

1. Il tuo numero

Cambia PERDITA e riesegui. È l'unica cella che devi toccare.

Output

perdita subita:         50.0%
ti resta:               50.0% del capitale
serve un guadagno del: 100.0% per tornare al punto di partenza
Espandi lo script di questo passo
calc_01_recupero_perdite.py
python
PERDITA = 0.50  # ← la perdita subita, in frazione: 0,50 vuol dire meno 50%
                # PROVA / TRY: qualunque valore fra 0,01 e 0,99 · guarda cosa
                # succede vicino a 0,90 (dove la curva diventa quasi verticale)

recupero = recupero_necessario(PERDITA)
print(t("perdita subita:        ", "loss taken:             ") + f"{PERDITA:6.1%}")
print(t("ti resta:              ", "you have left:          ") + f"{1 - PERDITA:6.1%}"
      + t(" del capitale", " of capital"))
print(t("serve un guadagno del: ", "you need a gain of:     ") + f"{recupero:6.1%}"
      + t(" per tornare al punto di partenza", " to get back to break even"))

2. La curva intera

La forma è la cosa da guardare: fino al 30% è una salita, dal 70% in poi è un muro. Non c'è nessuna soglia dichiarata da qualche parte — è aritmetica.

Una curva che sale sempre piu' ripida: in orizzontale la perdita subita, dall'1 al 95%, in verticale il guadagno che serve per tornare al capitale di partenza, con l'asse graduato fino a 1.000%. Quattro punti segnati la leggono: a una perdita del 20% serve un guadagno del 25%, al 50% ne serve uno del 100%, all'80% uno del 400%, al 90% uno del 900%.

Quanto serve guadagnare per tornare in pari, al crescere della perdita subita.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Per ogni perdita fra l'1 e il 95%, su 200 punti, il guadagno che riporta il capitale al valore iniziale.
Espandi lo script di questo passo
calc_01_recupero_perdite.py
python
perdite = np.linspace(0.01, 0.95, 200)
recuperi = np.array([recupero_necessario(p) for p in perdite])

with avvio.figura("schermo"):
    fig, ax = plt.subplots()
    ax.plot(perdite * 100, recuperi * 100, linewidth=2)
    for p in (0.2, 0.5, 0.8, 0.9):
        r = recupero_necessario(p)
        ax.plot([p * 100], [r * 100], marker="o")
        ax.annotate(
            f"-{p:.0%} → +{r:.0%}",
            xy=(p * 100, r * 100),
            xytext=(-6, 8),
            textcoords="offset points",
            ha="right",
        )
    ax.set_xlabel(t("Perdita subita (%)", "Loss taken (%)"))
    ax.set_ylabel(t("Guadagno necessario per tornare in pari (%)", "Gain needed to break even (%)"))
    ax.set_ylim(0, 1000)
    plt.show()

3. Il freno della volatilità, sui tuoi parametri

Due strategie con lo stesso rendimento medio non lasciano gli stessi soldi: la più volatile ne lascia meno. Il freno vale circa metà della varianza, e il calcolo qui sotto lo verifica invece di affermarlo.

Output

 volatilita/giorno   media aritm.     composto  capitale finale
            0.500%        0.0793%      0.0781%             2.18x
            1.000%        0.1433%      0.1380%             3.97x
            2.000%        0.1931%      0.1725%             5.60x
            3.500%       -0.0079%     -0.0708%             0.49x
            5.000%        0.1105%     -0.0175%             0.84x
Espandi lo script di questo passo
calc_01_recupero_perdite.py
python
MEDIA_GIORNALIERA = 0.0010  # ← rendimento medio per giorno
                            # PROVA / TRY: 0,0005 · 0,0010 · 0,0020 — il freno
                            # dipende dalla volatilità, non da questo valore
GIORNI = 1000               # PROVA / TRY: 250 (un anno) · 1000 · 3000

rng = np.random.default_rng(20260816)
# NON TOCCARE / DO NOT CHANGE: il seme è fisso perché la tabella qui sotto è
# commentata nel testo con questi numeri esatti; cambiarlo dopo aver visto il
# risultato è il p-hacking che il libro smonta altrove.
# The seed is fixed because the table below is discussed in the text with
# these exact numbers; changing it after seeing the result is the p-hacking
# the book takes apart elsewhere.

print(f"{t('volatilita/giorno', 'volatility/day'):>18s} "
      f"{t('media aritm.', 'arith. mean'):>14s} "
      f"{t('composto', 'compounded'):>12s} "
      f"{t('capitale finale', 'final capital'):>16s}")
for vol in (0.005, 0.01, 0.02, 0.035, 0.05):
    r = rng.normal(MEDIA_GIORNALIERA, vol, GIORNI)
    curva = equity(r)
    composto = curva[-1] ** (1 / GIORNI) - 1
    print(f"{vol:18.3%} {r.mean():14.4%} {composto:12.4%} {curva[-1]:16.2f}x")

La colonna della media aritmetica resta ferma; quella del composto scende. È lo stesso rendimento medio che produce risultati diversi, e la differenza è solo la volatilità.

4. La leva, che moltiplica il freno per il suo quadrato

Con leva k il rendimento atteso si moltiplica per k, ma il freno per . Ecco perché esiste un punto oltre il quale aumentare la leva peggiora tutto — e su un asset già volatile quel punto arriva prestissimo.

Output

 leva  capitale finale   calo massimo    azzerato il
    1          13.6811x         -83.2%              —
    2           2.1427x         -99.1%              —
    3           0.0000x        -100.0%     2020-03-12
    5           0.0000x        -100.0%     2020-03-12
   10           0.0000x        -100.0%     2017-09-14
Espandi lo script di questo passo
calc_01_recupero_perdite.py
python
df = carica("btcusdt").sort("data")
# PROVA / TRY: per usare un'altra serie aggiungila anche alla cella di setup
# (avvio.prepara([...])) — le 11 disponibili sono in codice/dati/registro.json:
# btcusdt · ethusdt · solusdt · lunausdt · fttusdt · ftsemib · eni · enel ·
# intesa · generali · eurusd
r_reali = rendimenti(df["chiusura"].to_numpy())


def curva_con_leva(rend: np.ndarray, k: float) -> np.ndarray:
    """Capitale con leva `k`, con l'azzeramento che e' definitivo.

    Un giorno in cui la posizione perde piu' del capitale non produce un numero
    negativo: produce la fine. Senza questo taglio il calcolo restituirebbe cali
    superiori al 100%, che non significano niente.

    Capital with `k`× leverage, where wipeout is permanent: a day in which the
    position loses more than the capital does not produce a negative number —
    it produces the end. Without this floor the calculation would return
    drawdowns above 100%, which mean nothing.
    """
    passi = np.maximum(1.0 + k * rend, 0.0)
    return np.concatenate([[1.0], np.cumprod(passi)])


print(f"{t('leva', 'leverage'):>5s} {t('capitale finale', 'final capital'):>16s} "
      f"{t('calo massimo', 'max drawdown'):>14s} {t('azzerato il', 'wiped out on'):>14s}")
for k in (1, 2, 3, 5, 10):  # PROVA / TRY: aggiungi 4 o 6, come suggerito negli esercizi
    curva = curva_con_leva(r_reali, k)
    azzerata = np.argmax(curva <= 0.0) if np.any(curva <= 0.0) else None
    quando = str(df["data"][int(azzerata)]) if azzerata is not None else "—"
    print(f"{k:5d} {curva[-1]:16.4f}x {drawdown_massimo(curva):14.1%} {quando:>14s}")

Esercizi

  1. Metti PERDITA = 0.83, che è il calo massimo realmente attraversato da questo asset nel periodo. Il numero che esce è il motivo per cui il capitolo sul rischio parla di sopravvivenza e non di rendimento.
  2. Nella cella della leva, prova k = 4 e k = 6. Trova il punto in cui il capitale finale smette di crescere. Nessuna previsione è cambiata: solo la dimensione.
  3. Nella cella del freno, tieni fissa MEDIA_GIORNALIERA e chiediti quale volatilità azzera il composto. La risposta è la radice quadrata del doppio della media — provala.

Riproducibilità e download

Eseguito il 2026-08-27 dal quaderno del repository

Il quaderno

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

Torna all’indice dei lab