/*
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.conversion;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.threeten.bp.DayOfWeek;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalTime;
import org.threeten.bp.Period;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.analytics.financial.instrument.annuity.AbstractAnnuityDefinitionBuilder.CouponStub;
import com.opengamma.analytics.financial.instrument.index.IborIndex;
import com.opengamma.analytics.financial.instrument.index.IndexDeposit;
import com.opengamma.core.AbstractSource;
import com.opengamma.core.change.ChangeManager;
import com.opengamma.core.convention.Convention;
import com.opengamma.core.convention.ConventionSource;
import com.opengamma.core.holiday.Holiday;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.holiday.HolidayType;
import com.opengamma.core.id.ExternalSchemes;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.financial.analytics.curve.ConverterUtils;
import com.opengamma.financial.analytics.curve.TestConventionSource;
import com.opengamma.financial.convention.IborIndexConvention;
import com.opengamma.financial.convention.StubType;
import com.opengamma.financial.convention.SwapFixedLegConvention;
import com.opengamma.financial.convention.VanillaIborLegConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConventions;
import com.opengamma.financial.convention.daycount.DayCount;
import com.opengamma.financial.convention.daycount.DayCounts;
import com.opengamma.financial.convention.frequency.PeriodFrequency;
import com.opengamma.financial.security.irs.FloatingInterestRateSwapLeg;
import com.opengamma.financial.security.irs.InterestRateSwapNotional;
import com.opengamma.financial.security.irs.PayReceiveType;
import com.opengamma.financial.security.irs.StubCalculationMethod;
import com.opengamma.financial.security.swap.FloatingRateType;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.service.ServiceContext;
import com.opengamma.service.ThreadLocalServiceContext;
import com.opengamma.service.VersionCorrectionProvider;
import com.opengamma.util.money.Currency;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.Tenor;
import com.opengamma.util.tuple.Pair;
@Test(groups = TestGroup.UNIT)
public class InterestRateSwapSecurityConverterTest {
private static final String SCHEME = "Test";
private static final BusinessDayConvention MODIFIED_FOLLOWING = BusinessDayConventions.MODIFIED_FOLLOWING;
private static final DayCount ACT_360 = DayCounts.ACT_360;
private static final DayCount THIRTY_360 = DayCounts.THIRTY_U_360;
private static final ExternalId US = ExternalSchemes.financialRegionId("US");
private static final ExternalId NYLON = ExternalSchemes.financialRegionId("US+GB");
private static final String TICKER = "TICKER";
private static final ExternalId FIXED_LEG_ID = ExternalId.of(SCHEME, "USD Swap Fixed Leg");
private static final ExternalId FIXED_LEG_PAY_LAG_ID = ExternalId.of(SCHEME, "USD Swap Fixed Leg Pay Lag");
private static final String USDLIBOR_ACT_360_CONVENTION_NAME = "USD Libor ACT/360";
private static final ExternalId USDLIBOR_ACT_360_CONVENTION_ID = ExternalId.of(SCHEME, USDLIBOR_ACT_360_CONVENTION_NAME);
private static final String USDLIBOR_30_360_CONVENTION_NAME = "USD Libor 30/360";
private static final ExternalId USDLIBOR_30_360_ID = ExternalId.of(SCHEME, USDLIBOR_30_360_CONVENTION_NAME);
private static final ExternalId LEG_USDLIBOR3M_ID = ExternalId.of(SCHEME, "USD 3m Floating Leg");
private static final ExternalId LEG_USDLIBOR6M_ID = ExternalId.of(SCHEME, "USD 6m Floating Leg");
// LIBOR Index
private static final String USDLIBOR1M_NAME = "USDLIBOR1M";
private static final com.opengamma.financial.security.index.IborIndex USDLIBOR1M =
new com.opengamma.financial.security.index.IborIndex(USDLIBOR1M_NAME, "ICE LIBOR 1M - USD", Tenor.ONE_MONTH, USDLIBOR_ACT_360_CONVENTION_ID);
private static final ExternalId USDLIBOR1M_ID = ExternalId.of(TICKER, "USDLIBOR1M");
private static final String USDLIBOR3M_NAME = "USDLIBOR3M";
private static final com.opengamma.financial.security.index.IborIndex USDLIBOR3M =
new com.opengamma.financial.security.index.IborIndex(USDLIBOR3M_NAME, "ICE LIBOR 3M - USD", Tenor.THREE_MONTHS, USDLIBOR_ACT_360_CONVENTION_ID);
private static final ExternalId USDLIBOR3M_ID = ExternalId.of(TICKER, "USDLIBOR3M");
private static final String USDLIBOR6M_NAME = "USDLIBOR6M";
private static final com.opengamma.financial.security.index.IborIndex USDLIBOR6M =
new com.opengamma.financial.security.index.IborIndex(USDLIBOR6M_NAME, "ICE LIBOR 6M - USD", Tenor.SIX_MONTHS, USDLIBOR_ACT_360_CONVENTION_ID);
private static final ExternalId USDLIBOR6M_ID = ExternalId.of(TICKER, "USDLIBOR6M");
private static final SwapFixedLegConvention FIXED_LEG = new SwapFixedLegConvention("USD Swap Fixed Leg", ExternalIdBundle.of(ExternalId.of(SCHEME, "USD Swap Fixed Leg")),
Tenor.SIX_MONTHS, ACT_360, MODIFIED_FOLLOWING, Currency.USD, NYLON, 2, false, StubType.NONE, false, 0);
private static final SwapFixedLegConvention FIXED_LEG_PAY_LAG = new SwapFixedLegConvention("USD Swap Fixed Leg Pay Lag", ExternalIdBundle.of(ExternalId.of(SCHEME, "USD Swap Fixed Leg")),
Tenor.SIX_MONTHS, ACT_360, MODIFIED_FOLLOWING, Currency.USD, NYLON, 2, false, StubType.NONE, false, 2);
private static final VanillaIborLegConvention LEG_USDLIBOR3M = new VanillaIborLegConvention("USD 3m Floating Leg", ExternalIdBundle.of(ExternalId.of(SCHEME, "USD 3m Floating Leg")),
USDLIBOR3M_ID, false, SCHEME, Tenor.THREE_MONTHS, 2, false, StubType.NONE, false, 2);
private static final VanillaIborLegConvention LEG_USDLIBOR6M = new VanillaIborLegConvention("USD 6m Floating Leg", ExternalIdBundle.of(ExternalId.of(SCHEME, "USD 6m Floating Leg")),
USDLIBOR6M_ID, false, SCHEME, Tenor.SIX_MONTHS, 2, false, StubType.LONG_END, false, 2);
private static final IborIndexConvention USDLIBOR_ACT_360 = new IborIndexConvention(USDLIBOR_ACT_360_CONVENTION_NAME, ExternalIdBundle.of(USDLIBOR_ACT_360_CONVENTION_ID),
ACT_360, MODIFIED_FOLLOWING, 2, false, Currency.USD, LocalTime.of(11, 0), "US", US, US, "Page");
private static final IborIndexConvention LIBOR_30_360 = new IborIndexConvention(USDLIBOR_30_360_CONVENTION_NAME, ExternalIdBundle.of(USDLIBOR_30_360_ID),
THIRTY_360, MODIFIED_FOLLOWING, 2, false, Currency.USD, LocalTime.of(11, 0), "US", US, US, "Page");
private static final Map<ExternalId, Convention> CONVENTIONS = new HashMap<>();
private static final Map<ExternalIdBundle, Security> SECURITY_MAP = new HashMap<>();
private static final SecuritySource SECURITY_SOURCE;
private static final ConventionSource CONVENTION_SOURCE;
private static final HolidaySource HOLIDAY_SOURCE;
static {
CONVENTIONS.put(FIXED_LEG_ID, FIXED_LEG);
CONVENTIONS.put(FIXED_LEG_PAY_LAG_ID, FIXED_LEG_PAY_LAG);
CONVENTIONS.put(USDLIBOR_ACT_360_CONVENTION_ID, USDLIBOR_ACT_360);
CONVENTIONS.put(USDLIBOR_30_360_ID, LIBOR_30_360);
CONVENTIONS.put(LEG_USDLIBOR3M_ID, LEG_USDLIBOR3M);
CONVENTIONS.put(LEG_USDLIBOR6M_ID, LEG_USDLIBOR6M);
// Security map. Used for index.
SECURITY_MAP.put(USDLIBOR1M_ID.toBundle(), USDLIBOR1M);
SECURITY_MAP.put(USDLIBOR3M_ID.toBundle(), USDLIBOR3M);
SECURITY_MAP.put(USDLIBOR6M_ID.toBundle(), USDLIBOR6M);
SECURITY_SOURCE = new MySecuritySource(SECURITY_MAP);
CONVENTION_SOURCE = new TestConventionSource(CONVENTIONS);
HOLIDAY_SOURCE = new MockHolidaySource();
}
@BeforeMethod
public static void setUp() {
VersionCorrectionProvider versionCorrectionProvider = new VersionCorrectionProvider() {
@Override
public VersionCorrection getPortfolioVersionCorrection() {
return VersionCorrection.LATEST;
}
@Override
public VersionCorrection getConfigVersionCorrection() {
return VersionCorrection.LATEST;
}
};
ServiceContext serviceContext = ServiceContext.of(
ImmutableMap.of(
VersionCorrectionProvider.class, versionCorrectionProvider,
ConventionSource.class, CONVENTION_SOURCE,
SecuritySource.class, SECURITY_SOURCE));
ThreadLocalServiceContext.init(serviceContext);
}
@Test
public void testShortStartStubCouponResolution() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.SHORT_START)
.firstStubEndDate(LocalDate.of(2014, 6, 18))
.firstStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME))
.firstStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
Pair<CouponStub, CouponStub> stubs = conv.parseStubs(receiveLeg.getStubCalculationMethod());
CouponStub firstStub = stubs.getFirst();
IborIndex firstIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR1M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex secondIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR3M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
StubType stubType = StubType.SHORT_START;
Assert.assertEquals(firstStub.getStubType(), stubType);
Assert.assertEquals(firstStub.getFirstIborIndex(), firstIborIndex);
Assert.assertEquals(firstStub.getSecondIborIndex(), secondIborIndex);
}
@Test
public void testLongStartStubCouponResolution() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.LONG_START)
.firstStubEndDate(LocalDate.of(2014, 6, 18))
.firstStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME))
.firstStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR6M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
Pair<CouponStub, CouponStub> stubs = conv.parseStubs(receiveLeg.getStubCalculationMethod());
CouponStub firstStub = stubs.getFirst();
IborIndex firstIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR3M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex secondIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR6M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
StubType stubType = StubType.LONG_START;
Assert.assertEquals(firstStub.getStubType(), stubType);
Assert.assertEquals(firstStub.getFirstIborIndex(), firstIborIndex);
Assert.assertEquals(firstStub.getSecondIborIndex(), secondIborIndex);
}
@Test
public void testShortEndStubCouponResolution() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.SHORT_END)
.lastStubEndDate(LocalDate.of(2014, 6, 18))
.lastStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME))
.lastStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
Pair<CouponStub, CouponStub> stubs = conv.parseStubs(receiveLeg.getStubCalculationMethod());
CouponStub secondStub = stubs.getSecond();
IborIndex firstIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR1M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex secondIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR3M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
StubType stubType = StubType.SHORT_END;
Assert.assertEquals(secondStub.getStubType(), stubType);
Assert.assertEquals(secondStub.getFirstIborIndex(), firstIborIndex);
Assert.assertEquals(secondStub.getSecondIborIndex(), secondIborIndex);
}
@Test
public void testLongEndStubCouponResolution() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.LONG_END)
.lastStubEndDate(LocalDate.of(2014, 6, 18))
.lastStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME))
.lastStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR6M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
Pair<CouponStub, CouponStub> stubs = conv.parseStubs(receiveLeg.getStubCalculationMethod());
CouponStub secondStub = stubs.getSecond();
IborIndex firstIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR3M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex secondIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR6M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
StubType stubType = StubType.LONG_END;
Assert.assertEquals(secondStub.getStubType(), stubType);
Assert.assertEquals(secondStub.getFirstIborIndex(), firstIborIndex);
Assert.assertEquals(secondStub.getSecondIborIndex(), secondIborIndex);
}
@Test
public void testBothStubCouponResolution() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.BOTH)
.firstStubEndDate(LocalDate.of(2014,6,18))
.firstStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME))
.firstStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR6M_NAME))
.lastStubEndDate(LocalDate.of(2014, 6, 18))
.lastStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME))
.lastStubEndReferenceRateId(ExternalId.of(TICKER, USDLIBOR6M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
Pair<CouponStub, CouponStub> stubs = conv.parseStubs(receiveLeg.getStubCalculationMethod());
CouponStub firstStub = stubs.getFirst();
CouponStub secondStub = stubs.getSecond();
IborIndex firstStartIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR1M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex firstEndIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR6M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex lastStartIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR3M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
IborIndex lastEndIborIndex = (IborIndex) getIborIndex(ExternalId.of(TICKER, USDLIBOR6M_NAME), SECURITY_SOURCE, CONVENTION_SOURCE);
StubType stubType = StubType.BOTH;
Assert.assertEquals(firstStub.getStubType(), stubType);
Assert.assertEquals(firstStub.getFirstIborIndex(), firstStartIborIndex);
Assert.assertEquals(firstStub.getSecondIborIndex(), firstEndIborIndex);
Assert.assertEquals(secondStub.getStubType(), stubType);
Assert.assertEquals(secondStub.getFirstIborIndex(), lastStartIborIndex);
Assert.assertEquals(secondStub.getSecondIborIndex(), lastEndIborIndex);
}
@Test(expectedExceptions = OpenGammaRuntimeException.class)
public void testStubBadlyDefinedShortStart() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.SHORT_START)
.firstStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
conv.parseStubs(receiveLeg.getStubCalculationMethod());
}
@Test(expectedExceptions = OpenGammaRuntimeException.class)
public void testStubBadlyDefinedShortLast() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.SHORT_END)
.lastStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
conv.parseStubs(receiveLeg.getStubCalculationMethod());
}
@Test(expectedExceptions = OpenGammaRuntimeException.class)
public void testStubBadlyDefinedLongStart() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.LONG_START)
.firstStubStartReferenceRateId(ExternalId.of(TICKER, USDLIBOR1M_NAME));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
conv.parseStubs(receiveLeg.getStubCalculationMethod());
}
@Test(expectedExceptions = OpenGammaRuntimeException.class)
public void testStubUndefinedIndexId() {
StubCalculationMethod.Builder shortStubBuilder = StubCalculationMethod.builder()
.type(StubType.SHORT_END)
.lastStubStartReferenceRateId(ExternalId.of(TICKER, "ZARJIBAR3M"))
.lastStubEndReferenceRateId(ExternalId.of(TICKER, "ZARJIBAR12M"));
InterestRateSwapNotional notional = new InterestRateSwapNotional(Currency.USD, 1000000);
PeriodFrequency freq3m = PeriodFrequency.of(Period.ofMonths(3));
Set<ExternalId> calendarUSNY = Sets.newHashSet(ExternalId.of(ExternalSchemes.ISDA_HOLIDAY, "USNY"));
FloatingInterestRateSwapLeg receiveLeg = new FloatingInterestRateSwapLeg();
receiveLeg.setNotional(notional);
receiveLeg.setDayCountConvention(DayCounts.ACT_360);
receiveLeg.setPaymentDateFrequency(freq3m);
receiveLeg.setPaymentDateBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setPaymentDateCalendars(calendarUSNY);
receiveLeg.setAccrualPeriodFrequency(freq3m);
receiveLeg.setAccrualPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setAccrualPeriodCalendars(calendarUSNY);
receiveLeg.setResetPeriodFrequency(freq3m);
receiveLeg.setResetPeriodBusinessDayConvention(BusinessDayConventions.MODIFIED_FOLLOWING);
receiveLeg.setResetPeriodCalendars(calendarUSNY);
receiveLeg.setFixingDateBusinessDayConvention(BusinessDayConventions.PRECEDING);
receiveLeg.setFixingDateCalendars(calendarUSNY);
receiveLeg.setFixingDateOffset(-2);
receiveLeg.setFloatingRateType(FloatingRateType.IBOR);
receiveLeg.setFloatingReferenceRateId(ExternalId.of(TICKER, USDLIBOR3M_NAME));
receiveLeg.setPayReceiveType(PayReceiveType.RECEIVE);
receiveLeg.setStubCalculationMethod(shortStubBuilder.build());
InterestRateSwapSecurityConverter conv = new InterestRateSwapSecurityConverter(HOLIDAY_SOURCE);
conv.parseStubs(receiveLeg.getStubCalculationMethod());
}
private IndexDeposit getIborIndex(ExternalId indexId, SecuritySource securitySource, ConventionSource conventionSource) {
// try security lookup
final Security sec = securitySource.getSingle(indexId.toBundle());
if (sec != null) {
final com.opengamma.financial.security.index.IborIndex indexSecurity = (com.opengamma.financial.security.index.IborIndex) sec;
IborIndexConvention indexConvention = conventionSource.getSingle(indexSecurity.getConventionId(), IborIndexConvention.class);
return ConverterUtils.indexIbor(indexSecurity.getName(), indexConvention, indexSecurity.getTenor());
}
// Fallback to convention lookup for old behaviour
Convention iborLegConvention = conventionSource.getSingle(indexId);
if (!(iborLegConvention instanceof VanillaIborLegConvention)) {
throw new OpenGammaRuntimeException("Could not resolve an index convention for rate reference id: " + indexId.getValue());
}
Convention iborConvention = conventionSource.getSingle(((VanillaIborLegConvention) iborLegConvention).getIborIndexConvention());
if (iborConvention == null) {
throw new OpenGammaRuntimeException("Convention not found for " + ((VanillaIborLegConvention) iborLegConvention).getIborIndexConvention());
}
IborIndexConvention iborIndexConvention = (IborIndexConvention) iborConvention;
return new IborIndex(iborIndexConvention.getCurrency(),
((VanillaIborLegConvention) iborLegConvention).getResetTenor().getPeriod(),
iborIndexConvention.getSettlementDays(), // fixing lag
iborIndexConvention.getDayCount(),
iborIndexConvention.getBusinessDayConvention(),
((IborIndexConvention) iborConvention).isIsEOM(),
indexId.getValue());
}
/**
* A simplified local version of a HolidaySource for tests.
*/
private static class MySecuritySource implements SecuritySource {
/** Security source as a map for tests **/
private final Map<ExternalIdBundle, Security> _map;
/**
* @param map The map of id/Security
*/
public MySecuritySource(Map<ExternalIdBundle, Security> map) {
super();
_map = map;
}
@Override
public Collection<Security> get(ExternalIdBundle bundle, VersionCorrection versionCorrection) {
return null;
}
@Override
public Map<ExternalIdBundle, Collection<Security>> getAll(Collection<ExternalIdBundle> bundles, VersionCorrection versionCorrection) {
return null;
}
@Override
public Collection<Security> get(ExternalIdBundle bundle) {
return null;
}
@Override
public Security getSingle(ExternalIdBundle bundle) {
return _map.get(bundle);
}
@Override
public Security getSingle(ExternalIdBundle bundle, VersionCorrection versionCorrection) {
return getSingle(bundle);
}
@Override
public Map<ExternalIdBundle, Security> getSingle(Collection<ExternalIdBundle> bundles, VersionCorrection versionCorrection) {
return null;
}
@Override
public Security get(UniqueId uniqueId) {
return null;
}
@Override
public Security get(ObjectId objectId, VersionCorrection versionCorrection) {
return null;
}
@Override
public Map<UniqueId, Security> get(Collection<UniqueId> uniqueIds) {
return null;
}
@Override
public Map<ObjectId, Security> get(Collection<ObjectId> objectIds, VersionCorrection versionCorrection) {
return null;
}
@Override
public ChangeManager changeManager() {
return null;
}
}
public static class MockHolidaySource extends AbstractSource<Holiday> implements HolidaySource {
/**
* Map of exception dates and whether they are working or non-working.
*/
private final ConcurrentMap<LocalDate, Boolean> _nonWorkingDay = new ConcurrentHashMap<>();
public MockHolidaySource() {
int startYear = 2013;
int endYear = 2063;
for (int loopy = startYear; loopy <= endYear; loopy++) {
addNonWorkingDay(LocalDate.of(loopy, 1, 1));
addNonWorkingDay(LocalDate.of(loopy, 7, 4));
addNonWorkingDay(LocalDate.of(loopy, 12, 25));
}
addNonWorkingDay(LocalDate.of(2015, 1, 19));
addNonWorkingDay(LocalDate.of(2015, 2, 16));
addNonWorkingDay(LocalDate.of(2015, 5, 25));
addNonWorkingDay(LocalDate.of(2015, 9, 7));
addNonWorkingDay(LocalDate.of(2015, 10, 12));
addNonWorkingDay(LocalDate.of(2015, 11, 11));
addNonWorkingDay(LocalDate.of(2015, 11, 26));
addNonWorkingDay(LocalDate.of(2016, 1, 18));
addNonWorkingDay(LocalDate.of(2016, 2, 15));
addNonWorkingDay(LocalDate.of(2016, 5, 30));
addNonWorkingDay(LocalDate.of(2016, 9, 5));
addNonWorkingDay(LocalDate.of(2016, 10, 10));
addNonWorkingDay(LocalDate.of(2016, 11, 11));
addNonWorkingDay(LocalDate.of(2016, 11, 24));
addNonWorkingDay(LocalDate.of(2016, 12, 26));
addNonWorkingDay(LocalDate.of(2017, 1, 2));
addNonWorkingDay(LocalDate.of(2017, 1, 16));
addNonWorkingDay(LocalDate.of(2017, 2, 20));
addNonWorkingDay(LocalDate.of(2017, 5, 29));
addNonWorkingDay(LocalDate.of(2017, 9, 4));
addNonWorkingDay(LocalDate.of(2017, 10, 9));
addNonWorkingDay(LocalDate.of(2017, 11, 23));
}
private void addNonWorkingDay(LocalDate date) {
_nonWorkingDay.put(date, true);
}
private boolean isHoliday(LocalDate dateToCheck) {
DayOfWeek day = dateToCheck.getDayOfWeek();
if (day.equals(DayOfWeek.SATURDAY) || day.equals(DayOfWeek.SUNDAY)) {
return true;
}
return _nonWorkingDay.containsKey(dateToCheck);
}
@Override
public boolean isHoliday(LocalDate dateToCheck, Currency currency) {
return isHoliday(dateToCheck);
}
@Override
public boolean isHoliday(LocalDate dateToCheck, HolidayType holidayType, ExternalIdBundle regionOrExchangeIds) {
return isHoliday(dateToCheck);
}
@Override
public boolean isHoliday(LocalDate dateToCheck, HolidayType holidayType, ExternalId regionOrExchangeId) {
return isHoliday(dateToCheck);
}
@Override
public Holiday get(UniqueId uniqueId) {
throw new UnsupportedOperationException();
}
@Override
public Holiday get(ObjectId objectId, VersionCorrection versionCorrection) {
throw new UnsupportedOperationException();
}
@Override
public Collection<Holiday> get(HolidayType holidayType, ExternalIdBundle regionOrExchangeIds) {
return null;
}
@Override
public Collection<Holiday> get(Currency currency) {
return null;
}
}
}