Heston Model with Jumps

Heston Model with Jumps#

The models complements the standard Heston stochastic volatility model, with the addition of a double exponential Compound Poisson process. The Compound Poisson process adds a jump component to the Heston diffusion SDEs which control the volatility smile and skew for shorter maturities.

(63)#\[\begin{align} y_t &= x_{\tau_t} + d j_t\\ \tau_t &= \int_0^t \nu_s ds \\ d x_t &= d w_t \\ d \nu_t &= \kappa\left(\theta - \nu_t\right) dt + \sigma\sqrt{\nu_t} d z_t \\ {\mathbb E}\left[d w_t d z_t\right] &= \rho dt \end{align}\]

where \(j_t\) is a double exponential Compound Poisson process which adds three additional parameter to the model

  • the jump intensity, which measures the expected number of jumps in a year

  • the jump percentage (fraction) contribution to the total variance

  • the jump asymmetry is defined as a parameter greater than 0; 1 means jump are symmetric

The jump process is independent from the Brownian motions. See HestonJ for python API documentation.

from quantflow.sp.heston import HestonJ
from quantflow.utils.distributions import DoubleExponential
pr = HestonJ.create(
    DoubleExponential,
    vol=0.6,
    kappa=2,
    sigma=0.8,
    rho=-0.0,
    jump_intensity=50,
    jump_fraction=0.2,
    jump_asymmetry=0.0
)
pr
HestonJ(variance_process=CIR(rate=0.288, kappa=2.0, sigma=0.8, theta=0.288, sample_algo=<SamplingAlgorithm.implicit: 'implicit'>), rho=-0.0, jumps=CompoundPoissonProcess(intensity=50.0, jumps=DoubleExponential(decay=37.26779962499649, loc=0.0, kappa=1.0)))
from quantflow.utils import plot
plot.plot_marginal_pdf(pr.marginal(0.5), 128, normal=True, analytical=False)
from quantflow.options.pricer import OptionPricer
pricer = OptionPricer(pr)
pricer
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[3], line 2
      1 from quantflow.options.pricer import OptionPricer
----> 2 pricer = OptionPricer(pr)
      3 pricer

TypeError: BaseModel.__init__() takes 1 positional argument but 2 were given
fig = None
for ttm in (0.05, 0.1, 0.2, 0.4, 0.6, 1):

    fig = pricer.maturity(ttm).plot(fig=fig, name=f"t={ttm}")
fig.update_layout(title="Implied black vols", height=500)