Skip to content
All library documents

Constructing a Heston Implied Volatility Surface with QuantLib

Article Quant Q&A · Author: FunnyBuzer

Summary

The document explains how to build and plot a Heston model volatility surface using Python QuantLib. The example creates a Heston process from spot, flat risk-free and dividend curves, and model parameters, then wraps it in a Heston model and passes it to a Heston black-volatility surface. A plotting routine samples implied volatility over a grid of strikes and maturities and renders the values as a three-dimensional surface.

The example uses illustrative parameters and flat curves, so it demonstrates the API and visualization workflow rather than a calibrated market surface. One answer links to a separate notebook, while the code example does not explain calibration, market-data inputs, or how parameter choices affect the surface. The initial question also reflects confusion about required inputs, but the example shows that the surface object can be created from a Heston model handle.

Key ideas

  • A Heston volatility surface can be queried for Black implied volatility at selected maturities and strikes.
  • A three-dimensional plot can display volatility across a grid of strikes and expiries.
  • The example constructs a Heston process using spot, yield curves, and variance model parameters.
  • Illustrative parameters show the plotting workflow but do not establish a market-calibrated surface.

Tags

Full text
# Heston volatility surface in Python QuantLib


# Heston volatility surface in Python QuantLib












Does anyone have experience with the Python QuantLib function `HestonBlackVolSurface`? I'm trying to produce a 3D plot of the volatility surface as done in the example

http://gouthamanbalaraman.com/blog/volatility-smile-heston-model-calibration-quantlib-python.html

Here is my attempt, based on the data of the example

```
import QuantLib as quant
heston_vol_surface = quant.HestonBlackVolSurface(
                        quant.HestonModelHandle(model),
                        quant.AnalyticHestonEngine.Gatheral)

strikes_grid = np.arange(strikes[0], strikes[-1],10)
expiry = 1.0
implied_vols = [heston_vol_surface.blackVol(expiry, s)
                for s in strikes_grid]
```

I understand that I need to pass the the volatility term structure, but my knowledge of QuantLib is too limited right now. Thanks for you help.

## Answer by Ege Yilmaz (score 3, accepted)

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

Here is something I did, maybe it helps:

https://colab.research.google.com/drive/1M1YJncdswd-A9SgIOAjw6g6Se7NHU9mG?usp=sharing

## Answer by StackG (score 3)

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

Here is a snip that will create and plot a Heston vol surface

```
import numpy as np
import QuantLib as ql
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Utility function to plot vol surfaces (can pass in ql.BlackVarianceSurface objects too)
def plot_vol_surface(vol_surface, plot_years=np.arange(0.1, 2, 0.1), plot_strikes=np.arange(80, 120, 1)):
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    X, Y = np.meshgrid(plot_strikes, plot_years)
    Z = np.array([vol_surface.blackVol(float(y), float(x)) 
                  for xr, yr in zip(X, Y) 
                      for x, y in zip(xr,yr) ]
                 ).reshape(len(X), len(X[0]))

    surf = ax.plot_surface(X,Y,Z, rstride=1, cstride=1, linewidth=0.1)

    fig.colorbar(surf, shrink=0.5, aspect=5)

# World State setup
spot = 100
rate = 0.0
today = ql.Date(1, 7, 2020)

# Set up the flat risk-free curves
riskFreeCurve = ql.FlatForward(today, rate, ql.Actual365Fixed())
flat_ts = ql.YieldTermStructureHandle(riskFreeCurve)
dividend_ts = ql.YieldTermStructureHandle(riskFreeCurve)

# Setting up a Heston model with dummy parameters (roughly 10% constant BS vol)
v0 = 0.01; kappa = 0.01; theta = 0.01; rho = 0.0; sigma = 0.01

process = ql.HestonProcess(flat_ts, dividend_ts, ql.QuoteHandle(ql.SimpleQuote(spot)), v0, kappa, theta, sigma, rho)

# Boilerplate to get to the Vol Surface object
heston_model = ql.HestonModel(process)
heston_handle = ql.HestonModelHandle(heston_model)
heston_vol_surface = ql.HestonBlackVolSurface(heston_handle)

# Plot the vol surface ...
plot_vol_surface(heston_vol_surface)
```

Produces:

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.