/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.payments.provider; import static org.testng.AssertJUnit.assertEquals; import org.testng.annotations.Test; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.instrument.index.IborIndex; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborAverageFixingDates; 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.MulticurveProviderDiscountDataSets; 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.multicurve.ParameterSensitivityMulticurveDiscountInterpolatedFDCalculator; import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator; import com.opengamma.analytics.financial.schedule.ScheduleCalculator; import com.opengamma.analytics.financial.util.AssertSensitivityObjects; import com.opengamma.analytics.util.time.TimeCalculator; 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.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; /** * */ @Test(groups = TestGroup.UNIT) public class CouponIborAverageFixingDatesDiscountingMethodTest { private static final MulticurveProviderDiscount MULTICURVES = MulticurveProviderDiscountDataSets.createMulticurveEurUsd(); private static final IborIndex[] IBOR_INDEXES = MulticurveProviderDiscountDataSets.getIndexesIborMulticurveEurUsd(); private static final Calendar CALENDAR = new MondayToFridayCalendar("A"); private static final Currency CUR = Currency.EUR; private static final IborIndex INDEX = IBOR_INDEXES[0]; private static final int NUM_OBS = 6; private static final ZonedDateTime ACCRUAL_START_DATE = DateUtils.getUTCDate(2011, 1, 6); private static final ZonedDateTime ACCRUAL_END_DATE = DateUtils.getUTCDate(2011, 7, 4); private static final ZonedDateTime PAYMENT_DATE = DateUtils.getUTCDate(2011, 7, 6); private static final ZonedDateTime[] FIXING_DATES = new ZonedDateTime[NUM_OBS]; private static final double[] WEIGHTS = new double[NUM_OBS]; static { for (int i = 0; i < NUM_OBS; ++i) { FIXING_DATES[i] = DateUtils.getUTCDate(2011, i + 1, 3); WEIGHTS[i] = 2. * (NUM_OBS - i) / NUM_OBS / (NUM_OBS + 1.); } } private static final DayCount DAY_COUNT_PAYMENT = DayCounts.ACT_365; private static final double ACCRUAL_FACTOR = DAY_COUNT_PAYMENT.getDayCountFraction(ACCRUAL_START_DATE, ACCRUAL_END_DATE); private static final double NOTIONAL = 1000000; private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2010, 12, 27); private static ZonedDateTime[] EXP_START_DATES = new ZonedDateTime[NUM_OBS]; private static ZonedDateTime[] EXP_END_DATES = new ZonedDateTime[NUM_OBS]; static { for (int i = 0; i < NUM_OBS; ++i) { EXP_START_DATES[i] = ScheduleCalculator.getAdjustedDate(FIXING_DATES[i], INDEX.getSpotLag(), CALENDAR); EXP_END_DATES[i] = ScheduleCalculator.getAdjustedDate(EXP_START_DATES[i], INDEX.getTenor(), INDEX.getBusinessDayConvention(), CALENDAR, INDEX.isEndOfMonth()); } } private static final double PAYMENT_TIME = TimeCalculator.getTimeBetween(REFERENCE_DATE, PAYMENT_DATE); private static final double[] FIXING_TIMES = TimeCalculator.getTimeBetween(REFERENCE_DATE, FIXING_DATES); private static final double[] FIXING_PERIOD_START_TIMES = TimeCalculator.getTimeBetween(REFERENCE_DATE, EXP_START_DATES); private static final double[] FIXING_PERIOD_END_TIMES = TimeCalculator.getTimeBetween(REFERENCE_DATE, EXP_END_DATES); private static final double[] FIX_ACC_FACTORS = new double[NUM_OBS]; static { for (int i = 0; i < NUM_OBS; ++i) { FIX_ACC_FACTORS[i] = INDEX.getDayCount().getDayCountFraction(EXP_START_DATES[i], EXP_END_DATES[i]); } } private static final double AMOUNT_ACC = 0.05; private static final CouponIborAverageFixingDates DER1 = new CouponIborAverageFixingDates(CUR, PAYMENT_TIME, ACCRUAL_FACTOR, NOTIONAL, INDEX, FIXING_TIMES, WEIGHTS, FIXING_PERIOD_START_TIMES, FIXING_PERIOD_END_TIMES, FIX_ACC_FACTORS, AMOUNT_ACC); private static final CouponIborAverageFixingDates DER2 = new CouponIborAverageFixingDates(CUR, PAYMENT_TIME, ACCRUAL_FACTOR, NOTIONAL, INDEX, FIXING_TIMES, WEIGHTS, FIXING_PERIOD_START_TIMES, FIXING_PERIOD_END_TIMES, FIX_ACC_FACTORS, 0.0); private static final CouponIborAverageFixingDatesDiscountingMethod METHOD = CouponIborAverageFixingDatesDiscountingMethod.getInstance(); private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance(); private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator.getInstance(); private static final ParameterSensitivityParameterCalculator<ParameterProviderInterface> PSC = new ParameterSensitivityParameterCalculator<>(PVCSDC); private static final double SHIFT = 1.0E-7; private static final ParameterSensitivityMulticurveDiscountInterpolatedFDCalculator PSC_DSC_FD = new ParameterSensitivityMulticurveDiscountInterpolatedFDCalculator(PVDC, SHIFT); private static final double EPS = 1.0e-10; private static final double TOLERANCE_PV_DELTA = 1.0; /** * */ @Test public void presentValueTest() { final MultipleCurrencyAmount pvComputed = METHOD.presentValue(DER1, MULTICURVES); double forward = AMOUNT_ACC; for (int i = 0; i < NUM_OBS; ++i) { forward += WEIGHTS[i] * MULTICURVES.getSimplyCompoundForwardRate(INDEX, FIXING_PERIOD_START_TIMES[i], FIXING_PERIOD_END_TIMES[i], FIX_ACC_FACTORS[i]); } final double pvExpected = DER1.getNotional() * MULTICURVES.getDiscountFactor(DER1.getCurrency(), DER1.getPaymentTime()) * DER1.getPaymentYearFraction() * forward; assertEquals(pvExpected, pvComputed.getAmount(DER1.getCurrency()), EPS * pvExpected); final MultipleCurrencyAmount pvWithCalc = PVDC.visitCouponIborAverageFixingDates(DER1, MULTICURVES); assertEquals(pvWithCalc.getAmount(DER1.getCurrency()), pvComputed.getAmount(DER1.getCurrency()), EPS * pvExpected); } /** * */ @Test public void presentValueNoFixTest() { final MultipleCurrencyAmount pvComputed = METHOD.presentValue(DER2, MULTICURVES); double forward = 0.0; for (int i = 0; i < NUM_OBS; ++i) { forward += WEIGHTS[i] * MULTICURVES.getSimplyCompoundForwardRate(INDEX, FIXING_PERIOD_START_TIMES[i], FIXING_PERIOD_END_TIMES[i], FIX_ACC_FACTORS[i]); } final double pvExpected = DER2.getNotional() * MULTICURVES.getDiscountFactor(DER2.getCurrency(), DER2.getPaymentTime()) * DER2.getPaymentYearFraction() * forward; assertEquals(pvExpected, pvComputed.getAmount(DER2.getCurrency()), EPS * pvExpected); final MultipleCurrencyAmount pvWithCalc = PVDC.visitCouponIborAverageFixingDates(DER2, MULTICURVES); assertEquals(pvWithCalc.getAmount(DER2.getCurrency()), pvComputed.getAmount(DER2.getCurrency()), EPS * pvExpected); } /** * */ @Test public void sensitivityFiniteDifferenceTest() { final MultipleCurrencyParameterSensitivity senseCalc1 = PSC.calculateSensitivity(DER1, MULTICURVES, MULTICURVES.getAllNames()); final MultipleCurrencyParameterSensitivity senseFd1 = PSC_DSC_FD.calculateSensitivity(DER1, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborAverageFixingDatesDiscountingMethod", senseCalc1, senseFd1, TOLERANCE_PV_DELTA); final MultipleCurrencyParameterSensitivity senseCalc2 = PSC.calculateSensitivity(DER2, MULTICURVES, MULTICURVES.getAllNames()); final MultipleCurrencyParameterSensitivity senseFd2 = PSC_DSC_FD.calculateSensitivity(DER2, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborAverageFixingDatesDiscountingMethod", senseCalc2, senseFd2, TOLERANCE_PV_DELTA); } /** * */ @Test public void presentValueMarketSensitivityMethodVsCalculator() { final MultipleCurrencyMulticurveSensitivity pvcsMethod1 = METHOD.presentValueCurveSensitivity(DER1, MULTICURVES); final MultipleCurrencyMulticurveSensitivity pvcsCalculator1 = DER1.accept(PVCSDC, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborAverageFixingDatesDiscountingMethod", pvcsMethod1, pvcsCalculator1, TOLERANCE_PV_DELTA); final MultipleCurrencyMulticurveSensitivity pvcsMethod2 = METHOD.presentValueCurveSensitivity(DER2, MULTICURVES); final MultipleCurrencyMulticurveSensitivity pvcsCalculator2 = DER2.accept(PVCSDC, MULTICURVES); AssertSensitivityObjects.assertEquals("CouponIborAverageFixingDatesDiscountingMethod", pvcsMethod2, pvcsCalculator2, TOLERANCE_PV_DELTA); } }