In [1]:
import numpy as np, pandas as pd
import matplotlib.pyplot as plt
plt.style.use('bmh')

Il modello di Black-Scholes si basa sull'assunto che il prezzo azionario segua un moto geometrico browniano (GBM).
Cioé che sia verificata la seguente equazione differenziale stocastica:

\begin{equation} dS(t)= \mu S(t) dt + \sigma S(t)dW(t) \end{equation}
dove W(t) segue un processo di Wiener ed S(t) è il processo stocastico del prezzo dello stock.
Il modello tuttavia non prende in considerazione che:

  1. La volatilità del rendimento dei titoli finanziari non é costante (come invece è nel modello).
  2. Non esiste la continuità temporale (e neanche quella relativa alle variabili) nel mondo reale delle contrattazioni dei titoli. I titoli possono essere scambiati quando i mercati di riferimento sono operativi e i prezzi delle azioni possono assumere solo valori discreti (multipli minimi di contrattazione).
  3. Il modello implica che i log-rendimenti siano distribuiti secondo una distribuzione normale. Questo è in netto contrasto con l'evidenza empirica, per cui i rendimenti assumono con frequenza maggiore rispetto alla normale dei valori vicini al valore atteso, con frequenza minore rispetto alla normale dei valori mediamente distanti dal valor atteso, e con frequenza maggiore valori molto distanti dal valore atteso (outliers). Secondo una distribuzione normale eventi superiori a 4 standard deviation sono molto improbabili, eventi di 10 standard deviation praticamente impossibili. Sui mercati finanziari non sono state poche le time series in cui si registra un'osservazione che eccede le 10 standard deviation.

Simulando un path stocastico che segue il GBM e riportando i log-rendimenti dello stock, vediamo che essi ripercorrono un white-noise process con distribuzione normale. Su 756 osservazioni il rendimento non ha mai raggiunto le 4 standard deviation (in valore assoluto) di excess rispetto alla standard deviation giornaliera stimata.

In [6]:
''' Simulazione del prezzo di un'azione seguendo il modello Black-Scholes su un arco temporale di 3 anni '''

stock_price = 100 # prezzo iniziale dell'azione
u = 0.25  # rendimento atteso annuo
sigma = 0.3 # volatilita' annua
_Paths = []
for i in range(756):
        dx = stock_price * ( u*(1/252) + sigma*np.sqrt(1/252)*np.random.randn() )
        stock_price += dx
        _Paths.append(stock_price)
        
_Paths = pd.Series(_Paths)   

def logR(lista):
        i = 0
        Rend = []
        while i <= len(lista)-2:
            Rend.append(np.log(lista[i+1]/lista[i]))
            i += 1
        return Rend
    
logR_daily = np.array(logR(_Paths))

def maxPicco(array):
    if array.max() >= abs(array.min()):
        return array.max()
    else:
        return array.min()
        
max_abs_rend = maxPicco(logR_daily)
max_range_oscillazione = max_abs_rend / logR_daily.std()

print("Daily standard deviation:", round(logR_daily.std(),4))
print("Massima picco di rendimento giornaliero registrato:", round(max_abs_rend,4))
print("Massima escursione di rendimento giornaliero rispetto alla standard deviation giornaliera:", round(max_range_oscillazione,4))

fig, (ax1,ax2) = plt.subplots(2,1, figsize=(10,15))
ax1.plot(logR_daily, label= 'log return daily')
ax2.plot(_Paths,'r--', label= 'stock price')
ax1.set_xlabel('trading day')
ax2.set_xlabel('trading day')
ax1.legend();
ax2.legend();
    
Daily standard deviation: 0.0192
Massima picco di rendimento giornaliero registrato: -0.0659
Massima escursione di rendimento giornaliero rispetto alla standard deviation giornaliera: -3.4415

Sotto vediamo invece i rendimenti giornalieri dal 1993 al 2014 del fondo passivo SPY, che replica l'indice S&P 500.
Questo grafico, in cui sono presenti osservazioni oltre le 10 deviazioni standard in eccesso e in cui la volatilità non sembra costante, ci induce a riflettere sulla realisticità/utilità di taluni modelli dalle ipotesi eccessivamente rigide e date come assodate.

In [5]:
from IPython.display import Image
Image(filename="C:\\Users\\Admin\\Desktop\\realret.jpg") 
Out[5]:

In [ ]: