ConstantElasticityOfVarianceBlackEquivalentVolatilitySurfaceModel implements VolatilitySurfaceModel<Map<OptionDefinition, Double>, ConstantElasticityOfVarianceModelDataBundle> { @Override public VolatilitySurface getSurface(final Map<OptionDefinition, Double> optionData, final ConstantElasticityOfVarianceModelDataBundle data) { Validate.notNull(optionData, "option data"); ArgumentChecker.notEmpty(optionData, "option data"); Validate.notNull(data, "data"); if (optionData.size() > 1) { s_logger.warn("Have more than one option: only using the first"); } final OptionDefinition option = optionData.keySet().iterator().next(); final double k = option.getStrike(); final double t = option.getTimeToExpiry(data.getDate()); final double sigma = data.getVolatility(t, k); final double beta = data.getElasticity(); final double forward = data.getSpot(); final double f = 0.5 * (forward + k); final double beta1 = 1 - beta; final double sigmaAdjusted = sigma * (1 + beta1 * (2 + beta) * (f - k) * (f - k) / 24 / f / f + beta1 * beta1 * sigma * sigma * t / 24 / Math.pow(f, 2 * beta1)) / Math.pow(f, beta1); return new VolatilitySurface(ConstantDoublesSurface.from(sigmaAdjusted)); }  @Override VolatilitySurface getSurface(final Map<OptionDefinition, Double> optionData, final ConstantElasticityOfVarianceModelDataBundle data);  }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullOptionData() { MODEL.getSurface(null, DATA); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testEmptyOptionData() { MODEL.getSurface(Collections.<OptionDefinition, Double> emptyMap(), DATA); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testNullData() { MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(new EuropeanVanillaOptionDefinition(100, EXPIRY, true), 0.2), null); }
@Test public void test() { final double eps = 1e-4; OptionDefinition option = new EuropeanVanillaOptionDefinition(90, EXPIRY, true); ConstantElasticityOfVarianceModelDataBundle data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(0))); VolatilitySurface blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), BSM.getPricingFunction(option).evaluate(data), 0); data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(0.5))); blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), 9.7531, eps); data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(1))); option = new EuropeanVanillaOptionDefinition(95, EXPIRY, true); blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), 5.2678, eps); data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(2))); option = new EuropeanVanillaOptionDefinition(100, EXPIRY, true); blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), 3.8897, eps); data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(3))); option = new EuropeanVanillaOptionDefinition(105, EXPIRY, true); blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), 3.7832, eps); data = DATA.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(4))); option = new EuropeanVanillaOptionDefinition(115, EXPIRY, true); blackEquivalent = MODEL.getSurface(Collections.<OptionDefinition, Double> singletonMap(option, 0.), data); assertEquals(BSM.getPricingFunction(option).evaluate(data.withVolatilitySurface(blackEquivalent)), 2.7613, eps); }