/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.bondfutureoption;
import static com.opengamma.sesame.config.ConfigBuilder.argument;
import static com.opengamma.sesame.config.ConfigBuilder.arguments;
import static com.opengamma.sesame.config.ConfigBuilder.config;
import static com.opengamma.sesame.config.ConfigBuilder.function;
import static com.opengamma.sesame.config.ConfigBuilder.implementations;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.mock;
import java.util.List;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.threeten.bp.Instant;
import com.google.common.collect.ImmutableMap;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.core.link.ConfigLink;
import com.opengamma.financial.currency.CurrencyMatrix;
import com.opengamma.service.ServiceContext;
import com.opengamma.service.ThreadLocalServiceContext;
import com.opengamma.service.VersionCorrectionProvider;
import com.opengamma.sesame.CurveSelector;
import com.opengamma.sesame.DefaultFixingsFn;
import com.opengamma.sesame.Environment;
import com.opengamma.sesame.FixingsFn;
import com.opengamma.sesame.IssuerProviderFn;
import com.opengamma.sesame.LookupIssuerProviderFn;
import com.opengamma.sesame.MarketExposureSelector;
import com.opengamma.sesame.bondfuture.BondFutureTestData;
import com.opengamma.sesame.config.FunctionModelConfig;
import com.opengamma.sesame.engine.CalculationArguments;
import com.opengamma.sesame.engine.ComponentMap;
import com.opengamma.sesame.engine.FixedInstantVersionCorrectionProvider;
import com.opengamma.sesame.engine.FunctionRunner;
import com.opengamma.sesame.graph.FunctionModel;
import com.opengamma.sesame.marketdata.DefaultHistoricalMarketDataFn;
import com.opengamma.sesame.marketdata.EmptyMarketDataFactory;
import com.opengamma.sesame.marketdata.EmptyMarketDataSpec;
import com.opengamma.sesame.marketdata.HistoricalMarketDataFn;
import com.opengamma.sesame.marketdata.MarketDataEnvironment;
import com.opengamma.sesame.marketdata.builders.MarketDataBuilder;
import com.opengamma.sesame.marketdata.builders.MarketDataBuilders;
import com.opengamma.sesame.marketdata.builders.MarketDataEnvironmentFactory;
import com.opengamma.sesame.trade.BondFutureOptionTrade;
import com.opengamma.util.function.Function;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.result.Result;
import com.opengamma.util.test.TestGroup;
/**
* Test for bond future options using the black calculator.
* Validated against BondFuturesOptionPremiumBlackExpStrikeE2ETest
*/
@Test(groups = TestGroup.UNIT)
public class BondFutureOptionFnTest {
/** Tolerances */
private static final double TOLERANCE_GREEKS = 1.0E-6;
private static final double TOLERANCE_PV = 1.0E-2;
/** Expected values validated against BondFuturesOptionPremiumBlackExpStrikeE2ETest */
public static final double EXPECTED_PV = -81090395.9457;
public static final double EXPECTED_DELTA = -0.56391967;
public static final double EXPECTED_GAMMA = 23.70913668;
public static final double EXPECTED_VEGA = 0.2109653;
public static final double EXPECTED_THETA = -0.02435502;
public static final BondFutureOptionTrade BOND_FUTURE_OPTION_TRADE = BondFutureTestData.createBondFutureOptionTrade();
private BondFutureOptionFn _function;
private FunctionRunner _functionRunner;
private static final CalculationArguments ARGS =
CalculationArguments.builder()
.valuationTime(BondFutureTestData.VALUATION_TIME)
.marketDataSpecification(EmptyMarketDataSpec.INSTANCE)
.build();
private static MarketDataEnvironment ENV = BondFutureTestData.createMarketDataEnvironment();
@BeforeClass
public void setUp() {
FunctionModelConfig config =
config(
arguments(
function(
MarketExposureSelector.class,
argument("exposureFunctions", ConfigLink.resolved(BondFutureTestData.createExposureFunction())))),
implementations(
BlackBondFuturesProviderFn.class, BlackExpStrikeBondFuturesProviderFn.class,
BondFutureOptionFn.class, DefaultBondFutureOptionFn.class,
BondFutureOptionCalculatorFactory.class, BondFutureOptionBlackCalculatorFactory.class,
FixingsFn.class, DefaultFixingsFn.class,
IssuerProviderFn.class, LookupIssuerProviderFn.class,
CurveSelector.class, MarketExposureSelector.class,
HistoricalMarketDataFn.class, DefaultHistoricalMarketDataFn.class
));
ImmutableMap<Class<?>, Object> components = BondFutureTestData.generateBaseComponents();
VersionCorrectionProvider vcProvider = new FixedInstantVersionCorrectionProvider(Instant.now());
ServiceContext serviceContext = ServiceContext.of(components).with(VersionCorrectionProvider.class, vcProvider);
ThreadLocalServiceContext.init(serviceContext);
ComponentMap componentMap = ComponentMap.of(components);
_function = FunctionModel.build(BondFutureOptionFn.class,
config,
componentMap);
EmptyMarketDataFactory dataFactory = new EmptyMarketDataFactory();
ConfigLink<CurrencyMatrix> currencyMatrixLink = ConfigLink.resolved(componentMap.getComponent(CurrencyMatrix.class));
List<MarketDataBuilder> builders = MarketDataBuilders.standard(componentMap, "dataSource", currencyMatrixLink);
MarketDataEnvironmentFactory environmentFactory = new MarketDataEnvironmentFactory(dataFactory, builders);
_functionRunner = new FunctionRunner(environmentFactory);
}
@Test
public void testPresentValue() {
Result<MultipleCurrencyAmount> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<MultipleCurrencyAmount>>() {
@Override
public Result<MultipleCurrencyAmount> apply(Environment env) {
return _function.calculatePV(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
MultipleCurrencyAmount mca = result.getValue();
assertThat(mca.getAmount(Currency.JPY), is(closeTo(EXPECTED_PV, TOLERANCE_PV)));
}
@Test
public void testDelta() {
Result<Double> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _function.calculateDelta(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
Double delta = result.getValue();
assertThat(delta, is(closeTo(EXPECTED_DELTA, TOLERANCE_GREEKS)));
}
@Test
public void testGamma() {
Result<Double> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _function.calculateGamma(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
Double gamma = result.getValue();
assertThat(gamma, is(closeTo(EXPECTED_GAMMA, TOLERANCE_GREEKS)));
}
@Test
public void testVega() {
Result<Double> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _function.calculateVega(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
Double vega = result.getValue();
assertThat(vega, is(closeTo(EXPECTED_VEGA, TOLERANCE_GREEKS)));
}
@Test
public void testTheta() {
Result<Double> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _function.calculateTheta(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
Double theta = result.getValue();
assertThat(theta, is(closeTo(EXPECTED_THETA, TOLERANCE_GREEKS)));
}
@Test
public void testPV01() {
Result<Double> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<Double>>() {
@Override
public Result<Double> apply(Environment env) {
return _function.calculatePV01(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
}
@Test
public void testBucketedPV01() {
Result<MultipleCurrencyParameterSensitivity> result = _functionRunner.runFunction(
ARGS, ENV,
new Function<Environment, Result<MultipleCurrencyParameterSensitivity>>() {
@Override
public Result<MultipleCurrencyParameterSensitivity> apply(Environment env) {
return _function.calculateBucketedPV01(env, BOND_FUTURE_OPTION_TRADE);
}
});
assertThat(result.isSuccess(), is(true));
}
}