com.opengamma.analytics.financial.credit.schedulegeneration.isda.ISDAPremiumLegScheduleGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.credit.schedulegeneration.isda.ISDAPremiumLegScheduleGenerator.java

Source

/**
 * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.analytics.financial.credit.schedulegeneration.isda;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.NotImplementedException;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.analytics.financial.credit.StubType;
import com.opengamma.analytics.financial.credit.creditdefaultswap.definition.vanilla.CreditDefaultSwapDefinition;
import com.opengamma.analytics.financial.credit.schedulegeneration.IMMDates;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.util.ArgumentChecker;

/**
 *  Class containing methods to generate the premium leg cash-flow schedule for a CDS (following the market conventions for CDS)
 */
public class ISDAPremiumLegScheduleGenerator {
    // TODO : Add a check if the calendar is 'null' to signify no adjustment of business dates? Overloaded method
    // TODO : Fix the code for the back stubs (is there a better way of handling this than just duplicating code?) - front stubs seem to work okay
    // TODO : Add the code for the first coupons
    // TODO : Should convertDatesToDoubles be put somewhere else? To use it, need to create a GenerateCreditDefaultSwapPremiumLegSchedule object which is a bit wasteful
    // TODO : Look at TemporalAdjuster class for IMM date handling
    // TODO : FrontLong stubs - e.g. startDate = 20/12/2007, effDate = 21/12/2007; first coupon at 20/6/2008. ISDA model first coupon at 20/3/2008 (seems to use start date not eff date)
    // TODO : Remove one of the overloaded convertdatesToDoubles methods
    // TODO : Rewrite and integrate constructISDACompliantCashflowSchedule into the code better
    // TODO : Need to hook in the flags for adjusting various dates again
    // TODO : Add WORKDAY equivalent function

    public ZonedDateTime[] constructISDACompliantCreditDefaultSwapPremiumLegSchedule(
            final CreditDefaultSwapDefinition cds) {
        ArgumentChecker.notNull(cds, "cds");
        final ZonedDateTime startDate = cds.getStartDate();
        final ZonedDateTime endDate = cds.getMaturityDate();
        final boolean protectStart = cds.getProtectionStart();
        final StubType stubType = cds.getStubType();
        if (protectStart && endDate.equals(startDate)) {
            //note no adjustment of either date
            return new ZonedDateTime[] { startDate, startDate.plusDays(1) };
        }
        // Is the stub at the front end of the payment schedule
        if (stubType == StubType.FRONTSHORT || stubType == StubType.FRONTLONG) {
            final List<ZonedDateTime> reversedCashflowSchedule = new ArrayList<>();
            ZonedDateTime date = endDate;
            while (date.isAfter(startDate)) {
                reversedCashflowSchedule.add(date);
                date = date.minus(cds.getCouponFrequency().getPeriod());
            }
            // TODO : Check the FRONTSHORT/FRONTLONG logic here
            if (reversedCashflowSchedule.size() == 1 || date.isEqual(startDate)
                    || stubType == StubType.FRONTSHORT) {
                reversedCashflowSchedule.add(startDate);
            } else {
                reversedCashflowSchedule.set(reversedCashflowSchedule.size() - 1, startDate);
            }
            //TODO this logic assumes list was populated with decreasing dates
            final int nDatesInSchedule = reversedCashflowSchedule.size();
            final ZonedDateTime[] cashflowSchedule = new ZonedDateTime[nDatesInSchedule];
            //TODO not handling protectStart
            // Remember if protectStart = TRUE then there is an extra day of accrued that is not captured here
            cashflowSchedule[nDatesInSchedule - 1] = reversedCashflowSchedule.get(0);
            final Calendar calendar = cds.getCalendar();
            final BusinessDayConvention bdc = cds.getBusinessDayAdjustmentConvention();
            for (int i = nDatesInSchedule - 2; i > 0; i--) {
                cashflowSchedule[nDatesInSchedule - i - 1] = bdc.adjustDate(calendar,
                        reversedCashflowSchedule.get(i));
            }
            cashflowSchedule[0] = reversedCashflowSchedule.get(nDatesInSchedule - 1);
            return cashflowSchedule;
        }
        // TODO : Add the code for the back stub
        // Is the stub at the back end of the payment schedule
        throw new NotImplementedException();
    }

    //Public method to extract just the adjusted maturity date for a CDS according to the contract specifications (don't have to go through the whole schedule gen process)
    public ZonedDateTime getAdjustedMaturityDate(final CreditDefaultSwapDefinition cds) {
        ArgumentChecker.notNull(cds, "CDS");
        // Set the adjusted maturity date to be equal to the (user input) maturity date
        ZonedDateTime adjustedMaturityDate = cds.getMaturityDate();
        // If specified by the user adjust the maturity date to fall on the next IMM date
        if (cds.getIMMAdjustMaturityDate()) {
            adjustedMaturityDate = immAdjustDate(cds.getMaturityDate());
        }
        return adjustedMaturityDate;
    }

    // Method to adjust the specified maturity date to the next IMM date
    private ZonedDateTime immAdjustDate(final ZonedDateTime date) {
        // Start at the current maturityDate
        ZonedDateTime immAdjustedDate = date;
        // Get the year of the contract maturity
        final int year = date.getYear();
        // Construct an IMM object with the IMM dates for 'year'
        final IMMDates immDates = new IMMDates(year);
        // First of all check that the maturity date isn't one of the IMM dates for 'year'
        if (date.equals(immDates.getImmDateMarch())) {
            immAdjustedDate = immDates.getImmDateMarch();
            return immAdjustedDate;
        }
        if (date.equals(immDates.getImmDateJune())) {
            immAdjustedDate = immDates.getImmDateJune();
            return immAdjustedDate;
        }
        if (date.equals(immDates.getImmDateSeptember())) {
            immAdjustedDate = immDates.getImmDateSeptember();
            return immAdjustedDate;
        }
        if (date.equals(immDates.getImmDateDecember())) {
            immAdjustedDate = immDates.getImmDateDecember();
            return immAdjustedDate;
        }
        // Determine where the maturity date is in relation to the IMM dates
        // Is the maturity date between 20/12 of the previous year and 20/3 of the current year
        if (date.isAfter(immDates.getImmDatePreviousDecember()) && date.isBefore(immDates.getImmDateMarch())) {
            immAdjustedDate = immDates.getImmDateMarch();
            return immAdjustedDate;
        }

        // Is the maturity date between 20/3 of the current year and 20/6 of the current year
        if (date.isAfter(immDates.getImmDateMarch()) && date.isBefore(immDates.getImmDateJune())) {
            immAdjustedDate = immDates.getImmDateJune();
            return immAdjustedDate;
        }

        // Is the maturity date between 20/6 of the current year and 20/9 of the current year
        if (date.isAfter(immDates.getImmDateJune()) && date.isBefore(immDates.getImmDateSeptember())) {
            immAdjustedDate = immDates.getImmDateSeptember();
            return immAdjustedDate;
        }

        // Is the maturity date between 20/9 of the current year and 20/12 of the current year
        if (date.isAfter(immDates.getImmDateSeptember()) && date.isBefore(immDates.getImmDateDecember())) {
            immAdjustedDate = immDates.getImmDateDecember();
            return immAdjustedDate;
        }

        // Is the maturity date between 20/12 of the current year and 20/3 of the next year
        if (date.isAfter(immDates.getImmDateDecember()) && date.isBefore(immDates.getImmDateNextMarch())) {
            immAdjustedDate = immDates.getImmDateNextMarch();
            return immAdjustedDate;
        }
        return immAdjustedDate;
    }

}