Skip to content

CDS Schedules #72

Open
Open
@AlessandroGnoatto

Description

Hi,

I am trying to hack the Schedule generator in order to replicate the coupon of a Credit Default Swap according to the ISDA model. This is what I got so far. Any help in finding bugs/wrong reasonings etc is appreciated.

My source is the following document by ISDA: https://www.isda.org/a/vGiDE/amend-single-name-on-the-run-frequency-faq-revised-as-of-12-10.pdf

Here is my code:

package schedule;

import java.time.LocalDate;
import java.time.Month;
import java.util.StringTokenizer;

import net.finmath.time.Schedule;
import net.finmath.time.ScheduleGenerator;
import net.finmath.time.businessdaycalendar.BusinessdayCalendarExcludingTARGETHolidays;
import net.finmath.time.businessdaycalendar.BusinessdayCalendar.DateOffsetUnit;

public class ScheduleTest {

public static void main(String[] args) {

/*
 * Today is   
 */
LocalDate referenceDate = LocalDate.of(2015, 12, 20);

ScheduleTest test = new ScheduleTest();

String tenor = "5Y";

System.out.println(test.getPreviousRollDate(referenceDate).getDayOfWeek());
System.out.println(test.getFirstImmDateAfterRoll(referenceDate).getDayOfWeek());

System.out.println("Maturity Date of the CDS: this is an unadjusted IMM Date");
LocalDate unadjustedMaturityDate = test.getMaturityDate(referenceDate, tenor);
System.out.println(unadjustedMaturityDate);
System.out.println(unadjustedMaturityDate.getDayOfWeek());

BusinessdayCalendarExcludingTARGETHolidays cal = new BusinessdayCalendarExcludingTARGETHolidays();
if(cal.isBusinessday(unadjustedMaturityDate)==false) {
  System.out.println(unadjustedMaturityDate + " is not a good business day.");
}

Schedule schedule = ScheduleGenerator.createScheduleFromConventions(
    test.getPreviousRollDate(referenceDate)/* referenceDate */,
    test.getFirstImmDateAfterRoll(referenceDate)/* startDate */,
    test.getMaturityDate(referenceDate, tenor) /* maturity */,
    "quarterly" /* frequency */,
    "act/360" /* daycountConvention */,
    "first" /* shortPeriodConvention */,
    "following",
    new BusinessdayCalendarExcludingTARGETHolidays(),
    0,
    0);

System.out.println(schedule);

}

/**

  • CDS maturities are rolled twice a year, on March 20 and September 20
  • For a given trade date, return the previous roll date, this is either
  • March 20 or September 20.
  • @param tradeDate representing the date at which the trade is entered.
  • @return the previous roll date.
    */
    public LocalDate getPreviousRollDate(LocalDate tradeDate) {
    //Date is before march
    if(tradeDate.isBefore(LocalDate.of(tradeDate.getYear(), 3, 19))) {
    return LocalDate.of(tradeDate.getYear() -1, 9, 20);
    }else if(tradeDate.isAfter(LocalDate.of(tradeDate.getYear(), 3, 19)) && tradeDate.isBefore(LocalDate.of(tradeDate.getYear(), 9, 19)) ) {
    return LocalDate.of(tradeDate.getYear(), 3, 20);
    }else {
    return LocalDate.of(tradeDate.getYear(), 9, 20);
    }
    }

/**

  • Find the first IMM date after the previous roll date.
  • From this date we compute the maturity of the contract.
  • @param tradeDate representing the date at which the trade is entered.
  • @return the next IMM date after the previous roll date.
    */
    public LocalDate getFirstImmDateAfterRoll(LocalDate tradeDate) {
LocalDate rollDate = getPreviousRollDate(tradeDate);

//Roll month is march
if(rollDate.getMonth().equals(Month.MARCH)) {
  //The first Imm Date is 20 June of the same year
  return LocalDate.of(rollDate.getYear(), Month.JUNE, 20);
}else {
  //The roll month is September, hence the first IMM date is 20 December.
  return LocalDate.of(rollDate.getYear(), Month.DECEMBER, 20);
}

}

public LocalDate getMaturityDate(LocalDate tradeDate, String dateOffsetCode) {
dateOffsetCode = dateOffsetCode.trim();

StringTokenizer tokenizer = new StringTokenizer(dateOffsetCode);

LocalDate maturityDate = getFirstImmDateAfterRoll(tradeDate);

while(tokenizer.hasMoreTokens()) {
  String maturityCodeSingle = tokenizer.nextToken();
  String[] maturityCodeSingleParts = maturityCodeSingle.split("(?<=[0-9|\\.])(?=[A-Z|a-z])");
  
  if(maturityCodeSingleParts.length == 2) {
    int maturityValue = Integer.valueOf(maturityCodeSingleParts[0]);
    DateOffsetUnit dateOffsetUnit = DateOffsetUnit.getEnum(maturityCodeSingleParts[1]);

    switch(dateOffsetUnit) {
    case DAYS:
    {
      maturityDate = maturityDate.plusDays(maturityValue);
      break;
    }
    case WEEKS:
    {
      maturityDate = maturityDate.plusWeeks(maturityValue);
      break;
    }
    case MONTHS:
    {
      maturityDate = maturityDate.plusMonths(maturityValue);
      break;
    }
    case YEARS:
    {
      maturityDate = maturityDate.plusYears(maturityValue);
      break;
    }
    default:
      throw new IllegalArgumentException("Cannot handle dateOffsetCode '" + dateOffsetCode + "'.");
    }
  }
  else {
    throw new IllegalArgumentException("Cannot handle dateOffsetCode '" + dateOffsetCode + "'.");
  }
}
return maturityDate;

}

}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions