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

Lab del libro · L03

L03 — Mortalità dei token e distorsione da sopravvivenza

Lab 3 — Il cimitero dei token

Quaderno del capitolo «Il cimitero dei token» di La matematica di chi perde.

Questo quaderno contiene i prezzi veri dei due asset morti di cui parla il capitolo — uno andato a zero in nove giorni, uno il cui mercato è stato chiuso. Conservare quei dati è più difficile di quanto sembri: la maggior parte delle fonti comode espone solo ciò che è ancora attivo.

Il valore del quaderno non è la cronologia del crollo. È l'ultimo esercizio: ricostruire lo stesso paniere guardando solo i sopravvissuti, e vedere che risposta tranquillizzante si ottiene.

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_03_cimitero_token.py
python
import datetime as dt

import matplotlib.pyplot as plt
import numpy as np
import polars as pl

from cvbook.dati import DISCONTINUITA, carica, carica_strumento
from cvbook.metriche import recupero_necessario

1. Nove giorni

Scala logaritmica: ogni tacca vale un fattore dieci. Su scala lineare questo grafico sarebbe una riga verticale seguita da una riga piatta — ed è esattamente così che i crolli appaiono a chi li guarda mentre accadono.

La serie si ferma il 13 maggio 2022, ed è il punto più importante di questa cella. Dal 31 maggio lo stesso identificativo, sullo stesso mercato, quota un'altra cosa: LUNA 2.0, un progetto nuovo lanciato dopo il crollo. Chi disegna la serie per intero ottiene un grafico che scende a 0,00005 e poi risale di centomila volte — e chi lo guarda conclude l'esatto contrario di quello che è successo. La data del taglio non è scritta qui: sta nel registro dei dati (cvbook.dati.DISCONTINUITA), che è l'unico posto in cui vive.

Il prezzo di chiusura di lunausdt in USDT su scala logaritmica, dal 1° aprile al 13 maggio 2022, con l'asse verticale che copre sei ordini di grandezza da 10 alla meno 4 a 10 alla 2. La linea parte poco sopra 100, scende lentamente verso 80 durante aprile, poi cade quasi verticalmente in nove giorni fino a cinque centomillesimi e finisce lì.

Nove giorni di un crollo, in scala logaritmica: ogni tacca vale un fattore dieci. La serie si ferma il 13 maggio, dove quel codice smette di quotare lo stesso token.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Chiusure giornaliere dal 1° aprile 2022 fino alla discontinuità dichiarata nel registro dei dati, su scala logaritmica.
Espandi lo script di questo passo
lab_03_cimitero_token.py
python
luna = carica_strumento("lunausdt").sort("data").filter(pl.col("data") >= dt.date(2022, 4, 1))

with avvio.figura("schermo"):
    fig, ax = plt.subplots()
    ax.semilogy(luna["data"].to_list(), luna["chiusura"].to_numpy(), linewidth=1.6)
    ax.set_ylabel("Prezzo di chiusura (USDT, scala log)")
    fig.autofmt_xdate()
    plt.show()

Provalo tu: il grafico che racconta il contrario

Esegui la cella qui sotto. È la stessa serie, letta grezza — con dentro il ticker riusato — fino al 30 giugno. È il grafico che troveresti su quasi qualunque archivio, ed è quello che il capitolo ti chiede di non credere.

La stessa serie letta grezza: il prezzo di chiusura di lunausdt in USDT su scala logaritmica, dal 1° aprile al 30 giugno 2022, tracciato a linea tratteggiata sullo stesso asse verticale da 10 alla meno 4 a 10 alla 2. Una linea verticale punteggiata segna il 13 maggio. A sinistra della verticale c'è il crollo fino a cinque centomillesimi; a destra la linea risale di circa centomila volte e oscilla fra 2 e 9 fino a fine giugno.

Il grafico che racconta il contrario: senza il taglio, lo stesso codice disegna una resurrezione che nessuno ha vissuto.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Chiusure giornaliere dal 1° aprile al 30 giugno 2022 lette senza applicare la discontinuità, con la data del cambio di strumento segnata da una verticale.

Output

2022-05-05      82.35000 USDT   perdita  0.000%   servirebbe +0%
2022-05-06      77.30000 USDT   perdita  6.132%   servirebbe +7%
2022-05-07      68.13000 USDT   perdita 17.268%   servirebbe +21%
2022-05-08      64.26000 USDT   perdita 21.967%   servirebbe +28%
2022-05-09      30.29000 USDT   perdita 63.218%   servirebbe +172%
2022-05-10      17.46000 USDT   perdita 78.798%   servirebbe +372%
2022-05-11       1.07690 USDT   perdita 98.692%   servirebbe +7,547%
2022-05-12       0.00032 USDT   perdita 100.000%   servirebbe +25,734,275%
2022-05-13       0.00005 USDT   perdita 100.000%   servirebbe +99,999,900%
Espandi lo script di questo passo
lab_03_cimitero_token.py
python
grezza = carica("lunausdt").sort("data").filter(
    pl.col("data").is_between(dt.date(2022, 4, 1), dt.date(2022, 6, 30))
)

with avvio.figura("schermo"):
    fig, ax = plt.subplots()
    ax.semilogy(grezza["data"].to_list(), grezza["chiusura"].to_numpy(),
                linewidth=1.6, linestyle="--")
    ax.axvline(DISCONTINUITA["lunausdt"], linewidth=1.0, linestyle=":")
    ax.set_ylabel("Prezzo di chiusura (USDT, scala log)")
    ax.set_title("La stessa serie letta grezza: da qui in poi è un altro token")
    fig.autofmt_xdate()
    plt.show()

righe = luna.filter(pl.col("data").is_between(dt.date(2022, 5, 5), dt.date(2022, 5, 13)))
partenza = float(righe["chiusura"][0])
for d, p in zip(righe["data"].to_list(), righe["chiusura"].to_numpy()):
    perdita = 1 - p / partenza
    recupero = recupero_necessario(min(perdita, 0.999999))
    print(f"{d}  {p:12.5f} USDT   perdita {perdita:7.3%}   servirebbe +{recupero:,.0%}")

Guarda la penultima riga: la perdita era già del 98,7%. Il giorno dopo il prezzo si è diviso ancora per tremila. Anche dopo aver perso il 98%, c'era ancora tutto da perdere.

2. Quando il prezzo smette di esistere

Il secondo modo di sparire è peggiore, perché non lascia nemmeno un prezzo. Nota dove finisce la linea: non arriva a zero, si interrompe.

Il prezzo di chiusura di fttusdt in USDT dal primo ottobre al 15 novembre 2022, con l'asse verticale da 5 a 25. La linea, segnata da un punto per ogni giorno, oscilla attorno a 25 fino ai primi di novembre, poi scende e si interrompe: l'ultimo punto è il 15 novembre a 1,43, e dopo quella data non c'è più alcun prezzo.

Il secondo modo di sparire: la linea non arriva a zero, si interrompe.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Chiusure giornaliere fino all'ultimo giorno in cui la serie ha un prezzo; dopo quella data il dato non esiste, e la linea finisce lì.

Output

ultimo giorno con un prezzo: 2022-11-15  (1.43 USDT)
dopo quella data non esiste piu' un mercato: non c'e' un prezzo, non c'e' una quotazione, non c'e' modo di vendere.
Espandi lo script di questo passo
lab_03_cimitero_token.py
python
ftt = carica("fttusdt").sort("data").filter(pl.col("data") >= dt.date(2022, 10, 1))

with avvio.figura("schermo"):
    fig, ax = plt.subplots()
    ax.plot(ftt["data"].to_list(), ftt["chiusura"].to_numpy(), linewidth=1.6, marker="o",
            markersize=2.5)
    ax.set_ylabel("Prezzo di chiusura (USDT)")
    fig.autofmt_xdate()
    plt.show()

print(f"ultimo giorno con un prezzo: {ftt['data'][-1]}  ({float(ftt['chiusura'][-1]):.2f} USDT)")
print("dopo quella data non esiste piu' un mercato: non c'e' un prezzo, non c'e' "
      "una quotazione, non c'e' modo di vendere.")

3. Il paniere, con e senza i morti

Un paniere a peso uguale costruito il 1° aprile 2021. Lo misuriamo in due modi: guardando solo ciò che oggi esiste ancora, e guardando tutto quello che si era comprato davvero.

Due curve di capitale a base 100 dal 1° aprile 2021 al 31 dicembre 2022, con l'asse verticale graduato fino a 500 e una linea orizzontale punteggiata a quota 100. Entrambe salgono fino al massimo del 6 novembre 2021 — 564 quella dei soli sopravvissuti, 424 quella tratteggiata che tiene dentro anche i token morti — e poi scendono per tutto il 2022 sotto il livello di partenza: la prima chiude a 47,1, la seconda a 29,0, il 38,5% più in basso.

Lo stesso paniere misurato due volte: solo con ciò che esiste ancora, e con tutto ciò che era stato preso davvero.Fonte: Binance Data Vision · Periodo: 2017-08-17 … 2026-06-30 · Metodo: Paniere a peso uguale costruito il 1° aprile 2021 e tenuto fino al 31 dicembre 2022, calcolato una volta sui soli sopravvissuti e una volta su tutte le serie, morte comprese.

Output

paniere dei soli sopravvissuti: 47.1
paniere reale, morti compresi:  29.0
differenza:                     -38.5%
Espandi lo script di questo passo
lab_03_cimitero_token.py
python
INIZIO = dt.date(2021, 4, 1)  # ← PROVA / TRY: sposta a gennaio 2022 (vedi esercizio 2)
FINE = dt.date(2022, 12, 31)  # ← PROVA / TRY: porta a oggi e guarda cosa cambia
VIVI = ["btcusdt", "ethusdt", "solusdt"]  # ← PROVA / TRY: togli "solusdt" (esercizio 1)
MORTI = ["lunausdt", "fttusdt"]
# NON TOCCARE / DO NOT CHANGE: MORTI deve restare com'è — sono gli unici due
# token defunti congelati nel registro dati; la dimostrazione è proprio che
# le fonti comode non li avrebbero mai lasciati scegliere (vedi esercizio 3)
# MORTI must stay as it is — these are the only two dead tokens frozen in the
# data registry; the whole demonstration is that convenient sources would
# never have let you choose them (see exercise 3)


def curva_paniere(nomi: list[str]) -> tuple[list, np.ndarray]:
    """Paniere a peso uguale, ribilanciato una sola volta all'inizio.

    Due scelte, e vanno dette perché sono le stesse della figura stampata nel
    libro — altrimenti questo quaderno risponderebbe a una domanda diversa da
    quella del capitolo, che è esattamente ciò che non deve succedere.

    **Un asset delistato non sparisce: resta all'ultimo valore noto.** È quanto
    vale davvero per chi ce l'ha in portafoglio, e non è zero: FTT il 15 novembre
    2022 valeva ancora 1,43 dollari, semplicemente non si poteva più vendere.

    **Le serie si leggono con `carica_strumento`**, che si ferma dove
    l'identificativo cambia strumento. Con la serie grezza LUNA risaliva al 6,8%
    del valore iniziale e il paniere dei morti chiudeva a 30,3 invece che a 29,0:
    questo quaderno avrebbe sottostimato del 7% proprio l'errore che esiste per
    misurare.
    """
    calendario = [
        d for d in carica("btcusdt").sort("data")["data"].to_list()
        if INIZIO <= d <= FINE
    ]
    quote = []
    for n in nomi:
        s = carica_strumento(n).sort("data").filter(
            pl.col("data").is_between(INIZIO, FINE)
        )
        mappa = dict(zip(s["data"].to_list(), s["chiusura"].to_numpy()))
        base = mappa[min(mappa)]
        ultimo, riempita = base, []
        for d in calendario:
            ultimo = mappa.get(d, ultimo)
            riempita.append(ultimo / base)
        quote.append(riempita)
    return calendario, np.mean(np.array(quote), axis=0)


date_v, solo_vivi = curva_paniere(VIVI)
date_t, tutti = curva_paniere(VIVI + MORTI)

with avvio.figura("schermo"):
    fig, ax = plt.subplots()
    ax.plot(date_v, solo_vivi * 100, linewidth=1.8, label="solo i sopravvissuti")
    ax.plot(date_t, tutti * 100, linewidth=1.8, linestyle="--",
            label="tutti, morti compresi")
    ax.axhline(100, linestyle=":", linewidth=0.9)
    ax.set_ylabel("Capitale (base 100)")
    ax.legend()
    fig.autofmt_xdate()
    plt.show()

print(f"paniere dei soli sopravvissuti: {solo_vivi[-1] * 100:.1f}")
print(f"paniere reale, morti compresi:  {tutti[-1] * 100:.1f}")
print(f"differenza:                     {tutti[-1] / solo_vivi[-1] - 1:+.1%}")

Nessuno dei due numeri è sbagliato: sono risposte a due domande diverse. La prima è «come sono andati questi tre asset». La seconda è «come sarebbe andata a me». Quasi tutti fanno la prima e credono di aver risposto alla seconda.

Esercizi

  1. Togli "solusdt" da VIVI e riesegui: la distanza fra le due curve cambia parecchio. Quanto la conclusione dipende da quali nomi hai incluso?
  2. Sposta INIZIO a gennaio 2022. Il paniere reale peggiora molto di più di quello dei sopravvissuti: la distorsione cresce quando il periodo contiene più morti.
  3. L'esercizio che vale il capitolo: prova a ricostruire questa stessa figura usando una fonte gratuita qualunque di dati storici. Scoprirai che i due asset morti non ci sono, e otterrai la curva tranquillizzante senza nemmeno accorgerti di aver fatto un errore.

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

  • 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

  • lunausdt.parquet27,6 KB

    sha256 10fe10357f76eb408550f4809ce2a87cb1129164f6f6d074ae7eac730ccb7f15

    Fonte: Binance Data Vision · Periodo: 2020-08-21 → 2022-12-31 · 846 righe · estratto 2026-08-16

  • fttusdt.parquet27,5 KB

    sha256 7b235709ebb5ae31df0a9c315bd134b95e5249196a6c84b54763d9e63795fc06

    Fonte: Binance Data Vision · Periodo: 2019-12-20 → 2022-11-15 · 1062 righe · estratto 2026-08-16

Torna all’indice dei lab