MertonJumpDiffusionModel extends AnalyticOptionModel<OptionDefinition, MertonJumpDiffusionModelDataBundle> { @Override public Function1D<MertonJumpDiffusionModelDataBundle, Double> getPricingFunction(final OptionDefinition definition) { Validate.notNull(definition); final Function1D<MertonJumpDiffusionModelDataBundle, Double> pricingFunction = new Function1D<MertonJumpDiffusionModelDataBundle, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final MertonJumpDiffusionModelDataBundle data) { Validate.notNull(data); final ZonedDateTime date = data.getDate(); final double k = definition.getStrike(); final double t = definition.getTimeToExpiry(date); final double sigma = data.getVolatility(t, k); final double lambda = data.getLambda(); final double gamma = data.getGamma(); final double sigmaSq = sigma * sigma; final double delta = Math.sqrt(gamma * sigmaSq / lambda); final double z = Math.sqrt(sigmaSq - lambda * delta * delta); final double zSq = z * z; double sigmaAdjusted = z; final double lambdaT = lambda * t; double mult = Math.exp(-lambdaT); final StandardOptionDataBundle bsmData = new StandardOptionDataBundle(data.getInterestRateCurve(), data.getCostOfCarry(), new VolatilitySurface(ConstantDoublesSurface.from(sigmaAdjusted)), data.getSpot(), date); final Function1D<StandardOptionDataBundle, Double> bsmFunction = BSM.getPricingFunction(definition); double price = mult * bsmFunction.evaluate(bsmData); for (int i = 1; i < N; i++) { sigmaAdjusted = Math.sqrt(zSq + delta * delta * i / t); mult *= lambdaT / i; price += mult * bsmFunction.evaluate(bsmData.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(sigmaAdjusted)))); } return price; } }; return pricingFunction; }  @Override Function1D<MertonJumpDiffusionModelDataBundle, Double> getPricingFunction(final OptionDefinition definition);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullDefinition() { MODEL.getPricingFunction(null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { MODEL.getPricingFunction(new EuropeanVanillaOptionDefinition(100, EXPIRY1, true)).evaluate((MertonJumpDiffusionModelDataBundle) null); }
@Test public void test() { OptionDefinition call = new EuropeanVanillaOptionDefinition(80, EXPIRY1, true); MertonJumpDiffusionModelDataBundle data = new MertonJumpDiffusionModelDataBundle(CURVE, B, SURFACE, SPOT, DATE, 1., 0.); assertEquals(BSM.getPricingFunction(call).evaluate(data), MODEL.getPricingFunction(call).evaluate(data), EPS2); call = new EuropeanVanillaOptionDefinition(80, EXPIRY1, true); data = data.withLambda(1.).withGamma(0.25); assertEquals(20.67, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(90, EXPIRY2, true); data = data.withLambda(5.); assertEquals(12.75, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(100, EXPIRY3, true); data = data.withLambda(10.); assertEquals(9.03, MODEL.getPricingFunction(call).evaluate(data), EPS1); data = data.withGamma(0.5); data = data.withLambda(1.); call = new EuropeanVanillaOptionDefinition(90, EXPIRY1, true); assertEquals(11.04, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(100, EXPIRY2, true); data = data.withLambda(5.); assertEquals(5.87, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(110, EXPIRY3, true); data = data.withLambda(10.); assertEquals(4.71, MODEL.getPricingFunction(call).evaluate(data), EPS1); data = data.withGamma(0.75); data = data.withLambda(1.); call = new EuropeanVanillaOptionDefinition(100, EXPIRY1, true); assertEquals(2.70, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(110, EXPIRY2, true); data = data.withLambda(5.); assertEquals(2.05, MODEL.getPricingFunction(call).evaluate(data), EPS1); call = new EuropeanVanillaOptionDefinition(120, EXPIRY3, true); data = data.withLambda(10.); assertEquals(2.23, MODEL.getPricingFunction(call).evaluate(data), EPS1); }