Constructing a Heston Implied Volatility Surface with QuantLib
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.