Why Four-Parameter SABR Cannot Match Every Market Volatility Quote
Summary
The document presents a SABR calibration problem in which an optimizer minimizes the difference between model and market volatilities across many strikes. The data are converted before fitting, and a differential evolution routine searches within parameter bounds. The response’s central lesson is that a four-parameter model has limited flexibility: it can produce only a restricted range of smile shapes, so a dense or irregular set of market quotes may not be matched closely even when calibration is functioning as intended.
The evidence provided is qualitative: the displayed volatility curve has many points and a shape that a simple SABR smile cannot reproduce exactly. No parameter values, error statistics, or alternative calibration method are given. The answer therefore helps distinguish an optimizer failure from model misspecification or limited fit capacity, but offers little diagnostic guidance. It does not assess whether the input volatility transformation, selected bounds, or objective function are appropriate, so those implementation details remain possible sources of error.
Key ideas
- SABR has four parameters, which limits the variety of volatility smiles it can represent.
- A calibration can leave quote-level residuals when market volatilities are irregular or densely sampled.
- An imperfect fit does not by itself show that the optimizer failed.
- The response gives no quantitative fit diagnostics or recommendations for changing the calibration setup.
Tags
Full text
# Sabr Calibration not fitting the market volatility
# Sabr Calibration not fitting the market volatility
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()
```
## Answer by Jesper Tidblom (score 4)
https://quant.stackexchange.com/a/73460
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.Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.