Jump Diffusion Models#
The library allows to create a vast array of jump-diffusion models. The most famous one is the Merton jump-diffusion model.
Merton Model#
from quantflow.sp.jump_diffusion import JumpDiffusion
from quantflow.utils.distributions import Normal
merton = JumpDiffusion.create(Normal, jump_fraction=0.8, jump_intensity=50)
Marginal Distribution#
m = merton.marginal(0.02)
m.std(), m.std_from_characteristic()
(np.float64(0.07071067811865475), np.float64(0.0707106779037837))
m2 = jd.marginal(0.02)
m2.std(), m2.std_from_characteristic()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 1
----> 1 m2 = jd.marginal(0.02)
2 m2.std(), m2.std_from_characteristic()
NameError: name 'jd' is not defined
from quantflow.utils import plot
plot.plot_marginal_pdf(m, 128, normal=True, analytical=False, log_y=True)
Characteristic Function#
plot.plot_characteristic(m)
Option Pricing#
We can price options using the OptionPricer
tooling.
from quantflow.options.pricer import OptionPricer
pricer = OptionPricer(merton)
pricer
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 - Merton", height=500)
This term structure of volatility demostrates one of the principal weakness of the Merton’s model, and indeed of all jump diffusion models based on Lévy processes, namely the rapid flattening of the volatility surface as time-to-maturity increases. For very short time-to-maturities, however, the model has no problem in producing steep volatility smile and skew.
MC paths#
merton.sample(20, time_horizon=1, time_steps=1000).plot().update_traces(line_width=0.5)
Exponential Jump Diffusion#
This is a variation of the Mertoin model, where the jump distribution is a double exponential. The advantage of this model is that it allows for an asymmetric jump distribution, which can be useful in some cases, for example options prices with a skew.
from quantflow.utils.distributions import DoubleExponential
jd = JumpDiffusion.create(DoubleExponential, jump_fraction=0.8, jump_intensity=50, jump_asymmetry=0.2)
pricer = OptionPricer(jd)
pricer
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 - Double-exponential Jump Diffusion ", height=500)