CDS Schedules
AlessandroGnoatto opened this issue · 1 comments
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;
}
}
Hi @AlessandroGnoatto, are you still looking for help on this? I am interested to contribute to the repo.