Heston model can be used to value options by modeling the underlying asset such as the stock of a company. The one major feature of the Heston model is that it inocrporates a stochastic volatility term.
\begin{eqnarray} dS_t &=& \mu S_tdt + \sqrt{V_t} S_t dW_t^1 \\ dV_t &=& \kappa(\theta-V_t) + \sigma \sqrt{V_t} dW_t^2 \end{eqnarray}Here :
In contrast, the Black-Scholes-Merton process assumes that the volatility is constant.
In [1]:
# <!-- collapse=True -->
import QuantLib as ql
import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import simps, cumtrapz, romb
% matplotlib inline
import math
Let us consider a European call option for AAPL with a strike price of \$130 maturing on 15th Jan, 2016. Let the spot price be \$127.62. The volatility of the underlying stock is know to be 20%, and has a dividend yield of 1.63%. We assume a short term risk free rate of 0.1%. Lets value this option as of 8th May, 2015.
In [2]:
# <!-- collapse=True -->
# option parameters
strike_price = 110.0
payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price)
# option data
maturity_date = ql.Date(15, 1, 2016)
spot_price = 127.62
strike_price = 130
volatility = 0.20 # the historical vols for a year
dividend_rate = 0.0163
option_type = ql.Option.Call
risk_free_rate = 0.001
day_count = ql.Actual365Fixed()
calendar = ql.UnitedStates()
calculation_date = ql.Date(8, 5, 2015)
ql.Settings.instance().evaluationDate = calculation_date
Using the above inputs, we construct the European option as shown below.
In [3]:
# construct the European Option
payoff = ql.PlainVanillaPayoff(option_type, strike_price)
exercise = ql.EuropeanExercise(maturity_date)
european_option = ql.VanillaOption(payoff, exercise)
In order to price the option using the Heston model, we first create the Heston process. In order to create the Heston process, we use the parameter values: mean reversion strength kappa = 0.1
, the spot variance v0 = volatility*volatility = 0.04
, the mean reversion variance theta=v0
, volatility of volatility sigma = 0.1
and the correlation between the asset price and its variance is rho = -0.75
.
In [4]:
# <!-- collapse=True -->
# construct the Heston process
v0 = volatility*volatility # spot variance
kappa = 0.1
theta = v0
sigma = 0.1
rho = -0.75
spot_handle = ql.QuoteHandle(
ql.SimpleQuote(spot_price)
)
flat_ts = ql.YieldTermStructureHandle(
ql.FlatForward(calculation_date, risk_free_rate, day_count)
)
dividend_yield = ql.YieldTermStructureHandle(
ql.FlatForward(calculation_date, dividend_rate, day_count)
)
heston_process = ql.HestonProcess(flat_ts,
dividend_yield,
spot_handle,
v0,
kappa,
theta,
sigma,
rho)
On valuing the option using the Heston model, we get the net present value as:
In [5]:
engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process),0.01, 1000)
european_option.setPricingEngine(engine)
h_price = european_option.NPV()
print "The Heston model price is",h_price
Performing the same calculation using the Black-Scholes-Merton process, we get:
In [6]:
# <!-- collapse=True -->
flat_vol_ts = ql.BlackVolTermStructureHandle(
ql.BlackConstantVol(calculation_date, calendar, volatility, day_count)
)
bsm_process = ql.BlackScholesMertonProcess(spot_handle,
dividend_yield,
flat_ts,
flat_vol_ts)
european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process))
bs_price = european_option.NPV()
print "The Black-Scholes-Merton model price is ", bs_price
The difference in the price between the two models is: bs_price - h_price = 0.21840667525992163
. This difference is due to the stochastic modeling of the volatility as a CIR-process.