27 Agosto 2026 · ingegneria dei dati

Il tuo universo di simboli è una macchina del tempo: bias di sopravvivenza nei backtest sui perpetual crypto

Il tuo universo di simboli è una macchina del tempo: bias di sopravvivenza nei backtest sui perpetual crypto

Mi hai mandato il notebook domenica sera e da allora è rimasto aperto sul secondo monitor. Momentum cross-sectional, i 150 perpetual Binance USDⓈ-M con il maggior volume in dollari negli ultimi 30 giorni, ribilanciamento settimanale, long sul decile superiore e short su quello inferiore, da 2021-01 a 2026-06. Sharpe 2.31, drawdown massimo 14.2% e un modello dei costi che mi sembrava ben fatto: taker in entrata, taker in uscita, funding maturato a ogni intervallo, una componente di slippage che cresce con la dimensione della tua posizione rispetto al book. Hai fatto bene le parti difficili. Poi mi hai chiesto perché sei settimane di paper trading sono risultate piatte e se il vantaggio si fosse esaurito.

Non si è esaurito. Non era mai stato nel backtest. Guarda la cella 4:

info = requests.get(BASE + "/fapi/v1/exchangeInfo").json()
symbols = [s["symbol"] for s in info["symbols"]
           if s["status"] == "TRADING" and s["quoteAsset"] == "USDT"]

Hai interrogato quell'endpoint a giugno 2026 e hai usato la risposta per definire cosa fosse tradabile a marzo 2021. Per definizione, ogni simbolo presente in quell'elenco era ancora attivo a giugno 2026. Ecco tutto il problema, e il suo impatto supera quello di tutto il resto del tuo modello dei costi messo insieme.

2.31 → 0.74Sharpe, universo dei sopravvissuti vs point-in-time
~1 su 5dei simboli nel tuo universo del 2021 non esiste più
380 KBuno snapshot giornaliero di exchangeInfo, compresso con gzip

Cosa non ti dirà l'endpoint

exchangeInfo non contiene dati storici. Nessun parametro asOf, nessun archivio, nessun changelog. È una fotografia di oggi, e Binance non ti ha mai promesso altro. Quando un contratto viene rimosso dal listino, la sua voce sparisce dalla risposta e, per l'API, quel ticker smette di esistere. Dal 2019 Binance ha quotato oltre 600 perpetual USDⓈ-M e ne ha ritirati ben più di 100. BTS, COCOS, TOMO, RAY, FTT, SC e una lunga coda di contratti dell'alt season del 2021, protagonisti di uno splendido trimestre prima di perdere volume finché la piattaforma non li ha rimossi.

Chiediti quali asset ama uno screener di momentum a 30 giorni. Non BTC. Ama quello che è appena triplicato grazie al pump della quotazione e al ciclo su Twitter. Quell'insieme si sovrappone in larga misura a quello degli asset destinati a essere rimossi dal listino, e il filtro del tuo universo ha cancellato proprio la sovrapposizione.

Ho ricostruito la tua simulazione usando il nostro archivio di snapshot, un universo point-in-time, lo stesso segnale e gli stessi costi. Lo Sharpe è risultato 0.74, con un drawdown del 31%. Circa due quinti della differenza dipendono da simboli rimossi dal listino che non avresti mai potuto detenere. Un altro quarto è dovuto al problema speculare, più sottile e che sospetto ti piacerà meno.

L'altro verso della macchina del tempo: simboli che ancora non esistevano

La tua feature misura il rendimento a 90 giorni. La finestra mobile ha min_periods=20, perché l'hai impostata una volta per evitare che il warmup azzerasse il primo trimestre del campione e poi non l'hai più rivista. Così un contratto quotato da appena 21 giorni riceve un punteggio di momentum calcolato su 3 settimane di prezzi successivi alla quotazione, finisce nel decile superiore più o meno ogni volta che la quotazione va bene ed entra nel tuo portafoglio.

Questa parte si può anche considerare legittima. Ecco cosa non lo è: il tuo provider ha ricostruito a ritroso alcuni di quei simboli usando dati spot o dell'indice precedenti all'esistenza del perpetual, quindi per alcuni contratti la cronologia delle candele precede il loro onboardDate. Puoi verificarlo in circa 1 minuto. Unisci la tabella dei prezzi alle date di quotazione e conta le righe precedenti alla quotazione. Nei tuoi dati ci sono 41 simboli con barre pre-quotazione; uno di loro, nell'estate del 2023, aggiunge un guadagno del 6% in una singola settimana alla curva azionaria grazie a una posizione in un contratto che sarebbe stato quotato solo 9 giorni dopo.

Il ticker non è un identificativo. È un'etichetta che l'exchange ti affitta, a volte due volte.

E poi ci sono i cambi di nome. MATICUSDT è diventato POLUSDT. FTMUSDT è diventato SUSDT con una conversione 1:1. La vicenda LUNA del maggio 2022 ha lasciato LUNCUSDT e, in seguito, un nuovo LUNAUSDT, con una radice del ticker condivisa con qualcosa che ha perso praticamente tutto. Se il tuo loader usa la stringa del simbolo come chiave e concatena tutti i file che trova, hai almeno una serie con una discontinuità che non corrisponde a un movimento di prezzo, e la tua feature di momentum la interpreterà come il segnale più forte della sezione cross-sectional.

Tutto il resto che cambia nel tempo

Una volta accettato che l'elenco dei simboli varia nel tempo, lo stesso ragionamento vale per ogni altro campo di quella risposta. Tu usi i valori di oggi per tutti.

CampoCome cambiaCosa si rompe
statusTRADING → SETTLING → rimossoBias di sopravvivenza; uscite fantasma a un prezzo di chiusura mai negoziato
onboardDateOgni settimana ci sono nuove quotazioni; i simboli rimossi non compaiono piùContratti tradati prima ancora che esistessero
tickSize / stepSizeRicalibrati al variare dei prezziArrotondamento degli ordini e prezzi limite che sarebbero stati rifiutati
minNotionalAumentato nel tempo sui book poco liquidiGambe piccole che il tuo router live rifiuterebbe
fundingIntervalHours8h per anni, poi 4h o 1h su molti simboliCarry sballato di 2–3× proprio sugli alt che il tuo screener detiene
leverage bracketsLivelli e margine di mantenimento rivistiModello di liquidazione e capacità di margine

Nel tuo caso, il funding è l'aspetto più problematico. Il tuo ciclo di accumulo presume 3 pagamenti al giorno per tutta la serie storica. Una quota significativa del portafoglio di alt si è spostata su funding ogni 4 ore, e le gambe short sugli asset con funding elevato generano buona parte del tuo PnL simulato. Non sbagli di poco per via di un arrotondamento: sbagli di un fattore intero.

La rimozione dal listino è un evento, e tu non lo stai modellando

Nel tuo nuovo backtest point-in-time ho concesso alla strategia un'uscita generosa. Nella realtà le rimozioni seguono una procedura: un annuncio, di solito con 7-14 giorni di preavviso, poi una finestra reduce-only e infine il regolamento forzato a un prezzo mark. L'annuncio è un'informazione pubblica e puoi agire, quindi la simulazione corretta prevede l'uscita alla chiusura del giorno dell'annuncio. Ma su un tipico alt rimosso dal listino, quel prezzo di chiusura è già inferiore del 10-20% rispetto alla settimana precedente, il book è poco liquido e il modello di slippage deve sapere che si trova in un regime diverso. Se il tuo motore di esecuzione ti assegna il prezzo di regolamento senza alcun impatto sul mercato, stai assegnando di nascosto un fair value ad asset in via di estinzione.

Se non hai mai archiviato exchangeInfo, non è tutto perduto. Il dump pubblico su data.binance.vision/data/futures/um/monthly/klines/ conserva ancora le directory dei simboli rimossi molto tempo dopo che l'API li ha dimenticati. Elenca le directory: il primo e l'ultimo file mensile per ogni simbolo ti danno una finestra indicativa di quotazione e rimozione, senza bisogno di un vendor. È una ricostruzione, non una registrazione, e non ti permette di recuperare tick size o intervalli di funding. Ma ti dice quali simboli esistevano e quando: lunedì avrai già l'80% di quello che ti serve.

Cosa ti farei costruire prima di rimettere mano al segnale

  1. Un cron che scarica ogni giorno exchangeInfo da tutte le piattaforme che analizzi e lo salva nell'object storage, organizzato per data. Compresso con gzip occupa meno di mezzo megabyte. Dieci anni di dati ti costano una frazione trascurabile su S3 e ti danno una capacità di ricerca che non potrai acquistare in seguito.
  2. Un'anagrafica degli asset ricavata da quegli snapshot: una riga per ogni (venue, symbol, valid_from, valid_to), con l'intero set di campi. Confronta gli snapshot consecutivi per generarla e considera ogni modifica a un campo come una nuova riga.
  3. Una funzione per l'universo con un argomento timestamp obbligatorio. universe(ts), mai universe(). Rendi impossibile usare un valore predefinito, così nessuno, nemmeno tu in futuro all'1am, potrà ricorrere per sbaglio all'elenco dei sopravvissuti.
  4. Un controllo pre-quotazione nel loader dei dati: non deve esserci alcuna barra precedente a onboard_ts meno 1 giorno. Interrompi l'esecuzione, senza limitarti a mostrare un avviso.
  5. Un ID strumento interno e stabile che sopravvive ai cambi di nome, relegando il ticker a semplice attributo. Mappa POL e MATIC allo stesso ID e segnala le redenominazioni, così la logica di continuità può impedire di unire le serie.

Fai queste modifiche e rilancia il backtest. La mia stima è che arriverai vicino allo 0.74 che ho ottenuto io. A quel punto la domanda interessante sarà se uno 0.74 che include gli asset rimossi dal listino abbia abbastanza valore da meritare il paper trading. Potrebbe. Il momentum cross-sectional sui perpetual non è privo di valore, e una parte del rendimento rimasto dopo aver corretto l'universo è carry autentico dal lato short. Vedrai anche che i risultati del paper trading e del backtest cominciano a coincidere, perché il paper trading ha sempre usato un universo point-in-time. Non aveva scelta.

P.S. Non è una particolarità delle crypto, qui si nota solo di più. Chi fa ricerca azionaria si confronta con i rendimenti da delisting e i ticker riciclati da quando CRSP ha iniziato a distribuirli; i mercati predittivi spingono il fenomeno all'estremo: per definizione ogni contratto scade, quindi l'universo non è altro che quotazioni e scadenze. Se trasferirai mai questo screener su Kalshi, crea prima l'anagrafica degli asset. Lì non esiste un altro tipo di serie storica.

bias di sopravvivenzadati point-in-timefutures cryptobacktestingingegneria dei dati
← Tutti gli articoli