/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.swap.e2e; 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.BusinessDayConventions.PRECEDING; import static com.opengamma.strata.basics.date.DayCounts.ACT_360; import static com.opengamma.strata.basics.date.DayCounts.THIRTY_U_360; import static com.opengamma.strata.basics.index.OvernightIndices.USD_FED_FUND; import static com.opengamma.strata.basics.schedule.Frequency.P12M; import static com.opengamma.strata.basics.schedule.Frequency.P1M; import static com.opengamma.strata.basics.schedule.Frequency.P3M; import static com.opengamma.strata.basics.schedule.Frequency.P6M; import static com.opengamma.strata.basics.schedule.Frequency.TERM; 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 java.time.LocalDate; import java.util.ArrayList; import java.util.List; import org.testng.annotations.Test; import com.opengamma.strata.basics.ImmutableReferenceData; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.basics.date.BusinessDayAdjustment; import com.opengamma.strata.basics.date.DaysAdjustment; import com.opengamma.strata.basics.index.IborIndex; import com.opengamma.strata.basics.index.IborIndices; import com.opengamma.strata.basics.index.ImmutableIborIndex; import com.opengamma.strata.basics.schedule.Frequency; import com.opengamma.strata.basics.schedule.PeriodicSchedule; import com.opengamma.strata.basics.schedule.StubConvention; import com.opengamma.strata.basics.value.ValueAdjustment; import com.opengamma.strata.basics.value.ValueSchedule; import com.opengamma.strata.basics.value.ValueStep; import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries; import com.opengamma.strata.pricer.datasets.StandardDataSets; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.pricer.rate.RatesProvider; import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer; import com.opengamma.strata.pricer.swap.DiscountingSwapTradePricer; import com.opengamma.strata.product.TradeInfo; import com.opengamma.strata.product.common.PayReceive; import com.opengamma.strata.product.swap.CompoundingMethod; 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.OvernightAccrualMethod; import com.opengamma.strata.product.swap.OvernightRateCalculation; 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.ResolvedSwapTrade; import com.opengamma.strata.product.swap.IborRateStubCalculation; import com.opengamma.strata.product.swap.Swap; import com.opengamma.strata.product.swap.SwapLeg; import com.opengamma.strata.product.swap.SwapTrade; /** * Test end to end. */ @Test public class SwapEnd2EndTest { private static final ReferenceData REF_DATA = ReferenceData.standard() .combinedWith(ImmutableReferenceData.of(CalendarUSD.NYC, CalendarUSD.NYC_CALENDAR)); private static final LocalDate VAL_DATE = StandardDataSets.VAL_DATE_2014_01_22; static final IborIndex USD_LIBOR_1M = lockIndexCalendar(IborIndices.USD_LIBOR_1M); static final IborIndex USD_LIBOR_3M = lockIndexCalendar(IborIndices.USD_LIBOR_3M); static final IborIndex USD_LIBOR_6M = lockIndexCalendar(IborIndices.USD_LIBOR_6M); static final NotionalSchedule NOTIONAL = NotionalSchedule.of(USD, 100_000_000); static final BusinessDayAdjustment BDA_MF = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, CalendarUSD.NYC); static final BusinessDayAdjustment BDA_P = BusinessDayAdjustment.of(PRECEDING, CalendarUSD.NYC); private static final LocalDateDoubleTimeSeries TS_USDLIBOR1M = LocalDateDoubleTimeSeries.builder() .put(LocalDate.of(2013, 12, 10), 0.00123) .put(LocalDate.of(2013, 12, 12), 0.00123) .build(); private static final LocalDateDoubleTimeSeries TS_USDLIBOR3M = LocalDateDoubleTimeSeries.builder() .put(LocalDate.of(2013, 12, 10), 0.0024185) .put(LocalDate.of(2013, 12, 12), 0.0024285) .build(); private static final LocalDateDoubleTimeSeries TS_USDLIBOR6M = LocalDateDoubleTimeSeries.builder() .put(LocalDate.of(2013, 12, 10), 0.0030) .put(LocalDate.of(2013, 12, 12), 0.0035) .build(); private static final LocalDateDoubleTimeSeries TS_USDON = LocalDateDoubleTimeSeries.builder() .put(LocalDate.of(2014, 1, 17), 0.0007) .put(LocalDate.of(2014, 1, 21), 0.0007) .put(VAL_DATE, 0.0007) .build(); private static final DiscountingSwapProductPricer PRICER_PRODUCT = DiscountingSwapProductPricer.DEFAULT; // tolerance private static final double TOLERANCE_PV = 1.0E-4; private static final double TOLERANCE_RATE = 1.0E-10; //----------------------------------------------------------------------- public void test_VanillaFixedVsLibor1mSwap() { SwapLeg payLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2016, 9, 12), P6M, PAY, NOTIONAL, 0.0125, null); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 9, 12)) .frequency(P1M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P1M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_1M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -1003684.8402, TOLERANCE_PV); } //----------------------------------------------------------------------- public void test_VanillaFixedVsLibor3mSwap() { SwapLeg payLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2021, 9, 12), P6M, PAY, NOTIONAL, 0.015, null); SwapLeg receiveLeg = iborLeg(LocalDate.of(2014, 9, 12), LocalDate.of(2021, 9, 12), USD_LIBOR_3M, RECEIVE, NOTIONAL, null); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); // test pv DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 7170391.798257509, TOLERANCE_PV); // test par rate double parRate = PRICER_PRODUCT.parRate(trade.getProduct(), provider()); assertEquals(parRate, 0.02589471566819517, TOLERANCE_RATE); // test par rate vs pv ResolvedSwap swapPV0 = Swap.of(fixedLeg(LocalDate.of(2014, 9, 12), LocalDate.of(2021, 9, 12), P6M, PAY, NOTIONAL, parRate, null), receiveLeg) .resolve(REF_DATA); CurrencyAmount pv0 = PRICER_PRODUCT.presentValue(swapPV0, provider()).getAmount(USD); assertEquals(pv0.getAmount(), 0, TOLERANCE_PV); // PV at par rate should be 0 } //------------------------------------------------------------------------- public void test_VanillaFixedVsLibor3mSwapWithFixing() { SwapLeg payLeg = fixedLeg( LocalDate.of(2013, 9, 12), LocalDate.of(2020, 9, 12), P6M, PAY, NOTIONAL, 0.015, null); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2013, 9, 12)) .endDate(LocalDate.of(2020, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2013, 9, 10)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 3588376.471608199, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_BasisLibor3mVsLibor6mSwapWithSpread() { SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 8, 29)) .endDate(LocalDate.of(2024, 8, 29)) .frequency(P6M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(Frequency.P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_6M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 8, 29)) .endDate(LocalDate.of(2024, 8, 29)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(Frequency.P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .spread(ValueSchedule.of(0.0010)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 8, 27)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -21875.376339152455, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_BasisCompoundedLibor1mVsLibor3mSwap() { SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 8, 29)) .endDate(LocalDate.of(2019, 8, 29)) .frequency(P1M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(Frequency.P3M) .paymentDateOffset(DaysAdjustment.NONE) .compoundingMethod(CompoundingMethod.FLAT) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_1M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 8, 29)) .endDate(LocalDate.of(2019, 8, 29)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(Frequency.P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 8, 27)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -342874.98367929866, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_Stub3mFixed6mVsLibor3mSwap() { SwapLeg receiveLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2016, 6, 12), P6M, RECEIVE, NOTIONAL, 0.01, StubConvention.SHORT_INITIAL); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 6, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 502890.9443281095, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_Stub1mFixed6mVsLibor3mSwap() { SwapLeg receiveLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2016, 7, 12), P6M, RECEIVE, NOTIONAL, 0.01, StubConvention.SHORT_INITIAL); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 7, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 463962.5517136799, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_InterpolatedStub3mFixed6mVsLibor6mSwap() { SwapLeg receiveLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2016, 6, 12), P6M, RECEIVE, NOTIONAL, 0.01, StubConvention.SHORT_INITIAL); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 6, 12)) .frequency(P6M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_6M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .initialStub(IborRateStubCalculation.ofIborInterpolatedRate(USD_LIBOR_3M, USD_LIBOR_6M)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 364832.4284058402, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_InterpolatedStub4mFixed6mVsLibor6mSwap() { SwapLeg receiveLeg = fixedLeg( LocalDate.of(2014, 9, 12), LocalDate.of(2016, 7, 12), P6M, RECEIVE, NOTIONAL, 0.01, StubConvention.SHORT_INITIAL); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 7, 12)) .frequency(P6M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_6M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .initialStub(IborRateStubCalculation.ofIborInterpolatedRate(USD_LIBOR_3M, USD_LIBOR_6M)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 314215.2347116342, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_ZeroCouponFixedVsLibor3mSwap() { SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(P12M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.NONE) .compoundingMethod(CompoundingMethod.STRAIGHT) .build()) .notionalSchedule(NOTIONAL) .calculation(FixedRateCalculation.builder() .dayCount(THIRTY_U_360) .rate(ValueSchedule.of(0.015)) .build()) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.NONE) .compoundingMethod(CompoundingMethod.STRAIGHT) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), 7850279.042216873, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_AmortizingFixedVsLibor3mSwap() { ValueAdjustment stepReduction = ValueAdjustment.ofDeltaAmount(-3_000_000); List<ValueStep> steps = new ArrayList<>(); for (int i = 1; i < 28; i++) { steps.add(ValueStep.of(i, stepReduction)); } ValueSchedule notionalSchedule = ValueSchedule.of(100_000_000, steps); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(USD, notionalSchedule)) .calculation(FixedRateCalculation.builder() .dayCount(THIRTY_U_360) .rate(ValueSchedule.of(0.016)) .build()) .build(); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(USD, notionalSchedule)) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 9, 10)).build()) .product(Swap.of(receiveLeg, payLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -1850080.2895532502, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_CompoundingOisFixed2mVsFedFund12mSwap() { SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 2, 5)) .endDate(LocalDate.of(2014, 4, 7)) .frequency(TERM) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)) .build()) .notionalSchedule(NOTIONAL) .calculation(FixedRateCalculation.builder() .dayCount(ACT_360) .rate(ValueSchedule.of(0.00123)) .build()) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 2, 5)) .endDate(LocalDate.of(2014, 4, 7)) .frequency(TERM) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)) .build()) .notionalSchedule(NOTIONAL) .calculation(OvernightRateCalculation.builder() .dayCount(ACT_360) .index(USD_FED_FUND) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 2, 3)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -9723.264518929138, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_CompoundingOisFixed2mVsFedFund12mSwapWithFixing() { SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 1, 17)) .endDate(LocalDate.of(2014, 3, 17)) .frequency(TERM) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)) .build()) .notionalSchedule(NOTIONAL) .calculation(FixedRateCalculation.builder() .dayCount(ACT_360) .rate(ValueSchedule.of(0.00123)) .build()) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 1, 17)) .endDate(LocalDate.of(2014, 3, 17)) .frequency(TERM) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.ofBusinessDays(2, CalendarUSD.NYC)) .build()) .notionalSchedule(NOTIONAL) .calculation(OvernightRateCalculation.builder() .dayCount(ACT_360) .index(USD_FED_FUND) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 1, 15)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -7352.973875972721, TOLERANCE_PV); } //------------------------------------------------------------------------- public void test_OnAASpreadVsLibor3MSwap() { SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2020, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(IborRateCalculation.builder() .index(USD_LIBOR_3M) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, CalendarUSD.NYC, BDA_P)) .build()) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2020, 9, 12)) .frequency(P3M) .businessDayAdjustment(BDA_MF) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NOTIONAL) .calculation(OvernightRateCalculation.builder() .dayCount(ACT_360) .index(USD_FED_FUND) .accrualMethod(OvernightAccrualMethod.AVERAGED) .rateCutOffDays(0) // Should be 2, put to 0 for comparison .spread(ValueSchedule.of(0.0025)) .build()) .build(); ResolvedSwapTrade trade = SwapTrade.builder() .info(TradeInfo.builder().tradeDate(LocalDate.of(2014, 1, 15)).build()) .product(Swap.of(payLeg, receiveLeg)) .build() .resolve(REF_DATA); DiscountingSwapTradePricer pricer = swapPricer(); CurrencyAmount pv = pricer.presentValue(trade, provider()).getAmount(USD); assertEquals(pv.getAmount(), -160663.8362, TOLERANCE_PV); } //------------------------------------------------------------------------- // fixed rate leg private static SwapLeg fixedLeg( LocalDate start, LocalDate end, Frequency frequency, PayReceive payReceive, NotionalSchedule notional, double fixedRate, StubConvention stubConvention) { return RateCalculationSwapLeg.builder() .payReceive(payReceive) .accrualSchedule(PeriodicSchedule.builder() .startDate(start) .endDate(end) .frequency(frequency) .businessDayAdjustment(BDA_MF) .stubConvention(stubConvention) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(frequency) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(notional) .calculation(FixedRateCalculation.builder() .dayCount(THIRTY_U_360) .rate(ValueSchedule.of(fixedRate)) .build()) .build(); } // ibor rate leg private static SwapLeg iborLeg( LocalDate start, LocalDate end, IborIndex index, PayReceive payReceive, NotionalSchedule notional, StubConvention stubConvention) { Frequency freq = Frequency.of(index.getTenor().getPeriod()); return RateCalculationSwapLeg.builder() .payReceive(payReceive) .accrualSchedule(PeriodicSchedule.builder() .startDate(start) .endDate(end) .frequency(freq) .businessDayAdjustment(BDA_MF) .stubConvention(stubConvention) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(freq) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(notional) .calculation(IborRateCalculation.builder() .index(index) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, index.getFixingCalendar(), BDA_P)) .build()) .build(); } //------------------------------------------------------------------------- // pricer static DiscountingSwapTradePricer swapPricer() { return DiscountingSwapTradePricer.DEFAULT; } // rates provider static RatesProvider provider() { // StandardDataSets.providerUsdDscOnL1L3L6() with locked holidays and time-series return ImmutableRatesProvider.builder(VAL_DATE) .fxRateProvider(StandardDataSets.FX_MATRIX) .discountCurve(USD, StandardDataSets.GROUP1_USD_DSC) .overnightIndexCurve(USD_FED_FUND, StandardDataSets.GROUP1_USD_ON, TS_USDON) .iborIndexCurve(USD_LIBOR_1M, StandardDataSets.GROUP1_USD_L1M, TS_USDLIBOR1M) .iborIndexCurve(USD_LIBOR_3M, StandardDataSets.GROUP1_USD_L3M, TS_USDLIBOR3M) .iborIndexCurve(USD_LIBOR_6M, StandardDataSets.GROUP1_USD_L6M, TS_USDLIBOR6M) .build(); } // use a fixed known set of holiday dates to ensure tests produce same numbers private static IborIndex lockIndexCalendar(IborIndex index) { return ((ImmutableIborIndex) index).toBuilder() .fixingCalendar(CalendarUSD.NYC) .effectiveDateOffset(index.getEffectiveDateOffset().toBuilder() .calendar(CalendarUSD.NYC) .adjustment(index.getEffectiveDateOffset().getAdjustment().toBuilder() .calendar(CalendarUSD.NYC) .build()) .build()) .maturityDateOffset(index.getMaturityDateOffset().toBuilder() .adjustment(index.getMaturityDateOffset().getAdjustment().toBuilder() .calendar(CalendarUSD.NYC) .build()) .build()) .build(); } }