/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.instrument.payment;
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.Arrays;
import java.util.List;
import org.testng.annotations.Test;
import org.testng.internal.junit.ArrayAsserts;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.instrument.index.IborIndex;
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.CouponIborAverageFixingDatesCompounding;
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.timeseries.DoubleTimeSeries;
import com.opengamma.timeseries.precise.zdt.ImmutableZonedDateTimeDoubleTimeSeries;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.DateUtils;
/**
* Tests related to the construction of CouponIborAverageCompoundingDefinition.
*/
public class CouponIborAverageFixingDatesCompoundingDefinitionTest {
private static final Period TENOR = Period.ofMonths(1);
private static final int SETTLEMENT_DAYS = 2;
private static final Calendar CALENDAR = new MondayToFridayCalendar("A");
private static final DayCount DAY_COUNT_INDEX = DayCounts.ACT_360;
private static final BusinessDayConvention BUSINESS_DAY = BusinessDayConventions.MODIFIED_FOLLOWING;
private static final boolean IS_EOM = true;
private static final Currency CUR = Currency.EUR;
private static final IborIndex INDEX = new IborIndex(CUR, TENOR, SETTLEMENT_DAYS, DAY_COUNT_INDEX, BUSINESS_DAY, IS_EOM, "Index");
private static final int NUM_PRDS = 6;
private static final int NUM_OBS = 5;
private static final ZonedDateTime ACCRUAL_START_DATE = DateUtils.getUTCDate(2011, 1, 6);
private static final ZonedDateTime ACCRUAL_END_DATE = DateUtils.getUTCDate(2011, 7, 4);
private static final ZonedDateTime PAYMENT_DATE = DateUtils.getUTCDate(2011, 7, 6);
// The above dates are not standard but selected for insure correct testing.
//Example 1: EUR with same numbers of fixing in all periods
private static final ZonedDateTime[][] FIXING_DATES = new ZonedDateTime[NUM_PRDS][NUM_OBS];
private static final double[][] WEIGHTS = new double[NUM_PRDS][NUM_OBS];
static {
for (int i = 0; i < NUM_OBS; ++i) {
for (int j = 0; j < NUM_PRDS; ++j) {
FIXING_DATES[j][i] = DateUtils.getUTCDate(2011, j + 1, 3 + 6 * i);
WEIGHTS[j][i] = 2. * (NUM_OBS - i) / NUM_OBS / (NUM_OBS + 1.);
}
}
}
private static final DayCount DAY_COUNT_PAYMENT = DayCounts.ACT_365;
private static final double ACCRUAL_FACTOR = DAY_COUNT_PAYMENT.getDayCountFraction(ACCRUAL_START_DATE, ACCRUAL_END_DATE);
private static final double[] ACCRUAL_FACTORS = new double[NUM_PRDS];
static {
Arrays.fill(ACCRUAL_FACTORS, ACCRUAL_FACTOR / NUM_PRDS);
ACCRUAL_FACTORS[0] *= 1.01;
ACCRUAL_FACTORS[NUM_PRDS - 2] *= 0.99;
}
private static final double NOTIONAL = 1000000;
private static final CouponIborAverageFixingDatesCompoundingDefinition DFN1 =
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE,
ACCRUAL_FACTOR, NOTIONAL, ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, CALENDAR);
//Example 2: USD with same numbers of fixing in all periods, from full detail
private static ZonedDateTime[][] EXP_START_DATES = new ZonedDateTime[NUM_PRDS][NUM_OBS];
private static ZonedDateTime[][] EXP_END_DATES = new ZonedDateTime[NUM_PRDS][NUM_OBS];
private static double[][] FIX_ACC_FACTORS = new double[NUM_PRDS][NUM_OBS];
static {
for (int i = 0; i < NUM_OBS; ++i) {
for (int j = 0; j < NUM_PRDS; ++j) {
EXP_START_DATES[j][i] = ScheduleCalculator.getAdjustedDate(FIXING_DATES[j][i], INDEX.getSpotLag(), CALENDAR);
EXP_END_DATES[j][i] = ScheduleCalculator.getAdjustedDate(EXP_START_DATES[j][i], INDEX.getTenor(),
INDEX.getBusinessDayConvention(), CALENDAR, INDEX.isEndOfMonth());
FIX_ACC_FACTORS[j][i] = INDEX.getDayCount().getDayCountFraction(EXP_START_DATES[j][i], EXP_END_DATES[j][i], CALENDAR);
}
}
}
private static final CouponIborAverageFixingDatesCompoundingDefinition DFN2 =
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE,
ACCRUAL_FACTOR, NOTIONAL, ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, EXP_START_DATES, EXP_END_DATES, FIX_ACC_FACTORS);
// Example 3: different number of fixing in each subperiod
private static final int NB_SUBPERIODS = 3;
private static final ZonedDateTime[] ACCRUAL_START_DATE_SUB_3 = new ZonedDateTime[NB_SUBPERIODS + 1];
private static final ZonedDateTime[][] FIXING_DATES_3 = new ZonedDateTime[NB_SUBPERIODS][];
private static final double[][] WEIGHTS_3 = new double[NB_SUBPERIODS][];
private static final double[] ACCRUAL_FACTORS_3 = new double[NB_SUBPERIODS];
static {
for (int loopsub = 0; loopsub <= NB_SUBPERIODS; loopsub++) {
ACCRUAL_START_DATE_SUB_3[loopsub] = ScheduleCalculator.getAdjustedDate(ACCRUAL_START_DATE, Period.ofMonths(loopsub), INDEX, CALENDAR);
}
for (int loopsub = 0; loopsub < NB_SUBPERIODS; loopsub++) {
List<ZonedDateTime> listDates = new ArrayList<>();
ZonedDateTime startFixPeriod = ACCRUAL_START_DATE_SUB_3[loopsub];
listDates.add(ScheduleCalculator.getAdjustedDate(startFixPeriod, -INDEX.getSpotLag(), CALENDAR));
startFixPeriod = ScheduleCalculator.getAdjustedDate(startFixPeriod, 1, CALENDAR);
while (startFixPeriod.isBefore(ACCRUAL_START_DATE_SUB_3[loopsub + 1])) {
listDates.add(ScheduleCalculator.getAdjustedDate(startFixPeriod, -INDEX.getSpotLag(), CALENDAR));
startFixPeriod = ScheduleCalculator.getAdjustedDate(startFixPeriod, 1, CALENDAR);
}
FIXING_DATES_3[loopsub] = listDates.toArray(new ZonedDateTime[0]);
WEIGHTS_3[loopsub] = new double[FIXING_DATES_3[loopsub].length];
ACCRUAL_FACTORS_3[loopsub] = DAY_COUNT_INDEX.getDayCountFraction(ACCRUAL_START_DATE_SUB_3[loopsub],
ACCRUAL_START_DATE_SUB_3[loopsub + 1]);
for (int loopf = 0; loopf < FIXING_DATES_3[loopsub].length; loopf++) {
WEIGHTS_3[loopsub][loopf] = 1.0d / FIXING_DATES_3[loopsub].length;
}
}
}
private static final CouponIborAverageFixingDatesCompoundingDefinition DFN3 =
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, ACCRUAL_START_DATE_SUB_3[3], ACCRUAL_START_DATE_SUB_3[0],
ACCRUAL_START_DATE_SUB_3[3], ACCRUAL_FACTOR, NOTIONAL, ACCRUAL_FACTORS_3, INDEX, FIXING_DATES_3, WEIGHTS_3, CALENDAR);
private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2010, 12, 27);
/**
*
*/
@Test
public void getter() {
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", FIXING_DATES, DFN2.getFixingDates());
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", WEIGHTS, DFN2.getWeight());
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", EXP_START_DATES, DFN2.getFixingPeriodStartDates());
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", EXP_END_DATES, DFN2.getFixingPeriodEndDates());
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", FIX_ACC_FACTORS, DFN2.getFixingPeriodAccrualFactor());
ArrayAsserts.assertArrayEquals("CouponIborAverageCompoundingDefinition: getter", FIXING_DATES_3, DFN3.getFixingDates());
}
/**
* all fixed, none fixed, partially fixed cases
*/
@Test
public void toDerivativeGeneralTest() {
final ZonedDateTime[] dates1 = new ZonedDateTime[NUM_PRDS * NUM_OBS];
final double[] rates1 = new double[NUM_PRDS * NUM_OBS];
Arrays.fill(rates1, 0.01);
for (int i = 0; i < NUM_PRDS; ++i) {
for (int j = 0; j < NUM_OBS; ++j) {
dates1[NUM_OBS * i + j] = FIXING_DATES[i][j];
}
}
final DoubleTimeSeries<ZonedDateTime> fixingTS1 = ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(dates1, rates1);
final Coupon derivative1 = DFN1.toDerivative(FIXING_DATES[0][0].minusDays(10), fixingTS1);
final Coupon derivative2 = DFN1.toDerivative(FIXING_DATES[NUM_PRDS - 1][NUM_OBS - 1].plusDays(1), fixingTS1);
assertTrue((derivative2 instanceof CouponFixed));
double fixed = 1.0;
for (int i = 0; i < NUM_PRDS; ++i) {
double fwd = 0.0;
for (int j = 0; j < NUM_OBS; ++j) {
fwd += 0.01 * WEIGHTS[i][j];
}
fixed *= (1.0 + fwd * DFN1.getPaymentAccrualFactors()[i]);
}
assertEquals((fixed - 1.0) / DFN1.getPaymentYearFraction(), ((CouponFixed) derivative2).getFixedRate());
assertTrue((derivative1 instanceof CouponIborAverageFixingDatesCompounding));
checkOutputs(FIXING_DATES[0][0].minusDays(10), DFN1, (CouponIborAverageFixingDatesCompounding) derivative1, 0, 0);
assertEquals(0.0, ((CouponIborAverageFixingDatesCompounding) derivative1).getAmountAccrued());
assertEquals(1.0, ((CouponIborAverageFixingDatesCompounding) derivative1).getInvestmentFactor());
final int prd = 2;
final int dt = 3;
final ZonedDateTime refDate3 = FIXING_DATES[prd][dt].minusDays(1);
final CouponIborAverageFixingDatesCompounding derivative3 = (CouponIborAverageFixingDatesCompounding) DFN1.toDerivative(refDate3, fixingTS1);
checkOutputs(refDate3, DFN1, derivative3, prd, dt);
double refAcc = 1.0;
for (int i = 0; i < prd; ++i) {
double rate = 0.0;
for (int j = 0; j < NUM_OBS; ++j) {
rate += WEIGHTS[i][j] * 0.01;
}
refAcc *= (1.0 + rate * ACCRUAL_FACTORS[i]);
}
assertEquals(refAcc, derivative3.getAmountAccrued(), 1.e-14);
double refRate = 0.0;
for (int j = 0; j < dt; ++j) {
refRate += WEIGHTS[prd][j] * 0.01;
}
assertEquals(refRate, derivative3.getInvestmentFactor(), 1.e-14);
try {
DFN1.toDerivative(PAYMENT_DATE.plusDays(10), fixingTS1);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("date is after payment date", e.getMessage());
}
try {
DFN1.toDerivative(DateUtils.getUTCDate(2011, 5, 3), ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(
new ZonedDateTime[] {DateUtils.getUTCDate(2010, 2, 7) }, new double[] {0.01 }));
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("Could not get fixing value for date " + FIXING_DATES[0][0], e.getMessage());
}
}
/**
* reference date == final fixing date of a period
*/
@Test
public void toDerivativeEndOfPeriodTest() {
final ZonedDateTime[] dates1 = new ZonedDateTime[NUM_PRDS * NUM_OBS];
final double[] rates1 = new double[NUM_PRDS * NUM_OBS];
Arrays.fill(rates1, 0.01);
for (int i = 0; i < NUM_PRDS; ++i) {
for (int j = 0; j < NUM_OBS; ++j) {
dates1[NUM_OBS * i + j] = FIXING_DATES[i][j];
}
}
final DoubleTimeSeries<ZonedDateTime> fixingTS1 = ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(dates1, rates1);
final ZonedDateTime refDate4 = FIXING_DATES[2][4];
final CouponIborAverageFixingDatesCompounding derivative4 = (CouponIborAverageFixingDatesCompounding) DFN1.toDerivative(refDate4, fixingTS1);
checkOutputs(refDate4, DFN1, derivative4, 2 + 1, 0);
double refAcc = 1.0;
for (int i = 0; i < 3; ++i) {
double rate = 0.0;
for (int j = 0; j < NUM_OBS; ++j) {
rate += WEIGHTS[i][j] * 0.01;
}
refAcc *= (1.0 + rate * ACCRUAL_FACTORS[i]);
}
assertEquals(refAcc, derivative4.getAmountAccrued(), 1.e-14);
assertEquals(0., derivative4.getInvestmentFactor(), 1.e-14);
}
/**
* fixing Date == reference date, rate is available
*/
@Test
public void toDerivativeCoincideTest() {
final ZonedDateTime[] dates1 = new ZonedDateTime[NUM_PRDS * NUM_OBS];
final double[] rates1 = new double[NUM_PRDS * NUM_OBS];
Arrays.fill(rates1, 0.01);
for (int i = 0; i < NUM_PRDS; ++i) {
for (int j = 0; j < NUM_OBS; ++j) {
dates1[NUM_OBS * i + j] = FIXING_DATES[i][j];
}
}
final DoubleTimeSeries<ZonedDateTime> fixingTS1 = ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(dates1, rates1);
final ZonedDateTime refDate5 = FIXING_DATES[1][2];
final CouponIborAverageFixingDatesCompounding derivative5 = (CouponIborAverageFixingDatesCompounding) DFN1.toDerivative(refDate5, fixingTS1);
checkOutputs(refDate5, DFN1, derivative5, 1, 3);
double refAcc = 1.0;
for (int i = 0; i < 1; ++i) {
double rate = 0.0;
for (int j = 0; j < NUM_OBS; ++j) {
rate += WEIGHTS[i][j] * 0.01;
}
refAcc *= (1.0 + rate * ACCRUAL_FACTORS[i]);
}
assertEquals(refAcc, derivative5.getAmountAccrued(), 1.e-14);
double refRate = 0.0;
for (int j = 0; j < 3; ++j) {
refRate += WEIGHTS[1][j] * 0.01;
}
assertEquals(refRate, derivative5.getInvestmentFactor(), 1.e-14);
}
/**
* fixing Date == reference date, but rate is null
*/
@Test
public void toDerivativeNullRateTest() {
final ZonedDateTime[] dates1 = new ZonedDateTime[NUM_PRDS * NUM_OBS];
final double[] rates1 = new double[NUM_PRDS * NUM_OBS];
Arrays.fill(rates1, 0.01);
for (int i = 0; i < NUM_PRDS; ++i) {
for (int j = 0; j < NUM_OBS; ++j) {
dates1[NUM_OBS * i + j] = FIXING_DATES[i][j];
}
}
dates1[7] = dates1[7].plusDays(1);
final DoubleTimeSeries<ZonedDateTime> fixingTS1 = ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(dates1, rates1);
final ZonedDateTime refDate5 = FIXING_DATES[1][2];
final CouponIborAverageFixingDatesCompounding derivative5 = (CouponIborAverageFixingDatesCompounding) DFN1.toDerivative(refDate5, fixingTS1);
checkOutputs(refDate5, DFN1, derivative5, 1, 2);
double refAcc = 1.0;
for (int i = 0; i < 1; ++i) {
double rate = 0.0;
for (int j = 0; j < NUM_OBS; ++j) {
rate += WEIGHTS[i][j] * 0.01;
}
refAcc *= (1.0 + rate * ACCRUAL_FACTORS[i]);
}
assertEquals(refAcc, derivative5.getAmountAccrued(), 1.e-14);
double refRate = 0.0;
for (int j = 0; j < 2; ++j) {
refRate += WEIGHTS[1][j] * 0.01;
}
assertEquals(refRate, derivative5.getInvestmentFactor(), 1.e-14);
}
/**
* Fixing dates arrays are not the same size for all subperiods
*/
@Test
public void toDerivativeDifferentFixingSize() {
int dim = 0;
final int[] nDates = new int[NB_SUBPERIODS];
for (int i = 0; i < NB_SUBPERIODS; ++i) {
nDates[i] = FIXING_DATES_3[i].length;
dim += FIXING_DATES_3[i].length;
}
final ZonedDateTime[] dates1 = new ZonedDateTime[dim];
final double[] rates1 = new double[dim];
Arrays.fill(rates1, 0.01);
int k = 0;
for (int i = 0; i < NB_SUBPERIODS; ++i) {
for (int j = 0; j < nDates[i]; ++j) {
dates1[k] = FIXING_DATES_3[i][j];
++k;
}
}
dates1[nDates[0] + 1] = dates1[nDates[0] + 1].plusDays(1);
final DoubleTimeSeries<ZonedDateTime> fixingTS1 = ImmutableZonedDateTimeDoubleTimeSeries.ofUTC(dates1, rates1);
final ZonedDateTime refDate = FIXING_DATES_3[1][1];
final CouponIborAverageFixingDatesCompounding deriv = (CouponIborAverageFixingDatesCompounding) DFN3.toDerivative(refDate, fixingTS1);
checkOutputs(refDate, DFN3, deriv, 1, 1);
double refAcc = 1.0;
for (int i = 0; i < 1; ++i) {
double rate = 0.0;
for (int j = 0; j < nDates[i]; ++j) {
rate += WEIGHTS_3[i][j] * 0.01;
}
refAcc *= (1.0 + rate * ACCRUAL_FACTORS_3[i]);
}
assertEquals(refAcc, deriv.getAmountAccrued(), 1.e-14);
double refRate = 0.0;
for (int j = 0; j < 1; ++j) {
refRate += WEIGHTS_3[1][j] * 0.01;
}
assertEquals(refRate, deriv.getInvestmentFactor(), 1.e-14);
}
/**
* Exception expected
*/
@Test
public void exceptionTest() {
try {
new CouponIborAverageFixingDatesCompoundingDefinition(Currency.GBP, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, CALENDAR);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("index currency different from payment currency", e.getMessage());
}
try {
new CouponIborAverageFixingDatesCompoundingDefinition(Currency.USD, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, EXP_START_DATES, EXP_END_DATES, FIX_ACC_FACTORS);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("index currency different from payment currency", e.getMessage());
}
double[][] shortWeight = Arrays.copyOf(WEIGHTS, NUM_PRDS - 1);
try {
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, shortWeight, CALENDAR);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("weights length different from fixingDate length", e.getMessage());
}
try {
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, shortWeight, EXP_START_DATES, EXP_END_DATES, FIX_ACC_FACTORS);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("weights length different from fixingDate length", e.getMessage());
}
double[][] smallWeight = new double[NUM_PRDS][];
for (int i = 0; i < NUM_PRDS; ++i) {
smallWeight[i] = Arrays.copyOf(WEIGHTS[i], NUM_OBS - 1);
}
final ZonedDateTime[][] shortStartDates = Arrays.copyOf(EXP_START_DATES, NUM_PRDS - 1);
try {
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, shortStartDates, EXP_END_DATES, FIX_ACC_FACTORS);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("fixingPeriodStartDates length different from fixingDate length", e.getMessage());
}
final ZonedDateTime[][] shortEndDates = Arrays.copyOf(EXP_END_DATES, NUM_PRDS - 1);
try {
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, EXP_START_DATES, shortEndDates, FIX_ACC_FACTORS);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("fixingPeriodEndDates length different from fixingDate length", e.getMessage());
}
final double[][] shortAcc = Arrays.copyOf(FIX_ACC_FACTORS, NUM_PRDS - 1);
try {
new CouponIborAverageFixingDatesCompoundingDefinition(CUR, PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL,
ACCRUAL_FACTORS, INDEX, FIXING_DATES, WEIGHTS, EXP_START_DATES, EXP_END_DATES, shortAcc);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("fixingPeriodAccrualFactors length different from fixingDate length", e.getMessage());
}
final ZonedDateTime[][] smallStartDates = new ZonedDateTime[NUM_PRDS][];
final ZonedDateTime[][] smallEndDates = new ZonedDateTime[NUM_PRDS][];
final double[][] smallAcc = new double[NUM_PRDS][];
for (int i = 0; i < NUM_PRDS; ++i) {
smallStartDates[i] = Arrays.copyOf(EXP_START_DATES[i], NUM_OBS - 1);
smallEndDates[i] = Arrays.copyOf(EXP_END_DATES[i], NUM_OBS - 1);
smallAcc[i] = Arrays.copyOf(FIX_ACC_FACTORS[i], NUM_OBS - 1);
}
final ZonedDateTime afterPayment = PAYMENT_DATE.plusDays(1);
try {
DFN1.toDerivative(afterPayment);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("date is after payment date", e.getMessage());
}
final ZonedDateTime afterFixing = FIXING_DATES[0][0].plusDays(1);
try {
DFN1.toDerivative(afterFixing);
throw new RuntimeException();
} catch (final Exception e) {
assertEquals("Do not have any fixing data but are asking for a derivative at " + afterFixing + " which is after fixing date " + FIXING_DATES[0][0], e.getMessage());
}
}
/**
*
*/
@Test
public void consistencyTest() {
final CouponIborAverageFixingDatesCompoundingDefinition dfn1WithDouble = DFN1.withNotional(NOTIONAL * 2);
assertEquals(DFN1.getIndex(), DFN2.getIndex());
assertEquals(DFN1.getIndex(), dfn1WithDouble.getIndex());
for (int i = 0; i < NUM_OBS; ++i) {
for (int j = 0; j < NUM_PRDS; ++j) {
assertEquals(DFN1.getPaymentAccrualFactors()[j], DFN2.getPaymentAccrualFactors()[j]);
assertEquals(DFN1.getFixingDates()[j][i], DFN2.getFixingDates()[j][i]);
assertEquals(DFN1.getWeight()[j][i], DFN2.getWeight()[j][i]);
assertEquals(DFN1.getFixingPeriodStartDates()[j][i], DFN2.getFixingPeriodStartDates()[j][i]);
assertEquals(DFN1.getFixingPeriodEndDates()[j][i], DFN2.getFixingPeriodEndDates()[j][i]);
assertEquals(DFN1.getFixingPeriodAccrualFactor()[j][i], DFN2.getFixingPeriodAccrualFactor()[j][i]);
assertEquals(DFN1.getPaymentAccrualFactors()[j], dfn1WithDouble.getPaymentAccrualFactors()[j]);
assertEquals(DFN1.getFixingDates()[j][i], dfn1WithDouble.getFixingDates()[j][i]);
assertEquals(DFN1.getWeight()[j][i], dfn1WithDouble.getWeight()[j][i]);
assertEquals(DFN1.getFixingPeriodStartDates()[j][i], dfn1WithDouble.getFixingPeriodStartDates()[j][i]);
assertEquals(DFN1.getFixingPeriodEndDates()[j][i], dfn1WithDouble.getFixingPeriodEndDates()[j][i]);
assertEquals(DFN1.getFixingPeriodAccrualFactor()[j][i], dfn1WithDouble.getFixingPeriodAccrualFactor()[j][i]);
}
}
final CouponIborAverageFixingDatesCompoundingDefinition dfn1 = CouponIborAverageFixingDatesCompoundingDefinition.from(CUR,
PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL, ACCRUAL_FACTORS,
INDEX, FIXING_DATES, WEIGHTS, CALENDAR);
final CouponIborAverageFixingDatesCompoundingDefinition dfn2 = CouponIborAverageFixingDatesCompoundingDefinition.from(CUR,
PAYMENT_DATE, ACCRUAL_START_DATE, ACCRUAL_END_DATE, ACCRUAL_FACTOR, NOTIONAL, ACCRUAL_FACTORS,
INDEX, FIXING_DATES, WEIGHTS, EXP_START_DATES, EXP_END_DATES, FIX_ACC_FACTORS);
assertTrue(DFN1.equals(dfn1));
assertEquals(DFN1.hashCode(), dfn1.hashCode());
assertTrue(DFN2.equals(dfn2));
assertEquals(DFN2.hashCode(), dfn2.hashCode());
assertFalse(DFN1.hashCode() == dfn1WithDouble.hashCode());
assertFalse(DFN1.equals(dfn1WithDouble));
assertTrue(DFN1.toDerivative(REFERENCE_DATE).equals(dfn1.toDerivative(REFERENCE_DATE)));
}
private void checkOutputs(final ZonedDateTime refDate, final CouponIborAverageFixingDatesCompoundingDefinition def,
final CouponIborAverageFixingDatesCompounding dev, final int posPeriod, final int posDate) {
final int nPrds = def.getPaymentAccrualFactors().length;
assertEquals(nPrds - posPeriod, dev.getFixingPeriodAccrualFactor().length);
assertEquals(nPrds - posPeriod, dev.getFixingPeriodEndTime().length);
assertEquals(nPrds - posPeriod, dev.getFixingPeriodStartTime().length);
assertEquals(nPrds - posPeriod, dev.getFixingTime().length);
assertEquals(nPrds - posPeriod, dev.getPaymentAccrualFactors().length);
for (int i = 0; i < nPrds - posPeriod; ++i) {
assertEquals(def.getPaymentAccrualFactors()[i + posPeriod], dev.getPaymentAccrualFactors()[i]);
}
for (int i = 1; i < nPrds - posPeriod; ++i) {
assertEquals(def.getPaymentAccrualFactors()[i + posPeriod], dev.getPaymentAccrualFactors()[i]);
assertEquals(def.getFixingPeriodAccrualFactor()[i + posPeriod].length, dev.getFixingPeriodAccrualFactor()[i].length);
assertEquals(def.getFixingPeriodEndDates()[i + posPeriod].length, dev.getFixingPeriodEndTime()[i].length);
assertEquals(def.getFixingPeriodStartDates()[i + posPeriod].length, dev.getFixingPeriodStartTime()[i].length);
assertEquals(def.getFixingDates()[i + posPeriod].length, dev.getFixingTime()[i].length);
final int nDates = def.getFixingPeriodAccrualFactor()[i + posPeriod].length;
for (int j = 0; j < nDates; ++j) {
assertEquals(def.getFixingPeriodAccrualFactor()[i + posPeriod][j], dev.getFixingPeriodAccrualFactor()[i][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingDates()[i + posPeriod][j]), dev.getFixingTime()[i][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingPeriodEndDates()[i + posPeriod][j]), dev.getFixingPeriodEndTime()[i][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingPeriodStartDates()[i + posPeriod][j]), dev.getFixingPeriodStartTime()[i][j]);
}
}
final int nDates0 = def.getFixingPeriodAccrualFactor()[posPeriod].length;
assertEquals(nDates0 - posDate, dev.getFixingPeriodAccrualFactor()[0].length);
assertEquals(nDates0 - posDate, dev.getFixingPeriodEndTime()[0].length);
assertEquals(nDates0 - posDate, dev.getFixingPeriodStartTime()[0].length);
assertEquals(nDates0 - posDate, dev.getFixingTime()[0].length);
for (int j = 0; j < nDates0 - posDate; ++j) {
assertEquals(def.getFixingPeriodAccrualFactor()[posPeriod][j + posDate], dev.getFixingPeriodAccrualFactor()[0][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingDates()[posPeriod][j + posDate]), dev.getFixingTime()[0][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingPeriodEndDates()[posPeriod][j + posDate]), dev.getFixingPeriodEndTime()[0][j]);
assertEquals(TimeCalculator.getTimeBetween(refDate, def.getFixingPeriodStartDates()[posPeriod][j + posDate]), dev.getFixingPeriodStartTime()[0][j]);
}
}
}