← quantChapter 8 · Credit4 min read

Jump-diffusion: the Greek the smoothing breaks

Learn how Merton jump-diffusion affects option Greeks and why jump-intensity sensitivity can fail under some smoothing and JIT settings.

A diffusion alone can't fit a short-dated volatility smile — Black-Scholes has no mechanism for a sudden gap, and the market prices one in. Merton's 1976 fix adds a compound-Poisson jump to geometric Brownian motion: sometimes, with some intensity, the spot jumps by a random lognormal amount. Recording that on a tape means putting an actual coin flip — did a jump happen this step, yes or no — through the same reverse-mode machinery that differentiates a smooth diffusion. Most Greeks are well-behaved, but at the default smoothing width the jump-intensity Greek is NaN on cpu-jit and finite on cpu.

The whole story

Each step draws a diffusion normal and a uniform smoothed into a jump indicator, then applies a lognormal jump. At the default smoothing width the jump-intensity adjoint is NaN on cpu-jit but finite on cpu; the Monte Carlo price matches the exact Poisson-series price within 1.3%. Merton and Kou jumps produce a downward-sloping implied-volatility smile that a pure diffusion cannot produce.

Did you know?

MertonJumpModel.step's own comment states a precise, easy-to-get-wrong fact: the martingale-preserving drift compensator for this discretization is -ln(1 + λκdt), not the textbook continuous-time -λκdt. The smoothed "at-most-one-jump" factor has expectation exactly 1 + λκdt, not e^{λκdt}, so only the logarithmic form makes the discounted spot an exact per-step martingale under this specific scheme — the two forms agree only to O(dt²). Smooth.lt(rec, u, λ·dt, width) is what makes "at most one jump this step" differentiable at all: the underlying event is discrete and stochastic, but P(≥2 jumps per step) = O((λdt)²), so the smoothed at-most-one-jump approximation becomes exact as the step count grows — the same fine-grid argument 3.1 used to justify treating a discretely- monitored Asian option as continuous.

The step, verified against an exact reference

MertonJumpModel.step is validated against a completely independent oracle: MertonJumpDiffusion.price, the closed-form Poisson-weighted average of Black-Scholes prices, one term per possible jump count to expiry. JumpDiffusionShowcase runs both side by side on the same market:

double mc = price(merton, MertonJumpModel.european(OptionType.CALL, t, steps), paths, 42L);
double exact = MertonJumpDiffusion.price(OptionType.CALL, s0, 100, t, r, sigma,
    merton.jumpIntensity(), merton.jumpMean(), merton.jumpVol());

At 1.5 million paths, 128 steps: Monte-Carlo 7.4181 against the exact series 7.5152 — a 1.3% gap, inside the deeper doc's own claimed 1.5% convergence bound. That's the whole-price check. The interesting part is what happens when you ask the same recorded tape for a Greek instead of a price.

The jump-intensity Greek

At the default smoothing width (2×10⁻⁴), a standalone Java probe found that d(price)/d(jumpIntensity) is NaN with cpu-jit, but finite with cpu; a central bump also gives a finite result (1.90). This is a cpu-jit-specific issue, not a property of the model's price.

The real run

JumpDiffusionShowcase also prints the implied-volatility smile both jump models carve into an otherwise flat Black-Scholes surface, same strikes, same 6-month maturity:

strikeBlack ivolMerton ivolKou ivol
8015.00%28.98%27.08%
10015.00%23.77%21.34%
12015.00%22.50%20.48%

Black-Scholes is flat by construction — one input volatility, one output volatility, every strike. Both jump models produce a real downward slope instead, from the same negative jumpMean (−0.09) biasing the jump distribution toward crashes: a diffusion literally cannot produce this shape no matter how its single volatility parameter is tuned, which is the entire reason this model exists.

Try it yourself

Change merton.jumpMean() from -0.09 to +0.09 (a market that fears melt-ups, not crashes) and predict which side of the smile gets steeper before you rerun the showcase. (The slope flips: 80-strike ivol falls from 28.98% to 22.97% and 120-strike ivol rises from 22.50% to 30.19% — a positive jump mean fattens the right tail instead of the left, the mirror image of the negative-mean smile around the ATM strike.)

▶️ Run it

The TeaVM example uses cpu, so its browser run shows a finite gradient. The Java showcase below uses cpu-jit, but prints prices and implied volatilities only; it does not calculate the Greek:

Java · compile and run in this browser

Or run the Java price showcase:

mvn -o -q -pl nablatensor-examples exec:java \
  -Dexec.mainClass=com.nablatensor.examples.JumpDiffusionShowcase -Dpaths=1500000

⚠️ What this doesn't do

Only Merton's lognormal jump size is covered in depth here, though Kou's asymmetric double-exponential jump appears in the same showcase; neither Variance-Gamma nor Bates (Heston plus jumps) exist in this codebase yet — the deeper doc's own "Deferred" section names both directly, needing a recordable Gamma subordinator and a Heston-composed step respectively.

What's next

→ Deeper: Jump-diffusion step blocks: Merton and Kou has the full KouJumpModel API and the pinned test tolerances this page's numbers are checked against. → Chapter 8 (Credit) is complete. Next: VaR and Expected Shortfall: three routes to one number — Chapter 9 opens with risk aggregation, computed rather than looked up from a table.


Questions or corrections? open an issue