net.finmath.time.daycount.DayCountConvention_ACT_ACT_YEARFRAC Maven / Gradle / Ivy
/*
* (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
*
* Created on 07.09.2013
*/
package net.finmath.time.daycount;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.Month;
/**
* Implementation of ACT/ACT as in Excel (2013).
*
* Calculates the day count by calculating the actual number of days between startDate and endDate.
*
* A fractional day is rounded to the approximately nearest day.
*
* The day count fraction is calculated using ACT_ACT_YEARFRAC convention, that is, it is calculates the daycount fraction
* corresponding to the Excel (2013) function YEARFRAC(startDate, endDate, 1). The day count fraction is calculated by dividing
* the actual number of days between start and end date by a denominator, where the denominator is determines as follows:
*
* - If the interval from start to end spans more than one year fraction, denominator is the average number of days per year
* - If the interval from start to end spans less or equal one year and if start and end fall in a leap year, denominator is 366.0
* - If the interval from start to end spans less or equal one year and if either falls in a leap year and if February 29th of that leap year lies in between start and end (or is equal to start or end), denominator is 366.0
* - If the interval from start to end spans less or equal one year and neither of the above applied denominator is 365.0
*
*
*
*
* This method is not identical to ACT/ACT ISDA. For ACT/ACT ISDA use {@link net.finmath.time.daycount.DayCountConvention_ACT_ACT_ISDA}.
*
*
*
*
* In addition the method has the defect, that it is not additive (if you consider small intervals). For example
* YEARFRAC(30.12.2011, 04.01.2012, 1) is not equal to YEARFRAC(30.12.2011, 01.01.2012, 1) + YEARFRAC(01.01.2012, 04.01.2012, 1).
*
*
* @author Christian Fries
* @version 1.0
*/
public class DayCountConvention_ACT_ACT_YEARFRAC extends DayCountConvention_ACT implements Serializable {
private static final long serialVersionUID = -970929056011501752L;
/**
* Create an ACT/ACT YEARFRAC daycount convention.
*/
public DayCountConvention_ACT_ACT_YEARFRAC() {
}
/* (non-Javadoc)
* @see net.finmath.time.daycount.DayCountConvention#getDaycountFraction(java.time.LocalDate, java.time.LocalDate)
*/
@Override
public double getDaycountFraction(final LocalDate startDate, final LocalDate endDate) {
if(startDate.isAfter(endDate)) {
return -getDaycountFraction(endDate,startDate);
}
/*
* Determine the denominator of act/act.
*/
double denominator;
final LocalDate startDatePlusOneYear = startDate.plusYears(1);
if(endDate.isAfter(startDatePlusOneYear)) {
/*
* The following method applies, if the interval spans more than one year:
* fraction = actual number of days / average number of days per year.
*/
final LocalDate startDateYearStart = startDate.withDayOfYear(1);
final LocalDate endDateYearEnd = endDate.withDayOfYear(endDate.lengthOfYear()).plusDays(1);
final double spannedYears = endDate.getYear() - startDate.getYear() + 1;
denominator = getDaycount(startDateYearStart, endDateYearEnd) / spannedYears;
}
else {
final boolean isStartLeapYear = startDate.isLeapYear();
final boolean isEndLeapYear = endDate.isLeapYear();
/*
* If the start and end span less or equal one year:
* If start and end fall in a leap year, use ACT/366.
*/
if(isStartLeapYear && isEndLeapYear)
{
denominator = 366.0;
}
else
/*
* If the start and end span less or equal one year:
* If either falls in a leap year and Feb 29th of that leap year lies in between start and end (or is equal to start or end), use ACT/366.
*/
if(isStartLeapYear || isEndLeapYear)
{
// Get February 29th of the respective leap year
final LocalDate leapYearsFeb29th = isStartLeapYear ?
LocalDate.of(startDate.getYear(), Month.FEBRUARY, 29) :
LocalDate.of(endDate.getYear(), Month.FEBRUARY, 29);
// Check position of February 29th
if(startDate.compareTo(leapYearsFeb29th) <= 0 && endDate.compareTo(leapYearsFeb29th) >= 0) {
denominator = 366.0;
}
else {
denominator = 365.0;
}
}
else {
/*
* If the start and end span less or equal one year:
* If none of the above applies, use denominator = ACT/365.
*/
denominator = 365.0;
}
}
final double daycountFraction = getDaycount(startDate, endDate) / denominator;
return daycountFraction;
}
@Override
public String toString() {
return "DayCountConvention_ACT_ACT_YEARFRAC";
}
}