/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.sesame.fra; 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 com.opengamma.util.result.ResultTestUtils.assertSuccess; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.closeTo; import static org.hamcrest.core.IsNull.notNullValue; import static org.testng.Assert.assertTrue; import java.io.IOException; import java.math.BigDecimal; import java.util.Collections; import java.util.List; import java.util.Map; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.threeten.bp.Instant; import org.threeten.bp.LocalDate; import org.threeten.bp.OffsetTime; import org.threeten.bp.ZonedDateTime; import com.google.common.collect.ImmutableMap; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.analytics.util.amount.ReferenceAmount; import com.opengamma.core.id.ExternalSchemes; import com.opengamma.core.link.ConfigLink; import com.opengamma.core.position.Counterparty; import com.opengamma.core.position.Trade; import com.opengamma.core.position.impl.SimpleCounterparty; import com.opengamma.core.position.impl.SimpleTrade; import com.opengamma.engine.marketdata.spec.LiveMarketDataSpecification; import com.opengamma.financial.analytics.DoubleLabelledMatrix1D; import com.opengamma.financial.analytics.DoubleLabelledMatrix2D; import com.opengamma.financial.analytics.model.fixedincome.BucketedCrossSensitivities; import com.opengamma.financial.analytics.model.fixedincome.BucketedCurveSensitivities; import com.opengamma.financial.analytics.model.fixedincome.FixedCashFlowDetails; import com.opengamma.financial.analytics.model.fixedincome.FixedLegCashFlows; import com.opengamma.financial.analytics.model.fixedincome.FloatingCashFlowDetails; import com.opengamma.financial.analytics.model.fixedincome.FloatingLegCashFlows; import com.opengamma.financial.analytics.model.fixedincome.SwapLegCashFlows; import com.opengamma.financial.convention.businessday.BusinessDayConventionFactory; import com.opengamma.financial.convention.daycount.DayCountFactory; import com.opengamma.financial.convention.frequency.SimpleFrequency; import com.opengamma.financial.currency.CurrencyMatrix; import com.opengamma.financial.security.fra.FRASecurity; import com.opengamma.financial.security.fra.ForwardRateAgreementSecurity; import com.opengamma.id.ExternalId; import com.opengamma.service.ServiceContext; import com.opengamma.service.ThreadLocalServiceContext; import com.opengamma.service.VersionCorrectionProvider; import com.opengamma.sesame.CurveDefinitionCurveLabellingFn; import com.opengamma.sesame.CurveDefinitionFn; import com.opengamma.sesame.CurveLabellingFn; import com.opengamma.sesame.CurveSelector; import com.opengamma.sesame.CurveSelectorMulticurveBundleFn; import com.opengamma.sesame.DefaultCurveDefinitionFn; import com.opengamma.sesame.DefaultFXMatrixFn; import com.opengamma.sesame.DefaultFixingsFn; import com.opengamma.sesame.DiscountingMulticurveCombinerFn; import com.opengamma.sesame.Environment; import com.opengamma.sesame.FXMatrixFn; import com.opengamma.sesame.FixingsFn; import com.opengamma.sesame.MarketExposureSelector; import com.opengamma.sesame.TestMarketDataFactory; 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.interestrate.InterestRateMockSources; import com.opengamma.sesame.marketdata.DefaultHistoricalMarketDataFn; import com.opengamma.sesame.marketdata.DefaultMarketDataFn; import com.opengamma.sesame.marketdata.HistoricalMarketDataFn; import com.opengamma.sesame.marketdata.MarketDataFn; import com.opengamma.sesame.marketdata.MarketDataSource; 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.ForwardRateAgreementTrade; 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; import com.opengamma.util.time.DateUtils; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; @Test(groups = TestGroup.UNIT) public class FraPricingTest { private static final ZonedDateTime STD_REFERENCE_DATE = DateUtils.getUTCDate(2014, 1, 22); private static final ZonedDateTime STD_ACCRUAL_START_DATE = DateUtils.getUTCDate(2014, 9, 12); private static final ZonedDateTime STD_ACCRUAL_END_DATE = DateUtils.getUTCDate(2014, 12, 12); private static final ZonedDateTime VALUATION_TIME = DateUtils.getUTCDate(2014, 1, 22); private static final double STD_TOLERANCE_PV = 1.0E-3; private static final double STD_TOLERANCE_RATE = 1.0E-5; private static final LocalDate MARKET_DATA_DATE = LocalDate.of(2014, 1, 22); private static final double EXPECTED_PV = 23182.5437; private static final double EXPECTED_PAY_LEG = -8368.1461; private static final double EXPECTED_REC_LEG = 31550.6898; private static final double EXPECTED_PAR_RATE = 0.003315; private static final Map<Pair<String, Currency>, DoubleMatrix1D> EXPECTED_BUCKETED_PV01 = ImmutableMap.<Pair<String, Currency>, DoubleMatrix1D>builder() .put(Pairs.of(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, Currency.USD), new DoubleMatrix1D(119.7375367728506, 120.92969446825524, -26.46239944124458, -460.7550335902164, 0, 0, 0, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d)) .put(Pairs.of(InterestRateMockSources.USD_OIS_CURVE_NAME, Currency.USD), new DoubleMatrix1D(-0.006618053208045675, -0.006618053208189062, 3.4931205919522354E-4, -0.004729686527856287, -0.031139542713136088, -0.5519190718364266, -1.0406804627639228, 0.24701401372751566, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d)) .build(); private static final Map<String, DoubleMatrix2D> EXPECTED_GAMMA_MATRICES = ImmutableMap.<String, DoubleMatrix2D>builder() .put(InterestRateMockSources.USD_OIS_CURVE_NAME, new DoubleMatrix2D(new Double[][]{ {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 2.361676E-5, 2.361676E-5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 2.361676E-5, 2.361676E-5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, })) .put(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, new DoubleMatrix2D(new Double[][]{ {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.008507, -0.002277, -0.013508, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, -0.002277, 6.09676e-4, 0.003616, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, -0.0135072, 0.003615977, 0.021447, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, })) .build(); private FRAFn _fraFunction; private FRASecurity _fraSecurity = createSingleFra(); private ForwardRateAgreementSecurity _forwardRateAgreementSecurity = createSingleForwardRateAgreement(); private FunctionRunner _functionRunner; private static final CalculationArguments ARGS = CalculationArguments.builder() .valuationTime(VALUATION_TIME) .marketDataSpecification(LiveMarketDataSpecification.LIVE_SPEC) .build(); @BeforeClass public void setUpClass() throws IOException { FunctionModelConfig config = config( arguments( function( MarketExposureSelector.class, argument("exposureFunctions", ConfigLink.resolved(InterestRateMockSources.mockExposureFunctions())))), implementations( FRAFn.class, DiscountingFRAFn.class, FRACalculatorFactory.class, DiscountingFRACalculatorFactory.class, FRACalculator.class, DiscountingFRACalculator.class, FXMatrixFn.class, DefaultFXMatrixFn.class, CurveDefinitionFn.class, DefaultCurveDefinitionFn.class, CurveLabellingFn.class, CurveDefinitionCurveLabellingFn.class, DiscountingMulticurveCombinerFn.class, CurveSelectorMulticurveBundleFn.class, HistoricalMarketDataFn.class, DefaultHistoricalMarketDataFn.class, FixingsFn.class, DefaultFixingsFn.class, CurveSelector.class, MarketExposureSelector.class, MarketDataFn.class, DefaultMarketDataFn.class)); Map<Class<?>, Object> components = InterestRateMockSources.generateBaseComponents(); VersionCorrectionProvider vcProvider = new FixedInstantVersionCorrectionProvider(Instant.now()); ServiceContext serviceContext = ServiceContext.of(components).with(VersionCorrectionProvider.class, vcProvider); ThreadLocalServiceContext.init(serviceContext); ComponentMap componentMap = ComponentMap.of(components); MarketDataSource marketDataSource = InterestRateMockSources.createMarketDataSource(MARKET_DATA_DATE, true); TestMarketDataFactory marketDataFactory = new TestMarketDataFactory(marketDataSource); ConfigLink<CurrencyMatrix> currencyMatrixLink = ConfigLink.resolved(componentMap.getComponent(CurrencyMatrix.class)); List<MarketDataBuilder> builders = MarketDataBuilders.standard(componentMap, "dataSource", currencyMatrixLink); MarketDataEnvironmentFactory environmentFactory = new MarketDataEnvironmentFactory(marketDataFactory, builders); _functionRunner = new FunctionRunner(environmentFactory); _fraFunction = FunctionModel.build(FRAFn.class, config, ComponentMap.of(components)); } @Test public void discountingFRAPV() { Result<MultipleCurrencyAmount> resultPV = _functionRunner.runFunction( ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() { @Override public Result<MultipleCurrencyAmount> apply(Environment env) { return _fraFunction.calculatePV(env, _fraSecurity); } }); assertSuccess(resultPV); MultipleCurrencyAmount mca = resultPV.getValue(); assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_PV, STD_TOLERANCE_PV))); } @Test public void parRateFRA() { Result<Double> resultParRate = _functionRunner.runFunction( ARGS, new Function<Environment, Result<Double>>() { @Override public Result<Double> apply(Environment env) { return _fraFunction.calculateParRate(env, _fraSecurity); } }); assertSuccess(resultParRate); Double parRate = resultParRate.getValue(); assertThat(parRate, is(closeTo(EXPECTED_PAR_RATE, STD_TOLERANCE_RATE))); } @Test public void payCashflowsFRA() { Result<SwapLegCashFlows> resultCashflows = _functionRunner.runFunction( ARGS, new Function<Environment, Result<SwapLegCashFlows>>() { @Override public Result<SwapLegCashFlows> apply(Environment env) { return _fraFunction.calculatePayLegCashFlows(env, _forwardRateAgreementSecurity); } }); assertSuccess(resultCashflows); SwapLegCashFlows resultObject = resultCashflows.getValue(); assertTrue(resultObject instanceof FloatingLegCashFlows); FloatingLegCashFlows flows = (FloatingLegCashFlows) resultObject; assertThat(flows.getCashFlowDetails().size(), is(1)); FloatingCashFlowDetails details = flows.getCashFlowDetails().get(0); Assert.assertEquals(details.getPresentValue().getAmount(), EXPECTED_PAY_LEG, STD_TOLERANCE_PV); } @Test public void recCashflowsFRA() { Result<SwapLegCashFlows> resultCashflows = _functionRunner.runFunction( ARGS, new Function<Environment, Result<SwapLegCashFlows>>() { @Override public Result<SwapLegCashFlows> apply(Environment env) { return _fraFunction.calculateReceiveLegCashFlows(env, _forwardRateAgreementSecurity); } }); assertSuccess(resultCashflows); SwapLegCashFlows resultObject = resultCashflows.getValue(); assertTrue(resultObject instanceof FixedLegCashFlows); FixedLegCashFlows flows = (FixedLegCashFlows) resultObject; assertThat(flows.getCashFlowDetails().size(), is(1)); FixedCashFlowDetails details = flows.getCashFlowDetails().get(0); Assert.assertEquals(details.getPresentValue().getAmount(), EXPECTED_REC_LEG, STD_TOLERANCE_PV); } @Test public void discountingForwardRateAgreementPV() { Result<MultipleCurrencyAmount> resultPV = _functionRunner.runFunction( ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() { @Override public Result<MultipleCurrencyAmount> apply(Environment env) { return _fraFunction.calculatePV(env, _forwardRateAgreementSecurity); } }); assertSuccess(resultPV); MultipleCurrencyAmount mca = resultPV.getValue(); assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_PV, STD_TOLERANCE_PV))); } @Test public void parRateForwardRateAgreement() { Result<Double> resultParRate = _functionRunner.runFunction( ARGS, new Function<Environment, Result<Double>>() { @Override public Result<Double> apply(Environment env) { return _fraFunction.calculateParRate(env, _forwardRateAgreementSecurity); } }); assertSuccess(resultParRate); Double parRate = resultParRate.getValue(); assertThat(parRate, is(closeTo(EXPECTED_PAR_RATE, STD_TOLERANCE_RATE))); } @Test public void discountingForwardRateAgreementPV01() { Result<ReferenceAmount<Pair<String, Currency>>> pv01 = _functionRunner.runFunction( ARGS, new Function<Environment, Result<ReferenceAmount<Pair<String, Currency>>>>() { @Override public Result<ReferenceAmount<Pair<String, Currency>>> apply(Environment env) { return _fraFunction.calculatePV01(env, _forwardRateAgreementSecurity); } }); assertSuccess(pv01); assertThat(pv01.getValue().getMap().size(), is(2)); assertThat(pv01.getValue().getMap().get(Pairs.of(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, Currency.USD)), closeTo(-249.73451494798297, STD_TOLERANCE_PV)); assertThat(pv01.getValue().getMap().get(Pairs.of(InterestRateMockSources.USD_OIS_CURVE_NAME, Currency.USD)), closeTo(-1.479871968614848, STD_TOLERANCE_PV)); } @Test public void discountingForwardRateAgreementBucketedPV01() { Result<BucketedCurveSensitivities> pv01 = _functionRunner.runFunction( ARGS, new Function<Environment, Result<BucketedCurveSensitivities>>() { @Override public Result<BucketedCurveSensitivities> apply(Environment env) { return _fraFunction.calculateBucketedPV01(env, _forwardRateAgreementSecurity); } }); assertSuccess(pv01); Map<Pair<String, Currency>, DoubleLabelledMatrix1D> pv01s = pv01.getValue().getSensitivities(); assertThat(pv01s.size(), is(EXPECTED_BUCKETED_PV01.size())); for (Map.Entry<Pair<String, Currency>, DoubleLabelledMatrix1D> sensitivity : pv01s.entrySet()) { DoubleMatrix1D expectedSensitivities = EXPECTED_BUCKETED_PV01.get(sensitivity.getKey()); assertThat(sensitivity.getKey() + " not an expected sensitivity", expectedSensitivities, is(notNullValue())); assertThat(sensitivity.getValue().size(), is(expectedSensitivities.getNumberOfElements())); for (int i = 0; i < expectedSensitivities.getNumberOfElements(); i++) { assertThat(sensitivity.getValue().getValues()[i], is(closeTo(expectedSensitivities.getEntry(i), STD_TOLERANCE_PV))); } } } @Test public void interestRateSwapBucketedGamma() { Result<BucketedCrossSensitivities> resultCrossGamma = _functionRunner.runFunction( ARGS, new Function<Environment, Result<BucketedCrossSensitivities>>() { @Override public Result<BucketedCrossSensitivities> apply(Environment env) { return _fraFunction.calculateBucketedCrossGamma(env, _forwardRateAgreementSecurity); } }); assertSuccess(resultCrossGamma); Map<String, DoubleLabelledMatrix2D> bucketedGamma = resultCrossGamma.getValue().getCrossSensitivities(); assertThat(bucketedGamma.size(), is(EXPECTED_GAMMA_MATRICES.size())); for (Map.Entry<String, DoubleLabelledMatrix2D> sensitivity : bucketedGamma.entrySet()) { DoubleMatrix2D expectedSensitivities = new DoubleMatrix2D(EXPECTED_GAMMA_MATRICES.get(sensitivity.getKey()).getData()); assertThat(sensitivity.getValue().getXKeys().length, is(expectedSensitivities.getNumberOfColumns())); assertThat(sensitivity.getValue().getYKeys().length, is(expectedSensitivities.getNumberOfRows())); for (int i = 0; i < expectedSensitivities.getNumberOfColumns(); i++) { for (int j = 0; j < expectedSensitivities.getNumberOfRows(); j++) { assertThat(expectedSensitivities.getData()[i][j], is(closeTo(sensitivity.getValue().getValues()[i][j], STD_TOLERANCE_PV))); } } } } @Test public void tradeFunctions() { final ForwardRateAgreementTrade trade = getTrade(_forwardRateAgreementSecurity); Result<MultipleCurrencyAmount> resultPV = _functionRunner.runFunction( ARGS, new Function<Environment, Result<MultipleCurrencyAmount>>() { @Override public Result<MultipleCurrencyAmount> apply(Environment obj) { return _fraFunction.calculatePV(obj, trade); } }); assertSuccess(resultPV); MultipleCurrencyAmount mca = resultPV.getValue(); assertThat(mca.getCurrencyAmount(Currency.USD).getAmount(), is(closeTo(EXPECTED_PV, STD_TOLERANCE_PV))); Result<Double> resultParRate = _functionRunner.runFunction( ARGS, new Function<Environment, Result<Double>>() { @Override public Result<Double> apply(Environment env) { return _fraFunction.calculateParRate(env, trade); } }); assertThat(resultParRate.isSuccess(), is((true))); Double parRate = resultParRate.getValue(); assertThat(parRate, is(closeTo(EXPECTED_PAR_RATE, STD_TOLERANCE_RATE))); Result<ReferenceAmount<Pair<String, Currency>>> pv01 = _functionRunner.runFunction( ARGS, new Function<Environment, Result<ReferenceAmount<Pair<String, Currency>>>>() { @Override public Result<ReferenceAmount<Pair<String, Currency>>> apply(Environment obj) { return _fraFunction.calculatePV01(obj, trade); } }); assertThat(pv01.isSuccess(), is((true))); assertThat(pv01.getValue().getMap().size(), is(2)); assertThat(pv01.getValue().getMap().get(Pairs.of(InterestRateMockSources.USD_LIBOR3M_CURVE_NAME, Currency.USD)), closeTo(-249.73451494798297, STD_TOLERANCE_PV)); assertThat(pv01.getValue().getMap().get(Pairs.of(InterestRateMockSources.USD_OIS_CURVE_NAME, Currency.USD)), closeTo(-1.479871968614848, STD_TOLERANCE_PV)); Result<BucketedCurveSensitivities> pv01Bucketed = _functionRunner.runFunction( ARGS, new Function<Environment, Result<BucketedCurveSensitivities>>() { @Override public Result<BucketedCurveSensitivities> apply(Environment env) { return _fraFunction.calculateBucketedPV01(env, trade); } }); assertThat(pv01.isSuccess(), is((true))); Map<Pair<String, Currency>, DoubleLabelledMatrix1D> pv01s = pv01Bucketed.getValue().getSensitivities(); assertThat(pv01s.size(), is(EXPECTED_BUCKETED_PV01.size())); for (Map.Entry<Pair<String, Currency>, DoubleLabelledMatrix1D> sensitivity : pv01s.entrySet()) { DoubleMatrix1D expectedSensitivities = EXPECTED_BUCKETED_PV01.get(sensitivity.getKey()); assertThat(sensitivity.getKey() + " not an expected sensitivity", expectedSensitivities, is(notNullValue())); assertThat(sensitivity.getValue().size(), is(expectedSensitivities.getNumberOfElements())); for (int i = 0; i < expectedSensitivities.getNumberOfElements(); i++) { assertThat(sensitivity.getValue().getValues()[i], is(closeTo(expectedSensitivities.getEntry(i), STD_TOLERANCE_PV))); } } Result<BucketedCrossSensitivities> resultCrossGamma = _functionRunner.runFunction( ARGS, new Function<Environment, Result<BucketedCrossSensitivities>>() { @Override public Result<BucketedCrossSensitivities> apply(Environment env) { return _fraFunction.calculateBucketedCrossGamma(env, trade); } }); assertThat(resultCrossGamma.isSuccess(), is(true)); Map<String, DoubleLabelledMatrix2D> bucketedGamma = resultCrossGamma.getValue().getCrossSensitivities(); assertThat(bucketedGamma.size(), is(EXPECTED_GAMMA_MATRICES.size())); for (Map.Entry<String, DoubleLabelledMatrix2D> sensitivity : bucketedGamma.entrySet()) { DoubleMatrix2D expectedSensitivities = new DoubleMatrix2D(EXPECTED_GAMMA_MATRICES.get(sensitivity.getKey()).getData()); assertThat(sensitivity.getValue().getXKeys().length, is(expectedSensitivities.getNumberOfColumns())); assertThat(sensitivity.getValue().getYKeys().length, is(expectedSensitivities.getNumberOfRows())); for (int i = 0; i < expectedSensitivities.getNumberOfColumns(); i++) { for (int j = 0; j < expectedSensitivities.getNumberOfRows(); j++) { assertThat(expectedSensitivities.getData()[i][j], is(closeTo(sensitivity.getValue().getValues()[i][j], STD_TOLERANCE_PV))); } } } } private FRASecurity createSingleFra() { return new FRASecurity(Currency.USD, ExternalSchemes.financialRegionId("US"), STD_ACCRUAL_START_DATE, STD_ACCRUAL_END_DATE, 0.0125, -10000000, InterestRateMockSources.getLiborIndexId(), STD_REFERENCE_DATE); } private ForwardRateAgreementSecurity createSingleForwardRateAgreement() { return new ForwardRateAgreementSecurity( Currency.USD, InterestRateMockSources.getLiborIndexId(), SimpleFrequency.QUARTERLY, STD_ACCRUAL_START_DATE.toLocalDate(), STD_ACCRUAL_END_DATE.toLocalDate(), 0.0125, -10000000, DayCountFactory.of("30/360"), BusinessDayConventionFactory.of("Modified Following"), Collections.singleton(ExternalSchemes.financialRegionId("US")), Collections.singleton(ExternalSchemes.financialRegionId("US")), 2); } private ForwardRateAgreementTrade getTrade(ForwardRateAgreementSecurity security) { Trade trade = new SimpleTrade(security, BigDecimal.ONE, new SimpleCounterparty(ExternalId.of(Counterparty.DEFAULT_SCHEME, "CPARTY")), LocalDate.now(), OffsetTime.now()); return new ForwardRateAgreementTrade(trade); } }