/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.deposit; import static com.opengamma.strata.basics.currency.Currency.EUR; import static com.opengamma.strata.basics.date.BusinessDayConventions.MODIFIED_FOLLOWING; import static com.opengamma.strata.basics.date.DayCounts.ACT_360; import static com.opengamma.strata.basics.date.HolidayCalendarIds.EUTA; import static com.opengamma.strata.collect.TestHelper.date; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.time.LocalDate; import org.testng.annotations.Test; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.basics.date.BusinessDayAdjustment; import com.opengamma.strata.collect.array.DoubleArray; 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.param.CurrencyParameterSensitivities; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.pricer.DiscountFactors; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.pricer.rate.SimpleRatesProvider; import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator; import com.opengamma.strata.product.common.BuySell; import com.opengamma.strata.product.deposit.ResolvedTermDeposit; import com.opengamma.strata.product.deposit.TermDeposit; /** * Test {@link DiscountingTermDepositProductPricer}. */ @Test public class DiscountingTermDepositProductPricerTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final LocalDate VAL_DATE = date(2014, 1, 22); private static final LocalDate START_DATE = date(2014, 1, 24); private static final LocalDate END_DATE = date(2014, 7, 24); private static final double NOTIONAL = 100000000d; private static final double RATE = 0.0750; private static final BusinessDayAdjustment BD_ADJ = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUTA); private static final TermDeposit TERM_DEPOSIT = TermDeposit.builder() .buySell(BuySell.BUY) .startDate(START_DATE) .endDate(END_DATE) .businessDayAdjustment(BD_ADJ) .dayCount(ACT_360) .notional(NOTIONAL) .currency(EUR) .rate(RATE) .build(); private static final ResolvedTermDeposit RTERM_DEPOSIT = TERM_DEPOSIT.resolve(REF_DATA); private static final DiscountingTermDepositProductPricer PRICER = DiscountingTermDepositProductPricer.DEFAULT; private static final double TOLERANCE = 1E-12; private static final double EPS_FD = 1E-7; private static final RatesFiniteDifferenceSensitivityCalculator CAL_FD = new RatesFiniteDifferenceSensitivityCalculator(EPS_FD); private static final ImmutableRatesProvider IMM_PROV; static { CurveInterpolator interp = CurveInterpolators.DOUBLE_QUADRATIC; DoubleArray time_eur = DoubleArray.of(0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0); DoubleArray rate_eur = DoubleArray.of(0.0160, 0.0135, 0.0160, 0.0185, 0.0185, 0.0195, 0.0200, 0.0210); InterpolatedNodalCurve dscCurve = InterpolatedNodalCurve.of(Curves.zeroRates("EUR-Discount", ACT_360), time_eur, rate_eur, interp); IMM_PROV = ImmutableRatesProvider.builder(VAL_DATE) .discountCurve(EUR, dscCurve) .build(); } private static final double DF_START = 0.99; double DF_END = 0.94; //------------------------------------------------------------------------- public void test_presentValue_notStarted() { SimpleRatesProvider prov = provider(VAL_DATE, DF_START, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = ((1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END - DF_START) * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); } public void test_presentValue_onStart() { SimpleRatesProvider prov = provider(START_DATE, 1.0d, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = ((1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END - 1.0d) * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); } public void test_presentValue_started() { SimpleRatesProvider prov = provider(date(2014, 2, 22), 1.2d, DF_END); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = (1d + RATE * RTERM_DEPOSIT.getYearFraction()) * DF_END * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); } public void test_presentValue_onEnd() { SimpleRatesProvider prov = provider(END_DATE, 1.2d, 1.0d); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); double expected = (1d + RATE * RTERM_DEPOSIT.getYearFraction()) * 1.0d * NOTIONAL; assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected, TOLERANCE * NOTIONAL); } public void test_presentValue_ended() { SimpleRatesProvider prov = provider(date(2014, 9, 22), 1.2d, 1.1d); CurrencyAmount computed = PRICER.presentValue(RTERM_DEPOSIT, prov); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), 0.0d, TOLERANCE * NOTIONAL); } public void test_presentValueSensitivity() { PointSensitivities computed = PRICER.presentValueSensitivity(RTERM_DEPOSIT, IMM_PROV); CurrencyParameterSensitivities sensiComputed = IMM_PROV.parameterSensitivity(computed); CurrencyParameterSensitivities sensiExpected = CAL_FD.sensitivity(IMM_PROV, (p) -> PRICER.presentValue(RTERM_DEPOSIT, (p))); assertTrue(sensiComputed.equalWithTolerance(sensiExpected, NOTIONAL * EPS_FD)); } public void test_parRate() { SimpleRatesProvider prov = provider(VAL_DATE, DF_START, DF_END); double parRate = PRICER.parRate(RTERM_DEPOSIT, prov); TermDeposit depositPar = TermDeposit.builder() .buySell(BuySell.BUY) .startDate(START_DATE) .endDate(END_DATE) .businessDayAdjustment(BD_ADJ) .dayCount(ACT_360) .notional(NOTIONAL) .currency(EUR) .rate(parRate) .build(); double pvPar = PRICER.presentValue(depositPar.resolve(REF_DATA), prov).getAmount(); assertEquals(pvPar, 0.0, NOTIONAL * TOLERANCE); } public void test_parSpread() { SimpleRatesProvider prov = provider(VAL_DATE, DF_START, DF_END); double parSpread = PRICER.parSpread(RTERM_DEPOSIT, prov); TermDeposit depositPar = TermDeposit.builder() .buySell(BuySell.BUY) .startDate(START_DATE) .endDate(END_DATE) .businessDayAdjustment(BD_ADJ) .dayCount(ACT_360) .notional(NOTIONAL) .currency(EUR) .rate(RATE + parSpread) .build(); double pvPar = PRICER.presentValue(depositPar.resolve(REF_DATA), prov).getAmount(); assertEquals(pvPar, 0.0, NOTIONAL * TOLERANCE); } public void test_parSpreadSensitivity() { PointSensitivities computed = PRICER.parSpreadSensitivity(RTERM_DEPOSIT, IMM_PROV); CurrencyParameterSensitivities sensiComputed = IMM_PROV.parameterSensitivity(computed); CurrencyParameterSensitivities sensiExpected = CAL_FD.sensitivity(IMM_PROV, (p) -> CurrencyAmount.of(EUR, PRICER.parSpread(RTERM_DEPOSIT, (p)))); assertTrue(sensiComputed.equalWithTolerance(sensiExpected, NOTIONAL * EPS_FD)); } public void test_parRateSensitivity() { PointSensitivities computedSpread = PRICER.parSpreadSensitivity(RTERM_DEPOSIT, IMM_PROV); PointSensitivities computedRate = PRICER.parRateSensitivity(RTERM_DEPOSIT, IMM_PROV); assertTrue(computedSpread.equalWithTolerance(computedRate, NOTIONAL * EPS_FD)); } private SimpleRatesProvider provider(LocalDate valuationDate, double dfStart, double dfEnd) { DiscountFactors mockDf = mock(DiscountFactors.class); when(mockDf.discountFactor(START_DATE)).thenReturn(dfStart); when(mockDf.discountFactor(END_DATE)).thenReturn(dfEnd); SimpleRatesProvider prov = new SimpleRatesProvider(valuationDate, mockDf); return prov; } }