/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics.model.irfutureoption;
import org.apache.commons.lang.Validate;
import org.threeten.bp.DayOfWeek;
import org.threeten.bp.LocalDate;
import org.threeten.bp.temporal.TemporalAdjuster;
import org.threeten.bp.temporal.TemporalAdjusters;
import com.opengamma.analytics.util.time.TimeCalculator;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.calendar.MondayToFridayCalendar;
import com.opengamma.financial.convention.expirycalc.IMMFutureAndFutureOptionMonthlyExpiryCalculator;
import com.opengamma.financial.convention.expirycalc.IMMFutureAndFutureOptionQuarterlyExpiryCalculator;
/**
* Utility Class for computing Expiries of IR Future Options from ordinals (i.e. nth future after valuationDate)
*/
public class FutureOptionUtils {
private static final TemporalAdjuster THIRD_WED_ADJUSTER = TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.WEDNESDAY);
/** Calendar containing weekdays */
public static final Calendar WEEKDAYS = new MondayToFridayCalendar("MTWThF");
/**
* Compute time between now and future or future option's settlement date,
* typically two business days before the third Wednesday of the expiry month.
* @param n nth Future after now
* @param today Valuation Date
* @param holidayCalendar The holiday calendar
* @return OG-Analytic Time in years between now and the future's settlement date
*/
public static Double getIRFutureOptionTtm(final int n, final LocalDate today, final Calendar holidayCalendar) {
final LocalDate expiry = getIRFutureOptionWithSerialOptionsExpiry(n, today, holidayCalendar);
return TimeCalculator.getTimeBetween(today, expiry);
}
/**
* Compute time between now and future or future option's settlement date,
* typically two business days before the third Wednesday of the expiry month.
* @param n nth Future after now
* @param today Valuation Date
* @param holidayCalendar The holiday calendar
* @return OG-Analytic Time in years between now and the future's settlement date
*/
public static Double getIRFutureTtm(final int n, final LocalDate today, final Calendar holidayCalendar) {
final LocalDate expiry = getIRFutureQuarterlyExpiryDate(n, today, holidayCalendar);
return TimeCalculator.getTimeBetween(today, expiry);
}
public static LocalDate getIRFutureOptionWithSerialOptionsExpiry(final int nthFuture, final LocalDate valDate, final Calendar holidayCalendar) {
Validate.isTrue(nthFuture > 0, "nthFuture must be greater than 0.");
if (nthFuture <= 6) { // We look for expiries in the first 6 serial months after curveDate
return getIRFutureMonthlyExpiryDate(nthFuture, valDate, holidayCalendar);
} // And for Quarterly expiries thereafter
final int nthExpiryAfterSixMonths = nthFuture - 6;
final LocalDate sixMonthsForward = valDate.plusMonths(6);
return getIRFutureQuarterlyExpiryDate(nthExpiryAfterSixMonths, sixMonthsForward, holidayCalendar);
}
public static LocalDate getApproximateIRFutureOptionWithSerialOptionsExpiry(final int nthFuture, final LocalDate valDate) {
Validate.isTrue(nthFuture > 0, "nthFuture must be greater than 0.");
if (nthFuture <= 6) { // We look for expiries in the first 6 serial months after curveDate
final LocalDate expiry = getIRFutureMonthlyExpiry(nthFuture, valDate);
final LocalDate previousMonday = expiry.minusDays(2);
return previousMonday;
} // And for Quarterly expiries thereafter
final int nthExpiryAfterSixMonths = nthFuture - 6;
final LocalDate sixMonthsForward = valDate.plusMonths(6);
return getApproximateIRFutureQuarterlyExpiry(nthExpiryAfterSixMonths, sixMonthsForward);
}
public static LocalDate getIRFutureMonthlyExpiry(final int nthMonth, final LocalDate valDate) {
Validate.isTrue(nthMonth > 0, "nthFuture must be greater than 0.");
LocalDate expiry = valDate.with(THIRD_WED_ADJUSTER);
if (!expiry.isAfter(valDate)) { // If it is not strictly after valuationDate...
expiry = (valDate.plusMonths(1)).with(THIRD_WED_ADJUSTER); // nextExpiry is third Wednesday of next month
}
if (nthMonth > 1) {
expiry = (expiry.plusMonths(nthMonth - 1)).with(THIRD_WED_ADJUSTER);
}
return expiry;
}
public static LocalDate getIRFutureQuarterlyExpiryDate(final int nthFuture, final LocalDate valDate, final Calendar holidayCalendar) {
return IMMFutureAndFutureOptionQuarterlyExpiryCalculator.getInstance().getExpiryDate(nthFuture, valDate, holidayCalendar);
}
public static LocalDate getApproximateIRFutureQuarterlyExpiry(final int nthFuture, final LocalDate valDate) {
return IMMFutureAndFutureOptionQuarterlyExpiryCalculator.getInstance().getExpiryDate(nthFuture, valDate, WEEKDAYS);
}
public static LocalDate getIRFutureMonthlyExpiryDate(final int nthFuture, final LocalDate valDate, final Calendar holidayCalendar) {
return IMMFutureAndFutureOptionMonthlyExpiryCalculator.getInstance().getExpiryDate(nthFuture, valDate, holidayCalendar);
}
public static LocalDate getApproximateIRFutureMonth(final int nthFuture, final LocalDate valDate) {
return IMMFutureAndFutureOptionMonthlyExpiryCalculator.getInstance().getExpiryDate(nthFuture, valDate, WEEKDAYS);
}
}