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

Lab del libro · L02

L02 — Curve di capitale generate dal solo caso, e le più belle fra mille

Lab 2 — Il caso vestito da bravura

Quaderno del capitolo «Il caso vestito da bravura» di La matematica di chi perde.

Questo quaderno genera curve di capitale che non contengono nulla: nessuna decisione, nessun segnale, vantaggio atteso esattamente zero. Poi fa quello che fa chiunque mostri i propri risultati: tiene le migliori e butta il resto.

L'esercizio finale è il più utile del quaderno: ci metti dentro un risultato che hai visto in giro e ti dice quale percentuale di curve casuali fa meglio.

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
lab_02_equity_casuali.py
python
import matplotlib.pyplot as plt
import numpy as np

from cvbook import seed_for
from cvbook.metriche import drawdown_massimo
from cvbook.simulazioni import equity_casuali, migliori_per_caso

1. Dodici curve. Indovina quali sono quelle brave

Guardale prima di scorrere. Alcune ti sembreranno convincenti — e va bene così, è esattamente il punto del capitolo.

Dodici riquadri su quattro colonne, titolati dalla A alla L e intitolati nell'insieme «Dodici curve senza alcuna abilita' dentro»: ognuno porta 500 giorni di capitale a base 100 con una riga punteggiata sul valore di partenza. Gli esiti finali scritti nei titoli vanno da 0,41 a 1,62 volte il capitale iniziale, e le scale verticali dei riquadri arrivano da 40 fino a 180.

Dodici curve di capitale generate dal solo caso, senza alcun vantaggio dentro.Fonte: — dati generati nel quaderno · Periodo: — dati generati nel quaderno · Metodo: Cinquecento operazioni per curva, estratte con oscillazione tipica dell'1,8% e vantaggio esattamente nullo, seme fissato dal quaderno.
Espandi lo script di questo passo
lab_02_equity_casuali.py
python
GIORNI = 500          # ← due anni circa di operatività
                      # PROVA / TRY: 125 (sei mesi) · 500 · 1000
VOLATILITA = 0.018    # ← oscillazione tipica per operazione
                      # PROVA / TRY: 0,01 · 0,018 · 0,04
VANTAGGIO = 0.0       # ← lascialo a zero: è il punto

rng = np.random.default_rng(seed_for("lab-equity-casuali"))
# PROVA / TRY: cambia il nome dentro seed_for(...) per vedere altre dodici
# curve — nessuna delle due versioni contiene più abilità dell'altra
curve = equity_casuali(12, GIORNI, rendimento_atteso=VANTAGGIO,
                       volatilita_periodo=VOLATILITA, rng=rng)

with avvio.figura("schermo"):
    fig, assi = plt.subplots(3, 4, figsize=(11, 6), sharex=True)
    for k, ax in enumerate(assi.flat):
        ax.plot(curve[k] * 100, linewidth=1.2)
        ax.axhline(100, linestyle=":", linewidth=0.8)
        ax.set_title(f"{chr(65 + k)}   {curve[k][-1]:.2f}x", fontsize=9)
        ax.set_xticks([])
    fig.suptitle("Dodici curve senza alcuna abilità dentro")
    plt.show()

Non ce ne sono. Sono dodici estrazioni dallo stesso generatore, con vantaggio atteso zero. Le due che ti sono piaciute hanno avuto una buona settimana.

2. Le migliori cinque su mille

Adesso l'operazione che compie, senza dirlo, chiunque presenti i propri risultati: si generano mille tentativi e si mostrano i cinque migliori.

Due pannelli affiancati. A sinistra, «Le 5 migliori su 1000»: cinque curve di capitale a base 100 su 500 giorni, tutte in salita, la piu' alta oltre 400. A destra, «Da dove sono state estratte»: l'istogramma dei 1.000 esiti finali, centrato poco sotto 100 e con la coda destra che si assottiglia oltre 300. La mediana dei mille e' 0,91 volte il capitale iniziale.

Le cinque curve migliori di mille, e la distribuzione da cui sono state scelte.Fonte: — dati generati nel quaderno · Periodo: — dati generati nel quaderno · Metodo: Mille curve generate con vantaggio nullo; a sinistra le cinque col capitale finale piu' alto, a destra la distribuzione di tutti i mille esiti finali.

Output

mediana dei 1000 risultati: 0.907x
la migliore:               4.079x  (calo massimo -14.3%)
quota sopra 1,5x:          10.00%
quota sopra 2x:            2.80%
quota sopra 2x CON calo massimo sotto il 20%: 0.80%
Espandi lo script di questo passo
lab_02_equity_casuali.py
python
N = 1000  # PROVA / TRY: 200 (veloce) · 1000 · 10000 (il numero del capitolo si stabilizza)
rng = np.random.default_rng(seed_for("migliori-per-caso"))
# NON TOCCARE / DO NOT CHANGE: questa cella mostra le 5 migliori su 1000
# tentativi senza vantaggio — è la messa in scena del p-hacking, non
# l'occasione per cercare un seme che renda le 5 migliori ancora più belle.
# This cell shows the 5 best out of 1000 attempts with no edge — it's the
# staging of p-hacking, not a chance to hunt for a seed that makes the 5
# best look even more impressive.
tutte = equity_casuali(N, GIORNI, rendimento_atteso=VANTAGGIO,
                       volatilita_periodo=VOLATILITA, rng=rng)
migliori = migliori_per_caso(tutte, 5)

with avvio.figura("schermo"):
    fig, (sx, dx) = plt.subplots(1, 2, figsize=(11, 4))
    for curva in migliori:
        sx.plot(curva * 100, linewidth=1.4)
    sx.axhline(100, linestyle=":", linewidth=0.9)
    sx.set_title(f"Le 5 migliori su {N}")
    sx.set_ylabel("Capitale (base 100)")

    dx.hist(tutte[:, -1] * 100, bins=60)
    dx.axvline(100, linestyle=":", linewidth=1.2)
    dx.set_title("Da dove sono state estratte")
    dx.set_xlabel("Capitale finale (base 100)")
    plt.show()

finali = tutte[:, -1]
print(f"mediana dei {N} risultati: {np.median(finali):.3f}x")
print(f"la migliore:               {finali.max():.3f}x  "
      f"(calo massimo {drawdown_massimo(migliori[0]):.1%})")
print(f"quota sopra 1,5x:          {(finali > 1.5).mean():.2%}")
print(f"quota sopra 2x:            {(finali > 2.0).mean():.2%}")
print(f"quota sopra 2x CON calo massimo sotto il 20%: "
      f"{np.mean((finali > 2) & (np.array([drawdown_massimo(c) for c in tutte]) > -0.20)):.2%}")

L'ultima riga è il numero del capitolo: circa uno su cento. Su diecimila persone che ci provano, cento producono un biennio da fuoriclasse senza avere assolutamente nulla dentro.

3. E adesso il tuo caso

Prendi un risultato che ti ha colpito — un grafico, una pubblicità, una curva di un canale — e mettici i tre numeri qui sotto.

Output

risultato dichiarato: 2.50x su 500 giorni
curve casuali che fanno altrettanto o meglio: 0.76%
su 10.000 persone senza alcuna abilita', ne otterrebbero altrettanto: 76
Espandi lo script di questo passo
lab_02_equity_casuali.py
python
RISULTATO_DICHIARATO = 2.5   # ← capitale finale dichiarato, in volte (2,5 = +150%)
                             # PROVA / TRY: il risultato che ti ha colpito davvero
DURATA_GIORNI = 500          # ← su quanti giorni di operatività
                             # PROVA / TRY: 125 (vedi esercizio 1) · 500
VOLATILITA_TIPICA = 0.018    # ← oscillazione per operazione, se la conosci
                             # PROVA / TRY: 0,018 · 0,04 (vedi esercizio 2)

rng = np.random.default_rng(seed_for("confronto-personale"))
prova = equity_casuali(5000, DURATA_GIORNI, rendimento_atteso=0.0,
                       volatilita_periodo=VOLATILITA_TIPICA, rng=rng)[:, -1]
meglio = float((prova >= RISULTATO_DICHIARATO).mean())

print(f"risultato dichiarato: {RISULTATO_DICHIARATO:.2f}x su {DURATA_GIORNI} giorni")
print(f"curve casuali che fanno altrettanto o meglio: {meglio:.2%}")
print(f"su 10.000 persone senza alcuna abilita', ne otterrebbero altrettanto: "
      f"{meglio * 10_000:.0f}")

Esercizi

  1. Riduci DURATA_GIORNI a 125 (sei mesi) tenendo lo stesso risultato: la percentuale crolla. Un risultato spettacolare su un periodo corto è più difficile da ottenere per caso di uno spettacolare su un periodo lungo.
  2. Alza VOLATILITA_TIPICA a 0,04. La stessa cifra diventa molto più facile da ottenere per caso: quanto oscilla cambia il significato di quanto rende.
  3. Metti VANTAGGIO = 0.0005 nella prima cella. Ora un vantaggio c'è davvero. Riesci a distinguerlo a occhio dalle curve senza vantaggio? Quasi nessuno ci riesce, ed è il motivo per cui esiste il capitolo sulla potenza statistica.

Riproducibilità e download

Eseguito il 2026-08-27 dal quaderno del repository

Il quaderno

Torna all’indice dei lab