Skip to content
All library documents

Calibrating SABR Volatility Parameters with Python QuantLib

Article Quant Q&A · Author: Desi_Quant

Summary

The document shows how to fit SABR model parameters to a set of observed option volatilities using Python and QuantLib. It computes model volatilities for each strike, measures the root mean squared difference from market quotes, and uses a constrained numerical optimizer to minimize that error. The example plots the market and fitted volatility curves for visual comparison.

The parameter bounds shown restrict beta to a range from zero to 0.99 and require the final parameter to be nonnegative. The example uses one forward level, expiry, and a small set of strikes, so it illustrates an implementation pattern rather than a general calibration framework. It does not discuss calibration stability, quote weighting, data quality, parameter identifiability, or the suitability of the SABR assumptions for any particular market.

Key ideas

  • QuantLib's SABR volatility function can generate model volatilities across a set of strikes.
  • Calibration can minimize the difference between model and observed implied volatilities.
  • A constrained optimizer can enforce bounds on selected SABR parameters.
  • Plotting fitted and observed volatilities provides a visual calibration check.

Tags

Full text
# SABR Model Pricing Engine in Python QuantLib


# SABR Model Pricing Engine in Python QuantLib












I am looking for a SABR model pricing engine in Python QuantLib setting. I do know that it exists in C++ version, but not sure if available in Python. Any suggestion/feedback with respect to Python source code will be greatly appreciated!. Thanks!

## Answer by David Duarte (score 10, accepted)

https://quant.stackexchange.com/a/57789

Here is a simple example that might be useful. Basically finding parameters for a given section. Some of the parameters might be assumed at start instead of calibrated.

```
import QuantLib as ql
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import minimize

strikes = [105, 106, 107, 108, 109, 110, 111, 112]
fwd = 120.44
expiryTime = 17/365
marketVols = [0.4164, 0.408, 0.3996, 0.3913, 0.3832, 0.3754, 0.3678, 0.3604]

params = [0.1] * 4
def f(params):
    vols = np.array([
        ql.sabrVolatility(strike, fwd, expiryTime, *params)
        for strike in strikes
    ])
    return ((vols - np.array(marketVols))**2 ).mean() **.5

cons=(
    {'type': 'ineq', 'fun': lambda x:  0.99 - x[1]},
    {'type': 'ineq', 'fun': lambda x: x[1]},    
    {'type': 'ineq', 'fun': lambda x: x[3]}
)

result = minimize(f, params, constraints=cons)
new_params = result['x']

newVols = [ql.sabrVolatility(strike, fwd, expiryTime, *new_params) for strike in strikes]
plt.plot(strikes, marketVols, marker='o', label="market")
plt.plot(strikes, newVols, marker='o', label="SABR")
plt.legend();
```

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.