/**
* 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.USD;
import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_3M;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.date;
import static com.opengamma.strata.product.common.BuySell.BUY;
import static com.opengamma.strata.product.common.BuySell.SELL;
import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.USD_FIXED_6M_LIBOR_3M;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
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.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.market.surface.ConstantSurface;
import com.opengamma.strata.market.surface.Surface;
import com.opengamma.strata.pricer.datasets.RatesProviderDataSets;
import com.opengamma.strata.pricer.impl.option.BlackFormulaRepository;
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.product.common.LongShort;
import com.opengamma.strata.product.swap.ResolvedSwap;
import com.opengamma.strata.product.swap.Swap;
import com.opengamma.strata.product.swap.SwapLegType;
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;
import com.opengamma.strata.product.swaption.SwaptionSettlement;
/**
* Tests {@link BlackSwaptionPhysicalProductPricer}.
*/
@Test
public class BlackSwaptionPhysicalProductPricerTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final LocalDate VAL_DATE = date(2015, 8, 7);
private static final LocalDate SWAPTION_EXERCISE_DATE = VAL_DATE.plusYears(5);
private static final LocalDate SWAPTION_PAST_EXERCISE_DATE = VAL_DATE.minusYears(1);
private static final LocalTime SWAPTION_EXPIRY_TIME = LocalTime.of(11, 0);
private static final ZoneId SWAPTION_EXPIRY_ZONE = ZoneId.of("America/New_York");
private static final LocalDate SWAP_EFFECTIVE_DATE =
USD_LIBOR_3M.calculateEffectiveFromFixing(SWAPTION_EXERCISE_DATE, REF_DATA);
private static final int SWAP_TENOR_YEAR = 5;
private static final Period SWAP_TENOR = Period.ofYears(SWAP_TENOR_YEAR);
private static final LocalDate SWAP_MATURITY_DATE = SWAP_EFFECTIVE_DATE.plus(SWAP_TENOR);
private static final double STRIKE = 0.01;
private static final double NOTIONAL = 100_000_000;
private static final Swap SWAP_REC = USD_FIXED_6M_LIBOR_3M
.toTrade(VAL_DATE, SWAP_EFFECTIVE_DATE, SWAP_MATURITY_DATE, SELL, NOTIONAL, STRIKE).getProduct();
private static final ResolvedSwap RSWAP_REC = SWAP_REC.resolve(REF_DATA);
private static final Swap SWAP_PAY = USD_FIXED_6M_LIBOR_3M
.toTrade(VAL_DATE, SWAP_EFFECTIVE_DATE, SWAP_MATURITY_DATE, BUY, NOTIONAL, STRIKE).getProduct();
private static final ResolvedSwap RSWAP_PAY = SWAP_PAY.resolve(REF_DATA);
private static final Swap SWAP_PAST = USD_FIXED_6M_LIBOR_3M // Only for checks; no actual computation on that swap
.toTrade(SWAPTION_PAST_EXERCISE_DATE, SWAPTION_PAST_EXERCISE_DATE, SWAPTION_PAST_EXERCISE_DATE.plusYears(10),
BUY, NOTIONAL, STRIKE).getProduct();
private static final SwaptionSettlement PHYSICAL_SETTLE = PhysicalSwaptionSettlement.DEFAULT;
private static final SwaptionSettlement CASH_SETTLE =
CashSwaptionSettlement.of(SWAP_REC.getStartDate().getUnadjusted(), CashSwaptionSettlementMethod.PAR_YIELD);
private static final ResolvedSwaption SWAPTION_LONG_REC = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(SWAPTION_EXERCISE_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_REC)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_SHORT_REC = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(SWAPTION_EXERCISE_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.SHORT)
.underlying(SWAP_REC)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_LONG_PAY = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(SWAPTION_EXERCISE_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_PAY)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_LONG_REC_CASH = Swaption.builder()
.swaptionSettlement(CASH_SETTLE)
.expiryDate(AdjustableDate.of(SWAPTION_EXERCISE_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_REC)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_REC_AT_EXPIRY = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(VAL_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_REC)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_PAY_AT_EXPIRY = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(VAL_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_PAY)
.build()
.resolve(REF_DATA);
private static final ResolvedSwaption SWAPTION_PAST = Swaption.builder()
.swaptionSettlement(PHYSICAL_SETTLE)
.expiryDate(AdjustableDate.of(SWAPTION_PAST_EXERCISE_DATE))
.expiryTime(SWAPTION_EXPIRY_TIME)
.expiryZone(SWAPTION_EXPIRY_ZONE)
.longShort(LongShort.LONG)
.underlying(SWAP_PAST)
.build()
.resolve(REF_DATA);
private static final BlackSwaptionPhysicalProductPricer PRICER_SWAPTION_BLACK =
BlackSwaptionPhysicalProductPricer.DEFAULT;
private static final DiscountingSwapProductPricer PRICER_SWAP = DiscountingSwapProductPricer.DEFAULT;
private static final double FD_SHIFT = 0.5E-8;
private static final RatesFiniteDifferenceSensitivityCalculator FINITE_DIFFERENCE_CALCULATOR =
new RatesFiniteDifferenceSensitivityCalculator(FD_SHIFT);
private static final ImmutableRatesProvider MULTI_USD = RatesProviderDataSets.multiUsd(VAL_DATE);
private static final BlackSwaptionExpiryTenorVolatilities BLACK_VOLS_CST_USD =
SwaptionBlackVolatilityDataSets.BLACK_SWAPTION_VOLS_CST_USD;
private static final BlackSwaptionExpiryTenorVolatilities BLACK_VOLS_USD_STD =
SwaptionBlackVolatilityDataSets.BLACK_SWAPTION_VOLS_USD_STD;
private static final double TOLERANCE_PV = 1.0E-2;
private static final double TOLERANCE_PV_DELTA = 1.0E+2;
private static final double TOLERANCE_PV_VEGA = 1.0E+4;
private static final double TOLERANCE_RATE = 1.0E-8;
//-------------------------------------------------------------------------
public void validate_physical_settlement() {
assertThrowsIllegalArg(() -> PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_REC_CASH, MULTI_USD,
BLACK_VOLS_USD_STD));
}
//-------------------------------------------------------------------------
public void test_implied_volatility() {
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
double volExpected = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(),
SWAP_TENOR_YEAR, STRIKE, forward);
double volComputed = PRICER_SWAPTION_BLACK
.impliedVolatility(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(volComputed, volExpected, TOLERANCE_RATE);
}
public void test_implied_volatility_after_expiry() {
assertThrowsIllegalArg(() -> PRICER_SWAPTION_BLACK.impliedVolatility(SWAPTION_PAST, MULTI_USD,
BLACK_VOLS_USD_STD));
}
//-------------------------------------------------------------------------
public void present_value_formula() {
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
double volatility = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(),
SWAP_TENOR_YEAR, STRIKE, forward);
double expiry = BLACK_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry());
double pvExpected = Math.abs(pvbp) * BlackFormulaRepository.price(forward, STRIKE, expiry, volatility, false);
CurrencyAmount pvComputed =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvComputed.getCurrency(), USD);
assertEquals(pvComputed.getAmount(), pvExpected, TOLERANCE_PV);
}
public void present_value_long_short_parity() {
CurrencyAmount pvLong =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvShort =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvLong.getAmount(), -pvShort.getAmount(), TOLERANCE_PV);
}
public void present_value_payer_receiver_parity() {
CurrencyAmount pvLongPay =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvShortRec =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
MultiCurrencyAmount pvSwapPay =
PRICER_SWAP.presentValue(RSWAP_PAY, MULTI_USD);
assertEquals(pvLongPay.getAmount() + pvShortRec.getAmount(), pvSwapPay.getAmount(USD).getAmount(), TOLERANCE_PV);
}
public void present_value_at_expiry() {
CurrencyAmount pvRec =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvRec.getAmount(), 0.0d, TOLERANCE_PV);
CurrencyAmount pvPay =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvPay.getAmount(), PRICER_SWAP.presentValue(RSWAP_PAY, MULTI_USD).getAmount(USD).getAmount(), TOLERANCE_PV);
}
public void present_value_after_expiry() {
CurrencyAmount pv = PRICER_SWAPTION_BLACK.presentValue(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pv.getAmount(), 0.0d, TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void present_value_delta_formula() {
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
double volatility = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(),
SWAP_TENOR_YEAR, STRIKE, forward);
double expiry = BLACK_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry());
double pvDeltaExpected = BlackFormulaRepository.delta(forward, STRIKE, expiry, volatility, false) * Math.abs(pvbp);
CurrencyAmount pvDeltaComputed =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvDeltaComputed.getCurrency(), USD);
assertEquals(pvDeltaComputed.getAmount(), pvDeltaExpected, TOLERANCE_PV);
}
public void present_value_delta_long_short_parity() {
CurrencyAmount pvDeltaLong =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvDeltaShort =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvDeltaLong.getAmount(), -pvDeltaShort.getAmount(), TOLERANCE_PV);
}
public void present_value_delta_payer_receiver_parity() {
CurrencyAmount pvDeltaLongPay =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvDeltaShortRec =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_PAY.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
assertEquals(pvDeltaLongPay.getAmount() + pvDeltaShortRec.getAmount(), Math.abs(pvbp), TOLERANCE_PV);
}
public void present_value_delta_at_expiry() {
CurrencyAmount pvDeltaRec =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvDeltaRec.getAmount(), 0d, TOLERANCE_PV);
CurrencyAmount pvDeltaPay =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_PAY.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
assertEquals(pvDeltaPay.getAmount(), Math.abs(pvbp), TOLERANCE_PV);
}
public void present_value_delta_after_expiry() {
CurrencyAmount pvDelta =
PRICER_SWAPTION_BLACK.presentValueDelta(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvDelta.getAmount(), 0d, TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void present_value_gamma_formula() {
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
double volatility = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(),
SWAP_TENOR_YEAR, STRIKE, forward);
double expiry = BLACK_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry());
double pvGammaExpected = BlackFormulaRepository.gamma(forward, STRIKE, expiry, volatility) * Math.abs(pvbp);
CurrencyAmount pvGammaComputed =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGammaComputed.getCurrency(), USD);
assertEquals(pvGammaComputed.getAmount(), pvGammaExpected, TOLERANCE_PV);
}
public void present_value_gamma_long_short_parity() {
CurrencyAmount pvGammaLong =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvGammaShort =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGammaLong.getAmount(), -pvGammaShort.getAmount(), TOLERANCE_PV);
}
public void present_value_gamma_payer_receiver_parity() {
CurrencyAmount pvGammaLongPay =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvGammaShortRec =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGammaLongPay.getAmount() + pvGammaShortRec.getAmount(), 0d, TOLERANCE_PV);
}
public void present_value_gamma_at_expiry() {
CurrencyAmount pvGammaRec =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGammaRec.getAmount(), 0d, TOLERANCE_PV);
CurrencyAmount pvGammaPay =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGammaPay.getAmount(), 0d, TOLERANCE_PV);
}
public void present_value_gamma_after_expiry() {
CurrencyAmount pvGamma =
PRICER_SWAPTION_BLACK.presentValueGamma(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvGamma.getAmount(), 0d, TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void present_value_theta_formula() {
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD);
double volatility = BLACK_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(),
SWAP_TENOR_YEAR, STRIKE, forward);
double expiry = BLACK_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry());
double pvThetaExpected = BlackFormulaRepository.driftlessTheta(forward, STRIKE, expiry, volatility) * Math.abs(pvbp);
CurrencyAmount pvThetaComputed =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvThetaComputed.getCurrency(), USD);
assertEquals(pvThetaComputed.getAmount(), pvThetaExpected, TOLERANCE_PV);
}
public void present_value_theta_long_short_parity() {
CurrencyAmount pvThetaLong =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvThetaShort =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvThetaLong.getAmount(), -pvThetaShort.getAmount(), TOLERANCE_PV);
}
public void present_value_theta_payer_receiver_parity() {
CurrencyAmount pvThetaLongPay =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
CurrencyAmount pvThetaShortRec =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvThetaLongPay.getAmount() + pvThetaShortRec.getAmount(), 0d, TOLERANCE_PV);
}
public void present_value_theta_at_expiry() {
CurrencyAmount pvThetaRec =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvThetaRec.getAmount(), 0d, TOLERANCE_PV);
CurrencyAmount pvThetaPay =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvThetaPay.getAmount(), 0d, TOLERANCE_PV);
}
public void present_value_theta_after_expiry() {
CurrencyAmount pvTheta =
PRICER_SWAPTION_BLACK.presentValueTheta(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvTheta.getAmount(), 0d, TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void currency_exposure() {
CurrencyAmount pv =
PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
MultiCurrencyAmount ce =
PRICER_SWAPTION_BLACK.currencyExposure(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pv.getAmount(), ce.getAmount(USD).getAmount(), TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void present_value_sensitivity_FD() {
PointSensitivities pvpt = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_CST_USD)
.build();
CurrencyParameterSensitivities pvpsAd = MULTI_USD.parameterSensitivity(pvpt);
CurrencyParameterSensitivities pvpsFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(MULTI_USD,
(p) -> PRICER_SWAPTION_BLACK.presentValue(SWAPTION_SHORT_REC, p, BLACK_VOLS_CST_USD));
assertTrue(pvpsAd.equalWithTolerance(pvpsFd, TOLERANCE_PV_DELTA));
}
public void present_value_sensitivity_long_short_parity() {
PointSensitivities pvptLong = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD).build();
PointSensitivities pvptShort = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD)
.build();
CurrencyParameterSensitivities pvpsLong = MULTI_USD.parameterSensitivity(pvptLong);
CurrencyParameterSensitivities pvpsShort = MULTI_USD.parameterSensitivity(pvptShort);
assertTrue(pvpsLong.equalWithTolerance(pvpsShort.multipliedBy(-1.0), TOLERANCE_PV_DELTA));
}
public void present_value_sensitivity_payer_receiver_parity() {
PointSensitivities pvptLongPay = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD).build();
PointSensitivities pvptShortRec = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD)
.build();
PointSensitivities pvptSwapRec = PRICER_SWAP.presentValueSensitivity(RSWAP_PAY, MULTI_USD).build();
CurrencyParameterSensitivities pvpsLongPay = MULTI_USD.parameterSensitivity(pvptLongPay);
CurrencyParameterSensitivities pvpsShortRec = MULTI_USD.parameterSensitivity(pvptShortRec);
CurrencyParameterSensitivities pvpsSwapRec = MULTI_USD.parameterSensitivity(pvptSwapRec);
assertTrue(pvpsLongPay.combinedWith(pvpsShortRec).equalWithTolerance(pvpsSwapRec, TOLERANCE_PV_DELTA));
}
public void present_value_sensitivity_at_expiry() {
PointSensitivities sensiRec = PRICER_SWAPTION_BLACK.presentValueSensitivityRatesStickyStrike(
SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD).build();
for (PointSensitivity sensi : sensiRec.getSensitivities()) {
assertEquals(Math.abs(sensi.getSensitivity()), 0d);
}
PointSensitivities sensiPay = PRICER_SWAPTION_BLACK.presentValueSensitivityRatesStickyStrike(
SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD).build();
PointSensitivities sensiPaySwap = PRICER_SWAP.presentValueSensitivity(RSWAP_PAY, MULTI_USD).build();
assertTrue(MULTI_USD.parameterSensitivity(sensiPay).equalWithTolerance(
MULTI_USD.parameterSensitivity(sensiPaySwap), TOLERANCE_PV));
}
public void present_value_sensitivity_after_expiry() {
PointSensitivityBuilder pvpts = PRICER_SWAPTION_BLACK
.presentValueSensitivityRatesStickyStrike(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvpts, PointSensitivityBuilder.none());
}
//-------------------------------------------------------------------------
public void present_value_sensitivityBlackVolatility_FD() {
double shiftVol = 1.0E-4;
Surface surfaceUp = ConstantSurface.of(
SwaptionBlackVolatilityDataSets.META_DATA, SwaptionBlackVolatilityDataSets.VOLATILITY + shiftVol);
Surface surfaceDw = ConstantSurface.of(
SwaptionBlackVolatilityDataSets.META_DATA, SwaptionBlackVolatilityDataSets.VOLATILITY - shiftVol);
CurrencyAmount pvP = PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_PAY, MULTI_USD,
BlackSwaptionExpiryTenorVolatilities.of(
BLACK_VOLS_CST_USD.getConvention(), VAL_DATE.atStartOfDay(ZoneOffset.UTC), surfaceUp));
CurrencyAmount pvM = PRICER_SWAPTION_BLACK.presentValue(SWAPTION_LONG_PAY, MULTI_USD,
BlackSwaptionExpiryTenorVolatilities.of(
BLACK_VOLS_CST_USD.getConvention(), VAL_DATE.atStartOfDay(ZoneOffset.UTC), surfaceDw));
double pvnvsFd = (pvP.getAmount() - pvM.getAmount()) / (2 * shiftVol);
SwaptionSensitivity pvnvsAd = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_CST_USD);
assertEquals(pvnvsAd.getCurrency(), USD);
assertEquals(pvnvsAd.getSensitivity(), pvnvsFd, TOLERANCE_PV_VEGA);
assertEquals(pvnvsAd.getVolatilitiesName(), BLACK_VOLS_CST_USD.getName());
assertEquals(pvnvsAd.getExpiry(), BLACK_VOLS_CST_USD.relativeTime(SWAPTION_LONG_PAY.getExpiry()));
assertEquals(pvnvsAd.getTenor(), SWAP_TENOR_YEAR, TOLERANCE_RATE);
assertEquals(pvnvsAd.getStrike(), STRIKE, TOLERANCE_RATE);
double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD);
assertEquals(pvnvsAd.getForward(), forward, TOLERANCE_RATE);
}
public void present_value_sensitivityBlackVolatility_long_short_parity() {
SwaptionSensitivity pvptLongPay = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_LONG_REC, MULTI_USD, BLACK_VOLS_USD_STD);
SwaptionSensitivity pvptShortRec = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvptLongPay.getSensitivity(), -pvptShortRec.getSensitivity(), TOLERANCE_PV_VEGA);
}
public void present_value_sensitivityBlackVolatility_payer_receiver_parity() {
SwaptionSensitivity pvptLongPay = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_LONG_PAY, MULTI_USD, BLACK_VOLS_USD_STD);
SwaptionSensitivity pvptShortRec = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_SHORT_REC, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(pvptLongPay.getSensitivity() + pvptShortRec.getSensitivity(), 0, TOLERANCE_PV_VEGA);
}
public void present_value_sensitivityBlackVolatility_at_expiry() {
SwaptionSensitivity sensiRec = PRICER_SWAPTION_BLACK.presentValueSensitivityModelParamsVolatility(
SWAPTION_REC_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(sensiRec.getSensitivity(), 0d, TOLERANCE_PV);
SwaptionSensitivity sensiPay = PRICER_SWAPTION_BLACK.presentValueSensitivityModelParamsVolatility(
SWAPTION_PAY_AT_EXPIRY, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(sensiPay.getSensitivity(), 0d, TOLERANCE_PV);
}
public void present_value_sensitivityBlackVolatility_after_expiry() {
SwaptionSensitivity v = PRICER_SWAPTION_BLACK
.presentValueSensitivityModelParamsVolatility(SWAPTION_PAST, MULTI_USD, BLACK_VOLS_USD_STD);
assertEquals(v.getSensitivity(), 0.0d, TOLERANCE_PV_VEGA);
}
}