/** * Copyright (C) 2015 - 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 java.util.LinkedHashMap; import org.testng.annotations.Test; import org.threeten.bp.LocalDate; import org.threeten.bp.Period; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.instrument.NotionalProvider; import com.opengamma.analytics.financial.instrument.annuity.AdjustedDateParameters; import com.opengamma.analytics.financial.instrument.annuity.AnnuityCouponFixedDefinition; import com.opengamma.analytics.financial.instrument.annuity.AnnuityCouponIborDefinition; import com.opengamma.analytics.financial.instrument.annuity.AnnuityDefinition; import com.opengamma.analytics.financial.instrument.annuity.DateRelativeTo; import com.opengamma.analytics.financial.instrument.annuity.FixedAnnuityDefinitionBuilder; import com.opengamma.analytics.financial.instrument.annuity.FloatingAnnuityDefinitionBuilder; import com.opengamma.analytics.financial.instrument.annuity.OffsetAdjustedDateParameters; import com.opengamma.analytics.financial.instrument.annuity.OffsetType; import com.opengamma.analytics.financial.instrument.future.SwapFuturesPriceDeliverableSecurityDefinition; import com.opengamma.analytics.financial.instrument.future.SwapFuturesPriceDeliverableTransactionDefinition; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.instrument.index.IndexIborMaster; import com.opengamma.analytics.financial.instrument.payment.CouponFixedDefinition; import com.opengamma.analytics.financial.instrument.payment.CouponIborDefinition; import com.opengamma.analytics.financial.instrument.payment.PaymentDefinition; import com.opengamma.analytics.financial.instrument.swap.SwapFixedIborDefinition; import com.opengamma.analytics.financial.interestrate.future.calculator.FuturesPriceMulticurveCalculator; import com.opengamma.analytics.financial.interestrate.future.derivative.SwapFuturesPriceDeliverableTransaction; import com.opengamma.analytics.financial.model.interestrate.curve.YieldCurve; import com.opengamma.analytics.financial.provider.calculator.discounting.PV01CurveParametersCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueCurveSensitivityDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator; 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.MultipleCurrencyParameterSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator; import com.opengamma.analytics.financial.util.AssertSensitivityObjects; import com.opengamma.analytics.math.curve.InterpolatedDoublesCurve; import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolator; import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory; import com.opengamma.analytics.math.interpolation.Interpolator1DFactory; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.util.amount.ReferenceAmount; import com.opengamma.financial.convention.businessday.BusinessDayConventions; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.financial.convention.calendar.MondayToFridayCalendar; import com.opengamma.financial.convention.daycount.DayCount; import com.opengamma.financial.convention.daycount.DayCounts; import com.opengamma.financial.convention.rolldate.RollConvention; import com.opengamma.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.time.DateUtils; import com.opengamma.util.tuple.ObjectsPair; import com.opengamma.util.tuple.Pair; import com.opengamma.util.tuple.Pairs; /** * */ public class SwapFuturesPriceDeliverableTransactionDiscountingMethodE2ETest { private static final IndexIborMaster INDEX_MASTER = IndexIborMaster.getInstance(); private static final Calendar CALENDAR_EUR = new MondayToFridayCalendar("EUR"); private static final Calendar CALENDAR_GBP = new MondayToFridayCalendar("GBP"); private static final Calendar CALENDAR_USD = new MondayToFridayCalendar("USD"); private static final Currency EUR = Currency.EUR; private static final Currency GBP = Currency.GBP; private static final Currency USD = Currency.USD; private static final String DSC_CURVE_NAME_EUR = "EURDSFDisc-Definition"; private static final String DSC_CURVE_NAME_GBP = "GBPDSFDisc-Definition"; private static final String DSC_CURVE_NAME_USD = "USDDSFDisc-Definition"; private static final String FWD_CURVE_NAME_EUR = "EURDSFIndex-Definition"; private static final String FWD_CURVE_NAME_GBP = "GBPDSFIndex-Definition"; private static final String FWD_CURVE_NAME_USD = "USDDSFIndex-Definition"; private static final IborIndex INDEX_EUR = INDEX_MASTER.getIndex(IndexIborMaster.EURIBOR6M); private static final IborIndex INDEX_GBP = INDEX_MASTER.getIndex(IndexIborMaster.GBPLIBOR6M); private static final IborIndex INDEX_USD = INDEX_MASTER.getIndex(IndexIborMaster.USDLIBOR3M); /* multi-curves */ private static final CombinedInterpolatorExtrapolator INTERPOLATOR = CombinedInterpolatorExtrapolatorFactory .getInterpolator(Interpolator1DFactory.LINEAR, Interpolator1DFactory.FLAT_EXTRAPOLATOR, Interpolator1DFactory.LINEAR_EXTRAPOLATOR); private static final MulticurveProviderDiscount MULTI_CURVE_EUR = new MulticurveProviderDiscount(); static { double[] time1 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.038356164383561646, 0.057534246575342465, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.3315068493150685, 0.41643835616438357, 0.4986301369863014, 0.5808219178082191, 0.6657534246575343, 0.7479452054794521, 0.8328767123287671, 0.915068493150685, 1.0, 1.2493150684931507, 1.4986301369863013, 1.747945205479452, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate1 = new double[] {0.001520831, 0.001686041, 0.001780783, 0.001724785, 0.001656764, 0.001514997, 0.001409537, 0.001308517, 0.001278126, 0.001203197, 0.001162491, 0.001129328, 0.001111826, 0.001070508, 0.001098017, 0.001083745, 0.001104411, 0.001161028, 0.0012405, 0.001416104, 0.002709918, 0.004619998, 0.006737195, 0.008906654, 0.010991985, 0.01295629, 0.014749177, 0.016368837, 0.019106592, 0.022002805, 0.024189871, 0.024885653, 0.025030866, 0.025014315, 0.02518553, 0.025169289, 0.025275248 }; InterpolatedDoublesCurve interpolatedCurve1 = InterpolatedDoublesCurve.from(time1, rate1, INTERPOLATOR, DSC_CURVE_NAME_EUR); YieldCurve yieldCurve1 = YieldCurve.from(interpolatedCurve1); MULTI_CURVE_EUR.setCurve(EUR, yieldCurve1); double[] time2 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.4986301369863014, 0.7479452054794521, 1.0, 1.4986301369863013, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate2 = new double[] {0.001047686, 0.001618447, 0.002203446, 0.00231025, 0.002420615, 0.002498383, 0.002491481, 0.00252944, 0.002705515, 0.004412506, 0.005898884, 0.008002973, 0.010199302, 0.012357847, 0.01437717, 0.01622519, 0.017901075, 0.01939867, 0.021848319, 0.024328134, 0.025990946, 0.026347234, 0.026269751, 0.026279792, 0.026332547, 0.026339695, 0.02636908 }; InterpolatedDoublesCurve interpolatedCurve2 = InterpolatedDoublesCurve.from(time2, rate2, INTERPOLATOR, FWD_CURVE_NAME_EUR); YieldCurve yieldCurve2 = YieldCurve.from(interpolatedCurve2); MULTI_CURVE_EUR.setCurve(INDEX_EUR, yieldCurve2); } private static final MulticurveProviderDiscount MULTI_CURVE_GBP = new MulticurveProviderDiscount(); static { double[] time1 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.038356164383561646, 0.057534246575342465, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.3315068493150685, 0.41643835616438357, 0.4986301369863014, 0.5808219178082191, 0.6657534246575343, 0.7479452054794521, 0.8328767123287671, 0.915068493150685, 1.0, 1.2493150684931507, 1.4986301369863013, 1.747945205479452, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate1 = new double[] {0.004314975, 0.004232328, 0.004234656, 0.004224652, 0.004214515, 0.004213025, 0.004227271, 0.004237123, 0.004240462, 0.004257812, 0.004307273, 0.004374733, 0.004446931, 0.004560015, 0.004669298, 0.004792498, 0.005293175, 0.005908394, 0.006614075, 0.007400271, 0.01084908, 0.014103243, 0.016838812, 0.019066765, 0.020958033, 0.022607147, 0.024051441, 0.025266833, 0.02722904, 0.029292804, 0.031089389, 0.031738138, 0.031882506, 0.031460508, 0.031223231, 0.030944059, 0.031049522 }; InterpolatedDoublesCurve interpolatedCurve1 = InterpolatedDoublesCurve.from(time1, rate1, INTERPOLATOR, DSC_CURVE_NAME_GBP); YieldCurve yieldCurve1 = YieldCurve.from(interpolatedCurve1); MULTI_CURVE_GBP.setCurve(GBP, yieldCurve1); double[] time2 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.4986301369863014, 0.7479452054794521, 1.0, 1.4986301369863013, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate2 = new double[] {0.00462497, 0.00467479, 0.004830131, 0.004920495, 0.00501387, 0.005242587, 0.005564089, 0.006060153, 0.007416189, 0.009985379, 0.013820317, 0.017361736, 0.020314939, 0.022737604, 0.024759126, 0.026500577, 0.027982762, 0.029235558, 0.031154631, 0.032956585, 0.034131747, 0.034304467, 0.034116588, 0.033723836, 0.033294286, 0.033041469, 0.033038905 }; InterpolatedDoublesCurve interpolatedCurve2 = InterpolatedDoublesCurve.from(time2, rate2, INTERPOLATOR, FWD_CURVE_NAME_GBP); YieldCurve yieldCurve2 = YieldCurve.from(interpolatedCurve2); MULTI_CURVE_GBP.setCurve(INDEX_GBP, yieldCurve2); } private static final MulticurveProviderDiscount MULTI_CURVE_USD = new MulticurveProviderDiscount(); static { double[] time1 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.038356164383561646, 0.057534246575342465, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.3315068493150685, 0.41643835616438357, 0.4986301369863014, 0.5808219178082191, 0.6657534246575343, 0.7479452054794521, 0.8328767123287671, 0.915068493150685, 1.0, 1.2493150684931507, 1.4986301369863013, 1.747945205479452, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate1 = new double[] {6.08333E-4, 6.67474E-4, 7.01688E-4, 7.1555E-4, 7.07676E-4, 7.46728E-4, 7.57005E-4, 7.67452E-4, 7.77672E-4, 7.98007E-4, 8.08362E-4, 8.23328E-4, 8.52634E-4, 8.74259E-4, 9.06998E-4, 9.48031E-4, 0.001204219, 0.00146341, 0.001985715, 0.002516715, 0.00592515, 0.009970836, 0.013883528, 0.017349819, 0.020245655, 0.022683101, 0.024764926, 0.02648729, 0.029289453, 0.032052003, 0.034523481, 0.035541588, 0.035910913, 0.035828342, 0.035832452, 0.035395082, 0.034987264 }; InterpolatedDoublesCurve interpolatedCurve1 = InterpolatedDoublesCurve.from(time1, rate1, INTERPOLATOR, DSC_CURVE_NAME_USD); YieldCurve yieldCurve1 = YieldCurve.from(interpolatedCurve1); MULTI_CURVE_USD.setCurve(USD, yieldCurve1); double[] time2 = new double[] {0.0027397260273972603, 0.019178082191780823, 0.0821917808219178, 0.1643835616438356, 0.2493150684931507, 0.4986301369863014, 0.7479452054794521, 1.0, 1.4986301369863013, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0 }; double[] rate2 = new double[] {8.67888E-4, 0.001050381, 0.0015198, 0.001732796, 0.001952891, 0.002253123, 0.002378392, 0.002540154, 0.003185149, 0.004375999, 0.008068901, 0.012401796, 0.016506039, 0.020075813, 0.023076569, 0.025560429, 0.027689546, 0.02945934, 0.032294993, 0.035060511, 0.037481639, 0.038446592, 0.038769311, 0.03867287, 0.038672132, 0.038199935, 0.037758216 }; InterpolatedDoublesCurve interpolatedCurve2 = InterpolatedDoublesCurve.from(time2, rate2, INTERPOLATOR, FWD_CURVE_NAME_USD); YieldCurve yieldCurve2 = YieldCurve.from(interpolatedCurve2); MULTI_CURVE_USD.setCurve(INDEX_USD, yieldCurve2); } /* common setup */ private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2014, 2, 17, 0, 0); private static final long QUANTITY = 1; private static final double TRADE_PRICE = 0.0; private static final double LASTMARG_PRICE = 1.0; private static final ZonedDateTime TRADE_DATE = DateUtils.getUTCDate(2008, 12, 26, 1, 0); private static final double NOTIONAL = 100000.0; private static final NotionalProvider NOTIONAL_PROV = new NotionalProvider() { @Override public double getAmount(final LocalDate date) { return 1.0; } }; /* EUR */ private static final SwapFuturesPriceDeliverableTransaction TRANSACTION_EUR; static { boolean payer = true; LocalDate startDate = LocalDate.of(2014, 6, 18); LocalDate endDate = LocalDate.of(2019, 6, 18); DayCount fixedDc = DayCounts.THIRTY_360; AdjustedDateParameters accrualPeriodParameters = new AdjustedDateParameters(CALENDAR_EUR, INDEX_EUR.getBusinessDayConvention()); OffsetAdjustedDateParameters paymentDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_EUR, INDEX_EUR.getBusinessDayConvention()); OffsetAdjustedDateParameters resetDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_EUR, INDEX_EUR.getBusinessDayConvention()); OffsetAdjustedDateParameters fixingDateParameters = new OffsetAdjustedDateParameters(-2, OffsetType.BUSINESS, CALENDAR_EUR, BusinessDayConventions.PRECEDING); double rate = 0.015; AnnuityDefinition<?> fixedLeg = new FixedAnnuityDefinitionBuilder().payer(!payer).currency(EUR) .notional(NOTIONAL_PROV).startDate(startDate).endDate(endDate).dayCount(fixedDc) .rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).accrualPeriodFrequency(Period.ofYears(1)). accrualPeriodParameters(accrualPeriodParameters).paymentDateRelativeTo(DateRelativeTo.END). paymentDateAdjustmentParameters(paymentDateParameters).rate(rate).build(); AnnuityDefinition<? extends PaymentDefinition> iborLeg = new FloatingAnnuityDefinitionBuilder().payer(payer). currency(EUR).notional(NOTIONAL_PROV).startDate(startDate).endDate(endDate).dayCount(INDEX_EUR.getDayCount()) .rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).accrualPeriodFrequency(Period.ofMonths(6)). accrualPeriodParameters(accrualPeriodParameters).paymentDateRelativeTo(DateRelativeTo.END). paymentDateAdjustmentParameters(paymentDateParameters).index(INDEX_EUR) .resetDateAdjustmentParameters(resetDateParameters).resetRelativeTo(DateRelativeTo.START). fixingDateAdjustmentParameters(fixingDateParameters).build(); SwapFixedIborDefinition swapDefinition = new SwapFixedIborDefinition(toFixedLeg(fixedLeg), toIborLeg(iborLeg)); ZonedDateTime lastTradingDate = DateUtils.getUTCDate(2014, 6, 16, 0, 0); SwapFuturesPriceDeliverableSecurityDefinition underlyingSwapFuture = new SwapFuturesPriceDeliverableSecurityDefinition( lastTradingDate, swapDefinition, NOTIONAL); SwapFuturesPriceDeliverableTransactionDefinition swapFutureTransaction = new SwapFuturesPriceDeliverableTransactionDefinition( underlyingSwapFuture, QUANTITY, TRADE_DATE, TRADE_PRICE); TRANSACTION_EUR = swapFutureTransaction.toDerivative(REFERENCE_DATE, LASTMARG_PRICE); } /* GBP */ private static final SwapFuturesPriceDeliverableTransaction TRANSACTION_GBP; static { boolean payer = true; LocalDate startDate = LocalDate.of(2014, 6, 18); LocalDate endDate = LocalDate.of(2024, 6, 18); DayCount fixedDc = DayCounts.ACT_360; AdjustedDateParameters accrualPeriodParameters = new AdjustedDateParameters(CALENDAR_GBP, INDEX_GBP.getBusinessDayConvention()); OffsetAdjustedDateParameters paymentDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_GBP, INDEX_GBP.getBusinessDayConvention()); OffsetAdjustedDateParameters resetDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_GBP, INDEX_GBP.getBusinessDayConvention()); OffsetAdjustedDateParameters fixingDateParameters = new OffsetAdjustedDateParameters(-2, OffsetType.BUSINESS, CALENDAR_GBP, BusinessDayConventions.PRECEDING); double rate = 0.03; AnnuityDefinition<?> fixedLeg = new FixedAnnuityDefinitionBuilder().payer(!payer).currency(GBP). notional(NOTIONAL_PROV).startDate(startDate).endDate(endDate).dayCount(fixedDc). rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).accrualPeriodFrequency(Period.ofMonths(6)). accrualPeriodParameters(accrualPeriodParameters).paymentDateRelativeTo(DateRelativeTo.END). paymentDateAdjustmentParameters(paymentDateParameters).rate(rate).build(); AnnuityDefinition<? extends PaymentDefinition> iborLeg = new FloatingAnnuityDefinitionBuilder(). payer(payer).currency(GBP).notional(NOTIONAL_PROV).startDate(startDate). endDate(endDate).dayCount(INDEX_GBP.getDayCount()).rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)) .accrualPeriodFrequency(Period.ofMonths(6)).accrualPeriodParameters(accrualPeriodParameters). paymentDateRelativeTo(DateRelativeTo.END).paymentDateAdjustmentParameters(paymentDateParameters). index(INDEX_GBP).resetDateAdjustmentParameters(resetDateParameters).resetRelativeTo(DateRelativeTo.START). fixingDateAdjustmentParameters(fixingDateParameters).build(); SwapFixedIborDefinition swapDefinition = new SwapFixedIborDefinition(toFixedLeg(fixedLeg), toIborLeg(iborLeg)); ZonedDateTime lastTradingDate = DateUtils.getUTCDate(2014, 6, 18, 0, 0); SwapFuturesPriceDeliverableSecurityDefinition underlyingSwapFuture = new SwapFuturesPriceDeliverableSecurityDefinition( lastTradingDate, swapDefinition, NOTIONAL); SwapFuturesPriceDeliverableTransactionDefinition swapFutureTransaction = new SwapFuturesPriceDeliverableTransactionDefinition( underlyingSwapFuture, QUANTITY, TRADE_DATE, TRADE_PRICE); TRANSACTION_GBP = swapFutureTransaction.toDerivative(REFERENCE_DATE, LASTMARG_PRICE); } /* USD */ private static final SwapFuturesPriceDeliverableTransaction TRANSACTION_USD; static { boolean payer = true; LocalDate startDate = LocalDate.of(2014, 6, 18); LocalDate endDate = LocalDate.of(2044, 6, 20); DayCount fixedDc = DayCounts.THIRTY_U_360; AdjustedDateParameters accrualPeriodParameters = new AdjustedDateParameters(CALENDAR_USD, INDEX_USD.getBusinessDayConvention()); OffsetAdjustedDateParameters paymentDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_USD, INDEX_USD.getBusinessDayConvention()); double rate = 0.0375; AnnuityDefinition<?> fixedLeg = new FixedAnnuityDefinitionBuilder().payer(!payer).currency(USD) .notional(NOTIONAL_PROV).startDate(startDate).endDate(endDate).dayCount(fixedDc) .rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).accrualPeriodFrequency(Period.ofMonths(6)). accrualPeriodParameters(accrualPeriodParameters).paymentDateRelativeTo(DateRelativeTo.END). paymentDateAdjustmentParameters(paymentDateParameters).rate(rate).build(); OffsetAdjustedDateParameters resetDateParameters = new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, CALENDAR_USD, INDEX_USD.getBusinessDayConvention()); OffsetAdjustedDateParameters fixingDateParameters = new OffsetAdjustedDateParameters(-2, OffsetType.BUSINESS, CALENDAR_USD, BusinessDayConventions.PRECEDING); AnnuityDefinition<? extends PaymentDefinition> iborLeg = new FloatingAnnuityDefinitionBuilder().payer(payer) .currency(USD).notional(NOTIONAL_PROV).startDate(startDate).endDate(endDate).dayCount(INDEX_USD.getDayCount()). rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).accrualPeriodFrequency(Period.ofMonths(3)). accrualPeriodParameters(accrualPeriodParameters).paymentDateRelativeTo(DateRelativeTo.END) .paymentDateAdjustmentParameters(paymentDateParameters).index(INDEX_USD) .resetDateAdjustmentParameters(resetDateParameters).resetRelativeTo(DateRelativeTo.START). fixingDateAdjustmentParameters(fixingDateParameters).build(); SwapFixedIborDefinition swapDefinition = new SwapFixedIborDefinition(toFixedLeg(fixedLeg), toIborLeg(iborLeg)); ZonedDateTime lastTradingDate = DateUtils.getUTCDate(2014, 6, 16, 0, 0); SwapFuturesPriceDeliverableSecurityDefinition underlyingSwapFuture = new SwapFuturesPriceDeliverableSecurityDefinition( lastTradingDate, swapDefinition, NOTIONAL); SwapFuturesPriceDeliverableTransactionDefinition swapFutureTransaction = new SwapFuturesPriceDeliverableTransactionDefinition( underlyingSwapFuture, QUANTITY, TRADE_DATE, TRADE_PRICE); TRANSACTION_USD = swapFutureTransaction.toDerivative(REFERENCE_DATE, LASTMARG_PRICE); } private static final FuturesPriceMulticurveCalculator FPMC = FuturesPriceMulticurveCalculator.getInstance(); private static final PresentValueDiscountingCalculator PVC = PresentValueDiscountingCalculator.getInstance(); private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator .getInstance(); private static final PV01CurveParametersCalculator<ParameterProviderInterface> PV01C = new PV01CurveParametersCalculator<>( PVCSDC); private static final ParameterSensitivityParameterCalculator<ParameterProviderInterface> PVSC = new ParameterSensitivityParameterCalculator<>( PVCSDC); private static final double BASIS_POINT = 1.0E-4; private static final double HUNDRED = 100.0; private static final double TOL = 1.0e-12; /** * EUR Test */ @Test public void EURTest() { double price = TRANSACTION_EUR.accept(FPMC, MULTI_CURVE_EUR) * HUNDRED; MultipleCurrencyAmount pv = TRANSACTION_EUR.accept(PVC, MULTI_CURVE_EUR); ReferenceAmount<Pair<String, Currency>> pv01 = TRANSACTION_EUR.accept(PV01C, MULTI_CURVE_EUR); MultipleCurrencyParameterSensitivity bucketedPv01 = PVSC.calculateSensitivity(TRANSACTION_EUR, MULTI_CURVE_EUR) .multipliedBy(BASIS_POINT); double[] fwd = new double[] {0.0, 0.0, 0.0, 0.0, 2.224004998051028, 1.0937729498611615, -0.0024340263653379224, 0.004105708454739943, 0.004334541835107666, -0.052013939841404504, -0.20521668056167838, -0.47863759268134165, -35.038664488799554, -17.175207328536573, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; double[] dsc = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05763679246195801, 0.0, 0.0, 0.0, 0.0, 0.0, 0.010619418938792513, 0.0, 0.0, -0.12090902010823751, -0.059463452512248084, 0.04277998877591835, -0.12089376949471899, -0.12710288992082436, 0.026209100483393446, 0.14404291506708877, -0.07252746527971765, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivityM = new LinkedHashMap<>(); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_EUR.getName(INDEX_EUR), EUR), new DoubleMatrix1D(fwd)); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_EUR.getName(EUR), EUR), new DoubleMatrix1D(dsc)); MultipleCurrencyParameterSensitivity bucketedPv01Exp = new MultipleCurrencyParameterSensitivity(sensitivityM); assertRelative("EURTest", 101.73863051641443, price, TOL); assertRelative("EURTest", 1738.6305164144287, pv.getAmount(EUR), TOL); assertRelative("EURTest", -49.62595585858386, pv01.getMap().get(Pairs.of(MULTI_CURVE_EUR.getName(INDEX_EUR), EUR)), TOL); assertRelative("EURTest", -0.21960838158859544, pv01.getMap().get(Pairs.of(MULTI_CURVE_EUR.getName(EUR), EUR)), TOL); AssertSensitivityObjects.assertEquals("EURTest", bucketedPv01Exp, bucketedPv01, TOL); } /** * GBP Test */ @Test public void GBPTest() { double price = TRANSACTION_GBP.accept(FPMC, MULTI_CURVE_GBP) * HUNDRED; MultipleCurrencyAmount pv = TRANSACTION_GBP.accept(PVC, MULTI_CURVE_GBP); ReferenceAmount<Pair<String, Currency>> pv01 = TRANSACTION_GBP.accept(PV01C, MULTI_CURVE_GBP); MultipleCurrencyParameterSensitivity bucketedPv01 = PVSC.calculateSensitivity(TRANSACTION_GBP, MULTI_CURVE_GBP) .multipliedBy(BASIS_POINT); double[] fwd = new double[] {0.0, 0.0, 0.0, 0.0, 2.2237292670953432, 1.0936373444731198, -0.011648945266015653, -0.016263558184294744, -0.05230461397269246, -0.20921501881377483, -0.5716084841592151, -0.9616739944033951, -1.3163009548242264, -1.6684009963556077, -2.004684213156582, -2.334942500895381, -2.625361794468877, -69.19450857676361, -13.4912151440719, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; double[] dsc = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01740893660254634, 0.0, 0.0, 0.0, 0.0, 0.0, -0.10102693296666299, 0.0, 0.0, -0.09458842302982506, -0.04651889657204522, -0.09324673654613515, -0.15268987752566845, -0.19604298614940063, -0.038623713891763646, 0.12773776691358166, 0.28481019838588767, 0.44090350106077525, 0.6015709062808676, 0.7272592335788854, 0.7948794223061727, 0.06522225444788256, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivityM = new LinkedHashMap<>(); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_GBP.getName(INDEX_GBP), GBP), new DoubleMatrix1D(fwd)); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_GBP.getName(GBP), GBP), new DoubleMatrix1D(dsc)); MultipleCurrencyParameterSensitivity bucketedPv01Exp = new MultipleCurrencyParameterSensitivity(sensitivityM); assertRelative("GBPTest", 100.52514560825863, price, TOL); assertRelative("GBPTest", 525.1456082586228, pv.getAmount(GBP), TOL); assertRelative("GBPTest", -91.14076218376711, pv01.getMap().get(Pairs.of(MULTI_CURVE_GBP.getName(INDEX_GBP), GBP)), TOL); assertRelative("GBPTest", 2.337054652895098, pv01.getMap().get(Pairs.of(MULTI_CURVE_GBP.getName(GBP), GBP)), TOL); AssertSensitivityObjects.assertEquals("GBPTest", bucketedPv01Exp, bucketedPv01, TOL); } /** * USD Test */ @Test public void USDTest() { double price = TRANSACTION_USD.accept(FPMC, MULTI_CURVE_USD) * HUNDRED; MultipleCurrencyAmount pv = TRANSACTION_USD.accept(PVC, MULTI_CURVE_USD); ReferenceAmount<Pair<String, Currency>> pv01 = TRANSACTION_USD.accept(PV01C, MULTI_CURVE_USD); MultipleCurrencyParameterSensitivity bucketedPv01 = PVSC.calculateSensitivity(TRANSACTION_USD, MULTI_CURVE_USD) .multipliedBy(BASIS_POINT); double[] fwd = new double[] {0.0, 0.0, 0.0, 0.0, 2.2341729563375754, 1.1247207962261387, -0.21731877495047303, 0.24729110752094968, -0.04737275895735693, -0.1957045849596627, -0.4941071910486, -0.9690918913056125, -1.483785773436915, -1.941095916164625, -2.349760064001363, -2.720168442370897, -3.0261624004197403, -5.210166215922626, -8.877477030785501, -16.124887606936415, -20.676096470872203, -20.061496843580134, -106.67209531976185, -6.994907297508757, 0.0, 0.0, 0.0 }; double[] dsc = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.003444023821918926, -4.217549300573078E-5, 0.0, 0.0033636138437441506, 6.468488161046462E-4, 0.0, -0.13352862023619286, -0.020542864651721875, 0.005874469297784665, -0.14490518196124216, -0.07409506555979266, -0.18471836014345192, -0.3267225760840528, -0.5247792849123576, -0.3408063903707827, -0.10909334281992829, 0.1082151875601287, 0.2754266953339004, 0.4315221301355966, 0.5604032237595145, 0.984121106233526, 1.887198932994591, 2.9637167063138534, 3.2811449487467224, 2.1657999502129868, 0.45916736327544677, -0.04468623577721326, 0.0, 0.0, 0.0 }; LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivityM = new LinkedHashMap<>(); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_USD.getName(INDEX_USD), USD), new DoubleMatrix1D(fwd)); sensitivityM.put(ObjectsPair.of(MULTI_CURVE_USD.getName(USD), USD), new DoubleMatrix1D(dsc)); MultipleCurrencyParameterSensitivity bucketedPv01Exp = new MultipleCurrencyParameterSensitivity(sensitivityM); assertRelative("USDTest", 99.91455744642417, price, TOL); assertRelative("USDTest", -85.44255357583461, pv.getAmount(USD), TOL); assertRelative("USDTest", -194.45550972289809, pv01.getMap().get(Pairs.of(MULTI_CURVE_USD.getName(INDEX_USD), USD)), TOL); assertRelative("USDTest", 11.21923705469224, pv01.getMap().get(Pairs.of(MULTI_CURVE_USD.getName(USD), USD)), TOL); AssertSensitivityObjects.assertEquals("USDTest", bucketedPv01Exp, bucketedPv01, TOL); } static private AnnuityCouponFixedDefinition toFixedLeg(final AnnuityDefinition<?> leg) { return new AnnuityCouponFixedDefinition((CouponFixedDefinition[]) leg.getPayments(), leg.getCalendar()); } static private AnnuityCouponIborDefinition toIborLeg(final AnnuityDefinition<?> leg) { return new AnnuityCouponIborDefinition((CouponIborDefinition[]) leg.getPayments(), ((CouponIborDefinition) leg.getNthPayment(0)).getIndex(), leg.getCalendar()); } private void assertRelative(String message, double expected, double obtained, double relativeTol) { double ref = Math.max(Math.abs(expected), 1.0); assertEquals(message, expected, obtained, ref * relativeTol); } }