/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.instrument.annuity;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
import org.threeten.bp.DayOfWeek;
import org.threeten.bp.LocalTime;
import org.threeten.bp.Period;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedON;
import com.opengamma.analytics.financial.instrument.index.IndexON;
import com.opengamma.analytics.financial.interestrate.TestsDataSetsSABR;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity;
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.provider.CouponFixedDiscountingMethod;
import com.opengamma.analytics.financial.provider.description.MulticurveProviderDiscountDataSets;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount;
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.timeseries.DoubleTimeSeries;
import com.opengamma.timeseries.precise.zdt.ImmutableZonedDateTimeDoubleTimeSeries;
import com.opengamma.timeseries.precise.zdt.ZonedDateTimeDoubleTimeSeries;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.CurrencyAmount;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.DateUtils;
/**
* Test.
*/
@SuppressWarnings("deprecation")
@Test(groups = TestGroup.UNIT)
public class AnnuityCouponONDefinitionTest {
private static final Currency CCY = Currency.EUR;
private static final Period PAYMENT_PERIOD = Period.ofMonths(6);
private static final Calendar CALENDAR = new MondayToFridayCalendar("Weekend");
private static final DayCount DAY_COUNT = DayCounts.ACT_360;
private static final boolean IS_EOM = true;
private static final ZonedDateTime SETTLEMENT_DATE = DateUtils.getUTCDate(2012, 2, 1);
private static final ZonedDateTime MATURITY_DATE = DateUtils.getUTCDate(2022, 2, 1);
private static final Period MATURITY_TENOR = Period.ofYears(10);
private static final double NOTIONAL = 100000000;
private static final IndexON INDEX = new IndexON("O/N", CCY, DAY_COUNT, 0);
private static final BusinessDayConvention BUSINESS_DAY = BusinessDayConventions.FOLLOWING;
private static final GeneratorSwapFixedON GENERATOR = new GeneratorSwapFixedON("OIS", INDEX, PAYMENT_PERIOD, DAY_COUNT, BUSINESS_DAY, IS_EOM, 1, CALENDAR);
private static final boolean IS_PAYER = true;
private static final AnnuityCouponONDefinition DEFINITION = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL, GENERATOR, IS_PAYER);
private static final int NUM_PAYMENTS = DEFINITION.getNumberOfPayments();
private static final ZonedDateTime FINAL_PAYMENT_DATE = DEFINITION.getNthPayment(NUM_PAYMENTS - 1).getPaymentDate();
private static final ZonedDateTime DATE = DateUtils.getUTCDate(2012, 3, 15);
// Utility to create a time series of fixings
static ZonedDateTimeDoubleTimeSeries createFixingSeries(final ZonedDateTime startDate, final ZonedDateTime endDate) {
final List<ZonedDateTime> dates = new ArrayList<>();
final List<Double> data = new ArrayList<>();
ZonedDateTime dt = startDate;
while (dt.isBefore(endDate) || dt.equals(endDate)) {
dates.add(dt);
data.add(0.05 + Math.sin(dt.getDayOfYear()) / 100);
dt = dt.plusDays(1);
if (dt.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
dt = dt.plusDays(2);
}
}
return ImmutableZonedDateTimeDoubleTimeSeries.of(dates, data, ZoneOffset.UTC);
}
private static final DoubleTimeSeries<ZonedDateTime> FIXING_TS = createFixingSeries(SETTLEMENT_DATE, FINAL_PAYMENT_DATE);
@Test
/**
* Tests the toDerivative method on the payment date. valuation is at noon, payment set at midnight...
*/
public void toDerivativeOnDateOfFinalPayment() {
final MulticurveProviderDiscount provider = MulticurveProviderDiscountDataSets.createMulticurveEurUsd();
final ZonedDateTime valuationTimeIsNoon = FINAL_PAYMENT_DATE.with(LocalTime.NOON);
assertTrue("valuationTimeIsNoon to be after paymentDate, which was midnight. Confirm behaviour", valuationTimeIsNoon.isAfter(FINAL_PAYMENT_DATE));
final Annuity<? extends Coupon> derivative = DEFINITION.toDerivative(valuationTimeIsNoon, FIXING_TS);
assertEquals("On the payment date, we expect the derivative to have the same number of payments as its definition", 1, derivative.getNumberOfPayments());
assertTrue("CouponOIS should be of type CouponFixed on the payment date", derivative.getNthPayment(0) instanceof CouponFixed);
final MultipleCurrencyAmount pv = CouponFixedDiscountingMethod.getInstance().presentValue((CouponFixed) derivative.getNthPayment(0), provider);
assertEquals("CouponOIS definition: toDerivative", pv, MultipleCurrencyAmount.of(CCY, -2571693.2212814568));
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullCoupons() {
new AnnuityCouponONDefinition(null, null, null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullSettlementDate1() {
AnnuityCouponONDefinition.from(null, MATURITY_TENOR, NOTIONAL, GENERATOR, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullPaymentFrequency() {
AnnuityCouponONDefinition.from(SETTLEMENT_DATE, (Period) null, NOTIONAL, GENERATOR, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullGenerator1() {
AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_TENOR, NOTIONAL, (GeneratorSwapFixedON) null, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullSettlementDate2() {
AnnuityCouponONDefinition.from(null, MATURITY_DATE, NOTIONAL, GENERATOR, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullMaturityDate() {
AnnuityCouponONDefinition.from(SETTLEMENT_DATE, (ZonedDateTime) null, NOTIONAL, GENERATOR, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullGenerator2() {
AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL, (GeneratorSwapFixedON) null, IS_PAYER);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNoIndexTS() {
DEFINITION.toDerivative(DATE);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullDate() {
DEFINITION.toDerivative(null, FIXING_TS);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullIndexTS() {
DEFINITION.toDerivative(DATE, (DoubleTimeSeries<ZonedDateTime>) null);
}
@Test
public void testHashCodeAndEquals() {
AnnuityCouponONDefinition definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL, GENERATOR, IS_PAYER);
assertEquals(DEFINITION, definition);
assertEquals(DEFINITION.hashCode(), definition.hashCode());
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_TENOR, NOTIONAL, GENERATOR, IS_PAYER);
assertEquals(DEFINITION, definition);
assertEquals(DEFINITION.hashCode(), definition.hashCode());
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE.plusDays(1), MATURITY_DATE, NOTIONAL, GENERATOR, IS_PAYER);
assertFalse(DEFINITION.equals(definition));
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE.plusDays(1), NOTIONAL, GENERATOR, IS_PAYER);
assertFalse(DEFINITION.equals(definition));
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL / 2, GENERATOR, IS_PAYER);
assertFalse(DEFINITION.equals(definition));
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL, new GeneratorSwapFixedON("OIS", INDEX, PAYMENT_PERIOD, DAY_COUNT, BUSINESS_DAY, IS_EOM, 0, CALENDAR), IS_PAYER);
assertFalse(DEFINITION.equals(definition));
definition = AnnuityCouponONDefinition.from(SETTLEMENT_DATE, MATURITY_DATE, NOTIONAL, GENERATOR, !IS_PAYER);
assertFalse(DEFINITION.equals(definition));
}
}