Estoy intentando calibrar SABR pero no me cuadra la volatilidad dada.
import QuantLib as ql
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import minimize
from scipy.optimize import differential_evolution
moneyness=np.array([ 120.00, 115.00, 114.00, 113.00, 112.00, 111.00 ,
110.00, 109.00 ,108.00, 107.00, 106.00, 105.00, 104.00, 103.00, 102.50, 102.00,
101.50, 101.00, 100.50, 100.00, 99.50, 99.00, 98.50, 98.00, 97.50, 97.00,
96.50, 96.00, 95.50,95.00, 94.50, 94.00, 93.50, 93.00, 92.00, 91.00,90.00 ])
moneyness=moneyness/100
fwd = 1.361794
strikes=fwd*moneyness
expiryTime = 30/365
marketVols = np.array([0.0302, 0.08827, 0.10019, 0.11206, 0.12343, 0.13305, 0.13968,
0.14325, 0.14431, 0.14337, 0.14077, 0.13706, 0.1325, 0.12664,
0.12355, 0.12024, 0.11694, 0.11371, 0.11062, 0.10772, 0.10526,
0.10307, 0.10118 ,0.09953, 0.09811, 0.0967, 0.09487, 0.09313, 0.09096,
0.08795, 0.08359, 0.07751, 0.07003, 0.06203, 0.04591, 0.02975, 0.01347 ])
marketVols=1-marketVols
marketVols[20]=1-10.97/100
def f(params):
params[0] = max(params[0], 1e-8) # Avoid alpha going negative
params[1] = max(params[1], 1e-8) # Avoid beta going negative
params[2] = max(params[2], 1e-8) # Avoid nu going negative
params[3] = max(params[3], -0.999) # Avoid rhp going < -1.0
params[3] = min(params[3], 0.999) # Avoid rho going > 1.0
vols = np.array([
ql.sabrVolatility(strike, fwd, expiryTime, params[0],params[1],params[2],params[3])
#(Rate strike, Rate forward, Time expiryTime,Real alpha,Real beta,Real nu,Real rho,
for strike in strikes
])
return ((vols - np.array(marketVols))**2 ).mean() **.5
bounds = [(0.000001,1000000),(0.000001,0.99) ,(0.00001, 1000000), (-0.99, 0.99)]
result = differential_evolution(f, bounds,tol=0.0000001)
params=result.x
print(1-ql.sabrVolatility(1.279, fwd, expiryTime, params[0],params[1],params[2],params[3]))
newVols = [ql.sabrVolatility(strike, fwd, expiryTime, params[0],params[1],params[2],params[3]) for strike in strikes]
plt.plot(strikes, marketVols, marker='o', label="market")
plt.plot(strikes, newVols, marker='o', label="SABR")
plt.legend()
plt.show()