/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.product.dsf; import static com.opengamma.strata.basics.currency.Currency.GBP; import static com.opengamma.strata.basics.currency.Currency.USD; import static com.opengamma.strata.basics.date.BusinessDayConventions.MODIFIED_FOLLOWING; import static com.opengamma.strata.basics.date.BusinessDayConventions.PRECEDING; import static com.opengamma.strata.basics.date.DayCounts.THIRTY_U_360; import static com.opengamma.strata.basics.date.HolidayCalendarIds.SAT_SUN; import static com.opengamma.strata.basics.schedule.Frequency.P1M; import static com.opengamma.strata.basics.schedule.Frequency.P3M; import static com.opengamma.strata.basics.schedule.Frequency.P6M; import static com.opengamma.strata.collect.TestHelper.assertSerialization; import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg; import static com.opengamma.strata.collect.TestHelper.coverBeanEquals; import static com.opengamma.strata.collect.TestHelper.coverImmutableBean; import static com.opengamma.strata.product.common.PayReceive.PAY; import static com.opengamma.strata.product.common.PayReceive.RECEIVE; import static org.testng.Assert.assertEquals; import java.time.LocalDate; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.basics.date.BusinessDayAdjustment; import com.opengamma.strata.basics.date.DaysAdjustment; import com.opengamma.strata.basics.date.Tenor; import com.opengamma.strata.basics.index.IborIndex; import com.opengamma.strata.basics.index.IborIndices; import com.opengamma.strata.basics.schedule.PeriodicSchedule; import com.opengamma.strata.basics.schedule.StubConvention; import com.opengamma.strata.basics.value.ValueSchedule; import com.opengamma.strata.product.SecurityInfo; import com.opengamma.strata.product.SecurityPriceInfo; import com.opengamma.strata.product.TradeInfo; import com.opengamma.strata.product.common.BuySell; import com.opengamma.strata.product.swap.FixedRateCalculation; import com.opengamma.strata.product.swap.IborRateCalculation; import com.opengamma.strata.product.swap.KnownAmountSwapLeg; import com.opengamma.strata.product.swap.NotionalSchedule; import com.opengamma.strata.product.swap.PaymentSchedule; import com.opengamma.strata.product.swap.RateCalculationSwapLeg; import com.opengamma.strata.product.swap.Swap; import com.opengamma.strata.product.swap.SwapLeg; import com.opengamma.strata.product.swap.type.FixedIborSwapConventions; /** * Test {@link DsfSecurity}. */ @Test public class DsfSecurityTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final Dsf PRODUCT = DsfTest.sut(); private static final Dsf PRODUCT2 = DsfTest.sut2(); private static final SecurityPriceInfo PRICE_INFO = SecurityPriceInfo.of(0.1, CurrencyAmount.of(GBP, 25)); private static final SecurityInfo INFO = SecurityInfo.of(PRODUCT.getSecurityId(), PRICE_INFO); private static final SecurityInfo INFO2 = SecurityInfo.of(PRODUCT2.getSecurityId(), PRICE_INFO); private static final IborIndex INDEX = IborIndices.USD_LIBOR_3M; private static final BusinessDayAdjustment BDA_MF = BusinessDayAdjustment.of(MODIFIED_FOLLOWING, SAT_SUN); private static final BusinessDayAdjustment BDA_P = BusinessDayAdjustment.of(PRECEDING, SAT_SUN); private static final LocalDate LAST_TRADE_DATE = LocalDate.of(2014, 9, 5); private static final Swap SWAP = FixedIborSwapConventions.USD_FIXED_6M_LIBOR_3M .createTrade(LAST_TRADE_DATE, Tenor.TENOR_10Y, BuySell.SELL, 1d, 0.015, REF_DATA).getProduct(); private static final double NOTIONAL = 100000; //------------------------------------------------------------------------- public void test_builder() { DsfSecurity test = sut(); assertEquals(test.getInfo(), INFO); assertEquals(test.getSecurityId(), PRODUCT.getSecurityId()); assertEquals(test.getCurrency(), PRODUCT.getCurrency()); assertEquals(test.getUnderlyingIds(), ImmutableSet.of()); } public void test_builder_notUnitNotional() { SwapLeg fixedLeg10 = RateCalculationSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 9, 12)) .frequency(P6M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.of(USD, 10d)) .calculation(FixedRateCalculation.builder() .dayCount(THIRTY_U_360) .rate(ValueSchedule.of(0.015)) .build()) .build(); SwapLeg knownAmountLeg = KnownAmountSwapLeg.builder() .payReceive(RECEIVE) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 9, 12)) .frequency(P6M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P6M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .amount(ValueSchedule.of(0.015)) .currency(USD) .build(); SwapLeg iborLeg500 = RateCalculationSwapLeg.builder() .payReceive(PAY) .accrualSchedule(PeriodicSchedule.builder() .startDate(LocalDate.of(2014, 9, 12)) .endDate(LocalDate.of(2016, 9, 12)) .frequency(P1M) .businessDayAdjustment(BDA_MF) .stubConvention(StubConvention.SHORT_INITIAL) .build()) .paymentSchedule(PaymentSchedule.builder() .paymentFrequency(P3M) .paymentDateOffset(DaysAdjustment.NONE) .build()) .notionalSchedule(NotionalSchedule.builder() .currency(USD) .amount(ValueSchedule.of(500d)) .finalExchange(true) .initialExchange(true) .build()) .calculation(IborRateCalculation.builder() .index(INDEX) .fixingDateOffset(DaysAdjustment.ofBusinessDays(-2, SAT_SUN, BDA_P)) .build()) .build(); Swap swap1 = Swap.of(fixedLeg10, SWAP.getLeg(PAY).get()); Swap swap2 = Swap.of(SWAP.getLeg(RECEIVE).get(), iborLeg500); Swap swap3 = Swap.of(knownAmountLeg, SWAP.getLeg(PAY).get()); assertThrowsIllegalArg(() -> DsfSecurity.builder() .info(INFO) .notional(NOTIONAL) .lastTradeDate(LAST_TRADE_DATE) .underlyingSwap(swap1) .build()); assertThrowsIllegalArg(() -> DsfSecurity.builder() .info(INFO) .notional(NOTIONAL) .lastTradeDate(LAST_TRADE_DATE) .underlyingSwap(swap2) .build()); // should succeed normally (no notional to validate on known amount leg) DsfSecurity.builder() .info(INFO) .notional(NOTIONAL) .lastTradeDate(LAST_TRADE_DATE) .underlyingSwap(swap3) .build(); } //------------------------------------------------------------------------- public void test_createProduct() { DsfSecurity test = sut(); assertEquals(test.createProduct(ReferenceData.empty()), PRODUCT); TradeInfo tradeInfo = TradeInfo.of(PRODUCT.getLastTradeDate().minusDays(1)); DsfTrade expectedTrade = DsfTrade.builder() .info(tradeInfo) .product(PRODUCT) .quantity(100) .price(123.50) .build(); assertEquals(test.createTrade(tradeInfo, 100, 123.50, ReferenceData.empty()), expectedTrade); } //------------------------------------------------------------------------- public void coverage() { coverImmutableBean(sut()); coverBeanEquals(sut(), sut2()); } public void test_serialization() { assertSerialization(sut()); } //------------------------------------------------------------------------- static DsfSecurity sut() { return DsfSecurity.builder() .info(INFO) .notional(PRODUCT.getNotional()) .lastTradeDate(PRODUCT.getLastTradeDate()) .underlyingSwap(PRODUCT.getUnderlyingSwap()) .build(); } static DsfSecurity sut2() { return DsfSecurity.builder() .info(INFO2) .notional(PRODUCT2.getNotional()) .lastTradeDate(PRODUCT2.getLastTradeDate()) .underlyingSwap(PRODUCT2.getUnderlyingSwap()) .build(); } }