/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.instrument.index; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import org.threeten.bp.Period; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.datasets.CalendarUSD; import com.opengamma.analytics.financial.instrument.annuity.AnnuityDefinition; import com.opengamma.analytics.financial.instrument.annuity.CompoundingMethod; import com.opengamma.analytics.financial.instrument.payment.CouponIborCompoundingFlatSpreadDefinition; import com.opengamma.analytics.financial.instrument.payment.CouponIborCompoundingSpreadDefinition; import com.opengamma.analytics.financial.schedule.ScheduleCalculator; import com.opengamma.financial.convention.StubType; import com.opengamma.financial.convention.businessday.BusinessDayConventions; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.util.money.Currency; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; /** * Tests the generator of legs based on Ibor compounding. */ @Test(groups = TestGroup.UNIT) public class GeneratorLegIborCompoundingTest { private static final Calendar NYC = new CalendarUSD("NYC"); private static final IborIndex USDLIBOR1M = IndexIborMaster.getInstance().getIndex("USDLIBOR1M"); private static final Currency USD = Currency.USD; private static final String NAME = "LEG_USDLIBOR1MCMP3M"; private static final int OFFSET_SPOT = 2; private static final int OFFSET_PAYMENT = 0; private static final Period P3M = Period.ofMonths(3); private static final CompoundingMethod CMP_FLAT = CompoundingMethod.FLAT; private static final CompoundingMethod CMP_STRAIGHT = CompoundingMethod.STRAIGHT; private static final GeneratorLegIborCompounding GENERATOR = new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CMP_FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); @Test(expectedExceptions = IllegalArgumentException.class) public void nullName() { new GeneratorLegIborCompounding(null, USD, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCurrency() { new GeneratorLegIborCompounding(NAME, null, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullIndex() { new GeneratorLegIborCompounding(NAME, USD, null, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullTenor() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, null, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCompoundingMethod() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, null, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullBusinessDay() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, null, true, StubType.SHORT_START, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullStub() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, null, false, NYC, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCalendarIndex() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, null, NYC); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullCalendarPayment() { new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CompoundingMethod.FLAT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, null); } @Test public void getter() { assertEquals("GeneratorLegIborCompounding: getter", NAME, GENERATOR.getName()); assertEquals("GeneratorLegIborCompounding: getter", USD, GENERATOR.getCurrency()); assertEquals("GeneratorLegIborCompounding: getter", USDLIBOR1M, GENERATOR.getIndexIbor()); assertEquals("GeneratorLegIborCompounding: getter", P3M, GENERATOR.getPaymentPeriod()); assertEquals("GeneratorLegIborCompounding: getter", CMP_FLAT, GENERATOR.getCompoundingMethod()); assertEquals("GeneratorLegIborCompounding: getter", USDLIBOR1M, GENERATOR.getIndexIbor()); assertEquals("GeneratorLegIborCompounding: getter", OFFSET_SPOT, GENERATOR.getSpotOffset()); assertEquals("GeneratorLegIborCompounding: getter", OFFSET_PAYMENT, GENERATOR.getPaymentOffset()); assertEquals("GeneratorLegIborCompounding: getter", BusinessDayConventions.MODIFIED_FOLLOWING, GENERATOR.getBusinessDayConvention()); assertEquals("GeneratorLegIborCompounding: getter", true, GENERATOR.isEndOfMonth()); assertEquals("GeneratorLegIborCompounding: getter", StubType.SHORT_START, GENERATOR.getStubType()); assertEquals("GeneratorLegIborCompounding: getter", false, GENERATOR.isExchangeNotional()); assertEquals("GeneratorLegIborCompounding: getter", NYC, GENERATOR.getIndexCalendar()); assertEquals("GeneratorLegIborCompounding: getter", NYC, GENERATOR.getPaymentCalendar()); } @Test /** Tests the instrument generated by the generator with compounding method FLAT. */ public void generateInstrumentFlatCompounding() { double notional = 1000000; double spread = 0.0025; int legTenorYear = 3; Period legTenor = Period.ofYears(legTenorYear); GeneratorAttributeIR attribute = new GeneratorAttributeIR(legTenor); ZonedDateTime valuationDate = DateUtils.getUTCDate(2014, 1, 22); AnnuityDefinition<?> instrumentDefinition = GENERATOR.generateInstrument(valuationDate, spread, notional, attribute); assertEquals("GeneratorLegIborCompounding: generate - number of coupons", instrumentDefinition.getNumberOfPayments(), legTenorYear * 4); // Quarterly payments ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(valuationDate, GENERATOR.getSpotOffset(), NYC); ZonedDateTime startDate = spotDate; ZonedDateTime endDate; for(int loopcpn = 0 ; loopcpn<legTenorYear; loopcpn++) { assertTrue("GeneratorLegIborCompounding: generate - coupon type", instrumentDefinition.getNthPayment(loopcpn) instanceof CouponIborCompoundingFlatSpreadDefinition); CouponIborCompoundingFlatSpreadDefinition cpn = (CouponIborCompoundingFlatSpreadDefinition)instrumentDefinition.getNthPayment(loopcpn); endDate = ScheduleCalculator.getAdjustedDate(spotDate, GENERATOR.getPaymentPeriod().multipliedBy(loopcpn+1), GENERATOR.getBusinessDayConvention(), NYC, GENERATOR.isEndOfMonth()); // Sub-periods dates ZonedDateTime subperiodStartDate = startDate; ZonedDateTime subperiodEndDate; for(int loopcmp=0; loopcmp<3; loopcmp++) { subperiodEndDate = ScheduleCalculator.getAdjustedDate(startDate, GENERATOR.getIndexIbor().getTenor().multipliedBy(loopcmp+1), GENERATOR.getIndexIbor().getBusinessDayConvention(), NYC, GENERATOR.getIndexIbor().isEndOfMonth()); assertEquals("GeneratorLegIborCompounding: generate - start sub period", subperiodStartDate, cpn.getFixingSubperiodStartDates()[loopcmp]); ZonedDateTime endFixing = ScheduleCalculator.getAdjustedDate(subperiodStartDate, GENERATOR.getIndexIbor(), NYC); assertEquals("GeneratorLegIborCompounding: generate - end sub period", endFixing, cpn.getFixingSubperiodEndDates()[loopcmp]); subperiodStartDate = subperiodEndDate; } assertEquals("GeneratorLegIborCompounding: generate - start accrual date", startDate, cpn.getAccrualStartDate()); assertEquals("GeneratorLegIborCompounding: generate - end accrual date", endDate, cpn.getAccrualEndDate()); ZonedDateTime paymentDate = ScheduleCalculator.getAdjustedDate(cpn.getAccrualEndDate(), GENERATOR.getPaymentOffset(), NYC); assertEquals("GeneratorLegIborCompounding: generate - payment date", paymentDate, cpn.getPaymentDate()); assertEquals("GeneratorLegIborCompounding: generate - spread", spread, cpn.getSpread()); startDate = endDate; } } @Test /** Tests the instrument generated by the generator with compounding method FLAT. */ public void generateInstrumentStraightCompounding() { double notional = 1000000; double spread = 0.0025; int legTenorYear = 3; Period legTenor = Period.ofYears(legTenorYear); GeneratorAttributeIR attribute = new GeneratorAttributeIR(legTenor); ZonedDateTime valuationDate = DateUtils.getUTCDate(2014, 1, 22); GeneratorLegIborCompounding generator = new GeneratorLegIborCompounding(NAME, USD, USDLIBOR1M, P3M, CMP_STRAIGHT, OFFSET_SPOT, OFFSET_PAYMENT, BusinessDayConventions.MODIFIED_FOLLOWING, true, StubType.SHORT_START, false, NYC, NYC); AnnuityDefinition<?> instrumentDefinition = generator.generateInstrument(valuationDate, spread, notional, attribute); assertEquals("GeneratorLegONCompounded: generate - number of coupons", instrumentDefinition.getNumberOfPayments(), legTenorYear * 4); // Quarterly payments ZonedDateTime spotDate = ScheduleCalculator.getAdjustedDate(valuationDate, generator.getSpotOffset(), NYC); ZonedDateTime startDate = spotDate; ZonedDateTime endDate; for(int loopcpn = 0 ; loopcpn<legTenorYear; loopcpn++) { assertTrue("GeneratorLegONCompounded: generate - coupon type", instrumentDefinition.getNthPayment(loopcpn) instanceof CouponIborCompoundingSpreadDefinition); CouponIborCompoundingSpreadDefinition cpn = (CouponIborCompoundingSpreadDefinition)instrumentDefinition.getNthPayment(loopcpn); endDate = ScheduleCalculator.getAdjustedDate(spotDate, generator.getPaymentPeriod().multipliedBy(loopcpn+1), generator.getBusinessDayConvention(), NYC, generator.isEndOfMonth()); // Sub-periods dates ZonedDateTime subperiodStartDate = startDate; ZonedDateTime subperiodEndDate; for(int loopcmp=0; loopcmp<3; loopcmp++) { subperiodEndDate = ScheduleCalculator.getAdjustedDate(startDate, GENERATOR.getIndexIbor().getTenor().multipliedBy(loopcmp+1), GENERATOR.getIndexIbor().getBusinessDayConvention(), NYC, GENERATOR.getIndexIbor().isEndOfMonth()); assertEquals("GeneratorLegIborCompounding: generate - start sub period", subperiodStartDate, cpn.getFixingPeriodStartDates()[loopcmp]); ZonedDateTime endFixing = ScheduleCalculator.getAdjustedDate(subperiodStartDate, GENERATOR.getIndexIbor(), NYC); assertEquals("GeneratorLegIborCompounding: generate - end sub period", endFixing, cpn.getFixingPeriodEndDates()[loopcmp]); subperiodStartDate = subperiodEndDate; } assertEquals("GeneratorLegONCompounded: generate - start accrual date", startDate, cpn.getAccrualStartDate()); assertEquals("GeneratorLegONCompounded: generate - end accrual date", endDate, cpn.getAccrualEndDate()); ZonedDateTime paymentDate = ScheduleCalculator.getAdjustedDate(cpn.getAccrualEndDate(), generator.getPaymentOffset(), NYC); assertEquals("GeneratorLegONCompounded: generate - payment date", paymentDate, cpn.getPaymentDate()); assertEquals("GeneratorLegONCompounded: generate - spread", spread, cpn.getSpread()); startDate = endDate; } } }