Buckets:
| """ | |
| Non-Gaussian Stochastic Diffusions & Jump-Diffusion Calibration Engine | |
| Author: Ramprasad Atluri (@At1uri) | |
| License: MIT | |
| """ | |
| import math | |
| import numpy as np | |
| class MertonJumpDiffusionEngine: | |
| """ | |
| Implements Robert C. Merton's (1976) Jump-Diffusion Model: | |
| dS_t / S_{t-} = (mu - lambda * k) dt + sigma dW_t + (Y - 1) dN_t | |
| where ln(Y) ~ N(gamma, delta^2) and N_t is a Poisson process with intensity lambda. | |
| """ | |
| def __init__(self, s0=100.0, r=0.04, sigma=0.18, lam=0.75, gamma=-0.05, delta=0.12): | |
| self.s0 = s0 | |
| self.r = r | |
| self.sigma = sigma | |
| self.lam = lam # Jump intensity (expected jumps per year) | |
| self.gamma = gamma # Expected jump log-size | |
| self.delta = delta # Jump size dispersion | |
| self.k = math.exp(self.gamma + 0.5 * (self.delta ** 2)) - 1.0 # Drift compensator | |
| def characteristic_function(self, u, t): | |
| """ | |
| Closed-form characteristic function: Phi(u, t) = E[exp(i * u * ln(S_t / S_0))] | |
| under risk-neutral measure Q. | |
| """ | |
| i = 1j | |
| drift_comp = (self.r - 0.5 * (self.sigma ** 2) - self.lam * self.k) | |
| diffusion_part = i * u * drift_comp * t - 0.5 * (u ** 2) * (self.sigma ** 2) * t | |
| jump_part = self.lam * t * (np.exp(i * u * self.gamma - 0.5 * (u ** 2) * (self.delta ** 2)) - 1.0) | |
| return np.exp(diffusion_part + jump_part) | |
| def simulate_paths(self, t_years=1.0, steps=252, n_paths=1000, seed=42): | |
| """Vectorized Euler-Maruyama simulation with Poisson jump compounding.""" | |
| np.random.seed(seed) | |
| dt = t_years / float(steps) | |
| paths = np.zeros((n_paths, steps + 1)) | |
| paths[:, 0] = self.s0 | |
| drift = (self.r - 0.5 * (self.sigma ** 2) - self.lam * self.k) * dt | |
| for t in range(steps): | |
| # Brownian increments | |
| z = np.random.normal(0, 1, n_paths) | |
| diffusion = self.sigma * math.sqrt(dt) * z | |
| # Poisson jump arrivals | |
| n_jumps = np.random.poisson(self.lam * dt, n_paths) | |
| jump_magnitudes = np.zeros(n_paths) | |
| # Compound jump sizes | |
| jump_mask = n_jumps > 0 | |
| if np.any(jump_mask): | |
| for idx in np.where(jump_mask)[0]: | |
| j_count = n_jumps[idx] | |
| jump_magnitudes[idx] = np.sum(np.random.normal(self.gamma, self.delta, j_count)) | |
| ret = drift + diffusion + jump_magnitudes | |
| paths[:, t + 1] = paths[:, t] * np.exp(ret) | |
| return paths | |
| if __name__ == "__main__": | |
| engine = MertonJumpDiffusionEngine() | |
| sims = engine.simulate_paths(steps=60, n_paths=500) | |
| print(f"Merton Jump-Diffusion | Initial S0: 100 | Mean Terminal Price: {np.mean(sims[:, -1]):.2f}") | |
Xet Storage Details
- Size:
- 2.79 kB
- Xet hash:
- e73eae9497e0941fbb0fcc0afaa0b9ac56489f7b022f7c3805d88d265395a53b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.