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

Lab del libro · L01

L01 — Quanti conti al dettaglio chiudono in perdita, e in quanto tempo

Lab 1 — Chi perde davvero, e quanto

Quaderno del capitolo «Chi perde davvero, e quanto» di La matematica di chi perde.

Il capitolo mostra tre coordinate senza le quali un risultato non significa niente: su cosa, su quale periodo, con quali costi. Qui le vedi muoversi.

La figura del libro dice che, su questo asset e in questo periodo, il momento in cui si è cominciato conta più di qualunque altra cosa. Il quaderno serve a rifare quel conto e — soprattutto — a smontarlo, esattamente come fa il capitolo: il campione è un solo mercato in un periodo fortunato, e questo va guardato in faccia invece che nascosto.

Esegui le celle dall'alto verso il basso. La prima richiede una ventina di secondi, le altre sono immediate.

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.

Output

serie: Binance Data Vision, estratta il 2026-08-16
periodo: 2017-08-17 → 2026-06-30  (3240 giorni)
Espandi lo script di questo passo
lab_01_chi_perde.py
python
import matplotlib.pyplot as plt
import numpy as np

from cvbook.dati import carica, citazione
from cvbook.metriche import drawdown_massimo

df = carica("btcusdt").sort("data")  # ← PROVA / TRY: "ethusdt" · "solusdt" (vedi esercizio 3)
prezzi = df["chiusura"].to_numpy()
date = df["data"].to_list()
fonte, estratto = citazione("btcusdt")

print(f"serie: {fonte}, estratta il {estratto}")
print(f"periodo: {date[0]}{date[-1]}  ({len(prezzi)} giorni)")

1. Quanti ingressi finiscono in perdita, per orizzonte

Per ogni giorno della storia ci chiediamo: chi fosse entrato quel giorno e uscito dopo N giorni, come sarebbe andata? Poi contiamo la quota di ingressi chiusi in perdita.

È il conto che quasi nessuno fa, perché richiede di guardare tutti i giorni d'ingresso e non solo quello comodo.

Output

  1 mese:  46.4% degli ingressi in perdita  (3210 ingressi)
  3 mesi:  45.5% degli ingressi in perdita  (3150 ingressi)
  1 anno:  33.6% degli ingressi in perdita  (2875 ingressi)
  2 anni:  24.3% degli ingressi in perdita  (2510 ingressi)
  4 anni:   0.0% degli ingressi in perdita  (1780 ingressi)
Espandi lo script di questo passo
lab_01_chi_perde.py
python
ORIZZONTI = [(30, "1 mese"), (90, "3 mesi"), (365, "1 anno"), (730, "2 anni"), (1460, "4 anni")]
# PROVA / TRY: aggiungi o cambia un orizzonte, es. (180, "6 mesi")


def quota_in_perdita(p: np.ndarray, giorni: int) -> float:
    """Frazione di giorni d'ingresso che, dopo `giorni`, si trova sotto zero."""
    if giorni >= len(p):
        return float("nan")
    esiti = p[giorni:] / p[:-giorni] - 1.0
    return float((esiti < 0).mean())


for giorni, etichetta in ORIZZONTI:
    q = quota_in_perdita(prezzi, giorni)
    print(f"{etichetta:>8s}: {q:6.1%} degli ingressi in perdita  ({len(prezzi) - giorni} ingressi)")

2. Il primo limite: le osservazioni si sovrappongono

I numeri appena stampati sembrano basati su migliaia di casi. Non lo sono.

2.875 ingressi a dodici mesi su nove anni di storia non sono 2.875 esperimenti indipendenti: sono nove anni guardati da 2.875 angolazioni che si accavallano quasi tutte fra loro.

Il conto onesto delle occasioni indipendenti è più vicino a questo.

Output

  1 mese:  3210 righe nel file, ma circa 108 periodi davvero distinti
  3 mesi:  3150 righe nel file, ma circa  36 periodi davvero distinti
  1 anno:  2875 righe nel file, ma circa   8 periodi davvero distinti
  2 anni:  2510 righe nel file, ma circa   4 periodi davvero distinti
  4 anni:  1780 righe nel file, ma circa   2 periodi davvero distinti
Espandi lo script di questo passo
lab_01_chi_perde.py
python
for giorni, etichetta in ORIZZONTI:
    sovrapposti = len(prezzi) - giorni
    indipendenti = len(prezzi) // giorni
    print(
        f"{etichetta:>8s}: {sovrapposti:5d} righe nel file, "
        f"ma circa {indipendenti:3d} periodi davvero distinti"
    )

Guarda la colonna di destra. A quattro anni le osservazioni indipendenti sono due. Un numero su cui non si costruisce nessuna conclusione.

3. Il secondo limite: il periodo è fortunato

Cambia la finestra e guarda cosa succede ai numeri. Il capitolo lo dice esplicitamente: la colonna dei quattro anni non dimostra che a quattro anni non si perde — dimostra che in questa finestra non è successo.

Output

finestra scelta: 2017-08-17 → 2026-06-30  (3240 giorni)
risultato del compra-e-tieni: 13.68x
calo massimo attraversato:    -83.2%

  1 mese:  46.4% in perdita
  3 mesi:  45.5% in perdita
  1 anno:  33.6% in perdita
  2 anni:  24.3% in perdita
  4 anni:   0.0% in perdita
Espandi lo script di questo passo
lab_01_chi_perde.py
python
INIZIO, FINE = "2017-08-17", "2026-06-30"
# PROVA / TRY: FINE = "2022-12-31" · INIZIO = "2021-01-01" (vedi esercizi 1 e 2)

import datetime as dt

maschera = [
    dt.date.fromisoformat(INIZIO) <= d <= dt.date.fromisoformat(FINE) for d in date
]
sotto = prezzi[np.array(maschera)]

print(f"finestra scelta: {INIZIO}{FINE}  ({len(sotto)} giorni)")
print(f"risultato del compra-e-tieni: {sotto[-1] / sotto[0]:.2f}x")
print(f"calo massimo attraversato:    {drawdown_massimo(sotto):.1%}\n")
for giorni, etichetta in ORIZZONTI:
    q = quota_in_perdita(sotto, giorni)
    print(f"{etichetta:>8s}: {q:6.1%} in perdita")

Esercizi

  1. Metti FINE = "2022-12-31" ed esegui di nuovo la cella. La colonna dei quattro anni smette di essere zero. Non è cambiato nessun dato: è cambiata la finestra.
  2. Metti INIZIO = "2021-01-01". Il compra-e-tieni scende parecchio. È il capitolo che dice che dieci mesi di differenza sull'ingresso valevano 129 punti percentuali.
  3. Cambia "btcusdt" in "ethusdt" o "solusdt" nella cella del setup e in quella del caricamento. La conclusione regge? Su quali orizzonti?

Cosa portarsi via

Un risultato non è un numero: è un numero con il suo periodo, il suo campione e la sua dimensione effettiva. Se una di queste tre cose manca, la risposta corretta a «quindi funziona?» è: non lo so, e non lo sai nemmeno tu.

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