// ------------------------------------------------------------------------- public void test_builder_ensureDefaults() { ResetSchedule test = ResetSchedule.builder() .resetFrequency(P1M) .businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, GBLO)) .build(); assertEquals(test.getResetFrequency(), P1M); assertEquals(test.getBusinessDayAdjustment(), BusinessDayAdjustment.of(FOLLOWING, GBLO)); assertEquals(test.getResetMethod(), UNWEIGHTED); }
// ----------------------------------------------------------------------- // create a vanilla fixed vs libor 3m swap private static Trade createVanillaFixedVsLibor3mSwap() { NotionalSchedule notional = NotionalSchedule.of(Currency.USD, 100_000_000); SwapLeg payLeg = RateCalculationSwapLeg.builder() .payReceive(PayReceive.PAY) .accrualSchedule( PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(Frequency.P6M) .businessDayAdjustment( BusinessDayAdjustment.of(MODIFIED_FOLLOWING, HolidayCalendarIds.USNY)) .build()) .paymentSchedule( PaymentSchedule.builder() .paymentFrequency(Frequency.P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(notional) .calculation(FixedRateCalculation.of(0.015, DayCounts.THIRTY_U_360)) .build(); SwapLeg receiveLeg = RateCalculationSwapLeg.builder() .payReceive(PayReceive.RECEIVE) .accrualSchedule( PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2021, 9, 12)) .frequency(Frequency.P3M) .businessDayAdjustment( BusinessDayAdjustment.of(MODIFIED_FOLLOWING, HolidayCalendarIds.USNY)) .build()) .paymentSchedule( PaymentSchedule.builder() .paymentFrequency(Frequency.P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(notional) .calculation(IborRateCalculation.of(IborIndices.USD_LIBOR_3M)) .build(); return SwapTrade.builder() .product(Swap.of(payLeg, receiveLeg)) .info( TradeInfo.builder() .addAttribute(TradeAttributeType.DESCRIPTION, "Fixed vs Libor 3m") .counterparty(StandardId.of("example", "A")) .settlementDate(LocalDate.of(2014, 9, 12)) .build()) .build(); }
// ------------------------------------------------------------------------- public void coverage() { ResetSchedule test = ResetSchedule.builder() .resetFrequency(P1M) .businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, GBLO)) .build(); coverImmutableBean(test); ResetSchedule test2 = ResetSchedule.builder() .resetFrequency(P3M) .businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO)) .resetMethod(WEIGHTED) .build(); coverBeanEquals(test, test2); }
public void test_serialization() { ResetSchedule test = ResetSchedule.builder() .resetFrequency(P1M) .businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, GBLO)) .build(); assertSerialization(test); }
public void test_usdLibor3m() { IborIndex test = IborIndex.of("USD-LIBOR-3M"); assertEquals(test.getCurrency(), USD); assertEquals(test.getName(), "USD-LIBOR-3M"); assertEquals(test.getTenor(), TENOR_3M); assertEquals(test.getFixingCalendar(), GBLO); assertEquals(test.getFixingDateOffset(), DaysAdjustment.ofBusinessDays(-2, GBLO)); assertEquals( test.getEffectiveDateOffset(), DaysAdjustment.ofBusinessDays( 2, GBLO, BusinessDayAdjustment.of(FOLLOWING, GBLO.combineWith(USNY)))); assertEquals( test.getMaturityDateOffset(), TenorAdjustment.ofLastBusinessDay( TENOR_3M, BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO.combineWith(USNY)))); assertEquals(test.getDayCount(), ACT_360); assertEquals(test.toString(), "USD-LIBOR-3M"); }
public void test_gbpLibor3m() { IborIndex test = IborIndex.of("GBP-LIBOR-3M"); assertEquals(test.getCurrency(), GBP); assertEquals(test.getName(), "GBP-LIBOR-3M"); assertEquals(test.getTenor(), TENOR_3M); assertEquals(test.getFixingCalendar(), GBLO); assertEquals( test.getFixingDateOffset(), DaysAdjustment.ofCalendarDays(0, BusinessDayAdjustment.of(PRECEDING, GBLO))); assertEquals( test.getEffectiveDateOffset(), DaysAdjustment.ofCalendarDays(0, BusinessDayAdjustment.of(FOLLOWING, GBLO))); assertEquals( test.getMaturityDateOffset(), TenorAdjustment.ofLastBusinessDay( TENOR_3M, BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO))); assertEquals(test.getDayCount(), ACT_365F); assertEquals(test.toString(), "GBP-LIBOR-3M"); }
public void test_of_indexOnly() { ImmutableIborFixingDepositConvention test = ImmutableIborFixingDepositConvention.of(GBP_LIBOR_6M); assertEquals( test.getBusinessDayAdjustment(), BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBP_LIBOR_6M.getFixingCalendar())); assertEquals(test.getCurrency(), GBP_LIBOR_6M.getCurrency()); assertEquals(test.getDayCount(), GBP_LIBOR_6M.getDayCount()); assertEquals(test.getFixingDateOffset(), GBP_LIBOR_6M.getFixingDateOffset()); assertEquals(test.getIndex(), GBP_LIBOR_6M); assertEquals(test.getSpotDateOffset(), GBP_LIBOR_6M.getEffectiveDateOffset()); }
public void test_euibor3m() { IborIndex test = IborIndex.of("EUR-EURIBOR-3M"); assertEquals(test.getCurrency(), EUR); assertEquals(test.getName(), "EUR-EURIBOR-3M"); assertEquals(test.getTenor(), TENOR_3M); assertEquals(test.getFixingCalendar(), EUTA); assertEquals(test.getFixingDateOffset(), DaysAdjustment.ofBusinessDays(-2, EUTA)); assertEquals(test.getEffectiveDateOffset(), DaysAdjustment.ofBusinessDays(2, EUTA)); assertEquals( test.getMaturityDateOffset(), TenorAdjustment.ofLastBusinessDay( TENOR_3M, BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUTA))); assertEquals(test.getDayCount(), ACT_360); assertEquals(test.toString(), "EUR-EURIBOR-3M"); }
public void test_expand() { ImmutableIborFixingDepositConvention base = ImmutableIborFixingDepositConvention.of(EUR_LIBOR_3M); IborFixingDepositConvention test = base.expand(); IborFixingDepositConvention expected = ImmutableIborFixingDepositConvention.builder() .businessDayAdjustment( BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUR_LIBOR_3M.getFixingCalendar())) .currency(EUR_LIBOR_3M.getCurrency()) .dayCount(EUR_LIBOR_3M.getDayCount()) .fixingDateOffset(EUR_LIBOR_3M.getFixingDateOffset()) .index(EUR_LIBOR_3M) .name(EUR_LIBOR_3M.getName()) .spotDateOffset(EUR_LIBOR_3M.getEffectiveDateOffset()) .build(); assertEquals(test.getName(), EUR_LIBOR_3M.getName()); assertEquals(test, expected); }
// ------------------------------------------------------------------------- public void test_resolve() { ResetSchedule test = ResetSchedule.builder() .resetFrequency(P1M) .businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, GBLO)) .build(); SchedulePeriod accrualPeriod = SchedulePeriod.of(DATE_01_06, DATE_04_07, DATE_01_05, DATE_04_05); Schedule schedule = test.createSchedule(DAY_5, REF_DATA).apply(accrualPeriod); Schedule expected = Schedule.builder() .periods( SchedulePeriod.of(DATE_01_06, DATE_02_05, DATE_01_05, DATE_02_05), SchedulePeriod.of(DATE_02_05, DATE_03_05, DATE_02_05, DATE_03_05), SchedulePeriod.of(DATE_03_05, DATE_04_07, DATE_03_05, DATE_04_05)) .frequency(P1M) .rollConvention(DAY_5) .build(); assertEquals(schedule, expected); }
/** Test {@link TermDepositTrade}. */ @Test public class TermDepositTradeTest { private static final TermDeposit DEPOSIT = TermDeposit.builder() .buySell(BuySell.BUY) .currency(GBP) .notional(100000000d) .startDate(LocalDate.of(2015, 1, 19)) .endDate(LocalDate.of(2015, 7, 19)) .businessDayAdjustment(BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO)) .dayCount(ACT_365F) .rate(0.0250) .build(); private static final TradeInfo TRADE_INFO = TradeInfo.builder().tradeDate(date(2014, 6, 30)).build(); // ------------------------------------------------------------------------- public void test_builder() { TermDepositTrade test = TermDepositTrade.builder().product(DEPOSIT).tradeInfo(TRADE_INFO).build(); assertEquals(test.getProduct(), DEPOSIT); assertEquals(test.getTradeInfo(), TRADE_INFO); } // ------------------------------------------------------------------------- public void coverage() { TermDepositTrade test1 = TermDepositTrade.builder().product(DEPOSIT).tradeInfo(TRADE_INFO).build(); coverImmutableBean(test1); TermDepositTrade test2 = TermDepositTrade.builder().product(DEPOSIT).build(); coverBeanEquals(test1, test2); } public void test_serialization() { TermDepositTrade test = TermDepositTrade.builder().product(DEPOSIT).tradeInfo(TRADE_INFO).build(); assertSerialization(test); } }
/** Test {@link IborFixingDepositConvention}. */ @Test public class IborFixingDepositConventionTest { private static final BusinessDayAdjustment BDA_MOD_FOLLOW = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUTA); private static final DaysAdjustment SPOT_ADJ = DaysAdjustment.ofBusinessDays(2, EUTA); private static final DaysAdjustment FIXING_ADJ = DaysAdjustment.ofBusinessDays(-2, EUTA, BusinessDayAdjustment.of(PRECEDING, GBLO)); public void test_builder_full() { ImmutableIborFixingDepositConvention test = ImmutableIborFixingDepositConvention.builder() .businessDayAdjustment(BDA_MOD_FOLLOW) .currency(EUR) .dayCount(ACT_365F) .fixingDateOffset(FIXING_ADJ) .index(EUR_LIBOR_3M) .spotDateOffset(SPOT_ADJ) .build(); assertEquals(test.getBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getCurrency(), EUR); assertEquals(test.getDayCount(), ACT_365F); assertEquals(test.getFixingDateOffset(), FIXING_ADJ); assertEquals(test.getIndex(), EUR_LIBOR_3M); assertEquals(test.getName(), EUR_LIBOR_3M.getName()); assertEquals(test.getSpotDateOffset(), SPOT_ADJ); } public void test_builder_indexOnly() { ImmutableIborFixingDepositConvention test = ImmutableIborFixingDepositConvention.builder().index(GBP_LIBOR_6M).build(); assertEquals( test.getBusinessDayAdjustment(), BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBP_LIBOR_6M.getFixingCalendar())); assertEquals(test.getCurrency(), GBP_LIBOR_6M.getCurrency()); assertEquals(test.getDayCount(), GBP_LIBOR_6M.getDayCount()); assertEquals(test.getFixingDateOffset(), GBP_LIBOR_6M.getFixingDateOffset()); assertEquals(test.getIndex(), GBP_LIBOR_6M); assertEquals(test.getSpotDateOffset(), GBP_LIBOR_6M.getEffectiveDateOffset()); } public void test_of_indexOnly() { ImmutableIborFixingDepositConvention test = ImmutableIborFixingDepositConvention.of(GBP_LIBOR_6M); assertEquals( test.getBusinessDayAdjustment(), BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBP_LIBOR_6M.getFixingCalendar())); assertEquals(test.getCurrency(), GBP_LIBOR_6M.getCurrency()); assertEquals(test.getDayCount(), GBP_LIBOR_6M.getDayCount()); assertEquals(test.getFixingDateOffset(), GBP_LIBOR_6M.getFixingDateOffset()); assertEquals(test.getIndex(), GBP_LIBOR_6M); assertEquals(test.getSpotDateOffset(), GBP_LIBOR_6M.getEffectiveDateOffset()); } public void test_expand() { ImmutableIborFixingDepositConvention base = ImmutableIborFixingDepositConvention.of(EUR_LIBOR_3M); IborFixingDepositConvention test = base.expand(); IborFixingDepositConvention expected = ImmutableIborFixingDepositConvention.builder() .businessDayAdjustment( BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUR_LIBOR_3M.getFixingCalendar())) .currency(EUR_LIBOR_3M.getCurrency()) .dayCount(EUR_LIBOR_3M.getDayCount()) .fixingDateOffset(EUR_LIBOR_3M.getFixingDateOffset()) .index(EUR_LIBOR_3M) .name(EUR_LIBOR_3M.getName()) .spotDateOffset(EUR_LIBOR_3M.getEffectiveDateOffset()) .build(); assertEquals(test.getName(), EUR_LIBOR_3M.getName()); assertEquals(test, expected); } public void test_toTemplate() { IborFixingDepositConvention convention = IborFixingDepositConvention.of(GBP_LIBOR_6M); IborFixingDepositTemplate template = convention.toTemplate(); assertEquals(template.getConvention(), convention); assertEquals(template.getDepositPeriod(), GBP_LIBOR_6M.getTenor().getPeriod()); } public void test_toTrade() { IborFixingDepositConvention convention = ImmutableIborFixingDepositConvention.builder() .businessDayAdjustment(BDA_MOD_FOLLOW) .currency(EUR) .dayCount(ACT_365F) .fixingDateOffset(FIXING_ADJ) .index(EUR_LIBOR_3M) .spotDateOffset(SPOT_ADJ) .build(); LocalDate tradeDate = LocalDate.of(2015, 1, 22); Period depositPeriod = Period.ofMonths(3); double notional = 1d; double fixedRate = 0.045; IborFixingDepositTrade trade = convention.toTrade(tradeDate, depositPeriod, BUY, notional, fixedRate); LocalDate startExpected = SPOT_ADJ.adjust(tradeDate); LocalDate endExpected = startExpected.plus(depositPeriod); IborFixingDeposit productExpected = IborFixingDeposit.builder() .businessDayAdjustment(BDA_MOD_FOLLOW) .buySell(BUY) .currency(EUR) .dayCount(ACT_365F) .startDate(startExpected) .endDate(endExpected) .fixedRate(fixedRate) .fixingDateOffset(FIXING_ADJ) .index(EUR_LIBOR_3M) .notional(notional) .build(); TradeInfo tradeInfoExpected = TradeInfo.builder().tradeDate(tradeDate).build(); assertEquals(trade.getProduct(), productExpected); assertEquals(trade.getTradeInfo(), tradeInfoExpected); } // ------------------------------------------------------------------------- @DataProvider(name = "name") static Object[][] data_name() { return new Object[][] { {ImmutableIborFixingDepositConvention.of(GBP_LIBOR_3M), "GBP-LIBOR-3M"}, {ImmutableIborFixingDepositConvention.of(USD_LIBOR_3M), "USD-LIBOR-3M"}, }; } @Test(dataProvider = "name") public void test_name(IborFixingDepositConvention convention, String name) { assertEquals(convention.getName(), name); } @Test(dataProvider = "name") public void test_toString(IborFixingDepositConvention convention, String name) { assertEquals(convention.toString(), name); } @Test(dataProvider = "name") public void test_of_lookup(IborFixingDepositConvention convention, String name) { assertEquals(IborFixingDepositConvention.of(name), convention); } @Test(dataProvider = "name") public void test_extendedEnum(IborFixingDepositConvention convention, String name) { IborFixingDepositConvention.of(name); // ensures map is populated ImmutableMap<String, IborFixingDepositConvention> map = IborFixingDepositConvention.extendedEnum().lookupAll(); assertEquals(map.get(name), convention); } public void test_of_lookup_notFound() { assertThrowsIllegalArg(() -> IborFixingDepositConvention.of("Rubbish")); } public void test_of_lookup_null() { assertThrowsIllegalArg(() -> IborFixingDepositConvention.of((String) null)); } // ------------------------------------------------------------------------- public void coverage() { ImmutableIborFixingDepositConvention test1 = ImmutableIborFixingDepositConvention.of(GBP_LIBOR_6M); coverImmutableBean(test1); ImmutableIborFixingDepositConvention test2 = ImmutableIborFixingDepositConvention.of(EUR_LIBOR_3M).toBuilder().name("Foo").build(); coverBeanEquals(test1, test2); coverPrivateConstructor(IborFixingDepositConventions.class); coverPrivateConstructor(IborFixingDepositConventionLookup.class); } public void test_serialization() { ImmutableIborFixingDepositConvention test = ImmutableIborFixingDepositConvention.of(GBP_LIBOR_6M); assertSerialization(test); } }
/** Helper methods for testing curves. */ final class CurveTestUtils { private static final String TEST_SCHEME = "test"; private static final BusinessDayAdjustment BDA_FOLLOW = BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, HolidayCalendars.GBLO); private static final IborRateSwapLegConvention FLOATING_CONVENTION = IborRateSwapLegConvention.of(IborIndices.USD_LIBOR_3M); private static final FixedRateSwapLegConvention FIXED_CONVENTION = FixedRateSwapLegConvention.of(Currency.USD, DayCounts.ACT_360, Frequency.P6M, BDA_FOLLOW); private static final FixedIborSwapConvention SWAP_CONVENTION = ImmutableFixedIborSwapConvention.of("USD-Swap", FIXED_CONVENTION, FLOATING_CONVENTION); private CurveTestUtils() {} static InterpolatedNodalCurveDefinition fraCurveDefinition() { String fra1x4 = "fra1x4"; String fra2x5 = "fra2x5"; String fra3x6 = "fra3x6"; String fra6x9 = "fra6x9"; String fra9x12 = "fra9x12"; String fra12x15 = "fra12x15"; String fra18x21 = "fra18x21"; FraCurveNode fra1x4Node = fraNode(1, fra1x4); FraCurveNode fra2x5Node = fraNode(2, fra2x5); FraCurveNode fra3x6Node = fraNode(3, fra3x6); FraCurveNode fra6x9Node = fraNode(6, fra6x9); FraCurveNode fra9x12Node = fraNode(9, fra9x12); FraCurveNode fra12x15Node = fraNode(12, fra12x15); FraCurveNode fra18x21Node = fraNode(18, fra18x21); CurveName curveName = CurveName.of("FRA Curve"); List<CurveNode> nodes = ImmutableList.of( fra1x4Node, fra2x5Node, fra3x6Node, fra6x9Node, fra9x12Node, fra12x15Node, fra18x21Node); return InterpolatedNodalCurveDefinition.builder() .name(curveName) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.ZERO_RATE) .dayCount(DayCounts.ACT_ACT_ISDA) .nodes(nodes) .interpolator(CurveInterpolators.DOUBLE_QUADRATIC) .extrapolatorLeft(CurveExtrapolators.FLAT) .extrapolatorRight(CurveExtrapolators.FLAT) .build(); } static InterpolatedNodalCurveDefinition fraSwapCurveDefinition() { String fra3x6 = "fra3x6"; String fra6x9 = "fra6x9"; String swap1y = "swap1y"; String swap2y = "swap2y"; String swap3y = "swap3y"; FraCurveNode fra3x6Node = CurveTestUtils.fraNode(3, fra3x6); FraCurveNode fra6x9Node = CurveTestUtils.fraNode(6, fra6x9); FixedIborSwapCurveNode swap1yNode = fixedIborSwapNode(Tenor.TENOR_1Y, swap1y); FixedIborSwapCurveNode swap2yNode = fixedIborSwapNode(Tenor.TENOR_2Y, swap2y); FixedIborSwapCurveNode swap3yNode = fixedIborSwapNode(Tenor.TENOR_3Y, swap3y); CurveName curveName = CurveName.of("FRA and Fixed-Float Swap Curve"); List<CurveNode> nodes = ImmutableList.of(fra3x6Node, fra6x9Node, swap1yNode, swap2yNode, swap3yNode); return InterpolatedNodalCurveDefinition.builder() .name(curveName) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.ZERO_RATE) .dayCount(DayCounts.ACT_ACT_ISDA) .nodes(nodes) .interpolator(CurveInterpolators.DOUBLE_QUADRATIC) .extrapolatorLeft(CurveExtrapolators.FLAT) .extrapolatorRight(CurveExtrapolators.FLAT) .build(); } static FraCurveNode fraNode(int startMonths, String id) { Period periodToStart = Period.ofMonths(startMonths); QuoteKey quoteKey = QuoteKey.of(StandardId.of(TEST_SCHEME, id)); return FraCurveNode.of(FraTemplate.of(periodToStart, IborIndices.USD_LIBOR_3M), quoteKey); } static FixedIborSwapCurveNode fixedIborSwapNode(Tenor tenor, String id) { QuoteKey quoteKey = QuoteKey.of(StandardId.of(TEST_SCHEME, id)); FixedIborSwapTemplate template = FixedIborSwapTemplate.of(Period.ZERO, tenor, SWAP_CONVENTION); return FixedIborSwapCurveNode.of(template, quoteKey); } static ObservableId id(String nodeName) { return QuoteId.of(StandardId.of(TEST_SCHEME, nodeName)); } static ObservableId id(CurveNode node) { if (node instanceof FraCurveNode) { return ((FraCurveNode) node).getRateKey().toObservableId(MarketDataFeed.NONE); } else if (node instanceof FixedIborSwapCurveNode) { return ((FixedIborSwapCurveNode) node).getRateKey().toObservableId(MarketDataFeed.NONE); } else { throw new IllegalArgumentException("Unsupported node type " + node.getClass().getName()); } } }
/** Test {@link ThreeLegBasisSwapConvention}. */ @Test public class ThreeLegBasisSwapConventionTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final double NOTIONAL_2M = 2_000_000d; private static final BusinessDayAdjustment BDA_FOLLOW = BusinessDayAdjustment.of(FOLLOWING, EUTA); private static final DaysAdjustment PLUS_ONE_DAY = DaysAdjustment.ofBusinessDays(1, EUTA); private static final String NAME = "EUR-Swap"; private static final FixedRateSwapLegConvention FIXED = FixedRateSwapLegConvention.of(EUR, THIRTY_U_360, P12M, BDA_FOLLOW); private static final IborRateSwapLegConvention IBOR3M = IborRateSwapLegConvention.of(EUR_EURIBOR_3M); private static final IborRateSwapLegConvention IBOR6M = IborRateSwapLegConvention.of(EUR_EURIBOR_6M); private static final IborRateSwapLegConvention IBOR12M = IborRateSwapLegConvention.of(EUR_EURIBOR_12M); // ------------------------------------------------------------------------- public void test_of() { ImmutableThreeLegBasisSwapConvention test = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); assertEquals(test.getName(), NAME); assertEquals(test.getSpreadLeg(), FIXED); assertEquals(test.getSpreadFloatingLeg(), IBOR6M); assertEquals(test.getFlatFloatingLeg(), IBOR12M); assertEquals(test.getSpotDateOffset(), EUR_EURIBOR_6M.getEffectiveDateOffset()); } public void test_of_spotDateOffset() { ImmutableThreeLegBasisSwapConvention test = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M, PLUS_ONE_DAY); assertEquals(test.getName(), NAME); assertEquals(test.getSpreadLeg(), FIXED); assertEquals(test.getSpreadFloatingLeg(), IBOR6M); assertEquals(test.getFlatFloatingLeg(), IBOR12M); assertEquals(test.getSpotDateOffset(), PLUS_ONE_DAY); } public void test_builder() { ImmutableThreeLegBasisSwapConvention test = ImmutableThreeLegBasisSwapConvention.builder() .name(NAME) .spreadLeg(FIXED) .spreadFloatingLeg(IBOR6M) .flatFloatingLeg(IBOR12M) .spotDateOffset(PLUS_ONE_DAY) .build(); assertEquals(test.getName(), NAME); assertEquals(test.getSpreadLeg(), FIXED); assertEquals(test.getSpreadFloatingLeg(), IBOR6M); assertEquals(test.getFlatFloatingLeg(), IBOR12M); assertEquals(test.getSpotDateOffset(), PLUS_ONE_DAY); } // ------------------------------------------------------------------------- public void test_toTrade_tenor() { ThreeLegBasisSwapConvention base = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 5, 7); LocalDate endDate = date(2025, 5, 7); SwapTrade test = base.createTrade(tradeDate, TENOR_10Y, BUY, NOTIONAL_2M, 0.25d, REF_DATA); Swap expected = Swap.of( FIXED.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, PAY, NOTIONAL_2M), IBOR12M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } public void test_toTrade_periodTenor() { ThreeLegBasisSwapConvention base = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 8, 7); LocalDate endDate = date(2025, 8, 7); SwapTrade test = base.createTrade( tradeDate, Period.ofMonths(3), TENOR_10Y, BUY, NOTIONAL_2M, 0.25d, REF_DATA); Swap expected = Swap.of( FIXED.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, PAY, NOTIONAL_2M), IBOR12M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } public void test_toTrade_dates() { ThreeLegBasisSwapConvention base = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 8, 5); LocalDate endDate = date(2015, 11, 5); SwapTrade test = base.toTrade(tradeDate, startDate, endDate, BUY, NOTIONAL_2M, 0.25d); Swap expected = Swap.of( FIXED.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, PAY, NOTIONAL_2M), IBOR12M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } // ------------------------------------------------------------------------- @DataProvider(name = "name") static Object[][] data_name() { return new Object[][] { { ThreeLegBasisSwapConventions.EUR_FIXED_1Y_EURIBOR_3M_EURIBOR_6M, "EUR-FIXED-1Y-EURIBOR-3M-EURIBOR-6M" }, }; } @Test(dataProvider = "name") public void test_name(ThreeLegBasisSwapConvention convention, String name) { assertEquals(convention.getName(), name); } @Test(dataProvider = "name") public void test_toString(ThreeLegBasisSwapConvention convention, String name) { assertEquals(convention.toString(), name); } @Test(dataProvider = "name") public void test_of_lookup(ThreeLegBasisSwapConvention convention, String name) { assertEquals(ThreeLegBasisSwapConvention.of(name), convention); } @Test(dataProvider = "name") public void test_extendedEnum(ThreeLegBasisSwapConvention convention, String name) { ThreeLegBasisSwapConvention.of(name); // ensures map is populated ImmutableMap<String, ThreeLegBasisSwapConvention> map = ThreeLegBasisSwapConvention.extendedEnum().lookupAll(); assertEquals(map.get(name), convention); } public void test_of_lookup_notFound() { assertThrowsIllegalArg(() -> ThreeLegBasisSwapConvention.of("Rubbish")); } public void test_of_lookup_null() { assertThrowsIllegalArg(() -> ThreeLegBasisSwapConvention.of((String) null)); } // ------------------------------------------------------------------------- public void coverage() { ImmutableThreeLegBasisSwapConvention test = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); coverImmutableBean(test); ImmutableThreeLegBasisSwapConvention test2 = ImmutableThreeLegBasisSwapConvention.of("swap", FIXED, IBOR3M, IBOR6M); coverBeanEquals(test, test2); ImmutableThreeLegBasisSwapConvention test3 = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR3M, IBOR12M); coverBeanEquals(test, test3); } public void test_serialization() { ThreeLegBasisSwapConvention test = ImmutableThreeLegBasisSwapConvention.of(NAME, FIXED, IBOR6M, IBOR12M); assertSerialization(test); } }
/** Test {@link IborIborSwapConvention}. */ @Test public class IborIborSwapConventionTest { private static final double NOTIONAL_2M = 2_000_000d; private static final BusinessDayAdjustment BDA_FOLLOW = BusinessDayAdjustment.of(FOLLOWING, GBLO); private static final DaysAdjustment NEXT_SAME_BUS_DAY = DaysAdjustment.ofCalendarDays(0, BDA_FOLLOW); private static final DaysAdjustment PLUS_ONE_DAY = DaysAdjustment.ofBusinessDays(1, GBLO); private static final String NAME = "USD-Swap"; private static final IborRateSwapLegConvention IBOR1M = IborRateSwapLegConvention.of(USD_LIBOR_1M); private static final IborRateSwapLegConvention IBOR3M = IborRateSwapLegConvention.of(USD_LIBOR_3M); private static final IborRateSwapLegConvention IBOR6M = IborRateSwapLegConvention.of(USD_LIBOR_6M); // ------------------------------------------------------------------------- public void test_of() { ImmutableIborIborSwapConvention test = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); assertEquals(test.getName(), NAME); assertEquals(test.getSpreadLeg(), IBOR3M); assertEquals(test.getFlatLeg(), IBOR6M); assertEquals(test.getSpotDateOffset(), USD_LIBOR_3M.getEffectiveDateOffset()); } // ------------------------------------------------------------------------- public void test_builder_notEnoughData() { assertThrowsIllegalArg( () -> ImmutableIborIborSwapConvention.builder().spotDateOffset(NEXT_SAME_BUS_DAY).build()); } // ------------------------------------------------------------------------- public void test_expand() { ImmutableIborIborSwapConvention test = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M).expand(); assertEquals(test.getName(), NAME); assertEquals(test.getSpreadLeg(), IBOR3M.expand()); assertEquals(test.getFlatLeg(), IBOR6M.expand()); assertEquals(test.getSpotDateOffset(), USD_LIBOR_3M.getEffectiveDateOffset()); } public void test_expandAllSpecified() { ImmutableIborIborSwapConvention test = ImmutableIborIborSwapConvention.builder() .name(NAME) .spreadLeg(IBOR3M) .flatLeg(IBOR6M) .spotDateOffset(PLUS_ONE_DAY) .build() .expand(); assertEquals(test.getSpreadLeg(), IBOR3M.expand()); assertEquals(test.getFlatLeg(), IBOR6M.expand()); assertEquals(test.getSpotDateOffset(), PLUS_ONE_DAY); } // ------------------------------------------------------------------------- public void test_toTrade_tenor() { IborIborSwapConvention base = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 5, 7); LocalDate endDate = date(2025, 5, 7); SwapTrade test = base.toTrade(tradeDate, TENOR_10Y, BUY, NOTIONAL_2M, 0.25d); Swap expected = Swap.of( IBOR3M.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getTradeInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } public void test_toTrade_periodTenor() { IborIborSwapConvention base = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 8, 7); LocalDate endDate = date(2025, 8, 7); SwapTrade test = base.toTrade(tradeDate, Period.ofMonths(3), TENOR_10Y, BUY, NOTIONAL_2M, 0.25d); Swap expected = Swap.of( IBOR3M.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getTradeInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } public void test_toTrade_dates() { IborIborSwapConvention base = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); LocalDate tradeDate = LocalDate.of(2015, 5, 5); LocalDate startDate = date(2015, 8, 5); LocalDate endDate = date(2015, 11, 5); SwapTrade test = base.toTrade(tradeDate, startDate, endDate, BUY, NOTIONAL_2M, 0.25d); Swap expected = Swap.of( IBOR3M.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d), IBOR6M.toLeg(startDate, endDate, RECEIVE, NOTIONAL_2M)); assertEquals(test.getTradeInfo().getTradeDate(), Optional.of(tradeDate)); assertEquals(test.getProduct(), expected); } // ------------------------------------------------------------------------- @DataProvider(name = "name") static Object[][] data_name() { return new Object[][] { {IborIborSwapConventions.USD_LIBOR_1M_LIBOR_3M, "USD-LIBOR-1M-LIBOR-3M"}, {IborIborSwapConventions.USD_LIBOR_3M_LIBOR_6M, "USD-LIBOR-3M-LIBOR-6M"}, }; } @Test(dataProvider = "name") public void test_name(IborIborSwapConvention convention, String name) { assertEquals(convention.getName(), name); } @Test(dataProvider = "name") public void test_toString(IborIborSwapConvention convention, String name) { assertEquals(convention.toString(), name); } @Test(dataProvider = "name") public void test_of_lookup(IborIborSwapConvention convention, String name) { assertEquals(IborIborSwapConvention.of(name), convention); } @Test(dataProvider = "name") public void test_extendedEnum(IborIborSwapConvention convention, String name) { IborIborSwapConvention.of(name); // ensures map is populated ImmutableMap<String, IborIborSwapConvention> map = IborIborSwapConvention.extendedEnum().lookupAll(); assertEquals(map.get(name), convention); } public void test_of_lookup_notFound() { assertThrowsIllegalArg(() -> IborIborSwapConvention.of("Rubbish")); } public void test_of_lookup_null() { assertThrowsIllegalArg(() -> IborIborSwapConvention.of((String) null)); } // ------------------------------------------------------------------------- public void coverage() { ImmutableIborIborSwapConvention test = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); coverImmutableBean(test); ImmutableIborIborSwapConvention test2 = ImmutableIborIborSwapConvention.of(NAME, IBOR1M, IBOR6M); coverBeanEquals(test, test2); ImmutableIborIborSwapConvention test3 = ImmutableIborIborSwapConvention.of(NAME, IBOR1M, IBOR3M); coverBeanEquals(test, test3); } public void test_serialization() { IborIborSwapConvention test = ImmutableIborIborSwapConvention.of(NAME, IBOR3M, IBOR6M); assertSerialization(test); } }
/** Test {@link OvernightRateSwapLegConvention}. */ @Test public class OvernightRateSwapLegConventionTest { private static final double NOTIONAL_2M = 2_000_000d; private static final BusinessDayAdjustment BDA_FOLLOW = BusinessDayAdjustment.of(FOLLOWING, GBLO); private static final BusinessDayAdjustment BDA_MOD_FOLLOW = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, GBLO); private static final DaysAdjustment PLUS_TWO_DAYS = DaysAdjustment.ofBusinessDays(2, GBLO); // ------------------------------------------------------------------------- public void test_of() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.of(GBP_SONIA, P12M, 2); assertEquals(test.getIndex(), GBP_SONIA); assertEquals(test.getAccrualMethod(), COMPOUNDED); assertEquals(test.getRateCutOffDays(), 0); assertEquals(test.getCurrency(), GBP); assertEquals(test.getDayCount(), ACT_365F); assertEquals(test.getAccrualFrequency(), P12M); assertEquals(test.getAccrualBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStartDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getEndDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStubConvention(), StubConvention.SHORT_INITIAL); assertEquals(test.getRollConvention(), RollConventions.NONE); assertEquals(test.getPaymentFrequency(), P12M); assertEquals( test.getPaymentDateOffset(), DaysAdjustment.ofBusinessDays(2, GBP_SONIA.getFixingCalendar())); assertEquals(test.getCompoundingMethod(), CompoundingMethod.NONE); } public void test_of_method() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.of(GBP_SONIA, P12M, 2, AVERAGED); assertEquals(test.getIndex(), GBP_SONIA); assertEquals(test.getAccrualMethod(), AVERAGED); assertEquals(test.getRateCutOffDays(), 0); assertEquals(test.getCurrency(), GBP); assertEquals(test.getDayCount(), ACT_365F); assertEquals(test.getAccrualFrequency(), P12M); assertEquals(test.getAccrualBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStartDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getEndDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStubConvention(), StubConvention.SHORT_INITIAL); assertEquals(test.getRollConvention(), RollConventions.NONE); assertEquals(test.getPaymentFrequency(), P12M); assertEquals( test.getPaymentDateOffset(), DaysAdjustment.ofBusinessDays(2, GBP_SONIA.getFixingCalendar())); assertEquals(test.getCompoundingMethod(), CompoundingMethod.NONE); } // ------------------------------------------------------------------------- public void test_builder_notEnoughData() { assertThrowsIllegalArg(() -> OvernightRateSwapLegConvention.builder().build()); } // ------------------------------------------------------------------------- public void test_expand() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.of(GBP_SONIA, P12M, 2).expand(); assertEquals(test.getIndex(), GBP_SONIA); assertEquals(test.getAccrualMethod(), COMPOUNDED); assertEquals(test.getRateCutOffDays(), 0); assertEquals(test.getCurrency(), GBP); assertEquals(test.getDayCount(), ACT_365F); assertEquals(test.getAccrualFrequency(), P12M); assertEquals(test.getAccrualBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStartDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getEndDateBusinessDayAdjustment(), BDA_MOD_FOLLOW); assertEquals(test.getStubConvention(), StubConvention.SHORT_INITIAL); assertEquals(test.getRollConvention(), RollConventions.NONE); assertEquals(test.getPaymentFrequency(), P12M); assertEquals( test.getPaymentDateOffset(), DaysAdjustment.ofBusinessDays(2, GBP_SONIA.getFixingCalendar())); assertEquals(test.getCompoundingMethod(), CompoundingMethod.NONE); } public void test_expandAllSpecified() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.builder() .index(GBP_SONIA) .accrualMethod(COMPOUNDED) .rateCutOffDays(2) .currency(USD) .dayCount(ACT_360) .accrualFrequency(P6M) .accrualBusinessDayAdjustment(BDA_FOLLOW) .startDateBusinessDayAdjustment(BDA_FOLLOW) .endDateBusinessDayAdjustment(BDA_FOLLOW) .stubConvention(LONG_INITIAL) .rollConvention(RollConventions.EOM) .paymentFrequency(P6M) .paymentDateOffset(PLUS_TWO_DAYS) .compoundingMethod(CompoundingMethod.FLAT) .build(); assertEquals(test.getIndex(), GBP_SONIA); assertEquals(test.getAccrualMethod(), COMPOUNDED); assertEquals(test.getRateCutOffDays(), 2); assertEquals(test.getCurrency(), USD); assertEquals(test.getDayCount(), ACT_360); assertEquals(test.getAccrualFrequency(), P6M); assertEquals(test.getAccrualBusinessDayAdjustment(), BDA_FOLLOW); assertEquals(test.getStartDateBusinessDayAdjustment(), BDA_FOLLOW); assertEquals(test.getEndDateBusinessDayAdjustment(), BDA_FOLLOW); assertEquals(test.getStubConvention(), StubConvention.LONG_INITIAL); assertEquals(test.getRollConvention(), RollConventions.EOM); assertEquals(test.getPaymentFrequency(), P6M); assertEquals(test.getPaymentDateOffset(), PLUS_TWO_DAYS); assertEquals(test.getCompoundingMethod(), CompoundingMethod.FLAT); } // ------------------------------------------------------------------------- public void test_toLeg() { OvernightRateSwapLegConvention base = OvernightRateSwapLegConvention.builder().index(GBP_SONIA).accrualMethod(COMPOUNDED).build(); LocalDate startDate = LocalDate.of(2015, 5, 5); LocalDate endDate = LocalDate.of(2020, 5, 5); RateCalculationSwapLeg test = base.toLeg(startDate, endDate, PAY, NOTIONAL_2M); RateCalculationSwapLeg expected = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule( PeriodicSchedule.builder() .frequency(TERM) .startDate(startDate) .endDate(endDate) .businessDayAdjustment(BDA_MOD_FOLLOW) .build()) .paymentSchedule( PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(GBP, NOTIONAL_2M)) .calculation(OvernightRateCalculation.of(GBP_SONIA)) .build(); assertEquals(test, expected); } public void test_toLeg_withSpread() { OvernightRateSwapLegConvention base = OvernightRateSwapLegConvention.builder().index(GBP_SONIA).accrualMethod(AVERAGED).build(); LocalDate startDate = LocalDate.of(2015, 5, 5); LocalDate endDate = LocalDate.of(2020, 5, 5); RateCalculationSwapLeg test = base.toLeg(startDate, endDate, PAY, NOTIONAL_2M, 0.25d); RateCalculationSwapLeg expected = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule( PeriodicSchedule.builder() .frequency(TERM) .startDate(startDate) .endDate(endDate) .businessDayAdjustment(BDA_MOD_FOLLOW) .build()) .paymentSchedule( PaymentSchedule.builder() .paymentFrequency(TERM) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(GBP, NOTIONAL_2M)) .calculation( OvernightRateCalculation.builder() .index(GBP_SONIA) .accrualMethod(AVERAGED) .spread(ValueSchedule.of(0.25d)) .build()) .build(); assertEquals(test, expected); } // ------------------------------------------------------------------------- public void coverage() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.builder().index(GBP_SONIA).accrualMethod(COMPOUNDED).build(); coverImmutableBean(test); OvernightRateSwapLegConvention test2 = OvernightRateSwapLegConvention.builder() .index(USD_FED_FUND) .accrualMethod(AVERAGED) .rateCutOffDays(2) .currency(USD) .dayCount(ACT_360) .accrualFrequency(P6M) .accrualBusinessDayAdjustment(BDA_FOLLOW) .startDateBusinessDayAdjustment(BDA_FOLLOW) .endDateBusinessDayAdjustment(BDA_FOLLOW) .stubConvention(LONG_INITIAL) .rollConvention(RollConventions.EOM) .paymentFrequency(P6M) .paymentDateOffset(PLUS_TWO_DAYS) .build(); coverBeanEquals(test, test2); } public void test_serialization() { OvernightRateSwapLegConvention test = OvernightRateSwapLegConvention.of(GBP_SONIA, P12M, 2); assertSerialization(test); } }
/** Test {@link TermDepositCurveNode}. */ @Test public class TermDepositCurveNodeTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final LocalDate VAL_DATE = date(2015, 6, 30); private static final BusinessDayAdjustment BDA_MOD_FOLLOW = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, EUTA); private static final DaysAdjustment PLUS_TWO_DAYS = DaysAdjustment.ofBusinessDays(2, EUTA); private static final TermDepositConvention CONVENTION = TermDepositConventions.EUR_DEPOSIT_T2; private static final Period DEPOSIT_PERIOD = Period.ofMonths(3); private static final TermDepositTemplate TEMPLATE = TermDepositTemplate.of(DEPOSIT_PERIOD, CONVENTION); private static final QuoteId QUOTE_ID = QuoteId.of(StandardId.of("OG-Ticker", "Deposit1")); private static final double SPREAD = 0.0015; private static final String LABEL = "Label"; private static final String LABEL_AUTO = "3M"; public void test_builder() { TermDepositCurveNode test = TermDepositCurveNode.builder() .label(LABEL) .template(TEMPLATE) .rateId(QUOTE_ID) .additionalSpread(SPREAD) .date(CurveNodeDate.LAST_FIXING) .build(); assertEquals(test.getLabel(), LABEL); assertEquals(test.getRateId(), QUOTE_ID); assertEquals(test.getAdditionalSpread(), SPREAD); assertEquals(test.getTemplate(), TEMPLATE); assertEquals(test.getDate(), CurveNodeDate.LAST_FIXING); } public void test_builder_defaults() { TermDepositCurveNode test = TermDepositCurveNode.builder() .label(LABEL) .template(TEMPLATE) .rateId(QUOTE_ID) .additionalSpread(SPREAD) .build(); assertEquals(test.getLabel(), LABEL); assertEquals(test.getRateId(), QUOTE_ID); assertEquals(test.getAdditionalSpread(), SPREAD); assertEquals(test.getTemplate(), TEMPLATE); assertEquals(test.getDate(), CurveNodeDate.END); } public void test_of_noSpread() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID); assertEquals(test.getLabel(), LABEL_AUTO); assertEquals(test.getRateId(), QUOTE_ID); assertEquals(test.getAdditionalSpread(), 0.0d); assertEquals(test.getTemplate(), TEMPLATE); } public void test_of_withSpread() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); assertEquals(test.getLabel(), LABEL_AUTO); assertEquals(test.getRateId(), QUOTE_ID); assertEquals(test.getAdditionalSpread(), SPREAD); assertEquals(test.getTemplate(), TEMPLATE); } public void test_of_withSpreadAndLabel() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD, LABEL); assertEquals(test.getLabel(), LABEL); assertEquals(test.getRateId(), QUOTE_ID); assertEquals(test.getAdditionalSpread(), SPREAD); assertEquals(test.getTemplate(), TEMPLATE); } public void test_requirements() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); Set<ObservableId> set = test.requirements(); Iterator<ObservableId> itr = set.iterator(); assertEquals(itr.next(), QUOTE_ID); assertFalse(itr.hasNext()); } public void test_trade() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); double rate = 0.035; MarketData marketData = ImmutableMarketData.builder(VAL_DATE).addValue(QUOTE_ID, rate).build(); TermDepositTrade trade = node.trade(1d, marketData, REF_DATA); LocalDate startDateExpected = PLUS_TWO_DAYS.adjust(VAL_DATE, REF_DATA); LocalDate endDateExpected = startDateExpected.plus(DEPOSIT_PERIOD); TermDeposit depositExpected = TermDeposit.builder() .buySell(BuySell.BUY) .currency(EUR) .dayCount(ACT_360) .startDate(startDateExpected) .endDate(endDateExpected) .notional(1.0d) .businessDayAdjustment(BDA_MOD_FOLLOW) .rate(rate + SPREAD) .build(); TradeInfo tradeInfoExpected = TradeInfo.builder().tradeDate(VAL_DATE).build(); assertEquals(trade.getProduct(), depositExpected); assertEquals(trade.getInfo(), tradeInfoExpected); } public void test_trade_noMarketData() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); LocalDate valuationDate = LocalDate.of(2015, 1, 22); MarketData marketData = MarketData.empty(valuationDate); assertThrows(() -> node.trade(1d, marketData, REF_DATA), MarketDataNotFoundException.class); } public void test_initialGuess() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); double rate = 0.035; MarketData marketData = ImmutableMarketData.builder(VAL_DATE).addValue(QUOTE_ID, rate).build(); assertEquals(node.initialGuess(marketData, ValueType.ZERO_RATE), rate); assertEquals(node.initialGuess(marketData, ValueType.FORWARD_RATE), rate); assertEquals( node.initialGuess(marketData, ValueType.DISCOUNT_FACTOR), Math.exp(-rate * 0.25), 1.0e-12); } public void test_metadata_end() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); LocalDate valuationDate = LocalDate.of(2015, 1, 22); ParameterMetadata metadata = node.metadata(valuationDate, REF_DATA); assertEquals(((TenorDateParameterMetadata) metadata).getDate(), LocalDate.of(2015, 4, 27)); assertEquals(((TenorDateParameterMetadata) metadata).getTenor(), Tenor.TENOR_3M); } public void test_metadata_fixed() { LocalDate nodeDate = VAL_DATE.plusMonths(1); TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD).withDate(CurveNodeDate.of(nodeDate)); LocalDate valuationDate = LocalDate.of(2015, 1, 22); DatedParameterMetadata metadata = node.metadata(valuationDate, REF_DATA); assertEquals(metadata.getDate(), nodeDate); assertEquals(metadata.getLabel(), node.getLabel()); } public void test_metadata_last_fixing() { TermDepositCurveNode node = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD).withDate(CurveNodeDate.LAST_FIXING); assertThrowsWithCause( () -> node.metadata(VAL_DATE, REF_DATA), UnsupportedOperationException.class); } // ------------------------------------------------------------------------- public void coverage() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); coverImmutableBean(test); TermDepositCurveNode test2 = TermDepositCurveNode.of( TermDepositTemplate.of(Period.ofMonths(1), CONVENTION), QuoteId.of(StandardId.of("OG-Ticker", "Deposit2"))); coverBeanEquals(test, test2); } public void test_serialization() { TermDepositCurveNode test = TermDepositCurveNode.of(TEMPLATE, QUOTE_ID, SPREAD); assertSerialization(test); } }
/** Black volatility data sets for testing. */ public class SwaptionNormalVolatilityDataSets { private static final double BP1 = 1.0E-4; private static final Interpolator1D LINEAR_FLAT = CombinedInterpolatorExtrapolator.of( CurveInterpolators.LINEAR.getName(), CurveExtrapolators.FLAT.getName(), CurveExtrapolators.FLAT.getName()); private static final GridInterpolator2D INTERPOLATOR_2D = new GridInterpolator2D(LINEAR_FLAT, LINEAR_FLAT); // ===== Standard figures for testing ===== private static final DoubleArray TIMES = DoubleArray.of( 0.50, 1.00, 5.00, 10.0, 0.50, 1.00, 5.00, 10.0, 0.50, 1.00, 5.00, 10.0, 0.50, 1.00, 5.00, 10.0, 0.50, 1.00, 5.00, 10.0); private static final DoubleArray TENOR = DoubleArray.of( 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 5.0, 5.0, 5.0, 5.0, 10.0, 10.0, 10.0, 10.0, 30.0, 30.0, 30.0, 30.0); private static final DoubleArray NORMAL_VOL = DoubleArray.of( 0.010, 0.011, 0.012, 0.013, 0.011, 0.012, 0.013, 0.014, 0.012, 0.013, 0.014, 0.015, 0.013, 0.014, 0.015, 0.016, 0.014, 0.015, 0.016, 0.017); private static final SurfaceMetadata METADATA = DefaultSurfaceMetadata.builder() .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.YEAR_FRACTION) .zValueType(ValueType.VOLATILITY) .surfaceName(SurfaceName.of("Normal Vol")) .build(); private static final NodalSurface SURFACE_STD = InterpolatedNodalSurface.of(METADATA, TIMES, TENOR, NORMAL_VOL, INTERPOLATOR_2D); private static final LocalDate VALUATION_DATE_STD = RatesProviderDataSets.VAL_DATE_2014_01_22; private static final LocalTime VALUATION_TIME_STD = LocalTime.of(13, 45); private static final ZoneId VALUATION_ZONE_STD = ZoneId.of("Europe/London"); private static final BusinessDayAdjustment MOD_FOL_US = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, USNY); private static final FixedRateSwapLegConvention USD_FIXED_1Y_30U360 = FixedRateSwapLegConvention.of(USD, THIRTY_U_360, Frequency.P6M, MOD_FOL_US); private static final IborRateSwapLegConvention USD_IBOR_LIBOR3M = IborRateSwapLegConvention.of(USD_LIBOR_3M); public static final FixedIborSwapConvention USD_1Y_LIBOR3M = ImmutableFixedIborSwapConvention.of("USD-Swap", USD_FIXED_1Y_30U360, USD_IBOR_LIBOR3M); public static final NormalVolatilityExpiryTenorSwaptionProvider NORMAL_VOL_SWAPTION_PROVIDER_USD_STD = NormalVolatilityExpiryTenorSwaptionProvider.of( SURFACE_STD, USD_1Y_LIBOR3M, DayCounts.ACT_365F, VALUATION_DATE_STD, VALUATION_TIME_STD, VALUATION_ZONE_STD); /** * Returns the swaption normal volatility surface shifted by a given amount. The shift is * parallel. * * @param shift the shift * @return the swaption normal volatility surface */ public static NormalVolatilityExpiryTenorSwaptionProvider normalVolSwaptionProviderUsdStsShifted( double shift) { DoubleArray volShifted = NORMAL_VOL.map(v -> v + shift); return NormalVolatilityExpiryTenorSwaptionProvider.of( InterpolatedNodalSurface.of(METADATA, TIMES, TENOR, volShifted, INTERPOLATOR_2D), USD_1Y_LIBOR3M, DayCounts.ACT_365F, VALUATION_DATE_STD, VALUATION_TIME_STD, VALUATION_ZONE_STD); } public static NormalVolatilityExpiryTenorSwaptionProvider normalVolSwaptionProviderUsdStd( LocalDate valuationDate) { return NormalVolatilityExpiryTenorSwaptionProvider.of( SURFACE_STD, USD_1Y_LIBOR3M, DayCounts.ACT_365F, valuationDate, VALUATION_TIME_STD, VALUATION_ZONE_STD); } // ===== Flat volatilities for testing ===== private static final DoubleArray TIMES_FLAT = DoubleArray.of(0.0, 100.0, 0.0, 100.0); private static final DoubleArray TENOR_FLAT = DoubleArray.of(0.0, 0.0, 30.0, 30.0); private static final DoubleArray NORMAL_VOL_FLAT = DoubleArray.of(0.01, 0.01, 0.01, 0.01); private static final InterpolatedNodalSurface SURFACE_FLAT = InterpolatedNodalSurface.of( METADATA, TIMES_FLAT, TENOR_FLAT, NORMAL_VOL_FLAT, INTERPOLATOR_2D); public static final NormalVolatilityExpiryTenorSwaptionProvider NORMAL_VOL_SWAPTION_PROVIDER_USD_FLAT = NormalVolatilityExpiryTenorSwaptionProvider.of( SURFACE_FLAT, USD_1Y_LIBOR3M, DayCounts.ACT_365F, VALUATION_DATE_STD, VALUATION_TIME_STD, VALUATION_ZONE_STD); // ===== Market data as of 2014-03-20 ===== private static final DoubleArray TIMES_20150320 = DoubleArray.of( 0.25, 0.25, 0.25, 0.25, 0.25, 0.50, 0.50, 0.50, 0.50, 0.50, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 5.0, 5.0, 5.0, 5.0, 5.0, 10.0, 10.0, 10.0, 10.0, 10.0); private static final DoubleArray TENORS_20150320 = DoubleArray.of( 1.0, 2.0, 5.0, 10.0, 30.0, 1.0, 2.0, 5.0, 10.0, 30.0, 1.0, 2.0, 5.0, 10.0, 30.0, 1.0, 2.0, 5.0, 10.0, 30.0, 1.0, 2.0, 5.0, 10.0, 30.0, 1.0, 2.0, 5.0, 10.0, 30.0); private static final DoubleArray NORMAL_VOL_20150320_BP = DoubleArray.of( 43.6, 65.3, 88, 87.5, 88, // 3M 55.5, 72.2, 90.3, 89.3, 88.6, // 6M 72.6, 82.7, 91.6, 89.8, 87.3, // 1Y 90.4, 91.9, 93.4, 84.7, 93.5, // 2Y 99.3, 96.8, 94.3, 88.6, 77.3, // 5Y 88.4, 85.9, 82.2, 76.7, 65.1); // 10Y private static final DoubleArray NORMAL_VOL_20150320 = NORMAL_VOL_20150320_BP.map(v -> v * BP1); private static final NodalSurface SURFACE_20150320 = InterpolatedNodalSurface.of( METADATA, TIMES_20150320, TENORS_20150320, NORMAL_VOL_20150320, INTERPOLATOR_2D); private static final LocalDate VALUATION_DATE_20150320 = LocalDate.of(2015, 3, 20); private static final LocalTime VALUATION_TIME_20150320 = LocalTime.of(18, 00); private static final ZoneId VALUATION_ZONE_20150320 = ZoneId.of("Europe/London"); public static final NormalVolatilityExpiryTenorSwaptionProvider NORMAL_VOL_SWAPTION_PROVIDER_USD_20150320 = NormalVolatilityExpiryTenorSwaptionProvider.of( SURFACE_20150320, USD_1Y_LIBOR3M, DayCounts.ACT_365F, VALUATION_DATE_20150320, VALUATION_TIME_20150320, VALUATION_ZONE_20150320); }
/** Test {@link SabrExtrapolationReplicationCmsTradePricer}. */ @Test public class DiscountingCmsTradePricerTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); // trades private static final LocalDate VALUATION = LocalDate.of(2015, 8, 18); private static final SwapIndex INDEX = SwapIndices.EUR_EURIBOR_1100_5Y; private static final LocalDate START = LocalDate.of(2015, 10, 21); private static final LocalDate END = LocalDate.of(2020, 10, 21); private static final Frequency FREQUENCY = Frequency.P12M; private static final BusinessDayAdjustment BUSS_ADJ_EUR = BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, EUTA); private static final PeriodicSchedule SCHEDULE_EUR = PeriodicSchedule.of( START, END, FREQUENCY, BUSS_ADJ_EUR, StubConvention.NONE, RollConventions.NONE); private static final double NOTIONAL_VALUE = 1.0e6; private static final ValueSchedule NOTIONAL = ValueSchedule.of(NOTIONAL_VALUE); private static final ResolvedCmsLeg CMS_LEG = CmsLeg.builder() .index(INDEX) .notional(NOTIONAL) .payReceive(RECEIVE) .paymentSchedule(SCHEDULE_EUR) .build() .resolve(REF_DATA); private static final ResolvedSwapLeg PAY_LEG = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(SCHEDULE_EUR) .calculation(FixedRateCalculation.of(0.01, ACT_360)) .paymentSchedule( PaymentSchedule.builder() .paymentFrequency(FREQUENCY) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(CurrencyAmount.of(EUR, NOTIONAL_VALUE))) .build() .resolve(REF_DATA); private static final ResolvedCms CMS_TWO_LEGS = ResolvedCms.of(CMS_LEG, PAY_LEG); private static final ResolvedCms CMS_ONE_LEG = ResolvedCms.of(CMS_LEG); private static final Payment PREMIUM = Payment.of(CurrencyAmount.of(EUR, -0.03 * NOTIONAL_VALUE), VALUATION); private static final TradeInfo TRADE_INFO = TradeInfo.builder().tradeDate(VALUATION).build(); private static final ResolvedCmsTrade CMS_TRADE = ResolvedCmsTrade.builder().product(CMS_TWO_LEGS).info(TRADE_INFO).build(); private static final ResolvedCmsTrade CMS_TRADE_PREMIUM = ResolvedCmsTrade.builder().product(CMS_ONE_LEG).premium(PREMIUM).build(); // providers private static final ImmutableRatesProvider RATES_PROVIDER = SwaptionSabrRateVolatilityDataSet.getRatesProviderEur(VALUATION); // providers - valuation on payment date private static final LocalDate FIXING = LocalDate.of(2016, 10, 19); // fixing for the second period. private static final double OBS_INDEX = 0.013; private static final LocalDateDoubleTimeSeries TIME_SERIES = LocalDateDoubleTimeSeries.of(FIXING, OBS_INDEX); private static final LocalDate PAYMENT = LocalDate.of(2017, 10, 23); // payment date of the second payment private static final ImmutableRatesProvider RATES_PROVIDER_ON_PAY = SwaptionSabrRateVolatilityDataSet.getRatesProviderEur(PAYMENT, TIME_SERIES); // pricers private static final DiscountingCmsProductPricer PRODUCT_PRICER = DiscountingCmsProductPricer.DEFAULT; private static final DiscountingPaymentPricer PREMIUM_PRICER = DiscountingPaymentPricer.DEFAULT; private static final DiscountingCmsTradePricer TRADE_PRICER = DiscountingCmsTradePricer.DEFAULT; private static final double TOL = 1.0e-13; public void test_presentValue() { MultiCurrencyAmount pv1 = TRADE_PRICER.presentValue(CMS_TRADE_PREMIUM, RATES_PROVIDER); MultiCurrencyAmount pv2 = TRADE_PRICER.presentValue(CMS_TRADE, RATES_PROVIDER); MultiCurrencyAmount pvProd1 = PRODUCT_PRICER.presentValue(CMS_ONE_LEG, RATES_PROVIDER); MultiCurrencyAmount pvProd2 = PRODUCT_PRICER.presentValue(CMS_TWO_LEGS, RATES_PROVIDER); CurrencyAmount pvPrem = PREMIUM_PRICER.presentValue(PREMIUM, RATES_PROVIDER); assertEquals(pv1, pvProd1.plus(pvPrem)); assertEquals(pv2, pvProd2); } public void test_presentValueSensitivity() { PointSensitivities pt1 = TRADE_PRICER.presentValueSensitivity(CMS_TRADE_PREMIUM, RATES_PROVIDER); PointSensitivities pt2 = TRADE_PRICER.presentValueSensitivity(CMS_TRADE, RATES_PROVIDER); PointSensitivityBuilder ptProd1 = PRODUCT_PRICER.presentValueSensitivity(CMS_ONE_LEG, RATES_PROVIDER); PointSensitivityBuilder ptProd2 = PRODUCT_PRICER.presentValueSensitivity(CMS_TWO_LEGS, RATES_PROVIDER); PointSensitivityBuilder ptPrem = PREMIUM_PRICER.presentValueSensitivity(PREMIUM, RATES_PROVIDER); assertEquals(pt1, ptProd1.combinedWith(ptPrem).build()); assertEquals(pt2, ptProd2.build()); } public void test_currencyExposure() { MultiCurrencyAmount computed1 = TRADE_PRICER.currencyExposure(CMS_TRADE_PREMIUM, RATES_PROVIDER); MultiCurrencyAmount computed2 = TRADE_PRICER.currencyExposure(CMS_TRADE, RATES_PROVIDER); MultiCurrencyAmount pv1 = TRADE_PRICER.presentValue(CMS_TRADE_PREMIUM, RATES_PROVIDER); PointSensitivities pt1 = TRADE_PRICER.presentValueSensitivity(CMS_TRADE_PREMIUM, RATES_PROVIDER); MultiCurrencyAmount expected1 = RATES_PROVIDER.currencyExposure(pt1).plus(pv1); MultiCurrencyAmount pv2 = TRADE_PRICER.presentValue(CMS_TRADE, RATES_PROVIDER); PointSensitivities pt2 = TRADE_PRICER.presentValueSensitivity(CMS_TRADE, RATES_PROVIDER); MultiCurrencyAmount expected2 = RATES_PROVIDER.currencyExposure(pt2).plus(pv2); assertEquals( computed1.getAmount(EUR).getAmount(), expected1.getAmount(EUR).getAmount(), NOTIONAL_VALUE * TOL); assertEquals( computed2.getAmount(EUR).getAmount(), expected2.getAmount(EUR).getAmount(), NOTIONAL_VALUE * TOL); } public void test_currentCash() { MultiCurrencyAmount cc1 = TRADE_PRICER.currentCash(CMS_TRADE_PREMIUM, RATES_PROVIDER); MultiCurrencyAmount cc2 = TRADE_PRICER.currentCash(CMS_TRADE, RATES_PROVIDER); assertEquals(cc1, MultiCurrencyAmount.of(PREMIUM.getValue())); assertEquals(cc2, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); } public void test_currentCash_onPay() { MultiCurrencyAmount cc1 = TRADE_PRICER.currentCash(CMS_TRADE_PREMIUM, RATES_PROVIDER_ON_PAY); MultiCurrencyAmount cc2 = TRADE_PRICER.currentCash(CMS_TRADE, RATES_PROVIDER_ON_PAY); MultiCurrencyAmount ccProd1 = PRODUCT_PRICER.currentCash(CMS_ONE_LEG, RATES_PROVIDER_ON_PAY); MultiCurrencyAmount ccProd2 = PRODUCT_PRICER.currentCash(CMS_TWO_LEGS, RATES_PROVIDER_ON_PAY); assertEquals(cc1, ccProd1); assertEquals(cc2, ccProd2); } }
/** Test */ @Test public class DiscountingFixedCouponBondProductPricerTest { // fixed coupon bond private static final StandardId SECURITY_ID = StandardId.of("OG-Ticker", "GOVT1-BOND1"); private static final StandardId ISSUER_ID = StandardId.of("OG-Ticker", "GOVT1"); private static final LocalDate VAL_DATE = date(2016, 4, 25); private static final YieldConvention YIELD_CONVENTION = YieldConvention.GERMAN_BONDS; private static final double NOTIONAL = 1.0e7; private static final double FIXED_RATE = 0.015; private static final HolidayCalendar EUR_CALENDAR = HolidayCalendars.EUTA; private static final DaysAdjustment DATE_OFFSET = DaysAdjustment.ofBusinessDays(3, EUR_CALENDAR); private static final DayCount DAY_COUNT = DayCounts.ACT_365F; private static final LocalDate START_DATE = LocalDate.of(2015, 4, 12); private static final LocalDate END_DATE = LocalDate.of(2025, 4, 12); private static final BusinessDayAdjustment BUSINESS_ADJUST = BusinessDayAdjustment.of(BusinessDayConventions.MODIFIED_FOLLOWING, EUR_CALENDAR); private static final PeriodicSchedule PERIOD_SCHEDULE = PeriodicSchedule.of( START_DATE, END_DATE, Frequency.P6M, BUSINESS_ADJUST, StubConvention.SHORT_INITIAL, false); private static final DaysAdjustment EX_COUPON = DaysAdjustment.ofBusinessDays(-5, EUR_CALENDAR, BUSINESS_ADJUST); /** nonzero ex-coupon period */ private static final FixedCouponBond PRODUCT = FixedCouponBond.builder() .dayCount(DAY_COUNT) .fixedRate(FIXED_RATE) .legalEntityId(ISSUER_ID) .currency(EUR) .notional(NOTIONAL) .periodicSchedule(PERIOD_SCHEDULE) .settlementDateOffset(DATE_OFFSET) .yieldConvention(YIELD_CONVENTION) .exCouponPeriod(EX_COUPON) .build(); private static final Security<FixedCouponBond> BOND_SECURITY = UnitSecurity.builder(PRODUCT).standardId(SECURITY_ID).build(); /** no ex-coupon period */ private static final FixedCouponBond PRODUCT_NO_EXCOUPON = FixedCouponBond.builder() .dayCount(DAY_COUNT) .fixedRate(FIXED_RATE) .legalEntityId(ISSUER_ID) .currency(EUR) .notional(NOTIONAL) .periodicSchedule(PERIOD_SCHEDULE) .settlementDateOffset(DATE_OFFSET) .yieldConvention(YIELD_CONVENTION) .build(); // rates provider private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.LINEAR; private static final CurveName NAME_REPO = CurveName.of("TestRepoCurve"); private static final CurveMetadata METADATA_REPO = Curves.zeroRates(NAME_REPO, ACT_365F); private static final InterpolatedNodalCurve CURVE_REPO = InterpolatedNodalCurve.of( METADATA_REPO, DoubleArray.of(0.1, 2.0, 10.0), DoubleArray.of(0.05, 0.06, 0.09), INTERPOLATOR); private static final DiscountFactors DSC_FACTORS_REPO = ZeroRateDiscountFactors.of(EUR, VAL_DATE, CURVE_REPO); private static final BondGroup GROUP_REPO = BondGroup.of("GOVT1 BOND1"); private static final CurveName NAME_ISSUER = CurveName.of("TestIssuerCurve"); private static final CurveMetadata METADATA_ISSUER = Curves.zeroRates(NAME_ISSUER, ACT_365F); private static final InterpolatedNodalCurve CURVE_ISSUER = InterpolatedNodalCurve.of( METADATA_ISSUER, DoubleArray.of(0.2, 9.0, 15.0), DoubleArray.of(0.03, 0.05, 0.13), INTERPOLATOR); private static final DiscountFactors DSC_FACTORS_ISSUER = ZeroRateDiscountFactors.of(EUR, VAL_DATE, CURVE_ISSUER); private static final LegalEntityGroup GROUP_ISSUER = LegalEntityGroup.of("GOVT1"); private static final LegalEntityDiscountingProvider PROVIDER = LegalEntityDiscountingProvider.builder() .issuerCurves( ImmutableMap.<Pair<LegalEntityGroup, Currency>, DiscountFactors>of( Pair.<LegalEntityGroup, Currency>of(GROUP_ISSUER, EUR), DSC_FACTORS_ISSUER)) .legalEntityMap(ImmutableMap.<StandardId, LegalEntityGroup>of(ISSUER_ID, GROUP_ISSUER)) .repoCurves( ImmutableMap.<Pair<BondGroup, Currency>, DiscountFactors>of( Pair.<BondGroup, Currency>of(GROUP_REPO, EUR), DSC_FACTORS_REPO)) .bondMap(ImmutableMap.<StandardId, BondGroup>of(SECURITY_ID, GROUP_REPO)) .valuationDate(VAL_DATE) .build(); private static final double Z_SPREAD = 0.035; private static final int PERIOD_PER_YEAR = 4; private static final double TOL = 1.0e-12; private static final double EPS = 1.0e-6; // pricers private static final DiscountingFixedCouponBondProductPricer PRICER = DiscountingFixedCouponBondProductPricer.DEFAULT; private static final DiscountingPaymentPricer PRICER_NOMINAL = DiscountingPaymentPricer.DEFAULT; private static final DiscountingFixedCouponBondPaymentPeriodPricer PRICER_COUPON = DiscountingFixedCouponBondPaymentPeriodPricer.DEFAULT; private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL = new RatesFiniteDifferenceSensitivityCalculator(EPS); // ------------------------------------------------------------------------- public void test_presentValue() { CurrencyAmount computed = PRICER.presentValue(PRODUCT, PROVIDER); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue(expanded.getNominalPayment(), DSC_FACTORS_ISSUER); int size = expanded.getPeriodicPayments().size(); double pvCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvCupon += PRICER_COUPON.presentValue( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER)); } expected = expected.plus(pvCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } public void test_presentValueWithZSpread_continuous() { CurrencyAmount computed = PRICER.presentValueWithZSpread(PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue( expanded.getNominalPayment(), DSC_FACTORS_ISSUER, Z_SPREAD, CONTINUOUS, 0); int size = expanded.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValueWithSpread( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER), Z_SPREAD, CONTINUOUS, 0); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } public void test_presentValueWithZSpread_periodic() { CurrencyAmount computed = PRICER.presentValueWithZSpread(PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue( expanded.getNominalPayment(), DSC_FACTORS_ISSUER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); int size = expanded.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValueWithSpread( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER), Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } public void test_presentValue_noExcoupon() { CurrencyAmount computed = PRICER.presentValue(PRODUCT_NO_EXCOUPON, PROVIDER); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue(expanded.getNominalPayment(), DSC_FACTORS_ISSUER); int size = expanded.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValue( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER)); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } public void test_presentValueWithZSpread_continuous_noExcoupon() { CurrencyAmount computed = PRICER.presentValueWithZSpread(PRODUCT_NO_EXCOUPON, PROVIDER, Z_SPREAD, CONTINUOUS, 0); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue( expanded.getNominalPayment(), DSC_FACTORS_ISSUER, Z_SPREAD, CONTINUOUS, 0); int size = expanded.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValueWithSpread( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER), Z_SPREAD, CONTINUOUS, 0); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } public void test_presentValueWithZSpread_periodic_noExcoupon() { CurrencyAmount computed = PRICER.presentValueWithZSpread( PRODUCT_NO_EXCOUPON, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); ExpandedFixedCouponBond expanded = PRODUCT.expand(); CurrencyAmount expected = PRICER_NOMINAL.presentValue( expanded.getNominalPayment(), DSC_FACTORS_ISSUER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); int size = expanded.getPeriodicPayments().size(); double pvcCupon = 0d; for (int i = 2; i < size; ++i) { FixedCouponBondPaymentPeriod payment = expanded.getPeriodicPayments().get(i); pvcCupon += PRICER_COUPON.presentValueWithSpread( payment, IssuerCurveDiscountFactors.of(DSC_FACTORS_ISSUER, GROUP_ISSUER), Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); } expected = expected.plus(pvcCupon); assertEquals(computed.getCurrency(), EUR); assertEquals(computed.getAmount(), expected.getAmount(), NOTIONAL * TOL); } // ------------------------------------------------------------------------- public void test_dirtyPriceFromCurves() { double computed = PRICER.dirtyPriceFromCurves(BOND_SECURITY, PROVIDER); CurrencyAmount pv = PRICER.presentValue(PRODUCT, PROVIDER); LocalDate settlement = DATE_OFFSET.adjust(VAL_DATE); double df = DSC_FACTORS_REPO.discountFactor(settlement); assertEquals(computed, pv.getAmount() / df / NOTIONAL); } public void test_dirtyPriceFromCurvesWithZSpread_continuous() { double computed = PRICER.dirtyPriceFromCurvesWithZSpread(BOND_SECURITY, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurrencyAmount pv = PRICER.presentValueWithZSpread(PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0); LocalDate settlement = DATE_OFFSET.adjust(VAL_DATE); double df = DSC_FACTORS_REPO.discountFactor(settlement); assertEquals(computed, pv.getAmount() / df / NOTIONAL); } public void test_dirtyPriceFromCurvesWithZSpread_periodic() { double computed = PRICER.dirtyPriceFromCurvesWithZSpread( BOND_SECURITY, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyAmount pv = PRICER.presentValueWithZSpread(PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); LocalDate settlement = DATE_OFFSET.adjust(VAL_DATE); double df = DSC_FACTORS_REPO.discountFactor(settlement); assertEquals(computed, pv.getAmount() / df / NOTIONAL); } public void test_dirtyPriceFromCleanPrice_cleanPriceFromDirtyPrice() { double dirtyPrice = PRICER.dirtyPriceFromCurves(BOND_SECURITY, PROVIDER); LocalDate settlement = DATE_OFFSET.adjust(VAL_DATE); double cleanPrice = PRICER.cleanPriceFromDirtyPrice(PRODUCT, settlement, dirtyPrice); double accruedInterest = PRICER.accruedInterest(PRODUCT, settlement); assertEquals(cleanPrice, dirtyPrice - accruedInterest / NOTIONAL, NOTIONAL * TOL); double dirtyPriceRe = PRICER.dirtyPriceFromCleanPrice(PRODUCT, settlement, cleanPrice); assertEquals(dirtyPriceRe, dirtyPrice, TOL); } // ------------------------------------------------------------------------- public void test_zSpreadFromCurvesAndPV_continuous() { double dirtyPrice = PRICER.dirtyPriceFromCurvesWithZSpread(BOND_SECURITY, PROVIDER, Z_SPREAD, CONTINUOUS, 0); double computed = PRICER.zSpreadFromCurvesAndDirtyPrice(BOND_SECURITY, PROVIDER, dirtyPrice, CONTINUOUS, 0); assertEquals(computed, Z_SPREAD, TOL); } public void test_zSpreadFromCurvesAndPV_periodic() { double dirtyPrice = PRICER.dirtyPriceFromCurvesWithZSpread( BOND_SECURITY, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); double computed = PRICER.zSpreadFromCurvesAndDirtyPrice( BOND_SECURITY, PROVIDER, dirtyPrice, PERIODIC, PERIOD_PER_YEAR); assertEquals(computed, Z_SPREAD, TOL); } // ------------------------------------------------------------------------- public void test_presentValueSensitivity() { PointSensitivityBuilder point = PRICER.presentValueSensitivity(PRODUCT, PROVIDER); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> PRICER.presentValue(PRODUCT, (p))); assertTrue(computed.equalWithTolerance(expected, 30d * NOTIONAL * EPS)); } public void test_presentValueSensitivityWithZSpread_continuous() { PointSensitivityBuilder point = PRICER.presentValueSensitivityWithZSpread(PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> PRICER.presentValueWithZSpread(PRODUCT, (p), Z_SPREAD, CONTINUOUS, 0)); assertTrue(computed.equalWithTolerance(expected, 20d * NOTIONAL * EPS)); } public void test_presentValueSensitivityWithZSpread_periodic() { PointSensitivityBuilder point = PRICER.presentValueSensitivityWithZSpread( PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> PRICER.presentValueWithZSpread(PRODUCT, (p), Z_SPREAD, PERIODIC, PERIOD_PER_YEAR)); assertTrue(computed.equalWithTolerance(expected, 20d * NOTIONAL * EPS)); } public void test_presentValueProductSensitivity_noExcoupon() { PointSensitivityBuilder point = PRICER.presentValueSensitivity(PRODUCT_NO_EXCOUPON, PROVIDER); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> PRICER.presentValue(PRODUCT_NO_EXCOUPON, (p))); assertTrue(computed.equalWithTolerance(expected, 30d * NOTIONAL * EPS)); } public void test_presentValueSensitivityWithZSpread_continuous_noExcoupon() { PointSensitivityBuilder point = PRICER.presentValueSensitivityWithZSpread( PRODUCT_NO_EXCOUPON, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> PRICER.presentValueWithZSpread(PRODUCT_NO_EXCOUPON, (p), Z_SPREAD, CONTINUOUS, 0)); assertTrue(computed.equalWithTolerance(expected, 20d * NOTIONAL * EPS)); } public void test_presentValueSensitivityWithZSpread_periodic_noExcoupon() { PointSensitivityBuilder point = PRICER.presentValueSensitivityWithZSpread( PRODUCT_NO_EXCOUPON, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> PRICER.presentValueWithZSpread( PRODUCT_NO_EXCOUPON, (p), Z_SPREAD, PERIODIC, PERIOD_PER_YEAR)); assertTrue(computed.equalWithTolerance(expected, 20d * NOTIONAL * EPS)); } public void test_dirtyPriceSensitivity() { PointSensitivityBuilder point = PRICER.dirtyPriceSensitivity(BOND_SECURITY, PROVIDER); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> CurrencyAmount.of(EUR, PRICER.dirtyPriceFromCurves(BOND_SECURITY, (p)))); assertTrue(computed.equalWithTolerance(expected, NOTIONAL * EPS)); } public void test_dirtyPriceSensitivityWithZspread_continuous() { PointSensitivityBuilder point = PRICER.dirtyPriceSensitivityWithZspread(BOND_SECURITY, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> CurrencyAmount.of( EUR, PRICER.dirtyPriceFromCurvesWithZSpread( BOND_SECURITY, (p), Z_SPREAD, CONTINUOUS, 0))); assertTrue(computed.equalWithTolerance(expected, NOTIONAL * EPS)); } public void test_dirtyPriceSensitivityWithZspread_periodic() { PointSensitivityBuilder point = PRICER.dirtyPriceSensitivityWithZspread( BOND_SECURITY, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurveCurrencyParameterSensitivities computed = PROVIDER.curveParameterSensitivity(point.build()); CurveCurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> CurrencyAmount.of( EUR, PRICER.dirtyPriceFromCurvesWithZSpread( BOND_SECURITY, (p), Z_SPREAD, PERIODIC, PERIOD_PER_YEAR))); assertTrue(computed.equalWithTolerance(expected, NOTIONAL * EPS)); } // ------------------------------------------------------------------------- public void test_accruedInterest() { // settle before start LocalDate settleDate1 = START_DATE.minusDays(5); double accruedInterest1 = PRICER.accruedInterest(PRODUCT, settleDate1); assertEquals(accruedInterest1, 0d); // settle between endDate and endDate -lag LocalDate settleDate2 = date(2015, 10, 8); double accruedInterest2 = PRICER.accruedInterest(PRODUCT, settleDate2); assertEquals(accruedInterest2, -4.0 / 365.0 * FIXED_RATE * NOTIONAL, EPS); // normal LocalDate settleDate3 = date(2015, 4, 18); // not adjusted FixedCouponBond product = FixedCouponBond.builder() .dayCount(DAY_COUNT) .fixedRate(FIXED_RATE) .legalEntityId(ISSUER_ID) .currency(EUR) .notional(NOTIONAL) .periodicSchedule(PERIOD_SCHEDULE) .settlementDateOffset(DATE_OFFSET) .yieldConvention(YIELD_CONVENTION) .exCouponPeriod(DaysAdjustment.NONE) .build(); double accruedInterest3 = PRICER.accruedInterest(product, settleDate3); assertEquals(accruedInterest3, 6.0 / 365.0 * FIXED_RATE * NOTIONAL, EPS); } // ------------------------------------------------------------------------- /* US Street convention */ private static final LocalDate START_US = date(2006, 11, 15); private static final LocalDate END_US = START_US.plusYears(10); private static final PeriodicSchedule SCHEDULE_US = PeriodicSchedule.of( START_US, END_US, Frequency.P6M, BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, HolidayCalendars.SAT_SUN), StubConvention.SHORT_INITIAL, false); private static final FixedCouponBond PRODUCT_US = FixedCouponBond.builder() .dayCount(DayCounts.ACT_ACT_ICMA) .fixedRate(0.04625) .legalEntityId(ISSUER_ID) .currency(Currency.USD) .notional(100) .periodicSchedule(SCHEDULE_US) .settlementDateOffset(DaysAdjustment.ofBusinessDays(3, HolidayCalendars.SAT_SUN)) .yieldConvention(YieldConvention.US_STREET) .exCouponPeriod(DaysAdjustment.NONE) .build(); private static final LocalDate VALUATION_US = date(2011, 8, 18); private static final LocalDate SETTLEMENT_US = PRODUCT_US.getSettlementDateOffset().adjust(VALUATION_US); private static final LocalDate VALUATION_LAST_US = date(2016, 6, 3); private static final LocalDate SETTLEMENT_LAST_US = PRODUCT_US.getSettlementDateOffset().adjust(VALUATION_LAST_US); private static final double YIELD_US = 0.04; public void dirtyPriceFromYieldUS() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); assertEquals(dirtyPrice, 1.0417352500524246, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_US, SETTLEMENT_US, dirtyPrice); assertEquals(yield, YIELD_US, TOL); } public void dirtyPriceFromYieldUSLastPeriod() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); assertEquals(dirtyPrice, 1.005635683760684, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_US, SETTLEMENT_LAST_US, dirtyPrice); assertEquals(yield, YIELD_US, TOL); } public void modifiedDurationFromYieldUS() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); double price = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void modifiedDurationFromYieldUSLastPeriod() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); double price = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void convexityFromYieldUS() { double computed = PRICER.convexityFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); double duration = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void convexityFromYieldUSLastPeriod() { double computed = PRICER.convexityFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); double duration = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void macaulayDurationFromYieldUS() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_US, SETTLEMENT_US, YIELD_US); assertEquals(duration, 4.6575232098896215, TOL); // 2.x. } public void macaulayDurationFromYieldUSLastPeriod() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_US, SETTLEMENT_LAST_US, YIELD_US); assertEquals(duration, 0.43478260869565216, TOL); // 2.x. } /* UK BUMP/DMO convention */ private static final LocalDate START_UK = date(2002, 9, 7); private static final LocalDate END_UK = START_UK.plusYears(12); private static final PeriodicSchedule SCHEDULE_UK = PeriodicSchedule.of( START_UK, END_UK, Frequency.P6M, BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, HolidayCalendars.SAT_SUN), StubConvention.SHORT_INITIAL, false); private static final FixedCouponBond PRODUCT_UK = FixedCouponBond.builder() .dayCount(DayCounts.ACT_ACT_ICMA) .fixedRate(0.05) .legalEntityId(ISSUER_ID) .currency(Currency.GBP) .notional(100) .periodicSchedule(SCHEDULE_UK) .settlementDateOffset(DaysAdjustment.ofBusinessDays(1, HolidayCalendars.SAT_SUN)) .yieldConvention(YieldConvention.UK_BUMP_DMO) .exCouponPeriod( DaysAdjustment.ofCalendarDays( -7, BusinessDayAdjustment.of( BusinessDayConventions.PRECEDING, HolidayCalendars.SAT_SUN))) .build(); private static final LocalDate VALUATION_UK = date(2011, 9, 2); private static final LocalDate SETTLEMENT_UK = PRODUCT_UK.getSettlementDateOffset().adjust(VALUATION_UK); private static final LocalDate VALUATION_LAST_UK = date(2014, 6, 3); private static final LocalDate SETTLEMENT_LAST_UK = PRODUCT_UK.getSettlementDateOffset().adjust(VALUATION_LAST_UK); private static final double YIELD_UK = 0.04; public void dirtyPriceFromYieldUK() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); assertEquals(dirtyPrice, 1.0277859038905428, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_UK, SETTLEMENT_UK, dirtyPrice); assertEquals(yield, YIELD_UK, TOL); } public void dirtyPriceFromYieldUKLastPeriod() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); assertEquals(dirtyPrice, 1.0145736043763598, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_UK, SETTLEMENT_LAST_UK, dirtyPrice); assertEquals(yield, YIELD_UK, TOL); } public void modifiedDurationFromYieldUK() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); double price = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void modifiedDurationFromYieldUKLastPeriod() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); double price = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void convexityFromYieldUK() { double computed = PRICER.convexityFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); double duration = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void convexityFromYieldUKLastPeriod() { double computed = PRICER.convexityFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); double duration = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void macaulayDurationFromYieldUK() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_UK, SETTLEMENT_UK, YIELD_UK); assertEquals(duration, 2.8312260658609163, TOL); // 2.x. } public void macaulayDurationFromYieldUKLastPeriod() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_UK, SETTLEMENT_LAST_UK, YIELD_UK); assertEquals(duration, 0.25815217391304346, TOL); // 2.x. } /* German bond convention */ private static final LocalDate START_GER = date(2002, 9, 7); private static final LocalDate END_GER = START_GER.plusYears(12); private static final PeriodicSchedule SCHEDULE_GER = PeriodicSchedule.of( START_GER, END_GER, Frequency.P12M, BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, HolidayCalendars.SAT_SUN), StubConvention.SHORT_INITIAL, false); private static final FixedCouponBond PRODUCT_GER = FixedCouponBond.builder() .dayCount(DayCounts.ACT_ACT_ICMA) .fixedRate(0.05) .legalEntityId(ISSUER_ID) .currency(Currency.EUR) .notional(100) .periodicSchedule(SCHEDULE_GER) .settlementDateOffset(DaysAdjustment.ofBusinessDays(3, HolidayCalendars.SAT_SUN)) .yieldConvention(YieldConvention.GERMAN_BONDS) .exCouponPeriod(DaysAdjustment.NONE) .build(); private static final LocalDate VALUATION_GER = date(2011, 9, 2); private static final LocalDate SETTLEMENT_GER = PRODUCT_GER.getSettlementDateOffset().adjust(VALUATION_GER); private static final LocalDate VALUATION_LAST_GER = date(2014, 6, 3); private static final LocalDate SETTLEMENT_LAST_GER = PRODUCT_GER.getSettlementDateOffset().adjust(VALUATION_LAST_GER); private static final double YIELD_GER = 0.04; public void dirtyPriceFromYieldGerman() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); assertEquals(dirtyPrice, 1.027750910332271, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_GER, SETTLEMENT_GER, dirtyPrice); assertEquals(yield, YIELD_GER, TOL); } public void dirtyPriceFromYieldGermanLastPeriod() { double dirtyPrice = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); assertEquals(dirtyPrice, 1.039406595790844, TOL); // 2.x. double yield = PRICER.yieldFromDirtyPrice(PRODUCT_GER, SETTLEMENT_LAST_GER, dirtyPrice); assertEquals(yield, YIELD_GER, TOL); } public void modifiedDurationFromYieldGER() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); double price = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void modifiedDurationFromYieldGERLastPeriod() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); double price = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void convexityFromYieldGER() { double computed = PRICER.convexityFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); double duration = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void convexityFromYieldGERLastPeriod() { double computed = PRICER.convexityFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); double duration = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void macaulayDurationFromYieldGER() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_GER, SETTLEMENT_GER, YIELD_GER); assertEquals(duration, 2.861462874541554, TOL); // 2.x. } public void macaulayDurationFromYieldGERLastPeriod() { double duration = PRICER.macaulayDurationFromYield(PRODUCT_GER, SETTLEMENT_LAST_GER, YIELD_GER); assertEquals(duration, 0.26231286613148186, TOL); // 2.x. } /* Japan simple convention */ private static final LocalDate START_JP = date(2015, 9, 20); private static final LocalDate END_JP = START_JP.plusYears(10); private static final PeriodicSchedule SCHEDULE_JP = PeriodicSchedule.of( START_JP, END_JP, Frequency.P6M, BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, HolidayCalendars.JPTO), StubConvention.SHORT_INITIAL, false); private static final double RATE_JP = 0.004; private static final FixedCouponBond PRODUCT_JP = FixedCouponBond.builder() .dayCount(DayCounts.NL_365) .fixedRate(RATE_JP) .legalEntityId(ISSUER_ID) .currency(Currency.JPY) .notional(100) .periodicSchedule(SCHEDULE_JP) .settlementDateOffset(DaysAdjustment.ofBusinessDays(3, HolidayCalendars.JPTO)) .yieldConvention(YieldConvention.JAPAN_SIMPLE) .exCouponPeriod(DaysAdjustment.NONE) .build(); private static final LocalDate VALUATION_JP = date(2015, 9, 24); private static final LocalDate SETTLEMENT_JP = PRODUCT_JP.getSettlementDateOffset().adjust(VALUATION_JP); private static final LocalDate VALUATION_LAST_JP = date(2025, 6, 3); private static final LocalDate SETTLEMENT_LAST_JP = PRODUCT_JP.getSettlementDateOffset().adjust(VALUATION_LAST_JP); private static final LocalDate VALUATION_ENDED_JP = date(2026, 8, 3); private static final LocalDate SETTLEMENT_ENDED_JP = PRODUCT_JP.getSettlementDateOffset().adjust(VALUATION_ENDED_JP); private static final double YIELD_JP = 0.00321; public void dirtyPriceFromYieldJP() { double computed = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP); double maturity = DayCounts.NL_365.relativeYearFraction(SETTLEMENT_JP, END_JP); double expected = PRICER.dirtyPriceFromCleanPrice( PRODUCT_JP, SETTLEMENT_JP, (1d + RATE_JP * maturity) / (1d + YIELD_JP * maturity)); assertEquals(computed, expected, TOL); double yield = PRICER.yieldFromDirtyPrice(PRODUCT_JP, SETTLEMENT_JP, computed); assertEquals(yield, YIELD_JP, TOL); } public void dirtyPriceFromYieldJPLastPeriod() { double computed = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP); double maturity = DayCounts.NL_365.relativeYearFraction(SETTLEMENT_LAST_JP, END_JP); double expected = PRICER.dirtyPriceFromCleanPrice( PRODUCT_JP, SETTLEMENT_LAST_JP, (1d + RATE_JP * maturity) / (1d + YIELD_JP * maturity)); assertEquals(computed, expected, TOL); double yield = PRICER.yieldFromDirtyPrice(PRODUCT_JP, SETTLEMENT_LAST_JP, computed); assertEquals(yield, YIELD_JP, TOL); } public void dirtyPriceFromYieldJPEnded() { double computed = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_ENDED_JP, YIELD_JP); assertEquals(computed, 0d, TOL); } public void modifiedDurationFromYielddJP() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP); double price = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void modifiedDurationFromYieldJPLastPeriod() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP); double price = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP); double priceUp = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP + EPS); double priceDw = PRICER.dirtyPriceFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP - EPS); double expected = 0.5 * (priceDw - priceUp) / price / EPS; assertEquals(computed, expected, EPS); } public void modifiedDurationFromYielddJPEnded() { double computed = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_ENDED_JP, YIELD_JP); assertEquals(computed, 0d, EPS); } public void convexityFromYieldJP() { double computed = PRICER.convexityFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP); double duration = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void convexityFromYieldJPLastPeriod() { double computed = PRICER.convexityFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP); double duration = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP); double durationUp = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP + EPS); double durationDw = PRICER.modifiedDurationFromYield(PRODUCT_JP, SETTLEMENT_LAST_JP, YIELD_JP - EPS); double expected = 0.5 * (durationDw - durationUp) / EPS + duration * duration; assertEquals(computed, expected, EPS); } public void convexityFromYieldJPEnded() { double computed = PRICER.convexityFromYield(PRODUCT_JP, SETTLEMENT_ENDED_JP, YIELD_JP); assertEquals(computed, 0d, EPS); } public void macaulayDurationFromYieldYieldJP() { assertThrows( () -> PRICER.macaulayDurationFromYield(PRODUCT_JP, SETTLEMENT_JP, YIELD_JP), UnsupportedOperationException.class, "The convention JAPAN_SIMPLE is not supported."); } }