/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.product.bond;
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.DayCounts.ACT_ACT_ISDA;
import static com.opengamma.strata.basics.date.DayCounts.NL_365;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.GBLO;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.USNY;
import static com.opengamma.strata.basics.index.PriceIndices.US_CPI_U;
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.collect.TestHelper.date;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.GB_IL_FLOAT;
import static com.opengamma.strata.product.bond.CapitalIndexedBondYieldConvention.US_IL_REAL;
import static com.opengamma.strata.product.swap.PriceIndexCalculationMethod.INTERPOLATED;
import static org.testng.Assert.assertEquals;
import java.time.LocalDate;
import java.time.Period;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.concurrent.atomic.AtomicBoolean;
import org.testng.annotations.Test;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.StandardId;
import com.opengamma.strata.basics.date.BusinessDayAdjustment;
import com.opengamma.strata.basics.date.BusinessDayConventions;
import com.opengamma.strata.basics.date.DayCount;
import com.opengamma.strata.basics.date.DaysAdjustment;
import com.opengamma.strata.basics.schedule.RollConventions;
import com.opengamma.strata.basics.value.ValueSchedule;
import com.opengamma.strata.product.rate.RateComputation;
import com.opengamma.strata.product.swap.InflationRateCalculation;
/**
* Test {@link ResolvedCapitalIndexedBond}.
* <p>
* The accrued interest method is test in the pricer test.
*/
@Test
public class ResolvedCapitalIndexedBondTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final StandardId LEGAL_ENTITY = StandardId.of("OG-Ticker", "US-Govt");
private static final double COUPON = 0.01;
private static final InflationRateCalculation RATE_CALC = InflationRateCalculation.builder()
.gearing(ValueSchedule.of(COUPON))
.index(US_CPI_U)
.lag(Period.ofMonths(3))
.indexCalculationMethod(INTERPOLATED)
.firstIndexValue(198.475)
.build();
private static final double NOTIONAL = 10_000_000d;
private static final BusinessDayAdjustment SCHEDULE_ADJ =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, USNY);
private static final DaysAdjustment SETTLE_OFFSET = DaysAdjustment.ofBusinessDays(2, USNY);
private static final CapitalIndexedBondPaymentPeriod[] PERIODIC = new CapitalIndexedBondPaymentPeriod[4];
static {
LocalDate[] unAdjDates = new LocalDate[] {LocalDate.of(2008, 1, 13), LocalDate.of(2008, 7, 13),
LocalDate.of(2009, 1, 13), LocalDate.of(2009, 7, 13), LocalDate.of(2010, 1, 13)};
for (int i = 0; i < 4; ++i) {
LocalDate start = SCHEDULE_ADJ.adjust(unAdjDates[i], REF_DATA);
LocalDate end = SCHEDULE_ADJ.adjust(unAdjDates[i + 1], REF_DATA);
RateComputation rateComputation = RATE_CALC.createRateComputation(end);
PERIODIC[i] = CapitalIndexedBondPaymentPeriod.builder()
.currency(USD)
.startDate(start)
.endDate(end)
.unadjustedStartDate(unAdjDates[i])
.unadjustedEndDate(unAdjDates[i + 1])
.detachmentDate(end)
.realCoupon(COUPON)
.rateComputation(rateComputation)
.notional(NOTIONAL)
.build();
}
}
private static final CapitalIndexedBondPaymentPeriod NOMINAL =
PERIODIC[3].withUnitCoupon(PERIODIC[0].getStartDate(), PERIODIC[0].getUnadjustedStartDate());
public void test_builder() {
ResolvedCapitalIndexedBond test = sut();
assertEquals(test.getCurrency(), USD);
assertEquals(test.getDayCount(), ACT_ACT_ISDA);
assertEquals(test.getStartDate(), PERIODIC[0].getStartDate());
assertEquals(test.getEndDate(), PERIODIC[3].getEndDate());
assertEquals(test.getUnadjustedStartDate(), PERIODIC[0].getUnadjustedStartDate());
assertEquals(test.getUnadjustedEndDate(), PERIODIC[3].getUnadjustedEndDate());
assertEquals(test.getLegalEntityId(), LEGAL_ENTITY);
assertEquals(test.getNominalPayment(), NOMINAL);
assertEquals(test.getNotional(), NOTIONAL);
assertEquals(test.getPeriodicPayments().toArray(), PERIODIC);
assertEquals(test.getSettlementDateOffset(), SETTLE_OFFSET);
assertEquals(test.getYieldConvention(), US_IL_REAL);
assertEquals(test.hasExCouponPeriod(), false);
assertEquals(test.getFirstIndexValue(), RATE_CALC.getFirstIndexValue().getAsDouble());
assertEquals(test.findPeriod(PERIODIC[0].getUnadjustedStartDate()), Optional.of(test.getPeriodicPayments().get(0)));
assertEquals(test.findPeriod(LocalDate.MIN), Optional.empty());
assertEquals(test.findPeriodIndex(PERIODIC[0].getUnadjustedStartDate()), OptionalInt.of(0));
assertEquals(test.findPeriodIndex(PERIODIC[1].getUnadjustedStartDate()), OptionalInt.of(1));
assertEquals(test.findPeriodIndex(LocalDate.MIN), OptionalInt.empty());
assertEquals(
test.calculateSettlementDateFromValuation(date(2015, 6, 30), REF_DATA),
SETTLE_OFFSET.adjust(date(2015, 6, 30), REF_DATA));
}
public void test_builder_fail() {
CapitalIndexedBondPaymentPeriod period = CapitalIndexedBondPaymentPeriod.builder()
.startDate(PERIODIC[2].getStartDate())
.endDate(PERIODIC[2].getEndDate())
.currency(GBP)
.notional(NOTIONAL)
.rateComputation(PERIODIC[2].getRateComputation())
.realCoupon(COUPON)
.build();
assertThrowsIllegalArg(() -> ResolvedCapitalIndexedBond.builder()
.dayCount(ACT_ACT_ISDA)
.legalEntityId(LEGAL_ENTITY)
.nominalPayment(NOMINAL)
.periodicPayments(PERIODIC[0], PERIODIC[1], period, PERIODIC[3])
.settlementDateOffset(SETTLE_OFFSET)
.yieldConvention(US_IL_REAL)
.build());
}
//-------------------------------------------------------------------------
public void test_yearFraction_scheduleInfo() {
ResolvedCapitalIndexedBond base = sut();
CapitalIndexedBondPaymentPeriod period = base.getPeriodicPayments().get(0);
AtomicBoolean eom = new AtomicBoolean(false);
DayCount dc = new DayCount() {
@Override
public double yearFraction(LocalDate firstDate, LocalDate secondDate, ScheduleInfo scheduleInfo) {
assertEquals(scheduleInfo.getStartDate(), base.getUnadjustedStartDate());
assertEquals(scheduleInfo.getEndDate(), base.getUnadjustedEndDate());
assertEquals(scheduleInfo.getPeriodEndDate(firstDate), period.getUnadjustedEndDate());
assertEquals(scheduleInfo.getFrequency(), base.getFrequency());
assertEquals(scheduleInfo.isEndOfMonthConvention(), eom.get());
return 0.5;
}
@Override
public int days(LocalDate firstDate, LocalDate secondDate) {
return 182;
}
@Override
public String getName() {
return "";
}
};
ResolvedCapitalIndexedBond test = base.toBuilder().dayCount(dc).build();
assertEquals(test.yearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate()), 0.5);
// test with EOM=true
ResolvedCapitalIndexedBond test2 = test.toBuilder().rollConvention(RollConventions.EOM).build();
eom.set(true);
assertEquals(test2.yearFraction(period.getUnadjustedStartDate(), period.getUnadjustedEndDate()), 0.5);
}
//-------------------------------------------------------------------------
public void coverage() {
coverImmutableBean(sut());
coverBeanEquals(sut(), sut2());
}
public void test_serialization() {
assertSerialization(sut());
}
//-------------------------------------------------------------------------
static ResolvedCapitalIndexedBond sut() {
return ResolvedCapitalIndexedBond.builder()
.securityId(CapitalIndexedBondTest.sut().getSecurityId())
.dayCount(ACT_ACT_ISDA)
.legalEntityId(LEGAL_ENTITY)
.nominalPayment(NOMINAL)
.periodicPayments(PERIODIC)
.frequency(CapitalIndexedBondTest.sut().getAccrualSchedule().getFrequency())
.rollConvention(CapitalIndexedBondTest.sut().getAccrualSchedule().calculatedRollConvention())
.settlementDateOffset(SETTLE_OFFSET)
.yieldConvention(US_IL_REAL)
.rateCalculation(RATE_CALC)
.build();
}
static ResolvedCapitalIndexedBond sut2() {
return ResolvedCapitalIndexedBond.builder()
.securityId(CapitalIndexedBondTest.sut2().getSecurityId())
.dayCount(NL_365)
.legalEntityId(StandardId.of("OG-Ticker", "US-Govt1"))
.nominalPayment(PERIODIC[1].withUnitCoupon(PERIODIC[0].getStartDate(), PERIODIC[0].getUnadjustedStartDate()))
.periodicPayments(PERIODIC[0], PERIODIC[1])
.frequency(CapitalIndexedBondTest.sut2().getAccrualSchedule().getFrequency())
.rollConvention(CapitalIndexedBondTest.sut2().getAccrualSchedule().calculatedRollConvention())
.settlementDateOffset(DaysAdjustment.ofBusinessDays(3, GBLO))
.yieldConvention(GB_IL_FLOAT)
.rateCalculation(CapitalIndexedBondTest.sut2().getRateCalculation())
.build();
}
}