/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.swap;
import static com.opengamma.strata.basics.currency.Currency.EUR;
import static com.opengamma.strata.basics.currency.Currency.GBP;
import static com.opengamma.strata.basics.currency.Currency.USD;
import static com.opengamma.strata.basics.date.BusinessDayConventions.MODIFIED_FOLLOWING;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.GBLO;
import static com.opengamma.strata.basics.date.Tenor.TENOR_5Y;
import static com.opengamma.strata.basics.index.IborIndices.GBP_LIBOR_3M;
import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_3M;
import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_6M;
import static com.opengamma.strata.basics.index.PriceIndices.GB_RPI;
import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg;
import static com.opengamma.strata.collect.TestHelper.date;
import static com.opengamma.strata.pricer.datasets.RatesProviderDataSets.MULTI_EUR;
import static com.opengamma.strata.pricer.datasets.RatesProviderDataSets.MULTI_USD;
import static com.opengamma.strata.pricer.swap.SwapDummyData.FIXED_RATE_PAYMENT_PERIOD_PAY_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.FIXED_RATE_PAYMENT_PERIOD_PAY_USD;
import static com.opengamma.strata.pricer.swap.SwapDummyData.FIXED_SWAP_LEG_PAY;
import static com.opengamma.strata.pricer.swap.SwapDummyData.FIXED_SWAP_LEG_PAY_USD;
import static com.opengamma.strata.pricer.swap.SwapDummyData.IBOR_RATE_COMP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.IBOR_RATE_PAYMENT_PERIOD_REC_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.IBOR_SWAP_LEG_REC_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.INFLATION_FIXED_SWAP_LEG_PAY_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.INFLATION_FIXED_SWAP_LEG_PAY_GBP_FIXED_RATE;
import static com.opengamma.strata.pricer.swap.SwapDummyData.INFLATION_MONTHLY_SWAP_LEG_REC_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.NOTIONAL;
import static com.opengamma.strata.pricer.swap.SwapDummyData.NOTIONAL_EXCHANGE_PAY_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.NOTIONAL_EXCHANGE_PAY_USD;
import static com.opengamma.strata.pricer.swap.SwapDummyData.NOTIONAL_EXCHANGE_REC_GBP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.SWAP;
import static com.opengamma.strata.pricer.swap.SwapDummyData.SWAP_CROSS_CURRENCY;
import static com.opengamma.strata.pricer.swap.SwapDummyData.SWAP_INFLATION;
import static com.opengamma.strata.pricer.swap.SwapDummyData.SWAP_TRADE;
import static com.opengamma.strata.pricer.swap.SwapDummyData.SWAP_TRADE_CROSS_CURRENCY;
import static com.opengamma.strata.product.common.BuySell.BUY;
import static com.opengamma.strata.product.common.PayReceive.RECEIVE;
import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.GBP_FIXED_1Y_LIBOR_3M;
import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.USD_FIXED_6M_LIBOR_3M;
import static com.opengamma.strata.product.swap.type.IborIborSwapConventions.USD_LIBOR_3M_LIBOR_6M;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.time.LocalDate;
import java.time.Period;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.currency.Currency;
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.DayCounts;
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.value.ValueSchedule;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.market.amount.CashFlow;
import com.opengamma.strata.market.amount.CashFlows;
import com.opengamma.strata.market.curve.Curve;
import com.opengamma.strata.market.curve.Curves;
import com.opengamma.strata.market.curve.InterpolatedNodalCurve;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolator;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolators;
import com.opengamma.strata.market.explain.ExplainKey;
import com.opengamma.strata.market.explain.ExplainMap;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.ZeroRateSensitivity;
import com.opengamma.strata.pricer.datasets.RatesProviderDataSets;
import com.opengamma.strata.pricer.impl.MockRatesProvider;
import com.opengamma.strata.pricer.rate.IborRateSensitivity;
import com.opengamma.strata.pricer.rate.ImmutableRatesProvider;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator;
import com.opengamma.strata.product.swap.CompoundingMethod;
import com.opengamma.strata.product.swap.FixedRateCalculation;
import com.opengamma.strata.product.swap.NotionalSchedule;
import com.opengamma.strata.product.swap.SwapPaymentEvent;
import com.opengamma.strata.product.swap.SwapPaymentPeriod;
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.ResolvedSwapTrade;
import com.opengamma.strata.product.swap.SwapTrade;
import com.opengamma.strata.product.swap.type.FixedIborSwapTemplate;
import com.opengamma.strata.product.swap.type.FixedInflationSwapConventions;
import com.opengamma.strata.product.swap.type.IborIborSwapConvention;
import com.opengamma.strata.product.swap.type.IborIborSwapTemplate;
import com.opengamma.strata.product.swap.type.IborRateSwapLegConvention;
import com.opengamma.strata.product.swap.type.ImmutableIborIborSwapConvention;
import com.opengamma.strata.product.swap.type.ThreeLegBasisSwapConvention;
import com.opengamma.strata.product.swap.type.ThreeLegBasisSwapConventions;
/**
* Tests {@link DiscountingSwapProductPricer}.
*/
@Test
public class DiscountingSwapProductPricerTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final RatesProvider MOCK_PROV = new MockRatesProvider(RatesProviderDataSets.VAL_DATE_2014_01_22);
private static final LocalDate VAL_DATE_INFLATION = date(2014, 7, 8);
private static final ImmutableRatesProvider RATES_GBP = RatesProviderDataSets.MULTI_GBP;
private static final ImmutableRatesProvider RATES_GBP_USD = RatesProviderDataSets.MULTI_GBP_USD;
private static final double FD_SHIFT = 1.0E-7;
private static final RatesFiniteDifferenceSensitivityCalculator FINITE_DIFFERENCE_CALCULATOR =
new RatesFiniteDifferenceSensitivityCalculator(FD_SHIFT);
private static final double TOLERANCE_RATE = 1.0e-12;
private static final double TOLERANCE_RATE_DELTA = 1.0E-6;
private static final double TOLERANCE_PV = 1.0e-2;
private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.LINEAR;
private static final double[] INDEX_VALUES = {242d, 242d, 242d, 242d, 242d, 242d};
private static final double START_INDEX = 218d;
private static final LocalDateDoubleTimeSeries TS_INFLATION = LocalDateDoubleTimeSeries.of(date(2014, 3, 31), START_INDEX);
private static final Curve PRICE_CURVE = InterpolatedNodalCurve.of(
Curves.prices("GB_RPI_CURVE_FLAT"),
DoubleArray.of(1, 2, 3, 4, 5, 6),
DoubleArray.ofUnsafe(INDEX_VALUES),
INTERPOLATOR);
private static final ImmutableRatesProvider RATES_GBP_INFLATION = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RatesProviderDataSets.multiGbp(VAL_DATE_INFLATION).getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
// non compounding
private static final IborIborSwapConvention CONV_USD_LIBOR3M_LIBOR6M = ImmutableIborIborSwapConvention.of(
"USD-Swap", IborRateSwapLegConvention.of(USD_LIBOR_3M), IborRateSwapLegConvention.of(USD_LIBOR_6M));
private static final double FIXED_RATE = 0.01;
private static final double SPREAD = 0.0015;
private static final double NOTIONAL_SWAP = 100_000_000;
private static final SwapTrade SWAP_USD_FIXED_6M_LIBOR_3M_5Y = FixedIborSwapTemplate
.of(Period.ZERO, TENOR_5Y, USD_FIXED_6M_LIBOR_3M)
.createTrade(MULTI_USD.getValuationDate(), BUY, NOTIONAL_SWAP, FIXED_RATE, REF_DATA);
private static final SwapTrade SWAP_USD_LIBOR_3M_LIBOR_6M_5Y = IborIborSwapTemplate
.of(Period.ZERO, TENOR_5Y, CONV_USD_LIBOR3M_LIBOR6M)
.createTrade(MULTI_USD.getValuationDate(), BUY, NOTIONAL_SWAP, SPREAD, REF_DATA);
private static final SwapTrade SWAP_GBP_ZC_INFLATION_5Y = FixedInflationSwapConventions.GBP_FIXED_ZC_GB_RPI
.createTrade(VAL_DATE_INFLATION, TENOR_5Y, BUY, NOTIONAL_SWAP, FIXED_RATE, REF_DATA);
private static final DiscountingSwapProductPricer SWAP_PRODUCT_PRICER = DiscountingSwapProductPricer.DEFAULT;
private static final DiscountingSwapTradePricer SWAP_TRADE_PRICER = DiscountingSwapTradePricer.DEFAULT;
//-------------------------------------------------------------------------
public void test_getters() {
assertEquals(DiscountingSwapProductPricer.DEFAULT.getLegPricer(), DiscountingSwapLegPricer.DEFAULT);
assertEquals(DiscountingSwapTradePricer.DEFAULT.getProductPricer(), DiscountingSwapProductPricer.DEFAULT);
}
//-------------------------------------------------------------------------
public void test_legPricer() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.getLegPricer(), pricerLeg);
}
//-------------------------------------------------------------------------
public void test_parRate_singleCurrency() {
RatesProvider mockProv = mock(RatesProvider.class);
when(mockProv.discountFactor(GBP, FIXED_RATE_PAYMENT_PERIOD_PAY_GBP.getPaymentDate()))
.thenReturn(0.99d);
when(mockProv.getValuationDate()).thenReturn(RatesProviderDataSets.VAL_DATE_2014_01_22);
when(mockProv.fxRate(GBP, GBP)).thenReturn(1.0);
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
double fwdRate = 0.01;
double pvCpnIbor = 0.99 * fwdRate * 0.25 * 1_000_000;
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, mockProv))
.thenReturn(pvCpnIbor);
double pvbpCpnFixed = -0.99 * 0.25 * 1_000_000;
double pvCpnFixed = 0.0123d * pvbpCpnFixed;
when(mockPeriod.presentValue(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, mockProv))
.thenReturn(pvCpnFixed);
when(mockPeriod.pvbp(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, mockProv))
.thenReturn(pvbpCpnFixed);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
double pvNotional = 980_000d;
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_REC_GBP, mockProv))
.thenReturn(pvNotional);
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_PAY_GBP, mockProv))
.thenReturn(-pvNotional);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
double pvbp = pricerLeg.pvbp(FIXED_SWAP_LEG_PAY, mockProv);
double parRateExpected1 = -(pvCpnIbor + -pvNotional + pvNotional) / pvbp;
double parRateExpected2 = fwdRate;
double parRateComputed = pricerSwap.parRate(SWAP, mockProv);
assertEquals(parRateComputed, parRateExpected1, TOLERANCE_RATE);
assertEquals(parRateComputed, parRateExpected2, TOLERANCE_RATE);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.parRate(SWAP_TRADE, MOCK_PROV),
pricerSwap.parRate(SWAP, MOCK_PROV));
}
public void test_parRate_crossCurrency() {
RatesProvider mockProv = mock(RatesProvider.class);
when(mockProv.discountFactor(USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate()))
.thenReturn(0.99d);
when(mockProv.getValuationDate()).thenReturn(RatesProviderDataSets.VAL_DATE_2014_01_22);
when(mockProv.fxRate(GBP, GBP)).thenReturn(1.0);
when(mockProv.fxRate(USD, USD)).thenReturn(1.0);
double fxGbpUsd = 1.51d;
when(mockProv.fxRate(GBP, USD)).thenReturn(fxGbpUsd);
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
double fwdRate = 0.01;
double pvCpnIborGbp = 0.99 * fwdRate * 0.25 * 1_000_000;
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, mockProv))
.thenReturn(pvCpnIborGbp);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
double pvNotionalGbp = 980_000d;
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_REC_GBP, mockProv))
.thenReturn(pvNotionalGbp);
double pvNotionalUsd = -fxGbpUsd * 981_000d;
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_PAY_USD, mockProv))
.thenReturn(pvNotionalUsd);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
double pvbp = pricerLeg.pvbp(FIXED_SWAP_LEG_PAY_USD, mockProv);
double parRateExpected = -((pvCpnIborGbp + pvNotionalGbp) * fxGbpUsd + pvNotionalUsd) / pvbp;
double parRateComputed = pricerSwap.parRate(SWAP, mockProv);
assertEquals(parRateComputed, parRateExpected, TOLERANCE_RATE);
}
public void test_parRate_bothLegFloating() {
ResolvedSwap swap = ResolvedSwap.of(IBOR_SWAP_LEG_REC_GBP, IBOR_SWAP_LEG_REC_GBP);
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertThrowsIllegalArg(() -> pricerSwap.parRate(swap, MOCK_PROV));
}
public void test_parRate_inflation() {
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RATES_GBP_INFLATION.getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
double parRateComputed = pricerSwap.parRate(SWAP_INFLATION, prov);
ResolvedSwapLeg fixedLeg = RateCalculationSwapLeg.builder()
.payReceive(RECEIVE)
.accrualSchedule(PeriodicSchedule.builder()
.startDate(date(2014, 6, 9))
.endDate(date(2019, 6, 9))
.frequency(Frequency.P12M)
.businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO))
.build())
.paymentSchedule(PaymentSchedule.builder()
.paymentFrequency(Frequency.ofYears(5))
.paymentDateOffset(DaysAdjustment.ofBusinessDays(2, GBLO))
.compoundingMethod(CompoundingMethod.STRAIGHT)
.build())
.notionalSchedule(NotionalSchedule.of(GBP, NOTIONAL))
.calculation(FixedRateCalculation.builder()
.rate(ValueSchedule.of(parRateComputed))
.dayCount(DayCounts.ONE_ONE) // year fraction is always 1.
.build())
.build()
.resolve(REF_DATA);
ResolvedSwap swapWithParRate = ResolvedSwap.of(INFLATION_MONTHLY_SWAP_LEG_REC_GBP, fixedLeg);
double pvWithParRate = pricerSwap.presentValue(swapWithParRate, prov).getAmount(GBP).getAmount();
assertEquals(pvWithParRate, 0.0d, NOTIONAL * TOLERANCE_RATE);
}
public void test_parRate_inflation_periodic() {
ResolvedSwapLeg fixedLeg = RateCalculationSwapLeg.builder()
.payReceive(RECEIVE)
.accrualSchedule(PeriodicSchedule.builder()
.startDate(date(2014, 6, 9))
.endDate(date(2019, 6, 9))
.frequency(Frequency.P6M)
.businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO))
.build())
.paymentSchedule(PaymentSchedule.builder()
.paymentFrequency(Frequency.P6M)
.paymentDateOffset(DaysAdjustment.ofBusinessDays(2, GBLO))
.build())
.notionalSchedule(NotionalSchedule.of(GBP, NOTIONAL))
.calculation(FixedRateCalculation.builder()
.rate(ValueSchedule.of(0.04))
.dayCount(DayCounts.ACT_365F)
.build())
.build()
.resolve(REF_DATA);
ResolvedSwap swap = ResolvedSwap.of(INFLATION_MONTHLY_SWAP_LEG_REC_GBP, fixedLeg);
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RATES_GBP_INFLATION.getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
double parRateComputed = pricerSwap.parRate(swap, prov);
ResolvedSwapLeg fixedLegWithParRate = RateCalculationSwapLeg.builder()
.payReceive(RECEIVE)
.accrualSchedule(PeriodicSchedule.builder()
.startDate(date(2014, 6, 9))
.endDate(date(2019, 6, 9))
.frequency(Frequency.P6M)
.businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO))
.build())
.paymentSchedule(PaymentSchedule.builder()
.paymentFrequency(Frequency.P6M)
.paymentDateOffset(DaysAdjustment.ofBusinessDays(2, GBLO))
.build())
.notionalSchedule(NotionalSchedule.of(GBP, NOTIONAL))
.calculation(FixedRateCalculation.builder()
.rate(ValueSchedule.of(parRateComputed))
.dayCount(DayCounts.ACT_365F)
.build())
.build()
.resolve(REF_DATA);
ResolvedSwap swapWithParRate = ResolvedSwap.of(INFLATION_MONTHLY_SWAP_LEG_REC_GBP, fixedLegWithParRate);
double pvWithParRate = pricerSwap.presentValue(swapWithParRate, prov).getAmount(GBP).getAmount();
assertEquals(pvWithParRate, 0.0d, NOTIONAL * TOLERANCE_RATE);
}
//-------------------------------------------------------------------------
public void test_presentValue_singleCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.presentValue(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_REC_GBP, MOCK_PROV))
.thenReturn(35d);
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_PAY_GBP, MOCK_PROV))
.thenReturn(-30d);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.presentValue(SWAP, MOCK_PROV), MultiCurrencyAmount.of(GBP, 505d));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.presentValue(SWAP_TRADE, MOCK_PROV),
pricerSwap.presentValue(SWAP, MOCK_PROV));
}
public void test_presentValue_crossCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.presentValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
MultiCurrencyAmount expected = MultiCurrencyAmount.of(CurrencyAmount.of(GBP, 1000d), CurrencyAmount.of(USD, -500d));
assertEquals(pricerSwap.presentValue(SWAP_CROSS_CURRENCY, MOCK_PROV), expected);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.presentValue(SWAP_TRADE_CROSS_CURRENCY, MOCK_PROV),
pricerSwap.presentValue(SWAP_CROSS_CURRENCY, MOCK_PROV));
}
public void test_presentValue_withCurrency_crossCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.presentValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
CurrencyAmount expected = CurrencyAmount.of(USD, 1000d * MockRatesProvider.RATE - 500d);
assertEquals(pricerSwap.presentValue(SWAP_CROSS_CURRENCY, USD, MOCK_PROV), expected);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.presentValue(SWAP_TRADE_CROSS_CURRENCY, USD, MOCK_PROV),
pricerSwap.presentValue(SWAP_CROSS_CURRENCY, USD, MOCK_PROV));
}
public void test_presentValue_inflation() {
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
LocalDate paymentDate = SWAP_INFLATION.getLegs().get(0).getPaymentPeriods().get(0).getPaymentDate();
double fixedRate = INFLATION_FIXED_SWAP_LEG_PAY_GBP_FIXED_RATE;
MultiCurrencyAmount pvComputed = pricerSwap.presentValue(SWAP_INFLATION, RATES_GBP_INFLATION);
double pvExpected = (-(INDEX_VALUES[0] / START_INDEX - 1.0) + Math.pow(1 + fixedRate, 5) - 1.0)
* NOTIONAL * RATES_GBP_INFLATION.discountFactor(GBP, paymentDate);
assertTrue(pvComputed.getCurrencies().size() == 1);
assertEquals(pvComputed.getAmount(GBP).getAmount(), pvExpected, NOTIONAL * TOLERANCE_RATE);
}
//-------------------------------------------------------------------------
public void test_forecastValue_singleCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.forecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.forecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.forecastValue(SWAP, MOCK_PROV), MultiCurrencyAmount.of(GBP, 500d));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.forecastValue(SWAP_TRADE, MOCK_PROV),
pricerSwap.forecastValue(SWAP, MOCK_PROV));
}
public void test_forecastValue_crossCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.forecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.forecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
MultiCurrencyAmount expected = MultiCurrencyAmount.of(CurrencyAmount.of(GBP, 1000d), CurrencyAmount.of(USD, -500d));
assertEquals(pricerSwap.forecastValue(SWAP_CROSS_CURRENCY, MOCK_PROV), expected);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.forecastValue(SWAP_TRADE_CROSS_CURRENCY, MOCK_PROV),
pricerSwap.forecastValue(SWAP_CROSS_CURRENCY, MOCK_PROV));
}
public void test_forecastValue_inflation() {
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RATES_GBP_INFLATION.getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
MultiCurrencyAmount fvComputed = pricerSwap.forecastValue(SWAP_INFLATION, prov);
double fixedRate = INFLATION_FIXED_SWAP_LEG_PAY_GBP_FIXED_RATE;
double fvExpected = (-(INDEX_VALUES[0] / START_INDEX - 1.0) + Math.pow(1.0 + fixedRate, 5) - 1.0) * NOTIONAL;
assertTrue(fvComputed.getCurrencies().size() == 1);
assertEquals(fvComputed.getAmount(GBP).getAmount(), fvExpected, NOTIONAL * TOLERANCE_RATE);
}
//-------------------------------------------------------------------------
public void test_accruedInterest_firstAccrualPeriod() {
RatesProvider prov = new MockRatesProvider(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getStartDate().plusDays(7));
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.accruedInterest(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, prov))
.thenReturn(1000d);
when(mockPeriod.accruedInterest(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, prov))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.accruedInterest(SWAP, prov), MultiCurrencyAmount.of(GBP, 500d));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.accruedInterest(SWAP_TRADE, MOCK_PROV),
pricerSwap.accruedInterest(SWAP, MOCK_PROV));
}
public void test_accruedInterest_valDateBeforePeriod() {
RatesProvider prov = new MockRatesProvider(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getStartDate());
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.accruedInterest(SWAP, prov), MultiCurrencyAmount.of(GBP, 0d));
}
public void test_accruedInterest_valDateAfterPeriod() {
RatesProvider prov = new MockRatesProvider(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getEndDate().plusDays(1));
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.accruedInterest(SWAP, prov), MultiCurrencyAmount.of(GBP, 0d));
}
//-------------------------------------------------------------------------
public void test_parRateSensitivity_singleCurrency() {
PointSensitivities point = SWAP_PRODUCT_PRICER.parRateSensitivity(SWAP, RATES_GBP).build();
CurrencyParameterSensitivities prAd = RATES_GBP.parameterSensitivity(point);
CurrencyParameterSensitivities prFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(
RATES_GBP, p -> CurrencyAmount.of(GBP, SWAP_PRODUCT_PRICER.parRate(SWAP, p)));
assertTrue(prAd.equalWithTolerance(prFd, TOLERANCE_RATE_DELTA));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = DiscountingSwapTradePricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = DiscountingSwapProductPricer.DEFAULT;
assertEquals(
pricerTrade.parRateSensitivity(SWAP_TRADE, RATES_GBP),
pricerSwap.parRateSensitivity(SWAP, RATES_GBP).build());
}
public void test_parRateSensitivity_crossCurrency() {
PointSensitivities point = SWAP_PRODUCT_PRICER.parRateSensitivity(SWAP_CROSS_CURRENCY, RATES_GBP_USD).build();
CurrencyParameterSensitivities prAd = RATES_GBP_USD.parameterSensitivity(point);
CurrencyParameterSensitivities prFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(
RATES_GBP_USD, p -> CurrencyAmount.of(USD, SWAP_PRODUCT_PRICER.parRate(SWAP_CROSS_CURRENCY, p)));
assertTrue(prAd.equalWithTolerance(prFd, TOLERANCE_RATE_DELTA));
}
//-------------------------------------------------------------------------
public void test_presentValueSensitivity() {
// ibor leg
IborRateSensitivity fwdSense = IborRateSensitivity.of(IBOR_RATE_COMP.getObservation(), GBP, 140.0);
ZeroRateSensitivity dscSense = ZeroRateSensitivity.of(GBP, 3d, -162.0);
PointSensitivityBuilder sensiFloating = fwdSense.combinedWith(dscSense);
// fixed leg
PointSensitivityBuilder sensiFixed = ZeroRateSensitivity.of(GBP, 3d, 152.0);
// events
Currency ccy = IBOR_SWAP_LEG_REC_GBP.getCurrency();
PointSensitivityBuilder sensiEvent = ZeroRateSensitivity.of(ccy, 4d, -134.0);
PointSensitivities expected = sensiFloating.build()
.combinedWith(sensiEvent.build())
.combinedWith(sensiFixed.build())
.combinedWith(sensiEvent.build());
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
when(mockPeriod.presentValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentPeriods().get(0), MOCK_PROV))
.thenAnswer(t -> sensiFloating.build().toMutable());
when(mockPeriod.presentValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentPeriods().get(0), MOCK_PROV))
.thenAnswer(t -> sensiFixed.build().toMutable());
when(mockEvent.presentValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentEvents().get(0), MOCK_PROV))
.thenAnswer(t -> sensiEvent.build().toMutable());
when(mockEvent.presentValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentEvents().get(0), MOCK_PROV))
.thenAnswer(t -> sensiEvent.build().toMutable());
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
PointSensitivities res = pricerSwap.presentValueSensitivity(SWAP, MOCK_PROV).build();
assertTrue(res.equalWithTolerance(expected, TOLERANCE_RATE));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.presentValueSensitivity(SWAP_TRADE, MOCK_PROV),
pricerSwap.presentValueSensitivity(SWAP, MOCK_PROV).build());
}
public void test_presentValueSensitivity_inflation() {
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RATES_GBP_INFLATION.getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
PointSensitivityBuilder pvSensiComputed = pricerSwap.presentValueSensitivity(SWAP_INFLATION, prov);
PointSensitivityBuilder pvSensiInflationLeg =
pricerLeg.presentValueSensitivity(INFLATION_MONTHLY_SWAP_LEG_REC_GBP, prov);
PointSensitivityBuilder pvSensiFixedLeg =
pricerLeg.presentValueSensitivity(INFLATION_FIXED_SWAP_LEG_PAY_GBP, prov);
PointSensitivityBuilder pvSensiExpected = pvSensiFixedLeg.combinedWith(pvSensiInflationLeg);
assertTrue(pvSensiComputed.build().normalized()
.equalWithTolerance(pvSensiExpected.build().normalized(), TOLERANCE_RATE * NOTIONAL));
}
//-------------------------------------------------------------------------
public void test_forecastValueSensitivity() {
// ibor leg
PointSensitivityBuilder sensiFloating = IborRateSensitivity.of(IBOR_RATE_COMP.getObservation(), GBP, 140.0);
// fixed leg
PointSensitivityBuilder sensiFixed = PointSensitivityBuilder.none();
// events
PointSensitivityBuilder sensiEvent = PointSensitivityBuilder.none();
PointSensitivities expected = sensiFloating.build();
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
when(mockPeriod.forecastValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentPeriods().get(0), MOCK_PROV))
.thenAnswer(t -> sensiFloating.build().toMutable());
when(mockPeriod.forecastValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentPeriods().get(0), MOCK_PROV))
.thenAnswer(t -> sensiFixed.build().toMutable());
when(mockEvent.forecastValueSensitivity(IBOR_SWAP_LEG_REC_GBP.getPaymentEvents().get(0), MOCK_PROV))
.thenAnswer(t -> sensiEvent.build().toMutable());
when(mockEvent.forecastValueSensitivity(FIXED_SWAP_LEG_PAY.getPaymentEvents().get(0), MOCK_PROV))
.thenAnswer(t -> sensiEvent.build().toMutable());
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
PointSensitivities res = pricerSwap.forecastValueSensitivity(SWAP, MOCK_PROV).build();
assertTrue(res.equalWithTolerance(expected, TOLERANCE_RATE));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.forecastValueSensitivity(SWAP_TRADE, MOCK_PROV),
pricerSwap.forecastValueSensitivity(SWAP, MOCK_PROV).build());
}
public void test_forecastValueSensitivity_inflation() {
DiscountingSwapLegPricer pricerLeg = DiscountingSwapLegPricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE_INFLATION)
.discountCurves(RATES_GBP_INFLATION.getDiscountCurves())
.priceIndexCurve(GB_RPI, PRICE_CURVE)
.timeSeries(GB_RPI, TS_INFLATION)
.build();
PointSensitivityBuilder fvSensiComputed = pricerSwap.forecastValueSensitivity(SWAP_INFLATION, prov);
PointSensitivityBuilder fvSensiInflationLeg =
pricerLeg.forecastValueSensitivity(INFLATION_MONTHLY_SWAP_LEG_REC_GBP, prov);
PointSensitivityBuilder fvSensiFixedLeg =
pricerLeg.forecastValueSensitivity(INFLATION_FIXED_SWAP_LEG_PAY_GBP, prov);
PointSensitivityBuilder fvSensiExpected = fvSensiFixedLeg.combinedWith(fvSensiInflationLeg);
assertTrue(fvSensiComputed.build().normalized()
.equalWithTolerance(fvSensiExpected.build().normalized(), TOLERANCE_RATE * NOTIONAL));
}
//-------------------------------------------------------------------------
public void test_cashFlows() {
RatesProvider mockProv = mock(RatesProvider.class);
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
double df1 = 0.98;
double df2 = 0.93;
double fvGBP = 1000d;
double fvUSD = -500d;
when(mockPeriod.forecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, mockProv)).thenReturn(fvGBP);
when(mockPeriod.forecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, mockProv)).thenReturn(fvUSD);
when(mockProv.getValuationDate()).thenReturn(LocalDate.of(2014, 7, 1));
when(mockProv.discountFactor(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getCurrency(),
IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getPaymentDate())).thenReturn(df1);
when(mockProv.discountFactor(FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getCurrency(),
FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate())).thenReturn(df2);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
CashFlows computed = pricerSwap.cashFlows(SWAP_CROSS_CURRENCY, mockProv);
CashFlow flowGBP = CashFlow.ofForecastValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP.getPaymentDate(), GBP, fvGBP, df1);
CashFlow flowUSD = CashFlow.ofForecastValue(FIXED_RATE_PAYMENT_PERIOD_PAY_USD.getPaymentDate(), USD, fvUSD, df2);
CashFlows expected = CashFlows.of(ImmutableList.of(flowGBP, flowUSD));
assertEquals(computed, expected);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(pricerTrade.cashFlows(SWAP_TRADE, MOCK_PROV), pricerSwap.cashFlows(SWAP, MOCK_PROV));
}
//-------------------------------------------------------------------------
public void test_explainPresentValue_singleCurrency() {
SwapPaymentPeriodPricer<SwapPaymentPeriod> mockPeriod = mock(SwapPaymentPeriodPricer.class);
when(mockPeriod.presentValue(IBOR_RATE_PAYMENT_PERIOD_REC_GBP, MOCK_PROV))
.thenReturn(1000d);
when(mockPeriod.presentValue(FIXED_RATE_PAYMENT_PERIOD_PAY_GBP, MOCK_PROV))
.thenReturn(-500d);
SwapPaymentEventPricer<SwapPaymentEvent> mockEvent = mock(SwapPaymentEventPricer.class);
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_REC_GBP, MOCK_PROV))
.thenReturn(35d);
when(mockEvent.presentValue(NOTIONAL_EXCHANGE_PAY_GBP, MOCK_PROV))
.thenReturn(-30d);
DiscountingSwapLegPricer pricerLeg = new DiscountingSwapLegPricer(mockPeriod, mockEvent);
DiscountingSwapProductPricer pricerSwap = new DiscountingSwapProductPricer(pricerLeg);
assertEquals(pricerSwap.presentValue(SWAP, MOCK_PROV), MultiCurrencyAmount.of(GBP, 505d));
ExplainMap explain = pricerSwap.explainPresentValue(SWAP, MOCK_PROV);
assertEquals(explain.get(ExplainKey.ENTRY_TYPE).get(), "Swap");
assertEquals(explain.get(ExplainKey.LEGS).get().size(), 2);
ExplainMap explainLeg0 = explain.get(ExplainKey.LEGS).get().get(0);
ResolvedSwapLeg leg0 = SWAP.getLegs().get(0);
double fv0 = pricerLeg.forecastValue(leg0, MOCK_PROV).getAmount();
assertEquals(explainLeg0.get(ExplainKey.ENTRY_TYPE).get(), "Leg");
assertEquals(explainLeg0.get(ExplainKey.ENTRY_INDEX).get().intValue(), 0);
assertEquals(explainLeg0.get(ExplainKey.PAY_RECEIVE).get(), leg0.getPayReceive());
assertEquals(explainLeg0.get(ExplainKey.LEG_TYPE).get(), leg0.getType().toString());
assertEquals(explainLeg0.get(ExplainKey.PAYMENT_PERIODS).get().size(), 1);
assertEquals(explainLeg0.get(ExplainKey.PAYMENT_EVENTS).get().size(), 1);
assertEquals(explainLeg0.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), leg0.getCurrency());
assertEquals(explainLeg0.get(ExplainKey.FORECAST_VALUE).get().getAmount(), fv0, TOLERANCE_RATE);
ExplainMap explainLeg1 = explain.get(ExplainKey.LEGS).get().get(1);
ResolvedSwapLeg leg1 = SWAP.getLegs().get(0);
double fv1 = pricerLeg.forecastValue(leg1, MOCK_PROV).getAmount();
assertEquals(explainLeg1.get(ExplainKey.ENTRY_TYPE).get(), "Leg");
assertEquals(explainLeg1.get(ExplainKey.ENTRY_INDEX).get().intValue(), 1);
assertEquals(explainLeg1.get(ExplainKey.PAYMENT_PERIODS).get().size(), 1);
assertEquals(explainLeg1.get(ExplainKey.PAYMENT_EVENTS).get().size(), 1);
assertEquals(explainLeg1.get(ExplainKey.FORECAST_VALUE).get().getCurrency(), leg1.getCurrency());
assertEquals(explainLeg1.get(ExplainKey.FORECAST_VALUE).get().getAmount(), fv1, TOLERANCE_RATE);
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = new DiscountingSwapTradePricer(pricerSwap);
assertEquals(
pricerTrade.explainPresentValue(SWAP_TRADE, MOCK_PROV),
pricerSwap.explainPresentValue(SWAP, MOCK_PROV));
}
//-------------------------------------------------------------------------
public void test_parSpread_fixedIbor() {
ResolvedSwapTrade swapTrade = SWAP_USD_FIXED_6M_LIBOR_3M_5Y.resolve(REF_DATA);
double ps = SWAP_PRODUCT_PRICER.parSpread(swapTrade.getProduct(), MULTI_USD);
SwapTrade swap0 = FixedIborSwapTemplate
.of(Period.ZERO, TENOR_5Y, USD_FIXED_6M_LIBOR_3M)
.createTrade(MULTI_USD.getValuationDate(), BUY, NOTIONAL_SWAP, FIXED_RATE + ps, REF_DATA);
CurrencyAmount pv0 = SWAP_PRODUCT_PRICER.presentValue(swap0.getProduct().resolve(REF_DATA), USD, MULTI_USD);
assertEquals(pv0.getAmount(), 0, TOLERANCE_PV);
// test via SwapTrade
DiscountingSwapProductPricer pricerSwap = DiscountingSwapProductPricer.DEFAULT;
DiscountingSwapTradePricer pricerTrade = DiscountingSwapTradePricer.DEFAULT;
assertEquals(
pricerTrade.parSpread(swapTrade, MULTI_USD),
pricerSwap.parSpread(swapTrade.getProduct(), MULTI_USD));
}
public void test_parSpread_fixedInflation() {
ResolvedSwapTrade tradeZc = SWAP_GBP_ZC_INFLATION_5Y.resolve(REF_DATA);
double ps = SWAP_PRODUCT_PRICER.parSpread(tradeZc.getProduct(), RATES_GBP_INFLATION);
SwapTrade swap0 = FixedInflationSwapConventions.GBP_FIXED_ZC_GB_RPI
.createTrade(VAL_DATE_INFLATION, TENOR_5Y, BUY, NOTIONAL_SWAP, FIXED_RATE + ps, REF_DATA);
CurrencyAmount pv0 = SWAP_PRODUCT_PRICER.presentValue(swap0.getProduct().resolve(REF_DATA), GBP, RATES_GBP_INFLATION);
assertEquals(pv0.getAmount(), 0, TOLERANCE_PV);
}
public void test_parSpread_iborIbor() {
double ps = SWAP_PRODUCT_PRICER.parSpread(SWAP_USD_LIBOR_3M_LIBOR_6M_5Y.getProduct().resolve(REF_DATA), MULTI_USD);
SwapTrade swap0 = IborIborSwapTemplate
.of(Period.ZERO, TENOR_5Y, CONV_USD_LIBOR3M_LIBOR6M)
.createTrade(MULTI_USD.getValuationDate(), BUY, NOTIONAL_SWAP, SPREAD + ps, REF_DATA);
CurrencyAmount pv0 = SWAP_PRODUCT_PRICER.presentValue(swap0.getProduct().resolve(REF_DATA), USD, MULTI_USD);
assertEquals(pv0.getAmount(), 0, TOLERANCE_PV);
}
public void test_parSpread_iborCmpIbor() {
SwapTrade trade = USD_LIBOR_3M_LIBOR_6M
.createTrade(MULTI_USD.getValuationDate(), TENOR_5Y, BUY, NOTIONAL_SWAP, SPREAD, REF_DATA);
double ps = SWAP_PRODUCT_PRICER.parSpread(trade.getProduct().resolve(REF_DATA), MULTI_USD);
SwapTrade swap0 = USD_LIBOR_3M_LIBOR_6M
.createTrade(MULTI_USD.getValuationDate(), TENOR_5Y, BUY, NOTIONAL_SWAP, SPREAD + ps, REF_DATA);
CurrencyAmount pv0 = SWAP_PRODUCT_PRICER.presentValue(swap0.getProduct().resolve(REF_DATA), USD, MULTI_USD);
assertEquals(pv0.getAmount(), 0, TOLERANCE_PV);
}
//-------------------------------------------------------------------------
public void test_parSpreadSensitivity_fixedIbor() {
ResolvedSwapTrade trade = SWAP_USD_FIXED_6M_LIBOR_3M_5Y.resolve(REF_DATA);
PointSensitivities point = SWAP_PRODUCT_PRICER.parSpreadSensitivity(trade.getProduct(), MULTI_USD).build();
CurrencyParameterSensitivities prAd = MULTI_USD.parameterSensitivity(point);
CurrencyParameterSensitivities prFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(
MULTI_USD, p -> CurrencyAmount.of(USD, SWAP_PRODUCT_PRICER.parSpread(trade.getProduct(), p)));
assertTrue(prAd.equalWithTolerance(prFd, TOLERANCE_RATE_DELTA));
// test via SwapTrade
DiscountingSwapTradePricer pricerTrade = DiscountingSwapTradePricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = DiscountingSwapProductPricer.DEFAULT;
assertEquals(
pricerTrade.parSpreadSensitivity(trade, MULTI_USD),
pricerSwap.parSpreadSensitivity(trade.getProduct(), MULTI_USD).build());
}
public void test_parSpreadSensitivity_fixedInflation() {
ResolvedSwapTrade tradeZc = SWAP_GBP_ZC_INFLATION_5Y.resolve(REF_DATA);
PointSensitivities point = SWAP_PRODUCT_PRICER.parSpreadSensitivity(tradeZc.getProduct(), RATES_GBP_INFLATION).build();
CurrencyParameterSensitivities prAd = RATES_GBP_INFLATION.parameterSensitivity(point);
CurrencyParameterSensitivities prFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(
RATES_GBP_INFLATION, p -> CurrencyAmount.of(GBP, SWAP_PRODUCT_PRICER.parSpread(tradeZc.getProduct(), p)));
assertTrue(prAd.equalWithTolerance(prFd, TOLERANCE_RATE_DELTA));
// trade v product
DiscountingSwapTradePricer pricerTrade = DiscountingSwapTradePricer.DEFAULT;
DiscountingSwapProductPricer pricerSwap = DiscountingSwapProductPricer.DEFAULT;
assertEquals(
pricerTrade.parSpreadSensitivity(tradeZc, RATES_GBP_INFLATION),
pricerSwap.parSpreadSensitivity(tradeZc.getProduct(), RATES_GBP_INFLATION).build());
}
public void test_parSpreadSensitivity_iborIbor() {
ResolvedSwap expanded = SWAP_USD_LIBOR_3M_LIBOR_6M_5Y.getProduct().resolve(REF_DATA);
PointSensitivities point = SWAP_PRODUCT_PRICER.parSpreadSensitivity(expanded, MULTI_USD).build();
CurrencyParameterSensitivities prAd = MULTI_USD.parameterSensitivity(point);
CurrencyParameterSensitivities prFd = FINITE_DIFFERENCE_CALCULATOR.sensitivity(
MULTI_USD, p -> CurrencyAmount.of(USD, SWAP_PRODUCT_PRICER.parSpread(expanded, p)));
assertTrue(prAd.equalWithTolerance(prFd, TOLERANCE_RATE_DELTA));
}
//-------------------------------------------------------------------------
public void test_currencyExposure_singleCurrency() {
PointSensitivities point = SWAP_PRODUCT_PRICER.parRateSensitivity(SWAP, RATES_GBP).build();
MultiCurrencyAmount expected = RATES_GBP.currencyExposure(point)
.plus(SWAP_PRODUCT_PRICER.presentValue(SWAP, RATES_GBP));
MultiCurrencyAmount computed = SWAP_PRODUCT_PRICER.currencyExposure(SWAP, RATES_GBP);
assertEquals(computed, expected);
MultiCurrencyAmount fromTrade = SWAP_TRADE_PRICER.currencyExposure(SWAP_TRADE, RATES_GBP);
assertEquals(fromTrade, computed);
}
public void test_currencyExposure_crossCurrency() {
PointSensitivities point = SWAP_PRODUCT_PRICER.parRateSensitivity(SWAP_CROSS_CURRENCY, RATES_GBP_USD).build();
MultiCurrencyAmount expected = RATES_GBP_USD.currencyExposure(point)
.plus(SWAP_PRODUCT_PRICER.presentValue(SWAP_CROSS_CURRENCY, RATES_GBP_USD));
MultiCurrencyAmount computed = SWAP_PRODUCT_PRICER.currencyExposure(SWAP_CROSS_CURRENCY, RATES_GBP_USD);
assertEquals(computed, expected);
MultiCurrencyAmount fromTrade = SWAP_TRADE_PRICER.currencyExposure(SWAP_TRADE_CROSS_CURRENCY, RATES_GBP_USD);
assertEquals(fromTrade, computed);
}
//-------------------------------------------------------------------------
public void test_currentCash_zero() {
MultiCurrencyAmount computed = SWAP_PRODUCT_PRICER.currentCash(SWAP_CROSS_CURRENCY, RATES_GBP_USD);
assertEquals(computed, MultiCurrencyAmount.of(CurrencyAmount.zero(GBP), CurrencyAmount.zero(USD)));
MultiCurrencyAmount fromTrade = SWAP_TRADE_PRICER.currentCash(SWAP_TRADE_CROSS_CURRENCY, RATES_GBP_USD);
assertEquals(fromTrade, computed);
}
public void test_currentCash_onPayment() {
ResolvedSwapTrade trade = GBP_FIXED_1Y_LIBOR_3M
.createTrade(MULTI_USD.getValuationDate(), TENOR_5Y, BUY, NOTIONAL_SWAP, SPREAD, REF_DATA).resolve(REF_DATA);
ResolvedSwap expanded = trade.getProduct();
LocalDate payDate = expanded.getLegs().get(0).getPaymentPeriods().get(2).getPaymentDate();
ImmutableRatesProvider prov =
RatesProviderDataSets.multiGbp(payDate).toBuilder()
.timeSeries(GBP_LIBOR_3M, LocalDateDoubleTimeSeries.of(LocalDate.of(2016, 10, 24), 0.003))
.build();
MultiCurrencyAmount computed = SWAP_PRODUCT_PRICER.currentCash(expanded, prov);
MultiCurrencyAmount expected = MultiCurrencyAmount.of(
SWAP_PRODUCT_PRICER.getLegPricer().currentCash(expanded.getLegs().get(0), prov)
.plus(SWAP_PRODUCT_PRICER.getLegPricer().currentCash(expanded.getLegs().get(1), prov)));
assertEquals(computed, expected);
MultiCurrencyAmount fromTrade = SWAP_TRADE_PRICER.currentCash(trade, prov);
assertEquals(fromTrade, computed);
}
//-------------------------------------------------------------------------
public void three_leg_swap() {
ThreeLegBasisSwapConvention conv = ThreeLegBasisSwapConventions.EUR_FIXED_1Y_EURIBOR_3M_EURIBOR_6M;
LocalDate tradeDate = LocalDate.of(2014, 1, 22);
ResolvedSwap swap = conv.createTrade(tradeDate, Period.ofMonths(1), TENOR_5Y, BUY, NOTIONAL_SWAP, SPREAD, REF_DATA)
.getProduct().resolve(REF_DATA);
// pv
MultiCurrencyAmount pvComputed = SWAP_PRODUCT_PRICER.presentValue(swap, MULTI_EUR);
DiscountingSwapLegPricer legPricer = SWAP_PRODUCT_PRICER.getLegPricer();
CurrencyAmount pvExpected = legPricer.presentValue(swap.getLegs().get(0), MULTI_EUR)
.plus(legPricer.presentValue(swap.getLegs().get(1), MULTI_EUR))
.plus(legPricer.presentValue(swap.getLegs().get(2), MULTI_EUR));
assertEquals(pvComputed.getAmount(EUR), pvExpected);
// pv sensitivity
PointSensitivityBuilder pvPointComputed = SWAP_PRODUCT_PRICER.presentValueSensitivity(swap, MULTI_EUR);
PointSensitivityBuilder pvPointExpected = legPricer.presentValueSensitivity(swap.getLegs().get(0), MULTI_EUR)
.combinedWith(legPricer.presentValueSensitivity(swap.getLegs().get(1), MULTI_EUR))
.combinedWith(legPricer.presentValueSensitivity(swap.getLegs().get(2), MULTI_EUR));
assertEquals(pvPointComputed, pvPointExpected);
// par rate
double parRate = SWAP_PRODUCT_PRICER.parRate(swap, MULTI_EUR);
ResolvedSwap swapParRate = conv.createTrade(tradeDate, Period.ofMonths(1), TENOR_5Y, BUY, NOTIONAL_SWAP, parRate, REF_DATA)
.getProduct().resolve(REF_DATA);
MultiCurrencyAmount pvParRate = SWAP_PRODUCT_PRICER.presentValue(swapParRate, MULTI_EUR);
assertEquals(pvParRate, MultiCurrencyAmount.of(EUR, 0d));
// par rate sensitivity
PointSensitivities parRatePoint = SWAP_PRODUCT_PRICER.parRateSensitivity(swap, MULTI_EUR).build();
CurrencyParameterSensitivities parRateSensiComputed = MULTI_EUR.parameterSensitivity(parRatePoint);
CurrencyParameterSensitivities parRateSensiExpected = FINITE_DIFFERENCE_CALCULATOR.sensitivity(MULTI_EUR,
p -> CurrencyAmount.of(EUR, SWAP_PRODUCT_PRICER.parRate(swap, p)));
assertTrue(parRateSensiComputed.equalWithTolerance(parRateSensiExpected, TOLERANCE_RATE_DELTA));
// par spread
double parSpread = SWAP_PRODUCT_PRICER.parSpread(swap, MULTI_EUR);
ResolvedSwap swapParSpread =
conv.createTrade(tradeDate, Period.ofMonths(1), TENOR_5Y, BUY, NOTIONAL_SWAP, SPREAD + parSpread, REF_DATA)
.getProduct().resolve(REF_DATA);
MultiCurrencyAmount pvParSpread = SWAP_PRODUCT_PRICER.presentValue(swapParSpread, MULTI_EUR);
assertEquals(pvParSpread, MultiCurrencyAmount.of(EUR, 0d));
// par spread sensitivity
PointSensitivities parSpreadPoint = SWAP_PRODUCT_PRICER.parSpreadSensitivity(swap, MULTI_EUR).build();
CurrencyParameterSensitivities parSpreadSensiComputed = MULTI_EUR.parameterSensitivity(parSpreadPoint);
CurrencyParameterSensitivities parSpreadSensiExpected = FINITE_DIFFERENCE_CALCULATOR.sensitivity(MULTI_EUR,
p -> CurrencyAmount.of(EUR, SWAP_PRODUCT_PRICER.parSpread(swap, p)));
assertTrue(parSpreadSensiComputed.equalWithTolerance(parSpreadSensiExpected, TOLERANCE_RATE_DELTA));
}
}