CJDSimulatePathsQ
- class quantmetrics.price_calculators.cjd_pricing.cjd_paths_Q.CJDSimulatePathsQ(model: LevyModel, option: Option)[source]
Bases:
object
Implements the paths simulation for a constant jump-diffusion (CJD) model under the risk-neutral measure.
Parameters
- modelLevyModel
A LevyModel object specifying the underlying asset’s model and its parameters.
- optionOption
An Option object specifying the option parameters: interest rate, strike price, time to maturity, dividend yield and the equivalent martingale measure.
- simulate(num_timesteps: int, num_paths: int, seed: int) Dict[str, ndarray] [source]
Generate paths for the constant jump-diffusion model.
Parameters
- num_timestepsint
Number of time steps.
- num_pathsint
Number of simulated paths.
- seedint
Seed for random number generator.
Returns
- dict
A dictionary containing:
time_steps (np.ndarray): The simulated time steps.
S_exact (np.ndarray): The simulated LJD paths using the exact solution.
S_euler (np.ndarray): The simulated LJD paths using the Euler-Maruyama discretization.
Notes
The Euler-Maruyama discretization for the \(i^{th}\) timestep and \(j^{th}\) path, reads:
\[s_{i+1, j} \approx s_{i,j} + (r-q - \lambda^\mathbb{Q} \kappa^\mathbb{Q}) s_{i,j} \Delta t + \sigma s_{i,j} (W_{i+1, j} - W_{i,j}) + \gamma s_{i,j} (N_{i+1,j} -N_{i,j}),\]with \(\Delta t = t_{i+1} - t_i\), for any \(i=1,2,\cdots , m, \ s_0 = S(t_0)=S_0\), \(j = 1,2,\cdots, N\), \(W_{i+1, j} - W_{i,j} \sim \mathcal{N}(0, \Delta t)\) and \(N_{i+1,j} -N_{i,j} \sim \mathcal{Poi}(\lambda^\mathbb{Q} \Delta t)\).
The CJD process has as exact solution in the time interval \([t_i, t_{i+1}]\),
\[S(t_{i+1})=S(t_i)\exp\left\{(r-q-\frac{\sigma^2}{2}- \lambda^\mathbb{Q} \kappa^\mathbb{Q})\Delta t + \sigma [W(t_{i+1}) - W(t_i)] + \gamma [N(t_{i+1}) - N(t_i)] \right\}\]where
\(S_0\) is the underlying price.
\(r\) is the risk-free interest rate.
\(q\) is the dividend yield.
\(\sigma\) is the volatility.
\(\gamma\) is the constant jump size.
\(\lambda\) is the jump intensity rate.
The parameters \(\lambda^\mathbb{Q}\) and \(\kappa^\mathbb{Q}\) depend on the choice of the equivalent martingale measure.
If
emm = "mean-correcting"
then\[\lambda^\mathbb{Q} = \lambda \quad \text{and} \quad \kappa^\mathbb{Q} = \kappa = e^\gamma - 1\]If
emm = "Esscher"
then\[\lambda^\mathbb{Q} = \lambda \exp \left(\theta \gamma + \psi \gamma^2 \right) \quad \text{and} \quad \kappa^\mathbb{Q} = \kappa = e^\gamma - 1\]The first-order Esscher parameter \(\theta\) is the risk premium (market price of risk) and which is the unique solution to the martingale equation for each \(\psi\) which is the second-order Esscher parameter. See the documentation of the
RiskPremium
class for the martingale equation and refer to [1] for more details.Examples
>>> from quantmetrics.levy_models import CJD >>> from quantmetrics.option_pricing import Option >>> from quantmetrics.price_calculators.cjd_pricing.cjd_paths_Q import CJDSimulatePathsQ >>> cjd = CJD() # S0=50, sigma=0.2, lambda_=1, gamma=-0.1 >>> option = Option(K=np.array([20,50,80]), T = 20/252) # r=0.05, q=0.02 >>> paths = CJDSimulatePathsQ(cjd, option).simulate(num_timesteps=200, num_paths=10000,seed=42) >>> payoff = np.maximum(paths["S_exact"][:,-1].reshape(-1,1) - option.K, 0) >>> option_price = np.mean(np.exp(-option.r*option.T) * payoff, axis=0) >>> option_price array([30.01448984, 1.32307021, 0. ])
References