/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.option.pricing.analytic; import static org.testng.AssertJUnit.assertEquals; import java.util.HashSet; import java.util.Set; import org.testng.Assert; import org.testng.annotations.Test; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.greeks.Greek; import com.opengamma.analytics.financial.greeks.GreekResultCollection; import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve; import com.opengamma.analytics.financial.model.option.definition.EuropeanVanillaOptionDefinition; import com.opengamma.analytics.financial.model.option.definition.OptionDefinition; import com.opengamma.analytics.financial.model.option.definition.StandardOptionDataBundle; import com.opengamma.analytics.financial.model.volatility.surface.VolatilitySurface; import com.opengamma.analytics.math.curve.ConstantDoublesCurve; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.surface.ConstantDoublesSurface; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; import com.opengamma.util.time.Expiry; import com.opengamma.util.tuple.Pair; /** * Test. */ @Test(groups = TestGroup.UNIT) public abstract class AnalyticOptionModelTest { protected static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> BSM = new BlackScholesMertonModel(); private static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> DUMMY_MODEL = new AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle>() { @Override public Function1D<StandardOptionDataBundle, Double> getPricingFunction(final OptionDefinition definition) { return BSM.getPricingFunction(definition); } }; private static final ZonedDateTime DATE = DateUtils.getUTCDate(2009, 1, 1); private static final Expiry ONE_YEAR = new Expiry(DateUtils.getDateOffsetWithYearFraction(DATE, 1)); private static final EuropeanVanillaOptionDefinition PUT = new EuropeanVanillaOptionDefinition(15, ONE_YEAR, false); private static final EuropeanVanillaOptionDefinition CALL = new EuropeanVanillaOptionDefinition(15, ONE_YEAR, true); private static final StandardOptionDataBundle DATA = new StandardOptionDataBundle(YieldCurve.from(ConstantDoublesCurve.from(0.06)), 0.02, new VolatilitySurface(ConstantDoublesSurface.from(0.24)), 15., DATE); private static final double EPS = 1e-2; protected <S extends OptionDefinition, T extends StandardOptionDataBundle> void assertInputs(final AnalyticOptionModel<S, T> model, final S definition) { try { model.getPricingFunction(null); Assert.fail(); } catch (final IllegalArgumentException e) { // Expected } try { model.getPricingFunction(definition).evaluate((T) null); Assert.fail(); } catch (final IllegalArgumentException e) { // Expected } } @Test public void testFiniteDifferenceAgainstBSM() { final Set<Greek> greekTypes = new HashSet<>(Greek.getAllGreeks()); greekTypes.remove(Greek.DRIFTLESS_THETA); greekTypes.remove(Greek.STRIKE_DELTA); greekTypes.remove(Greek.STRIKE_GAMMA); greekTypes.remove(Greek.DUAL_DELTA); greekTypes.remove(Greek.DUAL_GAMMA); greekTypes.remove(Greek.ZETA); greekTypes.remove(Greek.ZETA_BLEED); GreekResultCollection bsm = BSM.getGreeks(PUT, DATA, greekTypes); GreekResultCollection finiteDifference = DUMMY_MODEL.getGreeks(PUT, DATA, greekTypes); assertResults(finiteDifference, bsm); bsm = BSM.getGreeks(CALL, DATA, greekTypes); finiteDifference = DUMMY_MODEL.getGreeks(CALL, DATA, greekTypes); assertResults(finiteDifference, bsm); } protected void assertResults(final GreekResultCollection results, final GreekResultCollection expected) { assertEquals(results.size(), expected.size()); for (final Pair<Greek, Double> entry : results) { final Double result2 = expected.get(entry.getFirst()); if (!(entry.getFirst().equals(Greek.VARIANCE_ULTIMA))) { assertEquals(entry.getSecond(), result2, EPS); } else { assertEquals(entry.getSecond(), result2, 1000 * EPS); } } } }