Raddoppiare gli scenari Monte Carlo rende più realistico il rischio di coda? 12 ETF alla prova
Quando una simulazione Monte Carlo del rischio restituisce numeri instabili, viene spontaneo proporre di raddoppiare gli scenari. Ma le altre 756 osservazioni simulate aggiungono davvero informazioni sulle perdite estreme? Volevo distinguere due effetti: una stima meno rumorosa e una rappresentazione più fedele del rischio osservato.
Ho confrontato 12 ETF con prezzi storici reali, sei metodi di generazione degli scenari e 50 semi casuali abbinati. Passare da 756 a 1.512 osservazioni simulate ha ridotto la variabilità di alcune stime. Tuttavia, per Gaussian la frequenza dei ribassi simultanei è rimasta intorno a 0.3180, contro 0.4211 nel periodo storico di addestramento fissato in anticipo.
Per «ribasso simultaneo» intendo una domanda concreta: nei giorni in cui SPY scende molto, quale quota degli altri ETF scende altrettanto? La soglia di «giorno molto negativo» è, per ciascun ETF, il 5° percentile inferiore dei rendimenti del training. Non la ridefinisco sulle simulazioni in modo da migliorarne artificialmente il risultato.
Per valutare un generatore di scenari oggi separo tre domande: più estrazioni rendono stabile la stima? Il modello conserva le perdite congiunte e le giornate difficili consecutive? Le soglie di rischio sono calibrate fuori campione? Le prime due riguardano gli stessi dati storici fissati. La terza appartiene a una verifica diversa e più limitata del VaR a un giorno, non a una gara OOS fra i sei generatori.
Dodici ETF e un training fisso di 756 giorni
Ho usato il Huge Stock Market Dataset di Boris Marjanovic. La descrizione dichiara licenza CC0 e prezzi corretti per dividendi e frazionamenti. Ho scelto dodici ETF che rappresentano azioni, titoli di Stato, credito, oro, materie prime, dollaro e immobiliare: guardare SPY da solo non basta per capire i ribassi fra classi di attività. I simboli completi sono riportati in fondo.
Ho incrociato le date dei prezzi Close rettificati nei dodici file originali, senza riempire le date mancanti. In questa versione Kaggle il file HYG comincia il 2007-04-11, quindi l’intersezione comprende 2.668 date di prezzo dal 2007-04-11 al 2017-11-10. Da queste ho ricavato i rendimenti semplici giornalieri e, per ogni giorno, la media con peso uguale dei dodici ETF. La definizione del portafoglio non cambia mai.
Per i generatori uso soltanto i primi 756 rendimenti giornalieri, circa tre anni di mercato compreso lo shock del 2008. Tenere fisso quel periodo significa fare confronti con le stesse informazioni, senza lasciare che ogni metodo scelga il campione più favorevole. Ho fissato anche a cinque i gradi di libertà di Student-t, senza ritoccarli dopo aver visto i risultati fuori campione.
| Metodo | Come vengono generati gli scenari di rendimento |
|---|---|
| Gaussian | Normale multivariata basata su medie e covarianze del training |
| Student-t df=5 | t multivariata con cinque gradi di libertà e covarianza allineata al training |
| IID Bootstrap | Estrazione indipendente con reinserimento di intere righe giornaliere di ETF |
| Moving-block 5 / 20 / 60 | Estrazione di blocchi consecutivi di 5, 20 o 60 giorni di rendimento |
La prima trappola che volevo evitare: se cambio numeri casuali fra le due simulazioni, posso scambiare una coincidenza per l’effetto della dimensione del campione. Per ogni metodo ho quindi usato gli stessi 50 semi, 1000–1049. A ogni seme genero prima 1.512 osservazioni e ne riutilizzo le prime 756 della stessa sequenza come campione piccolo. In pratica, continuo a estrarre dalla stessa storia di 756 giorni: 756 giorni simulati in più non sono 756 giorni reali di mercato in più.
Anche Student-t nasconde un errore frequente: scegliere una distribuzione «a code pesanti» e dimenticare di uniformare la varianza, aumentando così anche tutta la volatilità. Nell’implementazione ottengo vettori normali correlati tramite il fattore di Cholesky della covarianza storica e moltiplico per √(3/χ²₅), dove χ²₅ è una variabile chi-quadrato con cinque gradi di libertà. È equivalente a usare una matrice di scala t pari a 3/5 della covarianza del training. Senza il fattore correttivo, la covarianza generata crescerebbe fino a 5/3 del valore desiderato.
Che cosa è diventato davvero più stabile raddoppiando gli scenari
Parto dall’ES(5%) a un giorno, cioè dal rendimento medio nel 5% peggiore dei casi. Ho calcolato un ES per ciascun seme e confrontato la deviazione standard dei 50 valori ES fra semi con N=1.512 rispetto a N=756. Questo misura rumore di simulazione; non misura quanto il modello conosca un futuro mercato ignoto.
| Generatore | Rapporto fra deviazioni standard ES tra semi: 1.512 / 756 |
|---|---|
| Gaussian | 0.718 |
| Student-t df=5 | 0.671 |
| IID Bootstrap | 0.746 |
| Moving-block 5 | 0.768 |
| Moving-block 20 | 0.681 |
| Moving-block 60 | 0.734 |
Tutti e sei i rapporti sono fra 0.671 e 0.768, quindi inferiori a uno. In queste 50 prove abbinate le stime ES risultano più vicine dopo il raddoppio. Il noto 1/√2≈0.707 è un buon riferimento intuitivo per la diminuzione del rumore campionario, ma una statistica di coda come l’ES non deve necessariamente convergere esattamente con quella legge.
Per i ribassi simultanei il quadro cambia. Seleziono i giorni simulati in cui SPY scende sotto la soglia del 5% fissata nel training. Per ognuno calcolo quale frazione degli altri undici ETF supera al ribasso la propria soglia fissata e faccio la media. L’errore medio di Gaussian rispetto al riferimento storico rimane pressoché identico: circa −0.1036 con N=756, contro −0.1031 con N=1.512.
Estrarre di più stabilizza il numero. Non regala al generatore i ribassi congiunti che non sa rappresentare.
IID Bootstrap conserva chi perde nello stesso giorno, ma dimentica quando le perdite si accumulano
Una buona corrispondenza sui ribassi dello stesso giorno non implica che i giorni difficili si susseguano come nella storia. Calcolo tutti gli indicatori che seguono sui rendimenti giornalieri del portafoglio equiponderato dei dodici ETF. L’autocorrelazione dei rendimenti assoluti al primo ritardo, ACF(1), osserva in modo approssimativo se le grandi oscillazioni si raggruppano. ES e drawdown a 60 giorni guardano invece traiettorie più lunghe.
C’è anche una trappola numerica: sommare 60 rendimenti percentuali giornalieri non equivale a calcolare una perdita composta su 60 giorni. Faccio scorrere una finestra di 60 giorni, un giorno alla volta, lungo la sequenza generata e calcolo il rendimento composto con ∏(1+rₜ)-1. L’ES a 60 giorni è la media del 5% peggiore dei rendimenti di finestra. Per il drawdown massimo ricostruisco prima il percorso del capitale composto in ogni finestra, calcolo il massimo drawdown e infine prendo il 5° percentile di questi valori.
Ecco le medie su 50 semi a N=1.512, a confronto con il periodo storico fisso:
| Origine dello scenario | Ribassi simultanei | ACF(1) rendimenti assoluti | ES(5%) a 60 giorni | 5° percentile del drawdown massimo a 60 giorni |
|---|---|---|---|---|
| Riferimento training | 0.4211 | 0.3000 | -21.01% | -25.45% |
| Gaussian | 0.3180 | -0.0011 | -15.77% | -16.53% |
| Student-t df=5 | 0.3549 | -0.0005 | -15.97% | -17.00% |
| IID Bootstrap | 0.4265 | 0.0059 | -15.15% | -16.26% |
| Block 5 | 0.4209 | 0.2408 | -14.45% | -15.75% |
| Block 20 | 0.4227 | 0.2842 | -16.54% | -18.56% |
| Block 60 | 0.4113 | 0.2684 | -17.49% | -20.48% |
Non serve analizzare ogni casella. IID Bootstrap estrae l’intera riga dei rendimenti di una data: conserva così quali ETF erano scesi insieme. La sua quota di ribassi simultanei, 0.4265, è vicina al riferimento 0.4211. Ma le giornate vengono estratte indipendentemente e la ACF(1) crolla a 0.0059, contro 0.3000 nel training.
Detto semplicemente, ricorda quali attività possono scendere insieme, ma quasi dimentica se i grandi movimenti avvengono in giornate consecutive.
Con Block 20, ACF(1) sale a 0.2842, vicino al riferimento. Block 60 rende l’ES a 60 giorni più profondo, da −15.15% per IID a −17.49%, ma resta lontano dal −21.01% storico. E non è detto che blocchi più lunghi funzionino meglio: qui Block 5 ha un ES a 60 giorni perfino meno negativo di IID.
Perché usare finestre di 60 giorni sovrapposte? Se le impedissi di sovrapporsi, dai 756 giorni storici ricaverei appena 12 blocchi indipendenti; dai 1.512 simulati circa 25. Stimare il 5% peggiore da una dozzina di blocchi non mi convince. Con lo scorrimento quotidiano ottengo 697 finestre storiche e 1.453 simulate, ma le finestre condividono molti giorni: non sono altrettanti eventi di rischio indipendenti. Il training comprende il 2008, quindi −21.01% è il riferimento di quella storia particolare, non un bersaglio universale da centrare al decimale.
Moving-block: i punti di giunzione non sono il problema dei pesi ai bordi
Vedendo risalire la ACF con il metodo Block, la mia prima spiegazione era molto semplice: conserva l’ordine delle date. Quando ho ricontrollato il campionatore, mi sono accorto che stavo mescolando due meccanismi.
Il primo riguarda le giunzioni fra blocchi. Dentro ogni blocco le date storiche sono consecutive; all’inizio del blocco successivo si può saltare in tutt’altra parte della storia. Con lunghezza L, circa 1/L delle coppie di giorni adiacenti attraversa una giunzione. In un’approssimazione semplificata di blocchi indipendenti, la correlazione al primo ritardo si attenua su una scala simile a 1−1/L. Partendo dalla ACF del training, 0.3000, la stima grossolana dà 0.240 per L=5 e 0.285 per L=20, vicine ai valori osservati 0.2408 e 0.2842. Per L=60, invece, la scorciatoia non funziona altrettanto bene. È una spiegazione intuitiva del meccanismo, non una sostituzione della misura.
Il secondo riguarda la probabilità diversa di selezionare le date alle estremità della storia. Nel Moving-block non circolare, i punti di inizio ammessi vanno da 0 a 756−L. Una data al bordo può appartenere a meno blocchi di una data interna, con differenze nei pesi fino a un fattore L. Per capire quanto contasse in questo dataset, ho aggiunto un confronto con Circular Block: inizi uniformi, possibilità di continuare dall’ultima data alla prima, gli stessi 50 semi.
| Lunghezza blocco | ACF(1): normale / circolare | ES a 60 giorni: normale / circolare |
|---|---|---|
| 5 | 0.2408 / 0.2411 | -14.45% / -14.35% |
| 20 | 0.2842 / 0.2884 | -16.54% / -16.37% |
| 60 | 0.2684 / 0.2792 | -17.49% / -17.23% |
Le differenze sono contenute. Per Block 20 la ACF passa da 0.2842 a 0.2884 e l’ES a 60 giorni da −16.54% a −16.37%. I pesi dei bordi sono realmente differenti, ma in questo esperimento non spiegano gran parte della distanza fra Block e IID. Circular crea anche una continuità artificiale fra l’ultimo e il primo giorno storico: non lo proclamerei superiore per aver eliminato un solo effetto.
Questa prova aggiuntiva mi ha costretto a separare la discontinuità fra blocchi dal campionamento squilibrato delle date estreme. Si può approfondire nel documento sul Circular Block Resampling.
VaR a un giorno: tre metodi non passano la calibrazione sull’intero intervallo OOS
Ora passo a una domanda più ristretta: quando arriva il prossimo giorno reale di mercato, la soglia di perdita prevista è calibrata? Non è una classifica OOS dei sei generatori visti prima. Confronto solo tre metodi di VaR a un giorno: quantile storico empirico, Gaussian e Student-t con cinque gradi di libertà. Per ogni giorno da valutare, ricalcolo la soglia usando gli ultimi 756 rendimenti giornalieri reali del portafoglio. Non continuo a riutilizzare il periodo iniziale fisso usato nella simulazione.
Anche la soglia t5 al 5% rispetta la varianza del training. Per «superamento VaR» intendo una perdita effettiva del giorno successivo che attraversa verso il basso la soglia del 5% prevista. Il test usa 1.911 giorni obiettivo distinti, senza sovrapposizione giornaliera.
| Metodo VaR al 95% a un giorno | Superamenti | Frequenza | p di Kupiec | p d’indipendenza di Christoffersen |
|---|---|---|---|---|
| Quantile storico empirico | 52 | 2.72% | 6.16e-7 | 0.0145 |
| Gaussian | 51 | 2.67% | 3.16e-7 | 0.0122 |
| Student-t df=5 | 62 | 3.24% | 1.75e-4 | 0.0171 |
Al livello nominale del 5%, su 1.911 giorni ci aspetteremmo mediamente 95.55 superamenti. I tre metodi ne registrano soltanto 51–62. Meno superamenti non equivale a una calibrazione superata. Il test di Kupiec controlla la frequenza, quello di Christoffersen l’indipendenza degli eventi; qui entrambi restituiscono valori p piccoli.
La conclusione riguarda l’intero periodo di 1.911 giorni. Le prime finestre mobili includono ancora la crisi del 2008, che esce progressivamente dal training. Non ho eseguito un test separato per regime di mercato. I doppi superamenti in giorni adiacenti sono soltanto 5 / 5 / 6 per i tre metodi: un numero da tenere presente nell’interpretare il test di indipendenza.
Non ho nemmeno forzato l’ES a 60 giorni di Block 60 dentro questa tabella. Un test OOS multigiornaliero richiede di definire correttamente obiettivi di previsione a 60 giorni e di trattare la dipendenza fra finestre ampiamente sovrapposte. Non ho completato un impianto di backtest che mi convinca per questo caso. Copiare il test Kupiec/Christoffersen pensato per un giorno suggerirebbe una verifica che non c’è stata: qui, quindi, riporto solo il VaR giornaliero.
Student-t offre un’altra osservazione poco intuitiva: una distribuzione «a code pesanti» non implica automaticamente un VaR più prudente a ogni livello di confidenza. Con df=5 e varianza corrispondente a quella storica, il quantile standardizzato sinistro al 5% è circa −1.56085, più vicino a zero del quantile Gaussian −1.64485. Il nome della distribuzione non dice, da solo, quale soglia sarà più severa.
Dove spenderei il prossimo budget di simulazione
Se la prossima proposta fosse «i risultati oscillano, raddoppiamo gli scenari», prima di usare più CPU farei tre domande: è solo rumore del campionamento? Il generatore conserva i ribassi simultanei e le perdite che si susseguono? Abbiamo verificato la calibrazione OOS per l’orizzonte di rischio che conta? Più simulazioni rispondono soprattutto alla prima.
Se dovessi scegliere fra Block 20, Block 60 e Student-t come protezione di rischio in produzione, non eleggerei un vincitore sulla base di questo singolo periodo storico fisso. La ACF di Block 20 assomiglia a un aspetto del passato, non prova la copertura futura. Le code più spesse di Student-t non garantiscono neppure un VaR al 95% più prudente. Prima fisserei l’orizzonte di rischio, poi farei il test OOS pertinente.
Porto a casa soprattutto due risultati: il divario dei ribassi simultanei di Gaussian non è scomparso raddoppiando gli scenari; il confronto con Circular Block mi ha costretto a ridimensionare una spiegazione inizialmente troppo comoda. La prossima volta che leggerò «un milione di scenari di rischio», chiederò: quali osservazioni reali vengono ripetute e quali strutture di rischio sono state conservate?
Per un esempio più piccolo da riprodurre a mano, ho anche descritto come NaN cambia il denominatore dei campioni di coda del CVaR in vectorbt, con un esercizio sintetico in Python.
Fonte dati e parametri fissi: Kaggle Huge Stock Market Dataset v3; SPY, IWM, EFA, EEM, TLT, IEF, LQD, HYG, GLD, DBC, UUP, VNQ. Intersezione dei prezzi Close rettificati dal 2007-04-11 al 2017-11-10, per 2.668 righe, senza imputazione dei giorni mancanti. SHA-256 del CSV fisso: 0a20c095f0d9400fbf7d30e17a0c664716f147c460b03bf5439cd980ef8bf38a. Lo studio degli scenari usa 756 rendimenti giornalieri di training e 50 semi abbinati; un test separato del VaR giornaliero usa 1.911 obiettivi OOS. Confronto di metodi di modellazione storica del rischio, non consulenza finanziaria.