/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.swaption;
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.THIRTY_U_360;
import static com.opengamma.strata.basics.index.IborIndices.EUR_EURIBOR_6M;
import static com.opengamma.strata.basics.schedule.Frequency.P12M;
import static com.opengamma.strata.basics.schedule.Frequency.P6M;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.dateUtc;
import static com.opengamma.strata.product.common.LongShort.LONG;
import static com.opengamma.strata.product.common.LongShort.SHORT;
import static com.opengamma.strata.product.common.PayReceive.PAY;
import static com.opengamma.strata.product.common.PayReceive.RECEIVE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.date.AdjustableDate;
import com.opengamma.strata.basics.date.BusinessDayAdjustment;
import com.opengamma.strata.basics.date.DaysAdjustment;
import com.opengamma.strata.basics.date.HolidayCalendarId;
import com.opengamma.strata.basics.date.HolidayCalendarIds;
import com.opengamma.strata.basics.schedule.PeriodicSchedule;
import com.opengamma.strata.basics.schedule.RollConventions;
import com.opengamma.strata.basics.schedule.StubConvention;
import com.opengamma.strata.basics.value.ValueSchedule;
import com.opengamma.strata.collect.DoubleArrayMath;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivity;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.math.impl.statistics.distribution.NormalDistribution;
import com.opengamma.strata.math.impl.statistics.distribution.ProbabilityDistribution;
import com.opengamma.strata.pricer.impl.rate.swap.CashFlowEquivalentCalculator;
import com.opengamma.strata.pricer.index.HullWhiteIborFutureDataSet;
import com.opengamma.strata.pricer.model.HullWhiteOneFactorPiecewiseConstantParameters;
import com.opengamma.strata.pricer.model.HullWhiteOneFactorPiecewiseConstantParametersProvider;
import com.opengamma.strata.pricer.rate.ImmutableRatesProvider;
import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator;
import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer;
import com.opengamma.strata.pricer.swap.SwapPaymentEventPricer;
import com.opengamma.strata.product.common.LongShort;
import com.opengamma.strata.product.swap.FixedRateCalculation;
import com.opengamma.strata.product.swap.IborRateCalculation;
import com.opengamma.strata.product.swap.NotionalSchedule;
import com.opengamma.strata.product.swap.SwapPaymentEvent;
import com.opengamma.strata.product.swap.PaymentSchedule;
import com.opengamma.strata.product.swap.RateCalculationSwapLeg;
import com.opengamma.strata.product.swap.ResolvedSwap;
import com.opengamma.strata.product.swap.ResolvedSwapLeg;
import com.opengamma.strata.product.swap.Swap;
import com.opengamma.strata.product.swap.SwapLeg;
import com.opengamma.strata.product.swaption.CashSwaptionSettlement;
import com.opengamma.strata.product.swaption.CashSwaptionSettlementMethod;
import com.opengamma.strata.product.swaption.PhysicalSwaptionSettlement;
import com.opengamma.strata.product.swaption.ResolvedSwaption;
import com.opengamma.strata.product.swaption.Swaption;
/**
* Test {@link HullWhiteSwaptionPhysicalProductPricer}.
*/
@Test
public class HullWhiteSwaptionPhysicalProductPricerTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final ZonedDateTime MATURITY = dateUtc(2016, 7, 7);
private static final HolidayCalendarId CALENDAR = HolidayCalendarIds.SAT_SUN;
private static final BusinessDayAdjustment BDA_MF = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, CALENDAR);
private static final LocalDate SETTLE =
BDA_MF.adjust(CALENDAR.resolve(REF_DATA).shift(MATURITY.toLocalDate(), 2), REF_DATA);
private static final double NOTIONAL = 100000000; //100m
private static final int TENOR_YEAR = 5;
private static final LocalDate END = SETTLE.plusYears(TENOR_YEAR);
private static final double RATE = 0.0175;
private static final PeriodicSchedule PERIOD_FIXED = PeriodicSchedule.builder()
.startDate(SETTLE)
.endDate(END)
.frequency(P12M)
.businessDayAdjustment(BDA_MF)
.stubConvention(StubConvention.SHORT_FINAL)
.rollConvention(RollConventions.EOM)
.build();
private static final PaymentSchedule PAYMENT_FIXED = PaymentSchedule.builder()
.paymentFrequency(P12M)
.paymentDateOffset(DaysAdjustment.NONE)
.build();
private static final FixedRateCalculation RATE_FIXED = FixedRateCalculation.builder()
.dayCount(THIRTY_U_360)
.rate(ValueSchedule.of(RATE))
.build();
private static final PeriodicSchedule PERIOD_IBOR = PeriodicSchedule.builder()
.startDate(SETTLE)
.endDate(END)
.frequency(P6M)
.businessDayAdjustment(BDA_MF)
.stubConvention(StubConvention.SHORT_FINAL)
.rollConvention(RollConventions.EOM)
.build();
private static final PaymentSchedule PAYMENT_IBOR = PaymentSchedule.builder()
.paymentFrequency(P6M)
.paymentDateOffset(DaysAdjustment.NONE)
.build();
private static final IborRateCalculation RATE_IBOR = IborRateCalculation.builder()
.index(EUR_EURIBOR_6M)
.fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CALENDAR, BDA_MF))
.build();
private static final SwapLeg FIXED_LEG_REC = RateCalculationSwapLeg.builder()
.payReceive(RECEIVE)
.accrualSchedule(PERIOD_FIXED)
.paymentSchedule(PAYMENT_FIXED)
.notionalSchedule(NotionalSchedule.of(EUR, NOTIONAL))
.calculation(RATE_FIXED)
.build();
private static final SwapLeg FIXED_LEG_PAY = RateCalculationSwapLeg.builder()
.payReceive(PAY)
.accrualSchedule(PERIOD_FIXED)
.paymentSchedule(PAYMENT_FIXED)
.notionalSchedule(NotionalSchedule.of(EUR, NOTIONAL))
.calculation(RATE_FIXED)
.build();
private static final SwapLeg IBOR_LEG_REC = RateCalculationSwapLeg.builder()
.payReceive(RECEIVE)
.accrualSchedule(PERIOD_IBOR)
.paymentSchedule(PAYMENT_IBOR)
.notionalSchedule(NotionalSchedule.of(EUR, NOTIONAL))
.calculation(RATE_IBOR)
.build();
private static final SwapLeg IBOR_LEG_PAY = RateCalculationSwapLeg.builder()
.payReceive(PAY)
.accrualSchedule(PERIOD_IBOR)
.paymentSchedule(PAYMENT_IBOR)
.notionalSchedule(NotionalSchedule.of(EUR, NOTIONAL))
.calculation(RATE_IBOR)
.build();
private static final Swap SWAP_REC = Swap.of(FIXED_LEG_REC, IBOR_LEG_PAY);
private static final ResolvedSwap RSWAP_REC = SWAP_REC.resolve(REF_DATA);
private static final Swap SWAP_PAY = Swap.of(FIXED_LEG_PAY, IBOR_LEG_REC);
private static final ResolvedSwap RSWAP_PAY = SWAP_PAY.resolve(REF_DATA);
private static final CashSwaptionSettlement PAR_YIELD =
CashSwaptionSettlement.of(SETTLE, CashSwaptionSettlementMethod.PAR_YIELD);
private static final ResolvedSwaption SWAPTION_REC_LONG = Swaption
.builder()
.expiryDate(AdjustableDate.of(MATURITY.toLocalDate(), BDA_MF))
.expiryTime(MATURITY.toLocalTime())
.expiryZone(MATURITY.getZone())
.swaptionSettlement(PhysicalSwaptionSettlement.DEFAULT)
.longShort(LONG)
.underlying(SWAP_REC)
.build().
resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_REC_SHORT = Swaption
.builder()
.expiryDate(AdjustableDate.of(MATURITY.toLocalDate(), BDA_MF))
.expiryTime(MATURITY.toLocalTime())
.expiryZone(MATURITY.getZone())
.swaptionSettlement(PhysicalSwaptionSettlement.DEFAULT)
.longShort(SHORT)
.underlying(SWAP_REC)
.build().
resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_PAY_LONG = Swaption
.builder()
.expiryDate(AdjustableDate.of(MATURITY.toLocalDate(), BDA_MF))
.expiryTime(MATURITY.toLocalTime())
.expiryZone(MATURITY.getZone())
.swaptionSettlement(PhysicalSwaptionSettlement.DEFAULT)
.longShort(LONG)
.underlying(SWAP_PAY)
.build().
resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_PAY_SHORT = Swaption
.builder()
.expiryDate(AdjustableDate.of(MATURITY.toLocalDate(), BDA_MF))
.expiryTime(MATURITY.toLocalTime())
.expiryZone(MATURITY.getZone())
.swaptionSettlement(PhysicalSwaptionSettlement.DEFAULT)
.longShort(SHORT)
.underlying(SWAP_PAY)
.build().
resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_CASH = Swaption.builder()
.expiryDate(AdjustableDate.of(MATURITY.toLocalDate()))
.expiryTime(MATURITY.toLocalTime())
.expiryZone(MATURITY.getZone())
.longShort(LongShort.LONG)
.swaptionSettlement(PAR_YIELD)
.underlying(SWAP_REC)
.build().
resolve(REF_DATA);
private static final LocalDate VALUATION = LocalDate.of(2011, 7, 7);
private static final HullWhiteOneFactorPiecewiseConstantParametersProvider HW_PROVIDER =
HullWhiteIborFutureDataSet.createHullWhiteProvider(VALUATION);
private static final HullWhiteOneFactorPiecewiseConstantParametersProvider HW_PROVIDER_AT_MATURITY =
HullWhiteIborFutureDataSet.createHullWhiteProvider(MATURITY.toLocalDate());
private static final HullWhiteOneFactorPiecewiseConstantParametersProvider HW_PROVIDER_AFTER_MATURITY =
HullWhiteIborFutureDataSet.createHullWhiteProvider(MATURITY.toLocalDate().plusDays(1));
private static final ImmutableRatesProvider RATE_PROVIDER = HullWhiteIborFutureDataSet.createRatesProvider(VALUATION);
private static final ImmutableRatesProvider RATES_PROVIDER_AT_MATURITY = HullWhiteIborFutureDataSet
.createRatesProvider(MATURITY.toLocalDate());
private static final ImmutableRatesProvider RATES_PROVIDER_AFTER_MATURITY = HullWhiteIborFutureDataSet
.createRatesProvider(MATURITY.toLocalDate().plusDays(1));
private static final double TOL = 1.0e-12;
private static final double FD_TOL = 1.0e-7;
private static final HullWhiteSwaptionPhysicalProductPricer PRICER = HullWhiteSwaptionPhysicalProductPricer.DEFAULT;
private static final DiscountingSwapProductPricer SWAP_PRICER = DiscountingSwapProductPricer.DEFAULT;
private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL =
new RatesFiniteDifferenceSensitivityCalculator(FD_TOL);
private static final ProbabilityDistribution<Double> NORMAL = new NormalDistribution(0, 1);
//-------------------------------------------------------------------------
public void validate_physical_settlement() {
assertThrowsIllegalArg(() -> PRICER.presentValue(SWAPTION_CASH, RATE_PROVIDER, HW_PROVIDER));
}
//-------------------------------------------------------------------------
public void test_presentValue() {
CurrencyAmount computedRec = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
CurrencyAmount computedPay = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
SwapPaymentEventPricer<SwapPaymentEvent> paymentEventPricer = SwapPaymentEventPricer.standard();
ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(RSWAP_REC, RATE_PROVIDER);
LocalDate expiryDate = MATURITY.toLocalDate();
int nPayments = cashFlowEquiv.getPaymentEvents().size();
double[] alpha = new double[nPayments];
double[] discountedCashFlow = new double[nPayments];
for (int loopcf = 0; loopcf < nPayments; loopcf++) {
SwapPaymentEvent payment = cashFlowEquiv.getPaymentEvents().get(loopcf);
alpha[loopcf] = HW_PROVIDER.alpha(RATE_PROVIDER.getValuationDate(), expiryDate, expiryDate, payment.getPaymentDate());
discountedCashFlow[loopcf] = paymentEventPricer.presentValue(payment, RATE_PROVIDER);
}
double omegaPay = -1d;
double kappa = HW_PROVIDER.getModel().kappa(DoubleArray.copyOf(discountedCashFlow), DoubleArray.copyOf(alpha));
double expectedRec = 0.0;
double expectedPay = 0.0;
for (int loopcf = 0; loopcf < nPayments; loopcf++) {
expectedRec += discountedCashFlow[loopcf] * NORMAL.getCDF((kappa + alpha[loopcf]));
expectedPay += discountedCashFlow[loopcf] * NORMAL.getCDF(omegaPay * (kappa + alpha[loopcf]));
}
assertEquals(computedRec.getCurrency(), EUR);
assertEquals(computedRec.getAmount(), expectedRec, NOTIONAL * TOL);
assertEquals(computedPay.getCurrency(), EUR);
assertEquals(computedPay.getAmount(), expectedPay, NOTIONAL * TOL);
}
public void test_presentValue_atMaturity() {
CurrencyAmount computedRec =
PRICER.presentValue(SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
CurrencyAmount computedPay =
PRICER.presentValue(SWAPTION_PAY_SHORT, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
double swapPv = SWAP_PRICER.presentValue(RSWAP_REC, RATES_PROVIDER_AT_MATURITY).getAmount(EUR).getAmount();
assertEquals(computedRec.getAmount(), swapPv, NOTIONAL * TOL);
assertEquals(computedPay.getAmount(), 0d, NOTIONAL * TOL);
}
public void test_presentValue_afterExpiry() {
CurrencyAmount computedRec =
PRICER.presentValue(SWAPTION_REC_LONG, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
CurrencyAmount computedPay =
PRICER.presentValue(SWAPTION_PAY_SHORT, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
assertEquals(computedRec.getAmount(), 0d, NOTIONAL * TOL);
assertEquals(computedPay.getAmount(), 0d, NOTIONAL * TOL);
}
public void test_presentValue_parity() {
CurrencyAmount pvRecLong = PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
CurrencyAmount pvRecShort = PRICER.presentValue(SWAPTION_REC_SHORT, RATE_PROVIDER, HW_PROVIDER);
CurrencyAmount pvPayLong = PRICER.presentValue(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER);
CurrencyAmount pvPayShort = PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
assertEquals(pvRecLong.getAmount(), -pvRecShort.getAmount(), NOTIONAL * TOL);
assertEquals(pvPayLong.getAmount(), -pvPayShort.getAmount(), NOTIONAL * TOL);
double swapPv = SWAP_PRICER.presentValue(RSWAP_PAY, RATE_PROVIDER).getAmount(EUR).getAmount();
assertEquals(pvPayLong.getAmount() - pvRecLong.getAmount(), swapPv, NOTIONAL * TOL);
assertEquals(pvPayShort.getAmount() - pvRecShort.getAmount(), -swapPv, NOTIONAL * TOL);
}
//-------------------------------------------------------------------------
public void test_currencyExposure() {
MultiCurrencyAmount computedRec = PRICER.currencyExposure(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
MultiCurrencyAmount computedPay = PRICER.currencyExposure(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
PointSensitivityBuilder pointRec =
PRICER.presentValueSensitivityRates(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
MultiCurrencyAmount expectedRec = RATE_PROVIDER.currencyExposure(pointRec.build())
.plus(PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER));
assertEquals(computedRec.size(), 1);
assertEquals(computedRec.getAmount(EUR).getAmount(), expectedRec.getAmount(EUR).getAmount(), NOTIONAL * TOL);
PointSensitivityBuilder pointPay =
PRICER.presentValueSensitivityRates(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
MultiCurrencyAmount expectedPay = RATE_PROVIDER.currencyExposure(pointPay.build())
.plus(PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER));
assertEquals(computedPay.size(), 1);
assertEquals(computedPay.getAmount(EUR).getAmount(), expectedPay.getAmount(EUR).getAmount(), NOTIONAL * TOL);
}
public void test_currencyExposure_atMaturity() {
MultiCurrencyAmount computedRec = PRICER.currencyExposure(
SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
MultiCurrencyAmount computedPay = PRICER.currencyExposure(
SWAPTION_PAY_SHORT, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
PointSensitivityBuilder pointRec =
PRICER.presentValueSensitivityRates(SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
MultiCurrencyAmount expectedRec = RATE_PROVIDER.currencyExposure(pointRec.build())
.plus(PRICER.presentValue(SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY));
assertEquals(computedRec.size(), 1);
assertEquals(computedRec.getAmount(EUR).getAmount(), expectedRec.getAmount(EUR).getAmount(), NOTIONAL * TOL);
PointSensitivityBuilder pointPay =
PRICER.presentValueSensitivityRates(SWAPTION_PAY_SHORT, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
MultiCurrencyAmount expectedPay = RATE_PROVIDER.currencyExposure(pointPay.build())
.plus(PRICER.presentValue(SWAPTION_PAY_SHORT, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY));
assertEquals(computedPay.size(), 1);
assertEquals(computedPay.getAmount(EUR).getAmount(), expectedPay.getAmount(EUR).getAmount(), NOTIONAL * TOL);
}
public void test_currencyExposure_afterMaturity() {
MultiCurrencyAmount computedRec = PRICER.currencyExposure(
SWAPTION_REC_LONG, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
MultiCurrencyAmount computedPay = PRICER.currencyExposure(
SWAPTION_PAY_SHORT, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
assertEquals(computedRec.size(), 1);
assertEquals(computedRec.getAmount(EUR).getAmount(), 0d, NOTIONAL * TOL);
assertEquals(computedPay.size(), 1);
assertEquals(computedPay.getAmount(EUR).getAmount(), 0d, NOTIONAL * TOL);
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivity() {
PointSensitivityBuilder pointRec =
PRICER.presentValueSensitivityRates(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
CurrencyParameterSensitivities computedRec = RATE_PROVIDER.parameterSensitivity(pointRec.build());
CurrencyParameterSensitivities expectedRec =
FD_CAL.sensitivity(RATE_PROVIDER, (p) -> PRICER.presentValue(SWAPTION_REC_LONG, (p), HW_PROVIDER));
assertTrue(computedRec.equalWithTolerance(expectedRec, NOTIONAL * FD_TOL * 1000d));
PointSensitivityBuilder pointPay =
PRICER.presentValueSensitivityRates(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
CurrencyParameterSensitivities computedPay = RATE_PROVIDER.parameterSensitivity(pointPay.build());
CurrencyParameterSensitivities expectedPay =
FD_CAL.sensitivity(RATE_PROVIDER, (p) -> PRICER.presentValue(SWAPTION_PAY_SHORT, (p), HW_PROVIDER));
assertTrue(computedPay.equalWithTolerance(expectedPay, NOTIONAL * FD_TOL * 1000d));
}
public void test_presentValueSensitivity_atMaturity() {
PointSensitivityBuilder pointRec =
PRICER.presentValueSensitivityRates(SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
CurrencyParameterSensitivities computedRec =
RATES_PROVIDER_AT_MATURITY.parameterSensitivity(pointRec.build());
CurrencyParameterSensitivities expectedRec = FD_CAL.sensitivity(
RATES_PROVIDER_AT_MATURITY, (p) -> PRICER.presentValue(SWAPTION_REC_LONG, (p), HW_PROVIDER_AT_MATURITY));
assertTrue(computedRec.equalWithTolerance(expectedRec, NOTIONAL * FD_TOL * 1000d));
PointSensitivities pointPay = PRICER.presentValueSensitivityRates(SWAPTION_PAY_SHORT,
RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY).build();
for (PointSensitivity sensi : pointPay.getSensitivities()) {
assertEquals(Math.abs(sensi.getSensitivity()), 0d);
}
}
public void test_presentValueSensitivity_afterMaturity() {
PointSensitivities pointRec = PRICER.presentValueSensitivityRates(
SWAPTION_REC_LONG, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY).build();
for (PointSensitivity sensi : pointRec.getSensitivities()) {
assertEquals(Math.abs(sensi.getSensitivity()), 0d);
}
PointSensitivities pointPay = PRICER.presentValueSensitivityRates(
SWAPTION_PAY_SHORT, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY).build();
for (PointSensitivity sensi : pointPay.getSensitivities()) {
assertEquals(Math.abs(sensi.getSensitivity()), 0d);
}
}
public void test_presentValueSensitivity_parity() {
CurrencyParameterSensitivities pvSensiRecLong = RATE_PROVIDER.parameterSensitivity(
PRICER.presentValueSensitivityRates(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER).build());
CurrencyParameterSensitivities pvSensiRecShort = RATE_PROVIDER.parameterSensitivity(
PRICER.presentValueSensitivityRates(SWAPTION_REC_SHORT, RATE_PROVIDER, HW_PROVIDER).build());
CurrencyParameterSensitivities pvSensiPayLong = RATE_PROVIDER.parameterSensitivity(
PRICER.presentValueSensitivityRates(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER).build());
CurrencyParameterSensitivities pvSensiPayShort = RATE_PROVIDER.parameterSensitivity(
PRICER.presentValueSensitivityRates(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER).build());
assertTrue(pvSensiRecLong.equalWithTolerance(pvSensiRecShort.multipliedBy(-1d), NOTIONAL * TOL));
assertTrue(pvSensiPayLong.equalWithTolerance(pvSensiPayShort.multipliedBy(-1d), NOTIONAL * TOL));
PointSensitivities expectedPoint = SWAP_PRICER.presentValueSensitivity(RSWAP_PAY, RATE_PROVIDER).build();
CurrencyParameterSensitivities expected = RATE_PROVIDER.parameterSensitivity(expectedPoint);
assertTrue(expected.equalWithTolerance(pvSensiPayLong.combinedWith(pvSensiRecLong.multipliedBy(-1d)), NOTIONAL * TOL));
assertTrue(expected.equalWithTolerance(pvSensiRecShort.combinedWith(pvSensiPayShort.multipliedBy(-1d)), NOTIONAL * TOL));
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivityHullWhiteParameter() {
DoubleArray computedRec =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
DoubleArray computedPay =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
DoubleArray vols = HW_PROVIDER.getParameters().getVolatility();
int size = vols.size();
double[] expectedRec = new double[size];
double[] expectedPay = new double[size];
for (int i = 0; i < size; ++i) {
double[] volsUp = vols.toArray();
double[] volsDw = vols.toArray();
volsUp[i] += FD_TOL;
volsDw[i] -= FD_TOL;
HullWhiteOneFactorPiecewiseConstantParameters paramsUp = HullWhiteOneFactorPiecewiseConstantParameters.of(
HW_PROVIDER.getParameters().getMeanReversion(), DoubleArray.copyOf(volsUp), HW_PROVIDER.getParameters()
.getVolatilityTime().subArray(1, size));
HullWhiteOneFactorPiecewiseConstantParameters paramsDw = HullWhiteOneFactorPiecewiseConstantParameters.of(
HW_PROVIDER.getParameters().getMeanReversion(), DoubleArray.copyOf(volsDw), HW_PROVIDER.getParameters()
.getVolatilityTime().subArray(1, size));
HullWhiteOneFactorPiecewiseConstantParametersProvider provUp = HullWhiteOneFactorPiecewiseConstantParametersProvider
.of(paramsUp, HW_PROVIDER.getDayCount(), HW_PROVIDER.getValuationDateTime());
HullWhiteOneFactorPiecewiseConstantParametersProvider provDw = HullWhiteOneFactorPiecewiseConstantParametersProvider
.of(paramsDw, HW_PROVIDER.getDayCount(), HW_PROVIDER.getValuationDateTime());
expectedRec[i] = 0.5 * (PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, provUp).getAmount() -
PRICER.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, provDw).getAmount()) / FD_TOL;
expectedPay[i] = 0.5 * (PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, provUp).getAmount() -
PRICER.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, provDw).getAmount()) / FD_TOL;
}
assertTrue(DoubleArrayMath.fuzzyEquals(computedRec.toArray(), expectedRec, NOTIONAL * FD_TOL));
assertTrue(DoubleArrayMath.fuzzyEquals(computedPay.toArray(), expectedPay, NOTIONAL * FD_TOL));
}
public void test_presentValueSensitivityHullWhiteParameter_atMaturity() {
DoubleArray pvSensiRec = PRICER.presentValueSensitivityModelParamsHullWhite(
SWAPTION_REC_LONG, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
assertTrue(pvSensiRec.equalZeroWithTolerance(NOTIONAL * TOL));
DoubleArray pvSensiPay = PRICER.presentValueSensitivityModelParamsHullWhite(
SWAPTION_PAY_SHORT, RATES_PROVIDER_AT_MATURITY, HW_PROVIDER_AT_MATURITY);
assertTrue(pvSensiPay.equalZeroWithTolerance(NOTIONAL * TOL));
}
public void test_presentValueSensitivityHullWhiteParameter_afterMaturity() {
DoubleArray pvSensiRec = PRICER.presentValueSensitivityModelParamsHullWhite(
SWAPTION_REC_LONG, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
assertTrue(pvSensiRec.equalZeroWithTolerance(NOTIONAL * TOL));
DoubleArray pvSensiPay = PRICER.presentValueSensitivityModelParamsHullWhite(
SWAPTION_PAY_SHORT, RATES_PROVIDER_AFTER_MATURITY, HW_PROVIDER_AFTER_MATURITY);
assertTrue(pvSensiPay.equalZeroWithTolerance(NOTIONAL * TOL));
}
public void test_presentValueSensitivityHullWhiteParameter_parity() {
DoubleArray pvSensiRecLong =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_REC_LONG, RATE_PROVIDER, HW_PROVIDER);
DoubleArray pvSensiRecShort =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_REC_SHORT, RATE_PROVIDER, HW_PROVIDER);
DoubleArray pvSensiPayLong =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER);
DoubleArray pvSensiPayShort =
PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_PAY_SHORT, RATE_PROVIDER, HW_PROVIDER);
assertTrue(pvSensiRecLong.equalWithTolerance(pvSensiRecShort.multipliedBy(-1d), NOTIONAL * TOL));
assertTrue(pvSensiPayLong.equalWithTolerance(pvSensiPayShort.multipliedBy(-1d), NOTIONAL * TOL));
assertTrue(pvSensiPayLong.equalWithTolerance(pvSensiRecLong, NOTIONAL * TOL));
assertTrue(pvSensiRecShort.equalWithTolerance(pvSensiPayShort, NOTIONAL * TOL));
}
//-------------------------------------------------------------------------
public void regression_pv() {
CurrencyAmount pv = PRICER.presentValue(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER);
assertEquals(pv.getAmount(), 4213670.335092038, NOTIONAL * TOL);
}
public void regression_curveSensitivity() {
PointSensitivities point = PRICER.presentValueSensitivityRates(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER).build();
CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point);
double[] dscExp = new double[] {0.0, 0.0, 0.0, 0.0, -1.4127023229222856E7, -1.744958350376594E7};
double[] fwdExp = new double[] {0.0, 0.0, 0.0, 0.0, -2.0295973516660026E8, 4.12336887967829E8};
assertTrue(DoubleArrayMath.fuzzyEquals(computed.getSensitivity(HullWhiteIborFutureDataSet.DSC_NAME, EUR)
.getSensitivity().toArray(), dscExp, NOTIONAL * TOL));
assertTrue(DoubleArrayMath.fuzzyEquals(computed.getSensitivity(HullWhiteIborFutureDataSet.FWD6_NAME, EUR)
.getSensitivity().toArray(), fwdExp, NOTIONAL * TOL));
}
public void regression_hullWhiteSensitivity() {
DoubleArray computed = PRICER.presentValueSensitivityModelParamsHullWhite(SWAPTION_PAY_LONG, RATE_PROVIDER, HW_PROVIDER);
double[] expected = new double[] {
2.9365484063149095E7, 3.262667329294093E7, 7.226220286364576E7, 2.4446925038968167E8, 120476.73820821749};
assertTrue(DoubleArrayMath.fuzzyEquals(computed.toArray(), expected, NOTIONAL * TOL));
}
}