/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.convention;
import static org.threeten.bp.temporal.TemporalAdjusters.lastDayOfMonth;
import org.apache.commons.lang.Validate;
import org.threeten.bp.LocalDate;
/**
* Utility to calculate the stub type.
*/
public final class StubCalculator {
/**
* Restricted constructor.
*/
private StubCalculator() {
}
//-------------------------------------------------------------------------
/**
* Calculates the start stub type from a schedule and number of payments per year.
* <p>
* The {@code DateProvider[]} argument allows callers to pass in arrays of any class
* that implements {@code DateProvider}, such as {@code LocalDate[]}.
*
* @param schedule the schedule, at least size 2, not null
* @param paymentsPerYear the number of payments per year, one, two, three, four, six or twelve
* @return the stub type, not null
*/
public static StubType getStartStubType(final LocalDate[] schedule, final int paymentsPerYear) {
return getStartStubType(schedule, paymentsPerYear, false);
}
/**
* Calculates the start stub type from a schedule, number of payments per year and the end of month flag.
* <p>
* The {@code DateProvider[]} argument allows callers to pass in arrays of any class
* that implements {@code DateProvider}, such as {@code LocalDate[]}.
*
* @param schedule the schedule, at least size 2, not null
* @param paymentsPerYear the number of payments per year, one, two, three, four, six or twelve
* @param isEndOfMonthConvention whether to use end of month rules
* @return the stub type, not null
*/
public static StubType getStartStubType(final LocalDate[] schedule, final double paymentsPerYear, final boolean isEndOfMonthConvention) {
Validate.notNull(schedule, "schedule");
Validate.noNullElements(schedule, "schedule");
Validate.isTrue(paymentsPerYear > 0);
Validate.isTrue(12 % paymentsPerYear == 0);
final int months = (int) (12 / paymentsPerYear);
final LocalDate first = schedule[0];
final LocalDate second = schedule[1];
LocalDate date;
if (isEndOfMonthConvention && second.equals(second.with(lastDayOfMonth()))) {
date = second.minusMonths(months);
date = date.with(lastDayOfMonth());
} else {
date = second.minusMonths(months);
}
if (date.equals(first)) {
return StubType.NONE;
}
if (date.isBefore(first)) {
return StubType.SHORT_START;
}
return StubType.LONG_START;
}
//-------------------------------------------------------------------------
/**
* Calculates the end stub type from a schedule and number of payments per year.
* <p>
* The {@code DateProvider[]} argument allows callers to pass in arrays of any class
* that implements {@code DateProvider}, such as {@code LocalDate[]}.
*
* @param schedule the schedule, at least size 2, not null
* @param paymentsPerYear the number of payments per year, one, two, three, four, six or twelve
* @return the stub type, not null
*/
public static StubType getEndStubType(final LocalDate[] schedule, final int paymentsPerYear) {
return getEndStubType(schedule, paymentsPerYear, false);
}
/**
* Calculates the end stub type from a schedule, number of payments per year and the end of month flag.
* <p>
* The {@code DateProvider[]} argument allows callers to pass in arrays of any class
* that implements {@code DateProvider}, such as {@code LocalDate[]}.
*
* @param schedule the schedule, at least size 2, not null
* @param paymentsPerYear the number of payments per year, one, two, three, four, six or twelve
* @param isEndOfMonthConvention whether to use end of month rules
* @return the stub type, not null
*/
public static StubType getEndStubType(final LocalDate[] schedule, final double paymentsPerYear, final boolean isEndOfMonthConvention) {
Validate.notNull(schedule, "schedule");
Validate.noNullElements(schedule, "schedule");
Validate.isTrue(paymentsPerYear > 0);
Validate.isTrue(12 % paymentsPerYear == 0);
final int months = (int) (12 / paymentsPerYear);
final int n = schedule.length;
final LocalDate first = schedule[n - 2];
final LocalDate second = schedule[n - 1];
LocalDate date;
if (isEndOfMonthConvention && first.equals(first.with(lastDayOfMonth()))) {
date = first.plusMonths(months);
date = date.with(lastDayOfMonth());
} else {
date = first.plusMonths(months);
}
if (date.equals(second)) {
return StubType.NONE;
}
if (date.isAfter(second)) {
return StubType.SHORT_END;
}
return StubType.LONG_END;
}
}