/**
* 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.GBP;
import static com.opengamma.strata.basics.currency.Currency.JPY;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ICMA;
import static com.opengamma.strata.basics.date.DayCounts.NL_365;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.GBLO;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.JPTO;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.USNY;
import static com.opengamma.strata.basics.index.PriceIndices.GB_RPI;
import static com.opengamma.strata.basics.index.PriceIndices.JP_CPI_EXF;
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 com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.GB_IL_BOND;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.GB_IL_FLOAT;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.JP_IL_COMPOUND;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.JP_IL_SIMPLE;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.US_IL_REAL;
import static com.opengamma.strata.product.swap.PriceIndexCalculationMethod.INTERPOLATED;
import static com.opengamma.strata.product.swap.PriceIndexCalculationMethod.INTERPOLATED_JAPAN;
import static com.opengamma.strata.product.swap.PriceIndexCalculationMethod.MONTHLY;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.time.Period;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.StandardId;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.date.BusinessDayAdjustment;
import com.opengamma.strata.basics.date.BusinessDayConventions;
import com.opengamma.strata.basics.date.DaysAdjustment;
import com.opengamma.strata.basics.schedule.Frequency;
import com.opengamma.strata.basics.schedule.PeriodicSchedule;
import com.opengamma.strata.basics.schedule.RollConventions;
import com.opengamma.strata.basics.schedule.Schedule;
import com.opengamma.strata.basics.schedule.StubConvention;
import com.opengamma.strata.basics.value.ValueSchedule;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
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.SecurityId;
import com.opengamma.strata.product.bond.CapitalIndexedBond;
import com.opengamma.strata.product.bond.CapitalIndexedBondPaymentPeriod;
import com.opengamma.strata.product.bond.ResolvedCapitalIndexedBond;
import com.opengamma.strata.product.rate.RateComputation;
import com.opengamma.strata.product.swap.InflationRateCalculation;
/**
* Test {@link DiscountingCapitalIndexedBondProductPricer}.
*/
@Test
public class DiscountingCapitalIndexedBondProductPricerTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final double NOTIONAL = 10_000_000d;
private static final double START_INDEX = 198.47742;
private static final double REAL_COUPON_VALUE = 0.01;
private static final ValueSchedule REAL_COUPON = ValueSchedule.of(REAL_COUPON_VALUE);
private static final InflationRateCalculation RATE_CALC = InflationRateCalculation.builder()
.gearing(REAL_COUPON)
.index(US_CPI_U)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED)
.firstIndexValue(START_INDEX)
.build();
private static final BusinessDayAdjustment EX_COUPON_ADJ =
BusinessDayAdjustment.of(BusinessDayConventions.PRECEDING, USNY);
private static final DaysAdjustment SETTLE_OFFSET = DaysAdjustment.ofBusinessDays(2, USNY);
private static final StandardId LEGAL_ENTITY = CapitalIndexedBondCurveDataSet.getIssuerId();
private static final LocalDate START = LocalDate.of(2006, 1, 15);
private static final LocalDate END = LocalDate.of(2016, 1, 15);
private static final Frequency FREQUENCY = Frequency.P6M;
private static final BusinessDayAdjustment BUSINESS_ADJUST =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, USNY);
private static final PeriodicSchedule SCHEDULE =
PeriodicSchedule.of(START, END, FREQUENCY, BUSINESS_ADJUST, StubConvention.NONE, RollConventions.NONE);
private static final SecurityId SECURITY_ID = SecurityId.of("OG-Ticker", "BOND1");
private static final ResolvedCapitalIndexedBond PRODUCT = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NOTIONAL)
.currency(USD)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(US_IL_REAL)
.settlementDateOffset(SETTLE_OFFSET)
.accrualSchedule(SCHEDULE)
.build()
.resolve(REF_DATA);
private static final DaysAdjustment EX_COUPON = DaysAdjustment.ofCalendarDays(-5, EX_COUPON_ADJ);
private static final ResolvedCapitalIndexedBond PRODUCT_EX_COUPON = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NOTIONAL)
.currency(USD)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(US_IL_REAL)
.settlementDateOffset(SETTLE_OFFSET)
.accrualSchedule(SCHEDULE)
.exCouponPeriod(EX_COUPON)
.build()
.resolve(REF_DATA);
// detachment date (for nonzero ex-coupon days) < valuation date < payment date
private static final LocalDate VALUATION = LocalDate.of(2014, 7, 10);
private static final LocalDateDoubleTimeSeries TS = CapitalIndexedBondCurveDataSet.getTimeSeries(VALUATION);
private static final ImmutableRatesProvider RATES_PROVIDER =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION, TS);
private static final LegalEntityDiscountingProvider ISSUER_RATES_PROVIDER =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProvider(VALUATION);
private static final IssuerCurveDiscountFactors ISSUER_DISCOUNT_FACTORS =
CapitalIndexedBondCurveDataSet.getIssuerCurveDiscountFactors(VALUATION);
// valuation date = payment date
private static final LocalDate VALUATION_ON_PAY = LocalDate.of(2014, 1, 15);
private static final LocalDateDoubleTimeSeries TS_ON_PAY =
CapitalIndexedBondCurveDataSet.getTimeSeries(VALUATION_ON_PAY);
private static final ImmutableRatesProvider RATES_PROVIDER_ON_PAY =
CapitalIndexedBondCurveDataSet.getRatesProvider(VALUATION_ON_PAY, TS_ON_PAY);
private static final double Z_SPREAD = 0.015;
private static final int PERIOD_PER_YEAR = 4;
private static final double TOL = 1.0e-12;
private static final double EPS = 1.0e-6;
private static final DiscountingCapitalIndexedBondProductPricer PRICER = DiscountingCapitalIndexedBondProductPricer.DEFAULT;
private static final DiscountingCapitalIndexedBondPaymentPeriodPricer PERIOD_PRICER =
DiscountingCapitalIndexedBondPaymentPeriodPricer.DEFAULT;
private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL =
new RatesFiniteDifferenceSensitivityCalculator(EPS);
//-------------------------------------------------------------------------
public void test_getter() {
assertEquals(PRICER.getPeriodPricer(), PERIOD_PRICER);
}
//-------------------------------------------------------------------------
public void test_presentValue() {
CurrencyAmount computed = PRICER.presentValue(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
double expected = PERIOD_PRICER.presentValue(PRODUCT.getNominalPayment(), RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS);
int size = PRODUCT.getPeriodicPayments().size();
for (int i = 16; i < size; ++i) {
CapitalIndexedBondPaymentPeriod payment = PRODUCT.getPeriodicPayments().get(i);
expected += PERIOD_PRICER.presentValue(payment, RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS);
}
assertEquals(computed.getAmount(), expected, TOL * NOTIONAL);
}
public void test_presentValue_exCoupon() {
CurrencyAmount computed = PRICER.presentValue(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
double expected = PERIOD_PRICER.presentValue(
PRODUCT_EX_COUPON.getNominalPayment(), RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS);
int size = PRODUCT_EX_COUPON.getPeriodicPayments().size();
for (int i = 17; i < size; ++i) { // in ex-coupon period
CapitalIndexedBondPaymentPeriod payment = PRODUCT_EX_COUPON.getPeriodicPayments().get(i);
expected += PERIOD_PRICER.presentValue(payment, RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS);
}
assertEquals(computed.getAmount(), expected, TOL * NOTIONAL);
}
public void test_presentValueWithZSpread() {
CurrencyAmount computed = PRICER.presentValueWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double expected = PERIOD_PRICER.presentValueWithZSpread(PRODUCT.getNominalPayment(), RATES_PROVIDER,
ISSUER_DISCOUNT_FACTORS, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
int size = PRODUCT.getPeriodicPayments().size();
for (int i = 16; i < size; ++i) {
CapitalIndexedBondPaymentPeriod payment = PRODUCT.getPeriodicPayments().get(i);
expected += PERIOD_PRICER.presentValueWithZSpread(
payment, RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
}
assertEquals(computed.getAmount(), expected, TOL * NOTIONAL);
}
public void test_presentValueWithZSpread_exCoupon() {
CurrencyAmount computed = PRICER.presentValueWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0);
double expected = PERIOD_PRICER.presentValueWithZSpread(
PRODUCT_EX_COUPON.getNominalPayment(), RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS, Z_SPREAD, CONTINUOUS, 0);
int size = PRODUCT_EX_COUPON.getPeriodicPayments().size();
for (int i = 17; i < size; ++i) { // in ex-coupon period
CapitalIndexedBondPaymentPeriod payment = PRODUCT_EX_COUPON.getPeriodicPayments().get(i);
expected += PERIOD_PRICER.presentValueWithZSpread(
payment, RATES_PROVIDER, ISSUER_DISCOUNT_FACTORS, Z_SPREAD, CONTINUOUS, 0);
}
assertEquals(computed.getAmount(), expected, TOL * NOTIONAL);
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivity() {
PointSensitivities point = PRICER.presentValueSensitivity(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = fdPvSensitivity(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_presentValueSensitivity_exCoupon() {
PointSensitivities point =
PRICER.presentValueSensitivity(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected =
fdPvSensitivity(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_presentValueSensitivityWithZSpread() {
PointSensitivities point = PRICER.presentValueSensitivityWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = fdPvSensitivityWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_presentValueSensitivityWithZSpread_exCoupon() {
PointSensitivities point = PRICER.presentValueSensitivityWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = fdPvSensitivityWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
//-------------------------------------------------------------------------
public void test_zSpreadFromCurvesAndPV() {
CurrencyAmount pv = PRICER.presentValueWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double computed = PRICER.zSpreadFromCurvesAndPV(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, pv, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_zSpreadFromCurvesAndPV_exCoupon() {
CurrencyAmount pv = PRICER.presentValueWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0);
double computed = PRICER.zSpreadFromCurvesAndPV(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, pv, CONTINUOUS, 0);
assertEquals(computed, Z_SPREAD, TOL);
}
//-------------------------------------------------------------------------
public void test_dirtyNominalPriceFromCurves() {
double computed = PRICER.dirtyNominalPriceFromCurves(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA);
LocalDate settlement = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double df =
ISSUER_RATES_PROVIDER.repoCurveDiscountFactors(SECURITY_ID, LEGAL_ENTITY, USD).discountFactor(settlement);
double expected =
PRICER.presentValue(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, settlement).getAmount() / NOTIONAL / df;
assertEquals(computed, expected, TOL);
}
public void test_dirtyNominalPriceFromCurves_exCoupon() {
double computed = PRICER.dirtyNominalPriceFromCurves(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA);
LocalDate settlement = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double df =
ISSUER_RATES_PROVIDER.repoCurveDiscountFactors(SECURITY_ID, LEGAL_ENTITY, USD).discountFactor(settlement);
double expected =
PRICER.presentValue(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, settlement).getAmount() / NOTIONAL / df;
assertEquals(computed, expected, TOL);
}
public void test_dirtyNominalPriceFromCurvesWithZSpread() {
double computed = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, Z_SPREAD, CONTINUOUS, 0);
LocalDate settlement = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double df =
ISSUER_RATES_PROVIDER.repoCurveDiscountFactors(SECURITY_ID, LEGAL_ENTITY, USD).discountFactor(settlement);
double expected = PRICER.presentValueWithZSpread(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, settlement,
Z_SPREAD, CONTINUOUS, 0).getAmount() / NOTIONAL / df;
assertEquals(computed, expected, TOL);
}
public void test_dirtyNominalPriceFromCurvesWithZSpread_exCoupon() {
double computed = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
LocalDate settlement = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double df =
ISSUER_RATES_PROVIDER.repoCurveDiscountFactors(SECURITY_ID, LEGAL_ENTITY, USD).discountFactor(settlement);
double expected = PRICER.presentValueWithZSpread(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, settlement,
Z_SPREAD, PERIODIC, PERIOD_PER_YEAR).getAmount() / NOTIONAL / df;
assertEquals(computed, expected, TOL);
}
//-------------------------------------------------------------------------
public void test_dirtyPriceNominalPriceFromCurvesSensitivity() {
PointSensitivities point = PRICER.dirtyNominalPriceSensitivity(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected =
fdPriceSensitivity(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_dirtyPriceNominalPriceFromCurvesSensitivity_exCoupon() {
PointSensitivities point = PRICER.dirtyNominalPriceSensitivity(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected =
fdPriceSensitivity(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_dirtyPriceNominalPriceFromCurvesSensitivityWithZSpread() {
PointSensitivities point = PRICER.dirtyNominalPriceSensitivityWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = fdPriceSensitivityWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
public void test_dirtyPriceNominalPriceFromCurvesSensitivityWithZSpread_exCoupon() {
PointSensitivities point = PRICER.dirtyNominalPriceSensitivityWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, REF_DATA, Z_SPREAD, CONTINUOUS, 0).build();
CurrencyParameterSensitivities computed1 = RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities computed2 = ISSUER_RATES_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = fdPriceSensitivityWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0);
assertTrue(expected.equalWithTolerance(computed1.combinedWith(computed2), EPS * NOTIONAL));
}
//-------------------------------------------------------------------------
public void test_currencyExposure() {
MultiCurrencyAmount computed = PRICER.currencyExposure(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, VALUATION);
PointSensitivities point = PRICER.presentValueSensitivity(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER).build();
MultiCurrencyAmount expected = RATES_PROVIDER.currencyExposure(point)
.plus(PRICER.presentValue(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER));
assertEquals(computed.getCurrencies().size(), 1);
assertEquals(computed.getAmount(USD).getAmount(), expected.getAmount(USD).getAmount(), NOTIONAL * TOL);
}
public void test_currencyExposure_exCoupon() {
MultiCurrencyAmount computed =
PRICER.currencyExposure(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, VALUATION);
PointSensitivities point =
PRICER.presentValueSensitivity(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER).build();
MultiCurrencyAmount expected = RATES_PROVIDER.currencyExposure(point)
.plus(PRICER.presentValue(PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER));
assertEquals(computed.getCurrencies().size(), 1);
assertEquals(computed.getAmount(USD).getAmount(), expected.getAmount(USD).getAmount(), NOTIONAL * TOL);
}
public void test_currencyExposureWithZSpread() {
MultiCurrencyAmount computed = PRICER.currencyExposureWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, VALUATION, Z_SPREAD, CONTINUOUS, 0);
PointSensitivities point = PRICER.presentValueSensitivityWithZSpread(
PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0).build();
MultiCurrencyAmount expected = RATES_PROVIDER.currencyExposure(point).plus(
PRICER.presentValueWithZSpread(PRODUCT, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, CONTINUOUS, 0));
assertEquals(computed.getCurrencies().size(), 1);
assertEquals(computed.getAmount(USD).getAmount(), expected.getAmount(USD).getAmount(), NOTIONAL * TOL);
}
public void test_currencyExposureWithZSpread_exCoupon() {
MultiCurrencyAmount computed = PRICER.currencyExposureWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, VALUATION, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
PointSensitivities point = PRICER.presentValueSensitivityWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR).build();
MultiCurrencyAmount expected = RATES_PROVIDER.currencyExposure(point).plus(PRICER.presentValueWithZSpread(
PRODUCT_EX_COUPON, RATES_PROVIDER, ISSUER_RATES_PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR));
assertEquals(computed.getCurrencies().size(), 1);
assertEquals(computed.getAmount(USD).getAmount(), expected.getAmount(USD).getAmount(), NOTIONAL * TOL);
}
//-------------------------------------------------------------------------
public void test_currentCash() {
CurrencyAmount computed = PRICER.currentCash(PRODUCT, RATES_PROVIDER, VALUATION);
assertEquals(computed.getAmount(), 0d);
}
public void test_currentCash_exCoupon() {
CurrencyAmount computed = PRICER.currentCash(PRODUCT_EX_COUPON, RATES_PROVIDER, VALUATION);
assertEquals(computed.getAmount(), 0d);
}
public void test_currentCash_onPayment() {
CurrencyAmount computed = PRICER.currentCash(PRODUCT, RATES_PROVIDER_ON_PAY, VALUATION_ON_PAY.minusDays(7));
double expected = PERIOD_PRICER.forecastValue(PRODUCT.getPeriodicPayments().get(15), RATES_PROVIDER_ON_PAY);
assertEquals(computed.getAmount(), expected);
}
public void test_currentCash_onPayment_exCoupon() {
CurrencyAmount computed = PRICER.currentCash(PRODUCT_EX_COUPON, RATES_PROVIDER_ON_PAY, VALUATION_ON_PAY);
assertEquals(computed.getAmount(), 0d);
}
//-------------------------------------------------------------------------
public void test_dirtyPriceFromStandardYield() {
double yield = 0.0175;
LocalDate standardSettle = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double computed = PRICER.dirtyPriceFromStandardYield(PRODUCT, RATES_PROVIDER, standardSettle, yield);
Schedule sch = SCHEDULE.createSchedule(REF_DATA).toUnadjusted();
CapitalIndexedBondPaymentPeriod period = PRODUCT.getPeriodicPayments().get(16);
double factorPeriod =
ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate(), sch);
double factorSpot = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), standardSettle, sch);
double factorToNext = (factorPeriod - factorSpot) / factorPeriod;
double dscFactor = 1d / (1d + 0.5 * yield);
double expected = Math.pow(dscFactor, 3);
for (int i = 0; i < 4; ++i) {
expected += REAL_COUPON_VALUE * Math.pow(dscFactor, i);
}
expected *= Math.pow(dscFactor, factorToNext);
assertEquals(computed, expected, TOL);
}
public void test_modifiedDurationFromStandardYield() {
double yield = 0.0175;
LocalDate standardSettle = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double computed =
PRICER.modifiedDurationFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield);
double price = PRICER.dirtyPriceFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield);
double up = PRICER.dirtyPriceFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield + EPS);
double dw = PRICER.dirtyPriceFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield - EPS);
double expected = -0.5 * (up - dw) / price / EPS;
assertEquals(computed, expected, EPS);
}
public void test_convexityFromStandardYield() {
double yield = 0.0175;
LocalDate standardSettle = SETTLE_OFFSET.adjust(VALUATION, REF_DATA);
double computed = PRICER.convexityFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield);
double md = PRICER.modifiedDurationFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield);
double up = PRICER.modifiedDurationFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield + EPS);
double dw = PRICER.modifiedDurationFromStandardYield(PRODUCT_EX_COUPON, RATES_PROVIDER, standardSettle, yield - EPS);
double expected = -0.5 * (up - dw) / EPS + md * md;
assertEquals(computed, expected, EPS);
double computed1 = PRICER.convexityFromStandardYield(PRODUCT, RATES_PROVIDER, VALUATION, yield);
double md1 = PRICER.modifiedDurationFromStandardYield(PRODUCT, RATES_PROVIDER, VALUATION, yield);
double up1 = PRICER.modifiedDurationFromStandardYield(PRODUCT, RATES_PROVIDER, VALUATION, yield + EPS);
double dw1 = PRICER.modifiedDurationFromStandardYield(PRODUCT, RATES_PROVIDER, VALUATION, yield - EPS);
double expected1 = -0.5 * (up1 - dw1) / EPS + md1 * md1;
assertEquals(computed1, expected1, EPS);
}
//-------------------------------------------------------------------------
public void test_accruedInterest() {
LocalDate refDate = LocalDate.of(2014, 6, 10);
double computed = PRODUCT.accruedInterest(refDate);
Schedule sch = SCHEDULE.createSchedule(REF_DATA).toUnadjusted();
CapitalIndexedBondPaymentPeriod period = PRODUCT.getPeriodicPayments().get(16);
double factor = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), refDate, sch);
assertEquals(computed, factor * REAL_COUPON_VALUE * NOTIONAL * 2d, TOL * REAL_COUPON_VALUE * NOTIONAL);
}
public void test_accruedInterest_onPayment() {
CapitalIndexedBondPaymentPeriod period = PRODUCT.getPeriodicPayments().get(16);
LocalDate refDate = period.getPaymentDate();
double computed = PRODUCT.accruedInterest(refDate);
assertEquals(computed, 0d, TOL * REAL_COUPON_VALUE * NOTIONAL);
}
public void test_accruedInterest_before() {
LocalDate refDate = LocalDate.of(2003, 1, 22);
double computed = PRODUCT.accruedInterest(refDate);
assertEquals(computed, 0d, TOL * REAL_COUPON_VALUE * NOTIONAL);
}
public void test_accruedInterest_exCoupon_in() {
CapitalIndexedBondPaymentPeriod period = PRODUCT_EX_COUPON.getPeriodicPayments().get(16);
LocalDate refDate = period.getDetachmentDate();
double computed = PRODUCT_EX_COUPON.accruedInterest(refDate);
Schedule sch = SCHEDULE.createSchedule(REF_DATA).toUnadjusted();
double factor = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), refDate, sch);
double factorTotal =
ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate(), sch);
assertEquals(computed, (factor - factorTotal) * REAL_COUPON_VALUE * NOTIONAL * 2d,
TOL * REAL_COUPON_VALUE * NOTIONAL);
}
public void test_accruedInterest_exCoupon_out() {
LocalDate refDate = LocalDate.of(2014, 6, 10);
CapitalIndexedBondPaymentPeriod period = PRODUCT_EX_COUPON.getPeriodicPayments().get(16);
double computed = PRODUCT_EX_COUPON.accruedInterest(refDate);
Schedule sch = SCHEDULE.createSchedule(REF_DATA).toUnadjusted();
double factor = ACT_ACT_ICMA.relativeYearFraction(period.getUnadjustedStartDate(), refDate, sch);
assertEquals(computed, factor * REAL_COUPON_VALUE * NOTIONAL * 2d, TOL * REAL_COUPON_VALUE * NOTIONAL);
}
//-------------------------------------------------------------------------
public void test_cleanRealPrice_dirtyRealPrice() {
double dirtyRealPrice = 1.055;
LocalDate refDate = LocalDate.of(2014, 6, 10);
double cleanRealPrice = PRICER.cleanRealPriceFromDirtyRealPrice(PRODUCT, refDate, dirtyRealPrice);
double expected = dirtyRealPrice - PRODUCT.accruedInterest(refDate) / NOTIONAL;
assertEquals(cleanRealPrice, expected, TOL);
assertEquals(PRICER.dirtyRealPriceFromCleanRealPrice(PRODUCT, refDate, cleanRealPrice), dirtyRealPrice, TOL);
}
public void test_realPrice_nominalPrice_settleBefore() {
double realPrice = 1.055;
LocalDate refDate = LocalDate.of(2014, 6, 10);
double nominalPrice = PRICER.nominalPriceFromRealPrice(PRODUCT, RATES_PROVIDER_ON_PAY, refDate, realPrice);
RateComputation obs = RATE_CALC.createRateComputation(refDate);
double refRate = RateComputationFn.standard().rate(obs, null, null, RATES_PROVIDER_ON_PAY);
double expected = realPrice * (refRate + 1d);
assertEquals(nominalPrice, expected, TOL);
assertEquals(PRICER.realPriceFromNominalPrice(PRODUCT, RATES_PROVIDER_ON_PAY, refDate, nominalPrice),
realPrice, TOL);
}
public void test_realPrice_nominalPrice_settleAfter() {
double realPrice = 1.055;
LocalDate refDate = LocalDate.of(2014, 6, 10);
double nominalPrice = PRICER.nominalPriceFromRealPrice(PRODUCT, RATES_PROVIDER, refDate, realPrice);
RateComputation obs = RATE_CALC.createRateComputation(VALUATION);
double refRate = RateComputationFn.standard().rate(obs, null, null, RATES_PROVIDER);
double expected = realPrice * (refRate + 1d);
assertEquals(nominalPrice, expected, TOL);
assertEquals(PRICER.realPriceFromNominalPrice(PRODUCT, RATES_PROVIDER, refDate, nominalPrice), realPrice, TOL);
}
public void test_cleanNominalPrice_dirtyNominalPrice() {
double dirtyNominalPrice = 1.055;
LocalDate refDate = LocalDate.of(2014, 6, 10);
double cleanNominalPrice =
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT, RATES_PROVIDER, refDate, dirtyNominalPrice);
RateComputation obs = RATE_CALC.createRateComputation(VALUATION);
double refRate = RateComputationFn.standard().rate(obs, null, null, RATES_PROVIDER);
double expected = dirtyNominalPrice - PRODUCT.accruedInterest(refDate) * (refRate + 1d) / NOTIONAL;
assertEquals(cleanNominalPrice, expected, TOL);
assertEquals(PRICER.dirtyNominalPriceFromCleanNominalPrice(PRODUCT, RATES_PROVIDER, refDate, cleanNominalPrice),
dirtyNominalPrice, TOL);
}
//-------------------------------------------------------------------------
private static final double NTNL = 1_000_000d;
private static final LocalDate VAL_DATE = LocalDate.of(2016, 2, 29);
private static final ImmutableRatesProvider RATES_PROVS_US =
CapitalIndexedBondCurveDataSet.getRatesProvider(VAL_DATE, CapitalIndexedBondCurveDataSet.getTimeSeries(VAL_DATE));
private static final LegalEntityDiscountingProvider ISSUER_PROVS_US =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProvider(VAL_DATE);
private static final double START_INDEX_US = 218.085;
private static final double CPN_VALUE_US = 0.0125 * 0.5;
private static final ValueSchedule CPN_US = ValueSchedule.of(CPN_VALUE_US);
private static final InflationRateCalculation RATE_CALC_US = InflationRateCalculation.builder()
.gearing(CPN_US)
.index(US_CPI_U)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED)
.firstIndexValue(START_INDEX_US)
.build();
private static final LocalDate START_USD = LocalDate.of(2010, 7, 15);
private static final LocalDate END_USD = LocalDate.of(2020, 7, 15);
private static final DaysAdjustment SETTLE_OFFSET_US = DaysAdjustment.ofBusinessDays(1, USNY);
private static final PeriodicSchedule SCHEDULE_US =
PeriodicSchedule.of(START_USD, END_USD, FREQUENCY, BUSINESS_ADJUST, StubConvention.NONE, RollConventions.NONE);
private static final ResolvedCapitalIndexedBond PRODUCT_US = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(USD)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC_US)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(US_IL_REAL)
.settlementDateOffset(SETTLE_OFFSET_US)
.accrualSchedule(SCHEDULE_US)
.build()
.resolve(REF_DATA);
private static final double YIELD_US = -0.00189;
public void test_priceFromRealYield_us() {
LocalDate standardSettle = PRODUCT_US.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.cleanPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US);
assertEquals(computed, 1.06, 1.e-2);
double computedSmall =
PRICER.cleanPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, 0.0);
assertEquals(computedSmall, 1.05, 1.e-2);
double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US);
double cleanPrice = PRICER.cleanRealPriceFromDirtyRealPrice(PRODUCT_US, standardSettle, dirtyPrice);
assertEquals(computed, cleanPrice);
double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_US, RATES_PROVS_US, standardSettle, dirtyPrice);
assertEquals(yieldRe, YIELD_US, TOL);
}
public void test_modifiedDuration_convexity_us() {
double eps = 1.0e-5;
LocalDate standardSettle = PRODUCT_US.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double mdComputed =
PRICER.modifiedDurationFromRealYieldFiniteDifference(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US);
double cvComputed =
PRICER.convexityFromRealYieldFiniteDifference(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US);
double price = PRICER.cleanPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US);
double up = PRICER.cleanPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US + eps);
double dw = PRICER.cleanPriceFromRealYield(PRODUCT_US, RATES_PROVS_US, standardSettle, YIELD_US - eps);
assertEquals(mdComputed, 0.5 * (dw - up) / eps / price, eps);
assertEquals(cvComputed, (up + dw - 2d * price) / price / eps / eps, eps);
}
public void test_realYieldFromCurves_us() {
LocalDate standardSettle = PRODUCT_US.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.realYieldFromCurves(PRODUCT_US, RATES_PROVS_US, ISSUER_PROVS_US, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurves(
PRODUCT_US, RATES_PROVS_US, ISSUER_PROVS_US, REF_DATA);
double dirtyRealPrice =
PRICER.realPriceFromNominalPrice(PRODUCT_US, RATES_PROVS_US, standardSettle, dirtyNominalPrice);
double expected = PRICER.realYieldFromDirtyPrice(PRODUCT_US, RATES_PROVS_US, standardSettle, dirtyRealPrice);
assertEquals(computed, expected, TOL);
}
public void zSpreadFromCurvesAndCleanPrice_us() {
LocalDate standardSettle = PRODUCT_US.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_US, RATES_PROVS_US, ISSUER_PROVS_US, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double cleanRealPrice = PRICER.realPriceFromNominalPrice(PRODUCT_US, RATES_PROVS_US, standardSettle,
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT_US, RATES_PROVS_US, standardSettle, dirtyNominalPrice));
double computed = PRICER.zSpreadFromCurvesAndCleanPrice(
PRODUCT_US, RATES_PROVS_US, ISSUER_PROVS_US, REF_DATA, cleanRealPrice, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_accruedInterest_us() {
double accPositive = PRODUCT_US.accruedInterest(LocalDate.of(2016, 7, 14));
assertEquals(accPositive, 6216d, 1.0);
double accZero = PRODUCT_US.accruedInterest(LocalDate.of(2016, 7, 15));
assertEquals(accZero, 0d);
}
//-------------------------------------------------------------------------
private static final LocalDate VAL_DATE_GB = LocalDate.of(2016, 3, 1);
private static final ImmutableRatesProvider RATES_PROVS_GB = CapitalIndexedBondCurveDataSet.getRatesProviderGb(
VAL_DATE_GB, CapitalIndexedBondCurveDataSet.getTimeSeriesGb(VAL_DATE_GB));
private static final LegalEntityDiscountingProvider ISSUER_PROVS_GB =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProviderGb(VAL_DATE_GB);
private static final double START_INDEX_GOV = 82.966;
private static final double CPN_VALUE_GOV = 0.025 * 0.5;
private static final ValueSchedule CPN_GOV = ValueSchedule.of(CPN_VALUE_GOV);
private static final InflationRateCalculation RATE_CALC_GOV = InflationRateCalculation.builder()
.gearing(CPN_GOV)
.index(GB_RPI)
.lag(Period.ofMonths(8))
.indexCalculationMethod(MONTHLY)
.firstIndexValue(START_INDEX_GOV)
.build();
private static final LocalDate START_GOV = LocalDate.of(1983, 10, 16);
private static final LocalDate END_GOV = LocalDate.of(2020, 4, 16);
private static final BusinessDayAdjustment BUSINESS_ADJUST_GOV =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, GBLO);
private static final DaysAdjustment SETTLE_OFFSET_GB = DaysAdjustment.ofBusinessDays(1, GBLO);
private static final PeriodicSchedule SCHEDULE_GOV =
PeriodicSchedule.of(START_GOV, END_GOV, FREQUENCY, BUSINESS_ADJUST_GOV, StubConvention.NONE, RollConventions.NONE);
private static final BusinessDayAdjustment EX_COUPON_ADJ_GOV =
BusinessDayAdjustment.of(BusinessDayConventions.PRECEDING, GBLO);
private static final DaysAdjustment EX_COUPON_GOV = DaysAdjustment.ofCalendarDays(-8, EX_COUPON_ADJ_GOV);
private static final ResolvedCapitalIndexedBond PRODUCT_GOV = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(GBP)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC_GOV)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(GB_IL_FLOAT)
.settlementDateOffset(SETTLE_OFFSET_GB)
.accrualSchedule(SCHEDULE_GOV)
.exCouponPeriod(EX_COUPON_GOV)
.build()
.resolve(REF_DATA);
private static final double YIELD_GOV = -0.01532;
private static final double START_INDEX_GOV_OP = 81.623;
private static final LocalDate START_GOV_OP = LocalDate.of(1983, 1, 26);
private static final LocalDate END_GOV_OP = LocalDate.of(2016, 7, 26);
private static final PeriodicSchedule SCHEDULE_GOV_OP = PeriodicSchedule.of(
START_GOV_OP, END_GOV_OP, FREQUENCY, BUSINESS_ADJUST_GOV, StubConvention.NONE, RollConventions.NONE);
private static final ResolvedCapitalIndexedBond PRODUCT_GOV_OP = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(GBP)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC_GOV.toBuilder().firstIndexValue(START_INDEX_GOV_OP).build())
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(GB_IL_FLOAT)
.settlementDateOffset(SETTLE_OFFSET_GB)
.accrualSchedule(SCHEDULE_GOV_OP)
.exCouponPeriod(EX_COUPON_GOV)
.build()
.resolve(REF_DATA);
private static final double YIELD_GOV_OP = -0.0244;
public void test_priceFromRealYield_ukGov() {
LocalDate standardSettle = PRODUCT_GOV.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double computed = PRICER.cleanPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV);
assertEquals(computed, 3.60, 1.e-2);
double computedOnePeriod = PRICER.cleanPriceFromRealYield(PRODUCT_GOV_OP, RATES_PROVS_GB, PRODUCT_GOV_OP
.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA), YIELD_GOV_OP);
assertEquals(computedOnePeriod, 3.21, 4.e-2);
double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV);
double cleanPrice = PRICER.cleanNominalPriceFromDirtyNominalPrice(
PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyPrice);
assertEquals(computed, cleanPrice);
double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyPrice);
assertEquals(yieldRe, YIELD_GOV, TOL);
}
public void test_modifiedDuration_convexity_ukGov() {
double eps = 1.0e-5;
LocalDate standardSettle = PRODUCT_GOV.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double mdComputed =
PRICER.modifiedDurationFromRealYieldFiniteDifference(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV);
double cvComputed =
PRICER.convexityFromRealYieldFiniteDifference(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV);
double price = PRICER.cleanPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV);
double up = PRICER.cleanPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV + eps);
double dw = PRICER.cleanPriceFromRealYield(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, YIELD_GOV - eps);
assertEquals(mdComputed, 0.5 * (dw - up) / eps / price, eps);
assertEquals(cvComputed, (up + dw - 2d * price) / price / eps / eps, eps);
}
public void test_realYieldFromCurves_ukGov() {
LocalDate standardSettle = PRODUCT_GOV.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double computed = PRICER.realYieldFromCurves(PRODUCT_GOV, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurves(
PRODUCT_GOV, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA);
double expected = PRICER.realYieldFromDirtyPrice(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyNominalPrice);
assertEquals(computed, expected, TOL);
}
public void zSpreadFromCurvesAndCleanPrice_ukGov() {
LocalDate standardSettle = PRODUCT_GOV.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_GOV, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double cleanNominalPrice =
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT_GOV, RATES_PROVS_GB, standardSettle, dirtyNominalPrice);
double computed = PRICER.zSpreadFromCurvesAndCleanPrice(
PRODUCT_GOV, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA, cleanNominalPrice, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_accruedInterest_ukGov() {
double accPositive = PRODUCT_GOV.accruedInterest(LocalDate.of(2016, 4, 7));
assertEquals(accPositive, 11885d, 1.0);
double accNegative = PRODUCT_GOV.accruedInterest(LocalDate.of(2016, 4, 8));
assertEquals(accNegative, -546.44, 1.0e-2);
double accZero = PRODUCT_GOV.accruedInterest(LocalDate.of(2016, 4, 16));
assertEquals(accZero, 0d);
}
//-------------------------------------------------------------------------
private static final double START_INDEX_CORP = 216.52;
private static final double CPN_VALUE_CORP = 0.00625 * 0.5;
private static final ValueSchedule CPN_CORP = ValueSchedule.of(CPN_VALUE_CORP);
private static final InflationRateCalculation RATE_CALC_CORP = InflationRateCalculation.builder()
.gearing(CPN_CORP)
.index(GB_RPI)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED)
.firstIndexValue(START_INDEX_CORP)
.build();
private static final LocalDate START_CORP = LocalDate.of(2010, 3, 22);
private static final LocalDate END_CORP = LocalDate.of(2040, 3, 22);
private static final BusinessDayAdjustment BUSINESS_ADJUST_CORP =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, GBLO);
private static final PeriodicSchedule SCHEDULE_CORP =
PeriodicSchedule.of(START_CORP, END_CORP, FREQUENCY, BUSINESS_ADJUST_CORP, StubConvention.NONE,
RollConventions.NONE);
private static final BusinessDayAdjustment EX_COUPON_ADJ_CORP =
BusinessDayAdjustment.of(BusinessDayConventions.PRECEDING, GBLO);
private static final DaysAdjustment EX_COUPON_CORP = DaysAdjustment.ofCalendarDays(-8, EX_COUPON_ADJ_CORP);
private static final ResolvedCapitalIndexedBond PRODUCT_CORP = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(GBP)
.dayCount(ACT_ACT_ICMA)
.rateCalculation(RATE_CALC_CORP)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(GB_IL_BOND)
.settlementDateOffset(SETTLE_OFFSET_GB)
.accrualSchedule(SCHEDULE_CORP)
.exCouponPeriod(EX_COUPON_CORP)
.build()
.resolve(REF_DATA);
private static final double YIELD_CORP = -0.00842;
public void test_priceFromRealYield_ukCorp() {
LocalDate standardSettle = PRODUCT_CORP.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double computed = PRICER.cleanPriceFromRealYield(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP);
assertEquals(computed, 1.39, 1.e-2);
double computedOnePeriod = PRICER.cleanPriceFromRealYield(
PRODUCT_CORP, RATES_PROVS_GB, LocalDate.of(2039, 12, 1), -0.02842);
assertEquals(computedOnePeriod, 1.01, 1.e-2);
double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP);
double cleanPrice = PRICER.cleanRealPriceFromDirtyRealPrice(PRODUCT_CORP, standardSettle, dirtyPrice);
assertEquals(computed, cleanPrice);
double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, dirtyPrice);
assertEquals(yieldRe, YIELD_CORP, TOL);
}
public void test_modifiedDuration_convexity_ukCor() {
double eps = 1.0e-5;
LocalDate standardSettle = PRODUCT_CORP.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double mdComputed =
PRICER.modifiedDurationFromRealYieldFiniteDifference(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP);
double cvComputed =
PRICER.convexityFromRealYieldFiniteDifference(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP);
double price = PRICER.cleanPriceFromRealYield(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP);
double up = PRICER.cleanPriceFromRealYield(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP + eps);
double dw = PRICER.cleanPriceFromRealYield(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, YIELD_CORP - eps);
assertEquals(mdComputed, 0.5 * (dw - up) / eps / price, eps);
assertEquals(cvComputed, (up + dw - 2d * price) / price / eps / eps, eps);
}
public void test_realYieldFromCurves_ukCor() {
LocalDate standardSettle = PRODUCT_CORP.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double computed = PRICER.realYieldFromCurves(PRODUCT_CORP, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurves(
PRODUCT_CORP, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA);
double dirtyRealPrice =
PRICER.realPriceFromNominalPrice(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, dirtyNominalPrice);
double expected = PRICER.realYieldFromDirtyPrice(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, dirtyRealPrice);
assertEquals(computed, expected, TOL);
}
public void zSpreadFromCurvesAndCleanPrice_ukCor() {
LocalDate standardSettle = PRODUCT_CORP.getSettlementDateOffset().adjust(VAL_DATE_GB, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_CORP, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double cleanRealPrice = PRICER.realPriceFromNominalPrice(PRODUCT_CORP, RATES_PROVS_GB, standardSettle,
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT_CORP, RATES_PROVS_GB, standardSettle, dirtyNominalPrice));
double computed = PRICER.zSpreadFromCurvesAndCleanPrice(
PRODUCT_CORP, RATES_PROVS_GB, ISSUER_PROVS_GB, REF_DATA, cleanRealPrice, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_accruedInterest_ukCor() {
double accPositive = PRODUCT_CORP.accruedInterest(LocalDate.of(2016, 3, 13));
assertEquals(accPositive, 2971d, 1.0);
double accNegative = PRODUCT_CORP.accruedInterest(LocalDate.of(2016, 3, 14));
assertEquals(accNegative, -137.37, 1.0e-2);
double accZero = PRODUCT_CORP.accruedInterest(LocalDate.of(2016, 3, 22));
assertEquals(accZero, 0d);
}
//-------------------------------------------------------------------------
private static final ImmutableRatesProvider RATES_PROVS_JP = CapitalIndexedBondCurveDataSet.getRatesProviderJp(
VAL_DATE, CapitalIndexedBondCurveDataSet.getTimeSeriesJp(VAL_DATE));
private static final LegalEntityDiscountingProvider ISSUER_PROVS_JP =
CapitalIndexedBondCurveDataSet.getLegalEntityDiscountingProviderJp(VAL_DATE);
private static final double START_INDEX_JPI = 103.2d;
private static final double CPN_VALUE_JPI = 0.001 * 0.5;
private static final ValueSchedule CPN_JPI = ValueSchedule.of(CPN_VALUE_JPI);
private static final InflationRateCalculation RATE_CALC_JPI = InflationRateCalculation.builder()
.gearing(CPN_JPI)
.index(JP_CPI_EXF)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED_JAPAN)
.firstIndexValue(START_INDEX_JPI)
.build();
private static final LocalDate START_JPI = LocalDate.of(2015, 3, 10);
private static final LocalDate END_JPI = LocalDate.of(2025, 3, 10);
private static final BusinessDayAdjustment BUSINESS_ADJUST_JPI =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, JPTO);
private static final DaysAdjustment SETTLE_OFFSET_JPI = DaysAdjustment.ofBusinessDays(2, JPTO);
private static final PeriodicSchedule SCHEDULE_JPI =
PeriodicSchedule
.of(START_JPI, END_JPI, FREQUENCY, BUSINESS_ADJUST_JPI, StubConvention.NONE, RollConventions.NONE);
private static final ResolvedCapitalIndexedBond PRODUCT_JPI = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(JPY)
.dayCount(NL_365)
.rateCalculation(RATE_CALC_JPI)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(JP_IL_SIMPLE)
.settlementDateOffset(SETTLE_OFFSET_JPI)
.accrualSchedule(SCHEDULE_JPI)
.build()
.resolve(REF_DATA);
private static final double YIELD_JPI = -0.00309;
public void test_priceFromRealYield_jpi() {
LocalDate standardSettle = PRODUCT_JPI.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.cleanPriceFromRealYield(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI);
assertEquals(computed, 1.04, 1.e-2);
double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI);
double cleanPrice = PRICER.cleanRealPriceFromDirtyRealPrice(PRODUCT_JPI, standardSettle, dirtyPrice);
assertEquals(computed, cleanPrice);
double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, dirtyPrice);
assertEquals(yieldRe, YIELD_JPI, TOL);
}
public void test_modifiedDuration_convexity_jpi() {
double eps = 1.0e-5;
LocalDate standardSettle = PRODUCT_JPI.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double mdComputed =
PRICER.modifiedDurationFromRealYieldFiniteDifference(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI);
double cvComputed =
PRICER.convexityFromRealYieldFiniteDifference(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI);
double price = PRICER.cleanPriceFromRealYield(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI);
double up = PRICER.cleanPriceFromRealYield(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI + eps);
double dw = PRICER.cleanPriceFromRealYield(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, YIELD_JPI - eps);
assertEquals(mdComputed, 0.5 * (dw - up) / eps / price, eps);
assertEquals(cvComputed, (up + dw - 2d * price) / price / eps / eps, eps);
}
public void test_realYieldFromCurves_jpi() {
LocalDate standardSettle = PRODUCT_JPI.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.realYieldFromCurves(PRODUCT_JPI, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA);
double dirtyNominalPrice =
PRICER.dirtyNominalPriceFromCurves(PRODUCT_JPI, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA);
double dirtyRealPrice =
PRICER.realPriceFromNominalPrice(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, dirtyNominalPrice);
double expected = PRICER.realYieldFromDirtyPrice(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, dirtyRealPrice);
assertEquals(computed, expected, TOL);
}
public void zSpreadFromCurvesAndCleanPrice_jpi() {
LocalDate standardSettle = PRODUCT_JPI.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_JPI, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double cleanRealPrice = PRICER.realPriceFromNominalPrice(PRODUCT_JPI, RATES_PROVS_JP, standardSettle,
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT_JPI, RATES_PROVS_JP, standardSettle, dirtyNominalPrice));
double computed = PRICER.zSpreadFromCurvesAndCleanPrice(
PRODUCT_JPI, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA, cleanRealPrice, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_accruedInterest_jpi() {
double accPositive = PRODUCT_JPI.accruedInterest(LocalDate.of(2016, 3, 9));
CapitalIndexedBondPaymentPeriod period = PRODUCT_JPI.getPeriodicPayments().get(1);
double yc = PRODUCT_JPI.getDayCount().relativeYearFraction(period.getStartDate(), period.getEndDate());
double expected = CPN_VALUE_JPI * 2d * yc * NTNL; // accrual of total period based on ACT/365F
assertEquals(accPositive, expected, TOL * NTNL);
double accZero = PRODUCT_JPI.accruedInterest(LocalDate.of(2016, 3, 10));
assertEquals(accZero, 0d);
}
//-------------------------------------------------------------------------
private static final double START_INDEX_JPW = 100.0d;
private static final double CPN_VALUE_JPW = 0.008 * 0.5;
private static final ValueSchedule CPN_JPW = ValueSchedule.of(CPN_VALUE_JPW);
private static final InflationRateCalculation RATE_CALC_JPW = InflationRateCalculation.builder()
.gearing(CPN_JPW)
.index(JP_CPI_EXF)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED_JAPAN)
.firstIndexValue(START_INDEX_JPW)
.build();
private static final LocalDate START_JPW = LocalDate.of(2013, 9, 10);
private static final LocalDate END_JPW = LocalDate.of(2023, 9, 10);
private static final BusinessDayAdjustment BUSINESS_ADJUST_JPW =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, JPTO);
private static final DaysAdjustment SETTLE_OFFSET_JPW = DaysAdjustment.ofBusinessDays(2, JPTO);
private static final PeriodicSchedule SCHEDULE_JPW =
PeriodicSchedule
.of(START_JPW, END_JPW, FREQUENCY, BUSINESS_ADJUST_JPW, StubConvention.NONE, RollConventions.NONE);
private static final ResolvedCapitalIndexedBond PRODUCT_JPW = CapitalIndexedBond.builder()
.securityId(SECURITY_ID)
.notional(NTNL)
.currency(JPY)
.dayCount(NL_365)
.rateCalculation(RATE_CALC_JPW)
.legalEntityId(LEGAL_ENTITY)
.yieldConvention(JP_IL_COMPOUND)
.settlementDateOffset(SETTLE_OFFSET_JPW)
.accrualSchedule(SCHEDULE_JPW)
.build()
.resolve(REF_DATA);
private static final double YIELD_JPW = -0.005;
public void test_priceFromRealYield_jpw() {
LocalDate standardSettle = PRODUCT_JPW.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.cleanPriceFromRealYield(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW);
assertEquals(computed, 1.10, 1.e-2);
double dirtyPrice = PRICER.dirtyPriceFromRealYield(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW);
double cleanPrice = PRICER.cleanRealPriceFromDirtyRealPrice(PRODUCT_JPW, standardSettle, dirtyPrice);
assertEquals(computed, cleanPrice);
double yieldRe = PRICER.realYieldFromDirtyPrice(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, dirtyPrice);
assertEquals(yieldRe, YIELD_JPW, TOL);
}
public void test_modifiedDuration_convexity_jpw() {
double eps = 1.0e-5;
LocalDate standardSettle = PRODUCT_JPW.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double mdComputed =
PRICER.modifiedDurationFromRealYieldFiniteDifference(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW);
double cvComputed =
PRICER.convexityFromRealYieldFiniteDifference(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW);
double price = PRICER.cleanPriceFromRealYield(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW);
double up = PRICER.cleanPriceFromRealYield(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW + eps);
double dw = PRICER.cleanPriceFromRealYield(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, YIELD_JPW - eps);
assertEquals(mdComputed, 0.5 * (dw - up) / eps / price, eps);
assertEquals(cvComputed, (up + dw - 2d * price) / price / eps / eps, eps);
}
public void test_realYieldFromCurves_jpw() {
LocalDate standardSettle = PRODUCT_JPW.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double computed = PRICER.realYieldFromCurves(PRODUCT_JPW, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurves(
PRODUCT_JPW, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA);
double dirtyRealPrice =
PRICER.realPriceFromNominalPrice(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, dirtyNominalPrice);
double expected = PRICER.realYieldFromDirtyPrice(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, dirtyRealPrice);
assertEquals(computed, expected, TOL);
}
public void zSpreadFromCurvesAndCleanPrice_jpw() {
LocalDate standardSettle = PRODUCT_JPW.getSettlementDateOffset().adjust(VAL_DATE, REF_DATA);
double dirtyNominalPrice = PRICER.dirtyNominalPriceFromCurvesWithZSpread(
PRODUCT_JPW, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR);
double cleanRealPrice = PRICER.realPriceFromNominalPrice(PRODUCT_JPW, RATES_PROVS_JP, standardSettle,
PRICER.cleanNominalPriceFromDirtyNominalPrice(PRODUCT_JPW, RATES_PROVS_JP, standardSettle, dirtyNominalPrice));
double computed = PRICER.zSpreadFromCurvesAndCleanPrice(
PRODUCT_JPW, RATES_PROVS_JP, ISSUER_PROVS_JP, REF_DATA, cleanRealPrice, PERIODIC, PERIOD_PER_YEAR);
assertEquals(computed, Z_SPREAD, TOL);
}
public void test_accruedInterest_jpw() {
double accPositive = PRODUCT_JPW.accruedInterest(LocalDate.of(2016, 3, 9));
CapitalIndexedBondPaymentPeriod period = PRODUCT_JPW.getPeriodicPayments().get(4);
double yc = PRODUCT_JPW.getDayCount().relativeYearFraction(period.getStartDate(), period.getEndDate());
double expected = CPN_VALUE_JPW * 2d * yc * NTNL; // accrual of total period based on ACT/365F
assertEquals(accPositive, expected, NTNL * NOTIONAL);
double accZero = PRODUCT_JPW.accruedInterest(LocalDate.of(2016, 3, 10));
assertEquals(accZero, 0d);
}
//-------------------------------------------------------------------------
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdPvSensitivity(
ResolvedCapitalIndexedBond product,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider) {
CurrencyParameterSensitivities sensi1 =
FD_CAL.sensitivity(issuerRatesProvider, p -> PRICER.presentValue(product, ratesProvider, p));
CurrencyParameterSensitivities sensi2 =
FD_CAL.sensitivity(ratesProvider, p -> PRICER.presentValue(product, p, issuerRatesProvider));
return sensi1.combinedWith(sensi2);
}
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdPvSensitivityWithZSpread(
ResolvedCapitalIndexedBond product,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(
issuerRatesProvider,
p -> PRICER.presentValueWithZSpread(product, ratesProvider, p, zSpread, compoundedRateType, periodsPerYear));
CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(
ratesProvider,
p -> PRICER.presentValueWithZSpread(product, p, issuerRatesProvider, zSpread, compoundedRateType,
periodsPerYear));
return sensi1.combinedWith(sensi2);
}
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdPriceSensitivity(
ResolvedCapitalIndexedBond bond,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider) {
CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(
issuerRatesProvider,
p -> CurrencyAmount.of(USD, PRICER.dirtyNominalPriceFromCurves(bond, ratesProvider, p, REF_DATA)));
CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(
ratesProvider,
p -> CurrencyAmount.of(USD, PRICER.dirtyNominalPriceFromCurves(bond, p, issuerRatesProvider, REF_DATA)));
return sensi1.combinedWith(sensi2);
}
// computes sensitivity with finite difference approximation
private CurrencyParameterSensitivities fdPriceSensitivityWithZSpread(
ResolvedCapitalIndexedBond bond,
ImmutableRatesProvider ratesProvider,
LegalEntityDiscountingProvider issuerRatesProvider,
double zSpread,
CompoundedRateType compoundedRateType,
int periodsPerYear) {
CurrencyParameterSensitivities sensi1 = FD_CAL.sensitivity(issuerRatesProvider,
p -> CurrencyAmount.of(USD, PRICER.dirtyNominalPriceFromCurvesWithZSpread(
bond, ratesProvider, p, REF_DATA, zSpread, compoundedRateType, periodsPerYear)));
CurrencyParameterSensitivities sensi2 = FD_CAL.sensitivity(ratesProvider,
p -> CurrencyAmount.of(USD, PRICER.dirtyNominalPriceFromCurvesWithZSpread(
bond, p, issuerRatesProvider, REF_DATA, zSpread, compoundedRateType, periodsPerYear)));
return sensi1.combinedWith(sensi2);
}
}