ModifiedCorradoSuSkewnessKurtosisModel extends AnalyticOptionModel<OptionDefinition, SkewKurtosisOptionDataBundle> { @Override public Function1D<SkewKurtosisOptionDataBundle, Double> getPricingFunction(final OptionDefinition definition) { Validate.notNull(definition); final Function1D<SkewKurtosisOptionDataBundle, Double> pricingFunction = new Function1D<SkewKurtosisOptionDataBundle, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final SkewKurtosisOptionDataBundle data) { Validate.notNull(data); final double s = data.getSpot(); final double k = definition.getStrike(); final double t = definition.getTimeToExpiry(data.getDate()); final double sigma = data.getVolatility(t, k); final double r = data.getInterestRate(t); final double b = data.getCostOfCarry(); final double skew = data.getAnnualizedSkew(); final double kurtosis = data.getAnnualizedFisherKurtosis(); final double sigmaT = sigma * Math.sqrt(t); OptionDefinition callDefinition = definition; if (!definition.isCall()) { callDefinition = new EuropeanVanillaOptionDefinition(callDefinition.getStrike(), callDefinition.getExpiry(), true); } final Function1D<StandardOptionDataBundle, Double> bsm = BSM.getPricingFunction(callDefinition); final double bsmCall = bsm.evaluate(data); final double w = getW(sigma, t, skew, kurtosis); final double d = getD(s, k, sigma, t, b, w, sigmaT); final double call = bsmCall + skew * getQ3(s, d, w, sigmaT) + kurtosis * getQ4(s, d, w, sigmaT); if (!definition.isCall()) { return call - s * Math.exp((b - r) * t) + k * Math.exp(-r * t); } return call; } }; return pricingFunction; }  @Override Function1D<SkewKurtosisOptionDataBundle, Double> getPricingFunction(final OptionDefinition definition);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullDefinition() { CORRADO_SU.getPricingFunction(null); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { CORRADO_SU.getPricingFunction(CALL_100).evaluate((SkewKurtosisOptionDataBundle) null); }
@Test public void test() { assertEquals(BSM.getPricingFunction(CALL_100).evaluate(NORMAL_DATA), CORRADO_SU.getPricingFunction(CALL_100).evaluate(NORMAL_DATA), EPS); assertEquals(BSM.getPricingFunction(PUT_75).evaluate(NORMAL_DATA), CORRADO_SU.getPricingFunction(PUT_75).evaluate(NORMAL_DATA), EPS); final SkewKurtosisOptionDataBundle data = new SkewKurtosisOptionDataBundle(CURVE, B, SURFACE, SPOT, DATE, -0.2, 3); Function1D<SkewKurtosisOptionDataBundle, Double> f = CORRADO_SU.getPricingFunction(PUT_75); assertEquals(0.3103, f.evaluate(data), EPS); assertEquals(0.3186, f.evaluate(data.withSkew(-0.1).withKurtosis(3.5)), EPS); assertEquals(0.3267, f.evaluate(data.withSkew(0.).withKurtosis(4.)), EPS); assertEquals(0.3347, f.evaluate(data.withSkew(0.1).withKurtosis(4.5)), EPS); assertEquals(0.3427, f.evaluate(data.withSkew(0.2).withKurtosis(5.)), EPS); f = CORRADO_SU.getPricingFunction(PUT_100); assertEquals(6.0422, f.evaluate(data), EPS); assertEquals(5.9217, f.evaluate(data.withSkew(-0.1).withKurtosis(3.5)), EPS); assertEquals(5.8015, f.evaluate(data.withSkew(0.).withKurtosis(4.)), EPS); assertEquals(5.6814, f.evaluate(data.withSkew(0.1).withKurtosis(4.5)), EPS); assertEquals(5.5615, f.evaluate(data.withSkew(0.2).withKurtosis(5.)), EPS); f = CORRADO_SU.getPricingFunction(CALL_100); assertEquals(7.7770, f.evaluate(data), EPS); assertEquals(7.6565, f.evaluate(data.withSkew(-0.1).withKurtosis(3.5)), EPS); assertEquals(7.5363, f.evaluate(data.withSkew(0.).withKurtosis(4.)), EPS); assertEquals(7.4162, f.evaluate(data.withSkew(0.1).withKurtosis(4.5)), EPS); assertEquals(7.2963, f.evaluate(data.withSkew(0.2).withKurtosis(5.)), EPS); f = CORRADO_SU.getPricingFunction(CALL_125); assertEquals(0.9567, f.evaluate(data), EPS); assertEquals(1.1173, f.evaluate(data.withSkew(-0.1).withKurtosis(3.5)), EPS); assertEquals(1.2782, f.evaluate(data.withSkew(0.).withKurtosis(4.)), EPS); assertEquals(1.4391, f.evaluate(data.withSkew(0.1).withKurtosis(4.5)), EPS); assertEquals(1.6000, f.evaluate(data.withSkew(0.2).withKurtosis(5.)), EPS); }