Introduzione
La volatilità rientra nell'ambito di un concetto generale, quello che permette di rispondere alla domanda: "Quanto si discostano i dati dal loro valore centrale?".
La volatilità di un asset o di un portafoglio riguarda la dimensione temporale, informa sul rischio connesso all'investimento misurando l'incertezza dei rendimenti passati o previsti nell'immediato futuro; nella dimensione trasversale, la dispersione tra asset diversi in uno stesso momento ci informa se il mercato è guidato da fattori comuni o se dominano fattori specifici, settoriali o aziendali, e guida alla costruzione dei portafogli.
Soprattutto la volatilità prevista nell'immediato futuro valuta l'imprevedibilità e quindi il rischio che preoccupa molti investitori, fenomeno del tutto normale in questo tipo di attività e nel quale si nascondono rilevanti opportunità.
In queste pagine si vogliono esaminare questi concetti in maniera prevalentemente sperimentale a partire da dati reali e avvalendosi di un linguaggio di programmazione, Python in ambiente interattivo Google Colab (basato su Jupyter, un progetto Open Source).
Introduttivamente vediamo come esaminare la serie storica di un asset o di un indice finaziario prelevandola da Yahoo Finanza con il modulo yfinance che, innanzitutto, va installato.
!pip install yfinance
Quindi, dopo aver importato come oggetto yf.Ticker() un dizionario di eventi, guadagni e dividendi relativi al simbolo, ad esempio ^GSPC oppure ^SPX per S&P 500, si può scaricare lo storico mediante .history() come oggetto DataFrame del modulo pandas e poi visualizzare i primi e gli ultimi dati della tabella.
import yfinance as yf
stock = yf.Ticker("^GSPC")
df = stock.history(period="5y")
df
Open
High
Low
Close
Volume
Dividends
Stock Splits
Date
2021-05-06 00:00:00-04:00
4169.140137
4202.700195
4147.330078
4201.620117
4511000000
0.0
0.0
2021-05-07 00:00:00-04:00
4210.339844
4238.040039
4201.640137
4232.600098
4016080000
0.0
0.0
2021-05-10 00:00:00-04:00
4228.290039
4236.390137
4188.129883
4188.430176
4560700000
0.0
0.0
2021-05-11 00:00:00-04:00
4150.339844
4162.040039
4111.529785
4152.100098
4870710000
0.0
0.0
2021-05-12 00:00:00-04:00
4130.549805
4134.729980
4056.879883
4063.040039
4733070000
0.0
0.0
...
...
...
...
...
...
...
...
2026-04-29 00:00:00-04:00
7131.609863
7145.629883
7107.859863
7135.950195
5123100000
0.0
0.0
2026-04-30 00:00:00-04:00
7161.750000
7219.830078
7126.149902
7209.009766
5723790000
0.0
0.0
2026-05-01 00:00:00-04:00
7234.540039
7272.520020
7229.319824
7230.120117
4847390000
0.0
0.0
2026-05-04 00:00:00-04:00
7228.379883
7244.540039
7174.120117
7200.750000
5215480000
0.0
0.0
2026-05-05 00:00:00-04:00
7233.620117
7273.259766
7233.620117
7259.220215
5279760000
0.0
0.0
Data una serie storica \(P(t)\) di prezzi, i relativi rendimenti nell'intervallo di tempo \(\Delta t\) sono
\[R(t)=\frac{\Delta P(t-\Delta t)}{P(t-\Delta t)} = \frac{P(t)-P(t-\Delta t)}{P(t - \Delta t)} = \frac{P(t)}{P(t-\Delta t)}-1,\]
Dal DataFrame df dello storico relativo a un asset, si possono ottenere applicando alla colonna df.Close il metodo .pt_change().D'altra parte, poiché i prezzi sono strettamente positivi, è ragionevole rappresentarli come un'esponenziale \[P(t)=e^{\log P(t)}\] e, piuttosto che \(P(t),\) studiare \(\log P(t)\) le cui variazioni sono detti log-rendimenti dei prezzi \[ r(t)=\Delta \log P(t-\Delta t)=\log\frac{P(t)}{P(t-\Delta t)}=\log(1+R(t)),\] ottenibili con
np.log(df.Close).diff() o anche np.log(df.Close/df.Close.shift()).Considerando che per valori piccoli di \(x\) \[\log(1+x) = x - \frac{x^2}{2}+\frac{x^3}{3}-\dots\] possiamo dire che \[r(t)\approx R(t)-\frac{R^2(t)}{2}+O(R^3(t))\] I log-rendimenti, più che i rendimenti semplici, tendono a seguire una distribuzione normale \[r(t) ∼ N (\mu, σ^2 ), \quad t = 1, \dots, T,\] con valore atteso \(\mu,\) la tendenza o drift, e varianza \(σ^2\), un indice di dispersione rispetto al valore atteso.
import matplotlib.pyplot as plt
import numpy as np
log_returns = np.log(df.Close/df.Close.shift())
# Istogramma dei log-rendimenti reali
log_returns.plot(kind='hist',bins=20, title='log-rendimenti', density=True)
# Curva normale teorica
μ, σ = log_returns.mean(), log_returns.std()
x = np.linspace(log_returns.min(), log_returns.max(), 100)
normal_pdf = np.exp(-(x - μ)**2 / (2 * σ**2)) / (σ * np.sqrt(2 * np.pi))
plt.plot(x, normal_pdf, label='Distribuzione Normale', color='r', linestyle='--')
plt.legend()
Scelti ragionevoli valori per \(\mu\) e per \(σ^2\), diverse simulazioni possono fornire previsioni.
Nel seguito esamineremo metodi di valutazione dell'incertezza, sia quella legata allo storico sia quella prevedibile.
- The Variation of Certain Speculative Prices, by Benoit Mandelbrot
- Modeling Regime Structure and Informational Drivers of Stock Market Volatility via the Financial Chaos Index, by Masoud Ataei
- The Engineering of Skew A Path-Dependent Framework for Asymmetric Volatility Management, by Gregory A. Fanous
- Bayesian Dynamic Modeling of Realized Volatility in Financial Asset Price Forecasting, by Patrick Woitschig, Mike West
- Volatility (finance), From Wikipedia, the free encyclopedia
- Volatility risk, From Wikipedia, the free encyclopedia
- Volatility Tutorials and Resources, on macroption