/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.impl.swap; import static com.opengamma.strata.basics.currency.Currency.GBP; import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ISDA; import static java.time.temporal.ChronoUnit.DAYS; import static org.testng.Assert.assertEquals; import java.time.LocalDate; import org.testng.annotations.Test; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.basics.currency.MultiCurrencyAmount; import com.opengamma.strata.basics.currency.Payment; import com.opengamma.strata.basics.date.DayCount; import com.opengamma.strata.basics.date.DayCounts; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.market.curve.ConstantCurve; import com.opengamma.strata.market.curve.Curve; import com.opengamma.strata.market.curve.Curves; import com.opengamma.strata.market.curve.InterpolatedNodalCurve; import com.opengamma.strata.market.curve.interpolator.CurveInterpolator; import com.opengamma.strata.market.curve.interpolator.CurveInterpolators; import com.opengamma.strata.market.explain.ExplainKey; import com.opengamma.strata.market.explain.ExplainMap; import com.opengamma.strata.market.explain.ExplainMapBuilder; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder; import com.opengamma.strata.pricer.DiscountFactors; import com.opengamma.strata.pricer.SimpleDiscountFactors; import com.opengamma.strata.pricer.ZeroRateSensitivity; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.pricer.rate.RatesProvider; import com.opengamma.strata.pricer.rate.SimpleRatesProvider; import com.opengamma.strata.product.swap.KnownAmountSwapPaymentPeriod; /** * Test {@link DiscountingKnownAmountPaymentPeriodPricer} */ @Test public class DiscountingKnownAmountPaymentPeriodPricerTest { private static final DiscountingKnownAmountPaymentPeriodPricer PRICER = DiscountingKnownAmountPaymentPeriodPricer.DEFAULT; private static final LocalDate VAL_DATE = LocalDate.of(2014, 1, 22); private static final DayCount DAY_COUNT = DayCounts.ACT_360; private static final LocalDate DATE_1 = LocalDate.of(2014, 1, 24); private static final LocalDate DATE_2 = LocalDate.of(2014, 4, 25); private static final LocalDate DATE_2U = LocalDate.of(2014, 4, 24); private static final double AMOUNT_1000 = 1000d; private static final CurrencyAmount AMOUNT_GBP1000 = CurrencyAmount.of(GBP, 1000); private static final LocalDate PAYMENT_DATE = LocalDate.of(2014, 4, 26); private static final double DISCOUNT_FACTOR = 0.976d; private static final double TOLERANCE_PV = 1E-7; private static final Payment PAYMENT = Payment.of(AMOUNT_GBP1000, PAYMENT_DATE); private static final Payment PAYMENT_PAST = Payment.of(AMOUNT_GBP1000, VAL_DATE.minusDays(1)); private static final KnownAmountSwapPaymentPeriod PERIOD = KnownAmountSwapPaymentPeriod.builder() .payment(PAYMENT) .startDate(DATE_1) .endDate(DATE_2) .unadjustedEndDate(DATE_2U) .build(); private static final KnownAmountSwapPaymentPeriod PERIOD_PAST = KnownAmountSwapPaymentPeriod.builder() .payment(PAYMENT_PAST) .startDate(DATE_1) .endDate(DATE_2) .build(); private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.DOUBLE_QUADRATIC; private static final Curve DISCOUNT_CURVE_GBP; static { DoubleArray time_gbp = DoubleArray.of(0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0); DoubleArray rate_gbp = DoubleArray.of(0.0160, 0.0135, 0.0160, 0.0185, 0.0185, 0.0195, 0.0200, 0.0210); DISCOUNT_CURVE_GBP = InterpolatedNodalCurve.of( Curves.zeroRates("GBP-Discount", ACT_ACT_ISDA), time_gbp, rate_gbp, INTERPOLATOR); } //------------------------------------------------------------------------- public void test_presentValue() { SimpleRatesProvider prov = createProvider(VAL_DATE); double pvExpected = AMOUNT_1000 * DISCOUNT_FACTOR; double pvComputed = PRICER.presentValue(PERIOD, prov); assertEquals(pvComputed, pvExpected, TOLERANCE_PV); } public void test_presentValue_inPast() { SimpleRatesProvider prov = createProvider(VAL_DATE); double pvComputed = PRICER.presentValue(PERIOD_PAST, prov); assertEquals(pvComputed, 0, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_forecastValue() { SimpleRatesProvider prov = createProvider(VAL_DATE); double fvExpected = AMOUNT_1000; double fvComputed = PRICER.forecastValue(PERIOD, prov); assertEquals(fvComputed, fvExpected, TOLERANCE_PV); } public void test_forecastValue_inPast() { SimpleRatesProvider prov = createProvider(VAL_DATE); double fvComputed = PRICER.forecastValue(PERIOD_PAST, prov); assertEquals(fvComputed, 0, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_presentValueSensitivity() { SimpleRatesProvider prov = createProvider(VAL_DATE); PointSensitivities point = PRICER.presentValueSensitivity(PERIOD, prov).build(); double relativeYearFraction = DAY_COUNT.relativeYearFraction(VAL_DATE, PAYMENT_DATE); double expected = -DISCOUNT_FACTOR * relativeYearFraction * AMOUNT_1000; ZeroRateSensitivity actual = (ZeroRateSensitivity) point.getSensitivities().get(0); assertEquals(actual.getCurrency(), GBP); assertEquals(actual.getCurveCurrency(), GBP); assertEquals(actual.getYearFraction(), relativeYearFraction); assertEquals(actual.getSensitivity(), expected, AMOUNT_1000 * TOLERANCE_PV); } public void test_presentValueSensitivity_inPast() { SimpleRatesProvider prov = createProvider(VAL_DATE); PointSensitivities computed = PRICER.presentValueSensitivity(PERIOD_PAST, prov) .build(); assertEquals(computed, PointSensitivities.empty()); } //------------------------------------------------------------------------- public void test_forecastValueSensitivity() { SimpleRatesProvider prov = createProvider(VAL_DATE); assertEquals(PRICER.forecastValueSensitivity(PERIOD, prov), PointSensitivityBuilder.none()); } //------------------------------------------------------------------------- public void test_accruedInterest() { LocalDate valDate = PERIOD.getStartDate().plusDays(7); SimpleRatesProvider prov = createProvider(valDate); double expected = AMOUNT_1000 * (7d / (7 + 28 + 31 + 25)); double computed = PRICER.accruedInterest(PERIOD, prov); assertEquals(computed, expected, TOLERANCE_PV); } public void test_accruedInterest_valDateBeforePeriod() { SimpleRatesProvider prov = createProvider(PERIOD.getStartDate()); double computed = PRICER.accruedInterest(PERIOD, prov); assertEquals(computed, 0, TOLERANCE_PV); } public void test_accruedInterest_valDateAfterPeriod() { SimpleRatesProvider prov = createProvider(PERIOD.getEndDate().plusDays(1)); double computed = PRICER.accruedInterest(PERIOD, prov); assertEquals(computed, 0, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_explainPresentValue() { RatesProvider prov = createProvider(VAL_DATE); ExplainMapBuilder builder = ExplainMap.builder(); PRICER.explainPresentValue(PERIOD, prov, builder); ExplainMap explain = builder.build(); assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "KnownAmountPaymentPeriod"); assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD.getPaymentDate()); assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD.getCurrency()); assertEquals(explain.get(ExplainKey.DISCOUNT_FACTOR).get(), DISCOUNT_FACTOR, TOLERANCE_PV); int daysBetween = (int) DAYS.between(DATE_1, DATE_2); assertEquals(explain.get(ExplainKey.START_DATE).get(), PERIOD.getStartDate()); assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), PERIOD.getUnadjustedStartDate()); assertEquals(explain.get(ExplainKey.END_DATE).get(), PERIOD.getEndDate()); assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), PERIOD.getUnadjustedEndDate()); assertEquals(explain.get(ExplainKey.DAYS).get(), (Integer) daysBetween); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), PERIOD.getCurrency()); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), AMOUNT_1000, TOLERANCE_PV); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), PERIOD.getCurrency()); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), AMOUNT_1000 * DISCOUNT_FACTOR, TOLERANCE_PV); } public void test_explainPresentValue_inPast() { RatesProvider prov = createProvider(VAL_DATE); ExplainMapBuilder builder = ExplainMap.builder(); PRICER.explainPresentValue(PERIOD_PAST, prov, builder); ExplainMap explain = builder.build(); assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "KnownAmountPaymentPeriod"); assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_PAST.getPaymentDate()); assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_PAST.getCurrency()); int daysBetween = (int) DAYS.between(DATE_1, DATE_2); assertEquals(explain.get(ExplainKey.START_DATE).get(), PERIOD_PAST.getStartDate()); assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), PERIOD_PAST.getUnadjustedStartDate()); assertEquals(explain.get(ExplainKey.END_DATE).get(), PERIOD_PAST.getEndDate()); assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), PERIOD_PAST.getUnadjustedEndDate()); assertEquals(explain.get(ExplainKey.DAYS).get(), (Integer) daysBetween); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), PERIOD_PAST.getCurrency()); assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0, TOLERANCE_PV); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getCurrency(), PERIOD_PAST.getCurrency()); assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0 * DISCOUNT_FACTOR, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_currencyExposure() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE) .discountCurve(GBP, DISCOUNT_CURVE_GBP) .build(); MultiCurrencyAmount computed = PRICER.currencyExposure(PERIOD, prov); PointSensitivities point = PRICER.presentValueSensitivity(PERIOD, prov).build(); MultiCurrencyAmount expected = prov.currencyExposure(point) .plus(CurrencyAmount.of(GBP, PRICER.presentValue(PERIOD, prov))); assertEquals(computed, expected); } public void test_currentCash_zero() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE) .discountCurve(GBP, DISCOUNT_CURVE_GBP) .build(); double computed = PRICER.currentCash(PERIOD, prov); assertEquals(computed, 0d); } public void test_currentCash_onPayment() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(PERIOD.getPaymentDate()) .discountCurve(GBP, DISCOUNT_CURVE_GBP) .build(); double computed = PRICER.currentCash(PERIOD, prov); assertEquals(computed, AMOUNT_1000); } //------------------------------------------------------------------------- // creates a simple provider private SimpleRatesProvider createProvider(LocalDate valDate) { Curve curve = ConstantCurve.of(Curves.discountFactors("Test", DAY_COUNT), DISCOUNT_FACTOR); DiscountFactors df = SimpleDiscountFactors.of(GBP, valDate, curve); SimpleRatesProvider prov = new SimpleRatesProvider(valDate); prov.setDayCount(DAY_COUNT); prov.setDiscountFactors(df); return prov; } }