3
$\begingroup$

I am trying to calibrate SABR but I do not fit the given volatility.

 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() 

enter image description here

$\endgroup$

1 Answer 1

4
$\begingroup$

Well, it looks pretty good to me. The SABR model has only 4 parameters and there is only so much you can do with them.

If you have a lot of volatilities, especially if they have a quite irregular distribution, like in the picture, this is what you can expect when trying to fit the SABR model.

$\endgroup$