/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.instrument.bond; 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.instrument.annuity.AnnuityDefinition; import com.opengamma.analytics.financial.instrument.index.IndexPrice; import com.opengamma.analytics.financial.instrument.inflation.CouponInflationYearOnYearMonthlyWithMarginDefinition; import com.opengamma.analytics.financial.instrument.payment.CouponDefinition; import com.opengamma.analytics.financial.instrument.payment.PaymentFixedDefinition; import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity; import com.opengamma.analytics.financial.interestrate.bond.definition.BondInterestIndexedSecurity; import com.opengamma.analytics.financial.interestrate.inflation.derivative.CouponInflationYearOnYearMonthlyWithMargin; import com.opengamma.analytics.financial.interestrate.inflation.derivative.CouponInflationZeroCouponMonthlyGearing; import com.opengamma.analytics.financial.interestrate.payments.derivative.Coupon; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed; import com.opengamma.analytics.financial.interestrate.payments.derivative.PaymentFixed; import com.opengamma.analytics.financial.provider.description.MulticurveProviderDiscountDataSets; import com.opengamma.analytics.financial.schedule.ScheduleCalculator; import com.opengamma.analytics.util.time.TimeCalculator; import com.opengamma.financial.convention.businessday.BusinessDayConvention; import com.opengamma.financial.convention.businessday.BusinessDayConventions; import com.opengamma.financial.convention.calendar.Calendar; import com.opengamma.financial.convention.calendar.MondayToFridayCalendar; import com.opengamma.financial.convention.daycount.DayCount; import com.opengamma.financial.convention.daycount.DayCounts; import com.opengamma.financial.convention.yield.YieldConvention; import com.opengamma.financial.convention.yield.YieldConventionFactory; import com.opengamma.timeseries.DoubleTimeSeries; import com.opengamma.util.money.Currency; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; /** * Test. */ @Test(groups = TestGroup.UNIT) public class BondinterestIndexedSecurityDefinitionTest { //Index-Linked Gilt 2% Index-linked Treasury Stock 2035 - GB0031790826 private static final String NAME_INDEX_UK = "UK RPI"; private static final IndexPrice PRICE_INDEX_UKRPI = new IndexPrice(NAME_INDEX_UK, Currency.GBP); private static final Calendar CALENDAR_GBP = new MondayToFridayCalendar("GBP"); private static final BusinessDayConvention BUSINESS_DAY_GBP = BusinessDayConventions.FOLLOWING; private static final DayCount DAY_COUNT_1 = DayCounts.ACT_ACT_ISDA; private static final boolean IS_EOM_1 = false; private static final ZonedDateTime START_DATE_1 = DateUtils.getUTCDate(2002, 7, 11); private static final ZonedDateTime FIRST_COUPON_DATE_1 = DateUtils.getUTCDate(2003, 1, 26); private static final ZonedDateTime MATURITY_DATE_1 = DateUtils.getUTCDate(2012, 1, 26); private static final YieldConvention YIELD_CONVENTION_1 = YieldConventionFactory.INSTANCE.getYieldConvention("UK:BUMP/DMO METHOD"); // To check private static final int MONTH_LAG_1 = 8; private static final double NOTIONAL_1 = 1.00; private static final double REAL_RATE_1 = 0.02; private static final Period COUPON_PERIOD_1 = Period.ofMonths(6); private static final int COUPON_PER_YEAR_1 = 2; private static final int SETTLEMENT_DAYS_1 = 2; private static final double FACTOR = 0.02; private static final String ISSUER_UK = "UK GOVT"; private static final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> BOND_SECURITY_DEFINITION = BondInterestIndexedSecurityDefinition .fromMonthly(PRICE_INDEX_UKRPI, MONTH_LAG_1, START_DATE_1, FIRST_COUPON_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, NOTIONAL_1, REAL_RATE_1, BUSINESS_DAY_GBP, SETTLEMENT_DAYS_1, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, ISSUER_UK); @Test public void getter() { assertEquals("Capital Index Bond", DAY_COUNT_1, BOND_SECURITY_DEFINITION.getDayCount()); assertEquals("Capital Index Bond", IS_EOM_1, BOND_SECURITY_DEFINITION.isEOM()); assertEquals("Capital Index Bond", YIELD_CONVENTION_1, BOND_SECURITY_DEFINITION.getYieldConvention()); assertEquals("Capital Index Bond", COUPON_PER_YEAR_1, BOND_SECURITY_DEFINITION.getCouponPerYear()); assertEquals("Capital Index Bond", MONTH_LAG_1, BOND_SECURITY_DEFINITION.getMonthLag()); assertEquals("Capital Index Bond", CALENDAR_GBP, BOND_SECURITY_DEFINITION.getCalendar()); assertEquals("Capital Index Bond", PRICE_INDEX_UKRPI, BOND_SECURITY_DEFINITION.getPriceIndex()); assertEquals("Capital Index Bond", PRICE_INDEX_UKRPI.getCurrency(), BOND_SECURITY_DEFINITION.getCurrency()); } @Test /** * Tests the bond constructors. */ public void constructorBondsWithFirstCouponDate() { // Nominal construction final PaymentFixedDefinition nominalPayment = new PaymentFixedDefinition(PRICE_INDEX_UKRPI.getCurrency(), BUSINESS_DAY_GBP.adjustDate(CALENDAR_GBP, MATURITY_DATE_1), NOTIONAL_1); final AnnuityDefinition<PaymentFixedDefinition> nominalAnnuity = new AnnuityDefinition<>(new PaymentFixedDefinition[] {nominalPayment }, CALENDAR_GBP); // Coupon construction final ZonedDateTime[] paymentDatesUnadjusted = ScheduleCalculator.getUnadjustedDateSchedule(FIRST_COUPON_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, true, false); final ZonedDateTime[] paymentDates = ScheduleCalculator.getAdjustedDateSchedule(paymentDatesUnadjusted, BUSINESS_DAY_GBP, CALENDAR_GBP, false); final CouponInflationYearOnYearMonthlyWithMarginDefinition[] coupons = new CouponInflationYearOnYearMonthlyWithMarginDefinition[paymentDates.length + 1]; coupons[0] = CouponInflationYearOnYearMonthlyWithMarginDefinition.from(FACTOR, START_DATE_1, ScheduleCalculator.getAdjustedDate(FIRST_COUPON_DATE_1, 0, CALENDAR_GBP), NOTIONAL_1, PRICE_INDEX_UKRPI, MONTH_LAG_1, true); coupons[1] = CouponInflationYearOnYearMonthlyWithMarginDefinition.from(FACTOR, FIRST_COUPON_DATE_1, paymentDates[0], NOTIONAL_1, PRICE_INDEX_UKRPI, MONTH_LAG_1, true); for (int loopcpn = 1; loopcpn < paymentDates.length; loopcpn++) { coupons[loopcpn + 1] = CouponInflationYearOnYearMonthlyWithMarginDefinition.from(FACTOR, paymentDatesUnadjusted[loopcpn - 1], paymentDates[loopcpn], NOTIONAL_1, PRICE_INDEX_UKRPI, MONTH_LAG_1, true); } final AnnuityDefinition<CouponInflationYearOnYearMonthlyWithMarginDefinition> couponAnnuity = new AnnuityDefinition<>( coupons, CALENDAR_GBP); final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bond = new BondInterestIndexedSecurityDefinition<>( nominalAnnuity, couponAnnuity, 0, 2, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, MONTH_LAG_1, ISSUER_UK); final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bondFrom = BondInterestIndexedSecurityDefinition.fromMonthly( PRICE_INDEX_UKRPI, MONTH_LAG_1, START_DATE_1, FIRST_COUPON_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, NOTIONAL_1, FACTOR, BUSINESS_DAY_GBP, SETTLEMENT_DAYS_1, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, ISSUER_UK); assertEquals("Interest Index Bond: constructor", bond, bondFrom); } @Test /** * Tests the bond constructors. */ public void constructorBondsWithoutFirstCouponDate() { // Nominal construction final PaymentFixedDefinition nominalPayment = new PaymentFixedDefinition(PRICE_INDEX_UKRPI.getCurrency(), BUSINESS_DAY_GBP.adjustDate(CALENDAR_GBP, MATURITY_DATE_1), NOTIONAL_1); final AnnuityDefinition<PaymentFixedDefinition> nominalAnnuity = new AnnuityDefinition<>(new PaymentFixedDefinition[] {nominalPayment }, CALENDAR_GBP); // Coupon construction final ZonedDateTime[] paymentDatesUnadjusted = ScheduleCalculator.getUnadjustedDateSchedule(START_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, true, false); final ZonedDateTime[] paymentDates = ScheduleCalculator.getAdjustedDateSchedule(paymentDatesUnadjusted, BUSINESS_DAY_GBP, CALENDAR_GBP, false); final CouponInflationYearOnYearMonthlyWithMarginDefinition[] coupons = new CouponInflationYearOnYearMonthlyWithMarginDefinition[paymentDates.length]; coupons[0] = CouponInflationYearOnYearMonthlyWithMarginDefinition.from(FACTOR, START_DATE_1, paymentDates[0], NOTIONAL_1, PRICE_INDEX_UKRPI, MONTH_LAG_1, true); for (int loopcpn = 1; loopcpn < paymentDates.length; loopcpn++) { coupons[loopcpn] = CouponInflationYearOnYearMonthlyWithMarginDefinition.from(FACTOR, paymentDatesUnadjusted[loopcpn - 1], paymentDates[loopcpn], NOTIONAL_1, PRICE_INDEX_UKRPI, MONTH_LAG_1, true); } final AnnuityDefinition<CouponInflationYearOnYearMonthlyWithMarginDefinition> couponAnnuity = new AnnuityDefinition<>( coupons, CALENDAR_GBP); final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bond = new BondInterestIndexedSecurityDefinition<>( nominalAnnuity, couponAnnuity, 0, 2, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, MONTH_LAG_1, ISSUER_UK); final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bondFrom = BondInterestIndexedSecurityDefinition.fromMonthly( PRICE_INDEX_UKRPI, MONTH_LAG_1, START_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, NOTIONAL_1, FACTOR, BUSINESS_DAY_GBP, SETTLEMENT_DAYS_1, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, ISSUER_UK); assertEquals("Interest Index Bond: constructor", bond, bondFrom); } @Test /** * Tests the toDerivative method. */ public void toDerivative1Coupon() { final DoubleTimeSeries<ZonedDateTime> ukRpi = MulticurveProviderDiscountDataSets.ukRpiFrom2010(); final ZonedDateTime pricingDate = DateUtils.getUTCDate(2011, 8, 3); // One coupon fixed final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bondFromDefinition = BondInterestIndexedSecurityDefinition.fromMonthly( PRICE_INDEX_UKRPI, MONTH_LAG_1, START_DATE_1, FIRST_COUPON_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, NOTIONAL_1, FACTOR, BUSINESS_DAY_GBP, SETTLEMENT_DAYS_1, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, ISSUER_UK); final BondInterestIndexedSecurity<PaymentFixed, Coupon> bond = bondFromDefinition.toDerivative(pricingDate, ukRpi); final ZonedDateTime referenceDateNextCoupon = DateUtils.getUTCDate(2011, 5, 31); // May 11 final double referenceIndexNextCoupon = ukRpi.getValue(referenceDateNextCoupon); final ZonedDateTime referenceStartDateNextCoupon = DateUtils.getUTCDate(2010, 11, 30); // May 11 final double referenceStartIndexNextCoupon = ukRpi.getValue(referenceStartDateNextCoupon); final double amountNextCoupon = (referenceIndexNextCoupon / referenceStartIndexNextCoupon + FACTOR) * NOTIONAL_1; assertEquals("Interest Index Bond: toDerivative", amountNextCoupon, ((CouponFixed) bond.getCoupon().getNthPayment(0)).getAmount()); for (int loopcpn = 1; loopcpn < bond.getCoupon().getNumberOfPayments(); loopcpn++) { assertTrue("Interest Index Bond: toDerivative", (bond.getCoupon().getNthPayment(loopcpn) instanceof CouponInflationYearOnYearMonthlyWithMargin)); assertEquals("Interest Index Bond: toDerivative", ((CouponInflationYearOnYearMonthlyWithMargin) bond.getCoupon().getNthPayment(loopcpn)).getPriceIndex(), PRICE_INDEX_UKRPI); } final Annuity<PaymentFixed> nominal = (Annuity<PaymentFixed>) bondFromDefinition.getNominal().toDerivative(pricingDate); final Annuity<Coupon> coupon = (Annuity<Coupon>) bondFromDefinition.getCoupons().toDerivative(pricingDate, ukRpi); final ZonedDateTime spot = ScheduleCalculator.getAdjustedDate(pricingDate, SETTLEMENT_DAYS_1, CALENDAR_GBP); final double settleTime = TimeCalculator.getTimeBetween(pricingDate, spot); final AnnuityDefinition<CouponDefinition> couponDefinition = (AnnuityDefinition<CouponDefinition>) bondFromDefinition.getCoupons().trimBefore(spot); final double accruedInterest = bondFromDefinition.accruedInterest(spot); final double factorSpot = DAY_COUNT_1.getAccruedInterest(couponDefinition.getNthPayment(0).getAccrualStartDate(), spot, couponDefinition.getNthPayment(0) .getAccrualEndDate(), 1.0, COUPON_PER_YEAR_1); final double factorPeriod = DAY_COUNT_1.getAccruedInterest(couponDefinition.getNthPayment(0).getAccrualStartDate(), couponDefinition.getNthPayment(0) .getAccrualEndDate(), couponDefinition.getNthPayment(0).getAccrualEndDate(), 1.0, COUPON_PER_YEAR_1); final double factorToNextCoupon = (factorPeriod - factorSpot) / factorPeriod; final PaymentFixedDefinition nominalLast = bondFromDefinition.getNominal().getNthPayment(bondFromDefinition.getNominal().getNumberOfPayments() - 1); final ZonedDateTime settlementDate2 = spot; final double notional = 1.0; final PaymentFixedDefinition settlementDefinition = new PaymentFixedDefinition(nominalLast.getCurrency(), settlementDate2, notional); final PaymentFixed settlement = settlementDefinition.toDerivative(pricingDate); final BondInterestIndexedSecurity<PaymentFixed, Coupon> bondSecurityExpected = new BondInterestIndexedSecurity<>(nominal, coupon, settleTime, accruedInterest, factorToNextCoupon, YIELD_CONVENTION_1, COUPON_PER_YEAR_1, settlement, ISSUER_UK, PRICE_INDEX_UKRPI); assertEquals("Interest Index Bond: toDerivative", bondSecurityExpected, bond); } @Test /** * Tests the toDerivative method. */ public void toDerivative2Coupon() { final DoubleTimeSeries<ZonedDateTime> ukRpi = MulticurveProviderDiscountDataSets.ukRpiFrom2010(); final ZonedDateTime pricingDate = DateUtils.getUTCDate(2011, 7, 15); // Two coupons fixed final BondInterestIndexedSecurityDefinition<PaymentFixedDefinition, CouponInflationYearOnYearMonthlyWithMarginDefinition> bondFromDefinition = BondInterestIndexedSecurityDefinition.fromMonthly( PRICE_INDEX_UKRPI, MONTH_LAG_1, START_DATE_1, FIRST_COUPON_DATE_1, MATURITY_DATE_1, COUPON_PERIOD_1, NOTIONAL_1, FACTOR, BUSINESS_DAY_GBP, SETTLEMENT_DAYS_1, CALENDAR_GBP, DAY_COUNT_1, YIELD_CONVENTION_1, IS_EOM_1, ISSUER_UK); final BondInterestIndexedSecurity<PaymentFixed, Coupon> bond = bondFromDefinition.toDerivative(pricingDate, ukRpi); final ZonedDateTime[] referenceDateNextCoupon = new ZonedDateTime[] {DateUtils.getUTCDate(2010, 5, 31), DateUtils.getUTCDate(2010, 11, 30), DateUtils.getUTCDate(2011, 5, 31) }; // Nov 10, May 11 final double[] referenceIndexNextCoupon = new double[] {ukRpi.getValue(referenceDateNextCoupon[0]), ukRpi.getValue(referenceDateNextCoupon[1]), ukRpi.getValue(referenceDateNextCoupon[2]) }; for (int loopcpn = 0; loopcpn < 2; loopcpn++) { final double amountNextCoupon = (referenceIndexNextCoupon[loopcpn + 1] / referenceIndexNextCoupon[loopcpn] + FACTOR) * NOTIONAL_1; assertEquals("Capital Index Bond: toDerivative", amountNextCoupon, ((CouponFixed) bond.getCoupon().getNthPayment(loopcpn)).getAmount()); } for (int loopcpn = 2; loopcpn < bond.getCoupon().getNumberOfPayments(); loopcpn++) { assertTrue("Capital Index Bond: toDerivative", (bond.getCoupon().getNthPayment(loopcpn) instanceof CouponInflationZeroCouponMonthlyGearing)); assertEquals("Capital Index Bond: toDerivative", ((CouponInflationYearOnYearMonthlyWithMargin) bond.getCoupon().getNthPayment(loopcpn)).getPriceIndex(), PRICE_INDEX_UKRPI); } } }