Smile da Volatilidade

Smile da Volatilidade

Gráficos da Volatilidade Implícita em Python

O smile da volatilidade é uma representação gráfica do Strike (K) e da Volatilidade Implícita (VI) de um grupo de opções com o mesmo ativo subjacente e data de vencimento.

Nesse exemplo, vamos usar opções (Europeia) de compra da PETR4, referente ao dia 19/04/2021, com vencimentos de 22 dias, 41 dias e 60 dias, com preço da ação em 24.28 BRL (Fonte).

import pandas as pd
url = "https://www.dropbox.com/s/quk7zfe9bo97mtb/Vol_Call.csv?dl=1"
df = pd.read_csv(url)
df.head()

image.png

Vamos contruir um gráfico desses Strikes e VI:

import matplotlib.pyplot as plt

plt.rcParams['figure.figsize'] = [7, 5]
plt.plot(df["K22"], df["VI22"], label="VI22") 
plt.plot(df["K41"], df["VI41"], label="VI41")
plt.plot(df["K60"], df["VI60"], label="VI60")
plt.xlabel("VI")
plt.ylabel("K")
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)

image.png

Dá para imaginar um 'smile' nas opções com vencimento de 22 dias (VI22), diferentemente das outras curvas...

A seguir, vamos interpolar os dados observados, algo que pode ser útil na sua pesquisa.

import numpy as np
from scipy import interpolate

K = np.arange(219.6,329.6)/10
spln = interpolate.UnivariateSpline(df["K22"], df["VI22"], k=3)
newV22 = spln(K)

spln = interpolate.UnivariateSpline(df["K41"].dropna(), df["VI41"].dropna(), k=3)
newV41 = spln(K)

spln = interpolate.UnivariateSpline(df["K60"].dropna(), df["VI60"].dropna(), k=3)
newV60 = spln(K)

Vamos ver os resultados graficamente:

plt.rcParams['figure.figsize'] = [20, 5]
fig, (ax1, ax2,ax3) = plt.subplots(1,3)
fig.suptitle('VI Suavizada & Observada')
ax1.plot(K,newV22)
ax1.plot(df["K22"], df["VI22"])
ax1.set_title("T = 22")
ax1.set_xlabel("K")
ax1.set_ylabel("VI")
ax2.plot(K,newV41)
ax2.plot(df["K41"], df["VI41"])
ax2.set_title("T = 41")
ax2.set_xlabel("K")
ax2.set_ylabel("VI")
ax3.plot(K,newV60)
ax3.plot(df["K60"], df["VI60"])
ax3.set_title("T = 60")
ax3.set_xlabel("K")
ax3.set_ylabel("VI")

image.png

No primeiro gráfico, podemos ver o smile na linha azul; percebe-se também que o mínimo da volatilidade está entre os strikes de 27 e 28 BRL.

Minha intenção no próximo gráfico é mostrar a superfície da VI. Porém, faço isso com os dados suavizados e com apenas 3 vencimentos. O ideal seria ter mais vencimentos e usar os dados observados. De qualquer forma, o exercício está feito caso queira saber como funciona.

x = K
y = (22,41,60)

X, Y = np.meshgrid(x, y)
Z = [newV21,newV41,newV60]

plt.rcParams['figure.figsize'] = [20, 10]
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 1000, cmap='viridis')
ax.set_xlabel('K')
ax.set_ylabel('Dias')
ax.set_zlabel('VI');
ax.view_init(20, -155)

image.png

Até a próxima!