Estaba leyendo sobre el Modelo SABR y tenía curiosidad sobre esto. El proceso de ajuste del modelo SABR implica encontrar valores para los parámetros , , , que minimicen la diferencia entre los precios de las opciones o volatilidades implícitas en el modelo y los precios de las opciones o volatilidades implícitas observadas en el mercado. Esto se suele hacer utilizando técnicas de optimización numérica, como el algoritmo de Levenberg-Marquardt o un enfoque de optimización por mínimos cuadrados.
¿Podemos (al menos teóricamente) utilizar los criterios AIC/BIC o la divergencia KL para este tipo de problemas de optimización? En caso afirmativo, ¿puede alguien mostrarme una implementación en python? O si no, ¿podría explicar cuáles son los problemas y por qué en la práctica la gente no los utiliza?
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 #RSS Optimisation
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()
```