/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.bond;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.index.PriceIndices.US_CPI_U;
import static com.opengamma.strata.pricer.CompoundedRateType.CONTINUOUS;
import static com.opengamma.strata.pricer.CompoundedRateType.PERIODIC;
import static java.time.temporal.ChronoUnit.DAYS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.time.YearMonth;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.index.PriceIndexObservation;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
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.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.CompoundedRateType;
import com.opengamma.strata.pricer.rate.ImmutableRatesProvider;
import com.opengamma.strata.pricer.rate.RateComputationFn;
import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator;
import com.opengamma.strata.product.bond.CapitalIndexedBondPaymentPeriod;
import com.opengamma.strata.product.rate.InflationEndInterpolatedRateComputation;
import com.opengamma.strata.product.rate.InflationEndMonthRateComputation;
/**
* Test {@link DiscountingCapitalIndexedBondPaymentPeriodPricer}.
*/
@Test
public class DiscountingCapitalIndexedBondPaymentPeriodPricerTest {
// periods
private static final LocalDate START_UNADJ = LocalDate.of(2008, 1, 13);
private static final LocalDate END_UNADJ = LocalDate.of(2008, 7, 13);
private static final LocalDate START = LocalDate.of(2008, 1, 14);
private static final LocalDate END = LocalDate.of(2008, 7, 14);
private static final YearMonth REF_END = YearMonth.of(2008, 4);
private static final PriceIndexObservation OBS = PriceIndexObservation.of(US_CPI_U, REF_END);
private static final PriceIndexObservation OBS_PLUS1 = PriceIndexObservation.of(US_CPI_U, REF_END.plusMonths(1));
private static final double NOTIONAL = 10_000_000d;
private static final double REAL_COUPON = 0.01d;
private static final LocalDate DETACHMENT = LocalDate.of(2008, 1, 11);
private static final double START_INDEX = 198.475;
private static final double WEIGHT = 0.6;
private static final InflationEndInterpolatedRateComputation COMPUTE_INTERP =
InflationEndInterpolatedRateComputation.of(US_CPI_U, START_INDEX, REF_END, WEIGHT);
private static final InflationEndMonthRateComputation COMPUTE_MONTH =
InflationEndMonthRateComputation.of(US_CPI_U, START_INDEX, REF_END);
private static final CapitalIndexedBondPaymentPeriod PERIOD_INTERP = CapitalIndexedBondPaymentPeriod.builder()
.currency(USD)
.notional(NOTIONAL)
.detachmentDate(DETACHMENT)
.startDate(START)
.endDate(END)
.unadjustedStartDate(START_UNADJ)
.unadjustedEndDate(END_UNADJ)
.rateComputation(COMPUTE_INTERP)
.realCoupon(REAL_COUPON)
.build();
private static final CapitalIndexedBondPaymentPeriod PERIOD_MONTHLY = CapitalIndexedBondPaymentPeriod.builder()
.currency(USD)
.notional(NOTIONAL)
.detachmentDate(DETACHMENT)
.startDate(START)
.endDate(END)
.unadjustedStartDate(START_UNADJ)
.unadjustedEndDate(END_UNADJ)
.rateComputation(COMPUTE_MONTH)
.realCoupon(REAL_COUPON)
.build();
// rates providers
private static final LocalDate VALUATION_BEFORE_START = LocalDate.of(2007, 10, 9);
private static final LocalDate VALUATION_ON_FIX = LocalDate.of(2008, 4, 29);
private static final LocalDate VALUATION_AFTER_FIX = LocalDate.of(2008, 5, 20);
private static final LocalDate VALUATION_AFTER_PAY = LocalDate.of(2008, 8, 9);
private static final double Z_SPREAD = 0.005;
private static final int PERIOD_PER_YEAR = 4;
private static final IssuerCurveDiscountFactors ICDF_BEFORE_START =
CapitalIndexedBondCurveDataSet.getIssuerCurveDiscountFactors(VALUATION_BEFORE_START);
private static final IssuerCurveDiscountFactors ICDF_ON_FIX =
CapitalIndexedBondCurveDataSet.getIssuerCurveDiscountFactors(VALUATION_ON_FIX);
private static final IssuerCurveDiscountFactors ICDF_AFTER_FIX =
CapitalIndexedBondCurveDataSet.getIssuerCurveDiscountFactors(VALUATION_AFTER_FIX);
private static final IssuerCurveDiscountFactors ICDF_AFTER_PAY =
CapitalIndexedBondCurveDataSet.getIssuerCurveDiscountFactors(VALUATION_AFTER_PAY);
private static final LegalEntityDiscountingProvider LEDP_BEFORE_START =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProvider(VALUATION_BEFORE_START);
private static final LegalEntityDiscountingProvider LEDP_ON_FIX =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProvider(VALUATION_ON_FIX);
private static final LegalEntityDiscountingProvider LEDP_AFTER_FIX =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProvider(VALUATION_AFTER_FIX);
private static final LocalDateDoubleTimeSeries TIME_SERIES_OLD =
LocalDateDoubleTimeSeries.of(LocalDate.of(2007, 9, 30), 200.0);
private static final double INDEX_END_1 = 210.5;
private static final double INDEX_END_2 = 215.5;
private static final LocalDateDoubleTimeSeries TIME_SERIES_ONE =
LocalDateDoubleTimeSeries.of(REF_END.atEndOfMonth(), INDEX_END_1);
private static final LocalDateDoubleTimeSeries TIME_SERIES_TWO = LocalDateDoubleTimeSeries.builder()
.put(REF_END.atEndOfMonth(), INDEX_END_1)
.put(REF_END.plusMonths(1).atEndOfMonth(), INDEX_END_2)
.build();
private static final ImmutableRatesProvider IRP_BEFORE_START =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION_BEFORE_START, TIME_SERIES_OLD);
private static final ImmutableRatesProvider IRP_ON_FIX =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION_ON_FIX, TIME_SERIES_ONE);
private static final ImmutableRatesProvider IRP_AFTER_FIX =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION_AFTER_FIX, TIME_SERIES_TWO);
private static final ImmutableRatesProvider IRP_AFTER_PAY =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION_AFTER_PAY, TIME_SERIES_TWO);
// calculators
private static final double TOL = 1.0e-13;
private static final double FD_EPS = 1.0e-6;
private static final DiscountingCapitalIndexedBondPaymentPeriodPricer PRICER =
DiscountingCapitalIndexedBondPaymentPeriodPricer.DEFAULT;
private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL =
new RatesFiniteDifferenceSensitivityCalculator(FD_EPS);
//-------------------------------------------------------------------------
public void test_getter() {
assertEquals(PRICER.getRateComputationFn(), RateComputationFn.standard());
}
//-------------------------------------------------------------------------
public void test_presentValue_beforeStart() {
double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START);
double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_BEFORE_START, ICDF_BEFORE_START);
double computedFvInterp = PRICER.forecastValue(PERIOD_INTERP, IRP_BEFORE_START);
double computedFvMonthly = PRICER.forecastValue(PERIOD_MONTHLY, IRP_BEFORE_START);
double index1 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS);
double index2 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS_PLUS1);
double df = ICDF_BEFORE_START.discountFactor(END);
double expectedFvInterp = (index1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL;
double expectedFvMonthly = index1 / START_INDEX * REAL_COUPON * NOTIONAL;
assertEquals(computedFvInterp, expectedFvInterp, TOL * expectedFvInterp);
assertEquals(computedFvMonthly, expectedFvMonthly, TOL * expectedFvMonthly);
assertEquals(computedInterp, expectedFvInterp * df, TOL * expectedFvInterp * df);
assertEquals(computedMonthly, expectedFvMonthly * df, TOL * expectedFvMonthly * df);
}
public void test_presentValue_onFix() {
double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX);
double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX);
double index2 = IRP_ON_FIX.priceIndexValues(US_CPI_U).value(OBS_PLUS1);
double df = ICDF_ON_FIX.discountFactor(END);
double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL * df;
double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL * df;
assertEquals(computedInterp, expectedInterp, TOL * expectedInterp);
assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly);
}
public void test_presentValue_afterFix() {
double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX);
double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX);
double df = ICDF_AFTER_FIX.discountFactor(END);
double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * INDEX_END_2) / START_INDEX * REAL_COUPON * NOTIONAL * df;
double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL * df;
assertEquals(computedInterp, expectedInterp, TOL * expectedInterp);
assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly);
}
public void test_presentValue_afterPay() {
double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY);
double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_AFTER_PAY, ICDF_AFTER_PAY);
assertEquals(computedInterp, 0d, TOL);
assertEquals(computedMonthly, 0d, TOL);
}
//-------------------------------------------------------------------------
public void test_presentValueWithZSpread_beforeStart() {
double computedInterp = PRICER.presentValueWithZSpread(
PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double computedMonthly = PRICER.presentValueWithZSpread(
PERIOD_MONTHLY, IRP_BEFORE_START, ICDF_BEFORE_START, Z_SPREAD, CONTINUOUS, 0);
double index1 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS);
double index2 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS_PLUS1);
double expectedInterp = (index1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_BEFORE_START.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double expectedMonthly = index1 / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_BEFORE_START.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, CONTINUOUS, 0);
assertEquals(computedInterp, expectedInterp, TOL * expectedInterp);
assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly);
}
public void test_presentValueWithZSpread_onFix() {
double computedInterp = PRICER.presentValueWithZSpread(
PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX, Z_SPREAD, CONTINUOUS, 0);
double computedMonthly = PRICER.presentValueWithZSpread(
PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double index2 = IRP_ON_FIX.priceIndexValues(US_CPI_U).value(OBS_PLUS1);
double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_ON_FIX.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, CONTINUOUS, 0);
double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_ON_FIX.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computedInterp, expectedInterp, TOL * expectedInterp);
assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly);
}
public void test_presentValueWithZSpread_afterFix() {
double computedInterp = PRICER.presentValueWithZSpread(
PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double computedMonthly = PRICER.presentValueWithZSpread(
PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, CONTINUOUS, 0);
double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * INDEX_END_2) / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_AFTER_FIX.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL *
ICDF_AFTER_FIX.getDiscountFactors().discountFactorWithSpread(END, Z_SPREAD, CONTINUOUS, 0);
assertEquals(computedInterp, expectedInterp, TOL * expectedInterp);
assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly);
}
public void test_presentValueWithZSpread_afterPay() {
double computedInterp = PRICER.presentValueWithZSpread(
PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double computedMonthly = PRICER.presentValueWithZSpread(
PERIOD_MONTHLY, IRP_AFTER_PAY, ICDF_AFTER_PAY, Z_SPREAD, CONTINUOUS, 0);
assertEquals(computedInterp, 0d, TOL);
assertEquals(computedMonthly, 0d, TOL);
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivity_beforeStart() {
PointSensitivityBuilder pointInterp =
PRICER.presentValueSensitivity(PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START);
CurrencyParameterSensitivities computedInterp1 =
LEDP_BEFORE_START.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_BEFORE_START.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.presentValueSensitivity(PERIOD_MONTHLY, IRP_BEFORE_START, ICDF_BEFORE_START);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_BEFORE_START.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_BEFORE_START.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
fdSensitivity(PERIOD_INTERP, IRP_BEFORE_START, LEDP_BEFORE_START);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivity(PERIOD_MONTHLY, IRP_BEFORE_START, LEDP_BEFORE_START);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivity_onFix() {
PointSensitivityBuilder pointInterp =
PRICER.presentValueSensitivity(PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX);
CurrencyParameterSensitivities computedInterp1 =
LEDP_ON_FIX.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_ON_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.presentValueSensitivity(PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_ON_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_ON_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
fdSensitivity(PERIOD_INTERP, IRP_ON_FIX, LEDP_ON_FIX);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivity(PERIOD_MONTHLY, IRP_ON_FIX, LEDP_ON_FIX);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivity_afterFix() {
PointSensitivityBuilder pointInterp =
PRICER.presentValueSensitivity(PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX);
CurrencyParameterSensitivities computedInterp1 =
LEDP_AFTER_FIX.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_AFTER_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.presentValueSensitivity(PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_AFTER_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_AFTER_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
fdSensitivity(PERIOD_INTERP, IRP_AFTER_FIX, LEDP_AFTER_FIX);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivity(PERIOD_MONTHLY, IRP_AFTER_FIX, LEDP_AFTER_FIX);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivity_afterPay() {
PointSensitivityBuilder computedInterp =
PRICER.presentValueSensitivity(PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY);
PointSensitivityBuilder computedMonthly =
PRICER.presentValueSensitivity(PERIOD_MONTHLY, IRP_AFTER_PAY, ICDF_AFTER_PAY);
assertEquals(computedInterp, PointSensitivityBuilder.none());
assertEquals(computedMonthly, PointSensitivityBuilder.none());
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivityWithZSpread_beforeStart() {
PointSensitivityBuilder pointInterp = PRICER.presentValueSensitivityWithZSpread(
PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
CurrencyParameterSensitivities computedInterp1 =
LEDP_BEFORE_START.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_BEFORE_START.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly = PRICER.presentValueSensitivityWithZSpread(
PERIOD_MONTHLY, IRP_BEFORE_START, ICDF_BEFORE_START, Z_SPREAD, CONTINUOUS, 0);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_BEFORE_START.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_BEFORE_START.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp = fdSensitivityWithZSpread(
PERIOD_INTERP, IRP_BEFORE_START, LEDP_BEFORE_START, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivityWithZSpread(PERIOD_MONTHLY, IRP_BEFORE_START, LEDP_BEFORE_START, Z_SPREAD, CONTINUOUS, 0);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivityWithZSpread_onFix() {
PointSensitivityBuilder pointInterp =
PRICER.presentValueSensitivityWithZSpread(PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX, Z_SPREAD, CONTINUOUS, 0);
CurrencyParameterSensitivities computedInterp1 =
LEDP_ON_FIX.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_ON_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly = PRICER.presentValueSensitivityWithZSpread(
PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_ON_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_ON_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
fdSensitivityWithZSpread(PERIOD_INTERP, IRP_ON_FIX, LEDP_ON_FIX, Z_SPREAD, CONTINUOUS, 0);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivityWithZSpread(PERIOD_MONTHLY, IRP_ON_FIX, LEDP_ON_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivityWithZSpread_afterFix() {
PointSensitivityBuilder pointInterp = PRICER.presentValueSensitivityWithZSpread(
PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
CurrencyParameterSensitivities computedInterp1 =
LEDP_AFTER_FIX.parameterSensitivity(pointInterp.build());
CurrencyParameterSensitivities computedInterp2 =
IRP_AFTER_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly = PRICER.presentValueSensitivityWithZSpread(
PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX, Z_SPREAD, CONTINUOUS, 0);
CurrencyParameterSensitivities computedMonthly1 =
LEDP_AFTER_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities computedMonthly2 =
IRP_AFTER_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
fdSensitivityWithZSpread(PERIOD_INTERP, IRP_AFTER_FIX, LEDP_AFTER_FIX, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
CurrencyParameterSensitivities expectedMonthly =
fdSensitivityWithZSpread(PERIOD_MONTHLY, IRP_AFTER_FIX, LEDP_AFTER_FIX, Z_SPREAD, CONTINUOUS, 0);
assertTrue(computedInterp1.combinedWith(computedInterp2).equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly1.combinedWith(computedMonthly2).equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_presentValueSensitivityWithZSpread_afterPay() {
PointSensitivityBuilder computedInterp = PRICER.presentValueSensitivityWithZSpread(
PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
PointSensitivityBuilder computedMonthly = PRICER.presentValueSensitivityWithZSpread(
PERIOD_MONTHLY, IRP_AFTER_PAY, ICDF_AFTER_PAY, Z_SPREAD, CONTINUOUS, 0);
assertEquals(computedInterp, PointSensitivityBuilder.none());
assertEquals(computedMonthly, PointSensitivityBuilder.none());
}
//-------------------------------------------------------------------------
public void test_forecastValueSensitivity_beforeStart() {
PointSensitivityBuilder pointInterp =
PRICER.forecastValueSensitivity(PERIOD_INTERP, IRP_BEFORE_START);
CurrencyParameterSensitivities computedInterp =
IRP_BEFORE_START.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.forecastValueSensitivity(PERIOD_MONTHLY, IRP_BEFORE_START);
CurrencyParameterSensitivities computedMonthly =
IRP_BEFORE_START.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
FD_CAL.sensitivity(IRP_BEFORE_START, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_INTERP, p)));
CurrencyParameterSensitivities expectedMonthly =
FD_CAL.sensitivity(IRP_BEFORE_START, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_MONTHLY, p)));
assertTrue(computedInterp.equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly.equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_forecastValueSensitivity_onFix() {
PointSensitivityBuilder pointInterp =
PRICER.forecastValueSensitivity(PERIOD_INTERP, IRP_ON_FIX);
CurrencyParameterSensitivities computedInterp =
IRP_ON_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.forecastValueSensitivity(PERIOD_MONTHLY, IRP_ON_FIX);
CurrencyParameterSensitivities computedMonthly =
IRP_ON_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
FD_CAL.sensitivity(IRP_ON_FIX, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_INTERP, p)));
CurrencyParameterSensitivities expectedMonthly =
FD_CAL.sensitivity(IRP_ON_FIX, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_MONTHLY, p)));
assertTrue(computedInterp.equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly.equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_forecastValueSensitivity_afterFix() {
PointSensitivityBuilder pointInterp =
PRICER.forecastValueSensitivity(PERIOD_INTERP, IRP_AFTER_FIX);
CurrencyParameterSensitivities computedInterp =
IRP_AFTER_FIX.parameterSensitivity(pointInterp.build());
PointSensitivityBuilder pointMonthly =
PRICER.forecastValueSensitivity(PERIOD_MONTHLY, IRP_AFTER_FIX);
CurrencyParameterSensitivities computedMonthly =
IRP_AFTER_FIX.parameterSensitivity(pointMonthly.build());
CurrencyParameterSensitivities expectedInterp =
FD_CAL.sensitivity(IRP_AFTER_FIX, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_INTERP, p)));
CurrencyParameterSensitivities expectedMonthly =
FD_CAL.sensitivity(IRP_AFTER_FIX, p -> CurrencyAmount.of(USD, PRICER.forecastValue(PERIOD_MONTHLY, p)));
assertTrue(computedInterp.equalWithTolerance(expectedInterp, NOTIONAL * FD_EPS));
assertTrue(computedMonthly.equalWithTolerance(expectedMonthly, NOTIONAL * FD_EPS));
}
public void test_forecastValueSensitivity_afterPay() {
PointSensitivityBuilder computedInterp =
PRICER.forecastValueSensitivity(PERIOD_INTERP, IRP_AFTER_PAY);
PointSensitivityBuilder computedMonthly =
PRICER.forecastValueSensitivity(PERIOD_MONTHLY, IRP_AFTER_PAY);
assertEquals(computedInterp, PointSensitivityBuilder.none());
assertEquals(computedMonthly, PointSensitivityBuilder.none());
}
//-------------------------------------------------------------------------
public void test_explainPresentValue() {
ExplainMapBuilder builder = ExplainMap.builder();
PRICER.explainPresentValue(PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START, builder);
ExplainMap explain = builder.build();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "CapitalIndexedBondPaymentPeriod");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_INTERP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_INTERP.getCurrency());
assertEquals(explain.get(ExplainKey.START_DATE).get(), START);
assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), START_UNADJ);
assertEquals(explain.get(ExplainKey.END_DATE).get(), END);
assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), END_UNADJ);
assertEquals(explain.get(ExplainKey.DAYS).get().intValue(), (int) DAYS.between(START_UNADJ, END_UNADJ));
assertEquals(explain.get(ExplainKey.DISCOUNT_FACTOR).get(), ICDF_BEFORE_START.discountFactor(END));
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(),
PRICER.forecastValue(PERIOD_INTERP, IRP_BEFORE_START), NOTIONAL * TOL);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(),
PRICER.presentValue(PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START), NOTIONAL * TOL);
}
public void test_explainPresentValue_past() {
ExplainMapBuilder builder = ExplainMap.builder();
PRICER.explainPresentValue(PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY, builder);
ExplainMap explain = builder.build();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "CapitalIndexedBondPaymentPeriod");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_INTERP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_INTERP.getCurrency());
assertEquals(explain.get(ExplainKey.START_DATE).get(), START);
assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), START_UNADJ);
assertEquals(explain.get(ExplainKey.END_DATE).get(), END);
assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), END_UNADJ);
assertEquals(explain.get(ExplainKey.DAYS).get().intValue(), (int) DAYS.between(START_UNADJ, END_UNADJ));
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0d, NOTIONAL * TOL);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0d, NOTIONAL * TOL);
}
public void test_explainPresentValueWithZSpread() {
ExplainMapBuilder builder = ExplainMap.builder();
PRICER.explainPresentValueWithZSpread(
PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START, builder, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
ExplainMap explain = builder.build();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "CapitalIndexedBondPaymentPeriod");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_INTERP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_INTERP.getCurrency());
assertEquals(explain.get(ExplainKey.START_DATE).get(), START);
assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), START_UNADJ);
assertEquals(explain.get(ExplainKey.END_DATE).get(), END);
assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), END_UNADJ);
assertEquals(explain.get(ExplainKey.DAYS).get().intValue(), (int) DAYS.between(START_UNADJ, END_UNADJ));
assertEquals(explain.get(ExplainKey.DISCOUNT_FACTOR).get(), ICDF_BEFORE_START.discountFactor(END));
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(),
PRICER.forecastValue(PERIOD_INTERP, IRP_BEFORE_START), NOTIONAL * TOL);
assertEquals(
explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(),
PRICER.presentValueWithZSpread(
PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR),
NOTIONAL * TOL);
}
public void test_explainPresentValueWithZSpread_past() {
ExplainMapBuilder builder = ExplainMap.builder();
PRICER.explainPresentValueWithZSpread(
PERIOD_INTERP, IRP_AFTER_PAY, ICDF_AFTER_PAY, builder, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
ExplainMap explain = builder.build();
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "CapitalIndexedBondPaymentPeriod");
assertEquals(explain.get(ExplainKey.PAYMENT_DATE).get(), PERIOD_INTERP.getPaymentDate());
assertEquals(explain.get(ExplainKey.PAYMENT_CURRENCY).get(), PERIOD_INTERP.getCurrency());
assertEquals(explain.get(ExplainKey.START_DATE).get(), START);
assertEquals(explain.get(ExplainKey.UNADJUSTED_START_DATE).get(), START_UNADJ);
assertEquals(explain.get(ExplainKey.END_DATE).get(), END);
assertEquals(explain.get(ExplainKey.UNADJUSTED_END_DATE).get(), END_UNADJ);
assertEquals(explain.get(ExplainKey.DAYS).get().intValue(), (int) DAYS.between(START_UNADJ, END_UNADJ));
assertEquals(explain.get(ExplainKey.FORECAST_VALUE).get().getAmount(), 0d, NOTIONAL * TOL);
assertEquals(explain.get(ExplainKey.PRESENT_VALUE).get().getAmount(), 0d, NOTIONAL * TOL);
}
//-------------------------------------------------------------------------
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdSensitivity(
CapitalIndexedBondPaymentPeriod period,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider) {
CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(
issuerRatesProvider,
p -> CurrencyAmount.of(
USD,
PRICER.presentValue(
period,
ratesProvider,
p.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.getIssuerId(), USD))));
CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(
ratesProvider,
p -> CurrencyAmount.of(
USD,
PRICER.presentValue(
period,
p,
issuerRatesProvider.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.getIssuerId(), USD))));
return sensi1.combinedWith(sensi2);
}
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdSensitivityWithZSpread(
CapitalIndexedBondPaymentPeriod period,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(
issuerRatesProvider,
p -> CurrencyAmount.of(USD,
PRICER.presentValueWithZSpread(
period,
ratesProvider,
p.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.getIssuerId(), USD),
zSpread,
compoundedRateType,
periodsPerYear)));
CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(
ratesProvider,
p -> CurrencyAmount.of(
USD,
PRICER.presentValueWithZSpread(
period,
p,
issuerRatesProvider.issuerCurveDiscountFactors(CapitalIndexedBondCurveDataSet.getIssuerId(), USD),
zSpread,
compoundedRateType,
periodsPerYear)));
return sensi1.combinedWith(sensi2);
}
}