/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.future.provider; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import java.util.LinkedHashMap; import org.testng.annotations.Test; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.instrument.future.InterestRateFutureSecurityDefinition; import com.opengamma.analytics.financial.instrument.future.InterestRateFutureTransactionDefinition; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.interestrate.datasets.StandardDataSetsMulticurveEUR; import com.opengamma.analytics.financial.interestrate.future.derivative.InterestRateFutureTransaction; import com.opengamma.analytics.financial.provider.calculator.discounting.ParRateDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.ParSpreadMarketQuoteDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueCurveSensitivityDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.generic.MarketQuoteSensitivityBlockCalculator; import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount; import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator; import com.opengamma.analytics.financial.util.AssertSensitivityObjects; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; import com.opengamma.util.tuple.ObjectsPair; import com.opengamma.util.tuple.Pair; /** * Tests the STIR Futures discounting method with standard data. * Swap Desk EUR 1 / pv - bpv01 / OIS-IRS3-IRS6 */ @Test(groups = TestGroup.UNIT) public class STIRFuturesTransactionDiscountingMethodE2ETest { /** Data */ private static final IborIndex[] INDEX_IBOR_LIST = StandardDataSetsMulticurveEUR.indexIborArrayEUROisE3(); private static final IborIndex EUREURIBOR3M = INDEX_IBOR_LIST[0]; private static final Calendar CALENDAR = StandardDataSetsMulticurveEUR.calendarArray()[0]; private static final Currency EUR = EUREURIBOR3M.getCurrency(); private static final ZonedDateTime VALUATION_DATE = DateUtils.getUTCDate(2014, 2, 18); private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_PAIR = StandardDataSetsMulticurveEUR.getCurvesEurOisE3(); private static final MulticurveProviderDiscount MULTICURVE = MULTICURVE_PAIR.getFirst(); private static final CurveBuildingBlockBundle BLOCK = MULTICURVE_PAIR.getSecond(); /** Instruments */ private static final ZonedDateTime LAST_TRADING_DATE = DateUtils.getUTCDate(2014, 12, 15); private static final double NOTIONAL = 1000000.0; // 1m private static final double FUTURE_FACTOR = 0.25; private static final String NAME = "ERZ4"; private static final InterestRateFutureSecurityDefinition ERZ4_SEC_DEFINITION = new InterestRateFutureSecurityDefinition(LAST_TRADING_DATE, EUREURIBOR3M, NOTIONAL, FUTURE_FACTOR, NAME, CALENDAR); private static final long QUANTITY = -125; private static final ZonedDateTime TRADE_DATE = DateUtils.getUTCDate(2013, 5, 7); private static final double TRADE_PRICE = 0.999; private static final InterestRateFutureTransactionDefinition ERZ4_TRA_DEFINITION = new InterestRateFutureTransactionDefinition(ERZ4_SEC_DEFINITION, QUANTITY, TRADE_DATE, TRADE_PRICE); private static final double LAST_MARGIN_PRICE = 0.9973; // Closing on (2014, 2, 18); Using the last fixing before or on valuation date. private static final InterestRateFutureTransaction ERZ4_TRA = ERZ4_TRA_DEFINITION.toDerivative(VALUATION_DATE, LAST_MARGIN_PRICE); /** Calculators */ private static final InterestRateFutureSecurityDiscountingMethod METHOD_STIR = InterestRateFutureSecurityDiscountingMethod.getInstance(); private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance(); private static final ParRateDiscountingCalculator PRDC = ParRateDiscountingCalculator.getInstance(); private static final ParSpreadMarketQuoteDiscountingCalculator PSMQDC = ParSpreadMarketQuoteDiscountingCalculator.getInstance(); private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator.getInstance(); private static final ParameterSensitivityParameterCalculator<ParameterProviderInterface> PSC = new ParameterSensitivityParameterCalculator<>(PVCSDC); private static final MarketQuoteSensitivityBlockCalculator<ParameterProviderInterface> MQSBC = new MarketQuoteSensitivityBlockCalculator<>(PSC); private static final double TOLERANCE_PV = 1.0E-4; private static final double TOLERANCE_PV_DELTA = 1.0E-2; private static final double TOLERANCE_RATE = 1.0E-8; private static final double BP1 = 1.0E-4; /** Test the price with a standard set of data against hard-coded values. */ @Test public void price() { double priceExpected = 0.9973084085494923; double priceComputed = METHOD_STIR.price(ERZ4_TRA.getUnderlyingSecurity(), MULTICURVE); assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: price", priceExpected, priceComputed, TOLERANCE_RATE); } /** Test the present value with a standard set of data against hard-coded values. */ @Test public void presentValue() { MultipleCurrencyAmount pvComputed = ERZ4_TRA.accept(PVDC, MULTICURVE); assertTrue("STIRFuturesTransactionDiscountingMethodE2ETest: present value from standard curves", pvComputed.size() == 1); MultipleCurrencyAmount pvExpected = MultipleCurrencyAmount.of(Currency.EUR, -262.7672); double priceComputed = METHOD_STIR.price(ERZ4_TRA.getUnderlyingSecurity(), MULTICURVE); assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: present value from standard curves", pvExpected.getAmount(EUR), pvComputed.getAmount(EUR), TOLERANCE_PV); double pvDetailedInEUR = (priceComputed - LAST_MARGIN_PRICE) * NOTIONAL * FUTURE_FACTOR * QUANTITY; assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: present value from standard curves", pvDetailedInEUR, pvComputed.getAmount(EUR), TOLERANCE_PV); } /** Test the par rate with a standard set of data against hard-coded values. */ @Test public void parRate() { final double parRate = ERZ4_TRA.accept(PRDC, MULTICURVE); final double parRateExpected = 0.00269159145050768; assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: par rate from standard curves", parRateExpected, parRate, TOLERANCE_RATE); double parRateMethod = METHOD_STIR.parRate(ERZ4_TRA.getUnderlyingSecurity(), MULTICURVE); assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: par rate from standard curves", parRateMethod, parRate, TOLERANCE_RATE); } /** Test the par spread with a standard set of data against hard-coded values. */ @Test public void parSpread() { final double parSpreadComputed = ERZ4_TRA.accept(PSMQDC, MULTICURVE); final double parSpreadExpected = 8.4085E-6; assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: par rate from standard curves", parSpreadExpected, parSpreadComputed, TOLERANCE_RATE); } /** Tests bucketed PV01 with a standard set of data against hard-coded values. */ @Test public void BucketedPV01() { final double[] deltaDsc = {0.0003, 0.0003, 0.0000, 0.0000, 1.7334, 3.0714, 4.6402, -18.8887, -0.9835, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 }; final double[] deltaFwd = {-2398.5241, -2479.7772, -2479.1440, 9422.5946, 912.6277, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000 }; final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivity = new LinkedHashMap<>(); sensitivity.put(ObjectsPair.of(MULTICURVE.getName(EUR), EUR), new DoubleMatrix1D(deltaDsc)); sensitivity.put(ObjectsPair.of(MULTICURVE.getName(EUREURIBOR3M), EUR), new DoubleMatrix1D(deltaFwd)); final MultipleCurrencyParameterSensitivity pvpsExpected = new MultipleCurrencyParameterSensitivity(sensitivity); MultipleCurrencyMulticurveSensitivity pvPointSensi = ERZ4_TRA.accept(PVCSDC, MULTICURVE); MultipleCurrencyParameterSensitivity pvParameterSensi = PSC.pointToParameterSensitivity(pvPointSensi, MULTICURVE).multipliedBy(BP1); MultipleCurrencyParameterSensitivity pvMarketQuoteSensi = MQSBC.fromParameterSensitivity(pvParameterSensi, BLOCK); final MultipleCurrencyParameterSensitivity pvpsComputed = MQSBC.fromInstrument(ERZ4_TRA, MULTICURVE, BLOCK).multipliedBy(BP1); AssertSensitivityObjects.assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: bucketed deltas from standard curves", pvpsExpected, pvpsComputed, TOLERANCE_PV_DELTA); AssertSensitivityObjects.assertEquals("STIRFuturesTransactionDiscountingMethodE2ETest: bucketed deltas from standard curves", pvMarketQuoteSensi, pvpsComputed, TOLERANCE_PV_DELTA); } }