/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.basics.date; import java.time.LocalDate; import com.opengamma.strata.basics.date.DayCount.ScheduleInfo; import com.opengamma.strata.collect.named.ExtendedEnum; /** * Constants and implementations for standard day count conventions. * <p> * The purpose of each convention is to define how to convert dates into numeric year fractions. * The is of use when calculating accrued interest over time. */ public final class DayCounts { // constants are indirected via ENUM_LOOKUP to allow them to be replaced by config /** * The extended enum lookup from name to instance. */ static final ExtendedEnum<DayCount> ENUM_LOOKUP = ExtendedEnum.of(DayCount.class); /** * A simple schedule information object. * <p> * This returns true for end of month and an exception for all other methods. */ static final ScheduleInfo SIMPLE_SCHEDULE_INFO = new ScheduleInfo() {}; /** * The '1/1' day count, which always returns a day count of 1. * <p> * The result is always one. * <p> * Also known as 'One/One'. * Defined by the 2006 ISDA definitions 4.16a. */ public static final DayCount ONE_ONE = DayCount.of(StandardDayCounts.ONE_ONE.getName()); /** * The 'Act/Act ISDA' day count, which divides the actual number of days in a * leap year by 366 and the actual number of days in a standard year by 365. * <p> * The result is calculated in two parts. * The actual number of days in the requested period that fall in a leap year is divided by 366. * The actual number of days in the requested period that fall in a standard year is divided by 365. * The result is the sum of the two. * The first day in the period is included, the last day is excluded. * <p> * Also known as 'Actual/Actual'. * Defined by the 2006 ISDA definitions 4.16b. */ public static final DayCount ACT_ACT_ISDA = DayCount.of(StandardDayCounts.ACT_ACT_ISDA.getName()); /** * The 'Act/Act ICMA' day count, which divides the actual number of days by * the actual number of days in the coupon period multiplied by the frequency. * <p> * The result is calculated as follows. * <p> * First, the underlying schedule period is obtained treating the first date as the start of the schedule period. * <p> * Second, if the period is a stub, then nominal regular periods are created matching the * schedule frequency, working forwards or backwards from the known regular schedule date. * An end-of-month flag is used to handle month-ends. * If the period is not a stub then the schedule period is treated as a nominal period below. * <p> * Third, the result is calculated as the sum of a calculation for each nominal period. * The actual days between the first and second date are allocated to the matching nominal period. * Each calculation is a division. The numerator is the actual number of days in * the nominal period, which could be zero in the case of a long stub. * The denominator is the length of the nominal period multiplied by the frequency. * The first day in the period is included, the last day is excluded. * <p> * Due to the way that the nominal periods are determined ignoring business day adjustments, * this day count is recommended for use by bonds, not swaps. * <p> * The method {@link DayCount#yearFraction(LocalDate, LocalDate)} will throw an * exception because schedule information is required for this day count. * <p> * Also known as 'Actual/Actual ICMA' or 'Actual/Actual (Bond)'. * Defined by the 2006 ISDA definitions 4.16c and ICMA rule 251.1(iii) and 251.3 * as later clarified by ISDA 'EMU and market conventions' http://www.isda.org/c_and_a/pdf/mktc1198.pdf. */ public static final DayCount ACT_ACT_ICMA = DayCount.of(StandardDayCounts.ACT_ACT_ICMA.getName()); /** * The 'Act/Act AFB' day count, which divides the actual number of days by 366 * if a leap day is contained, or by 365 if not, with additional rules for periods over one year. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is determined by examining the period end date (the date of the next coupon). * The denominator is 366 if the schedule period contains February 29th, if not it is 365. * The first day in the schedule period is included, the last day is excluded. * <p> * Also known as 'Actual/Actual AFB' or 'Actual/Actual (Euro)'. * Defined by the Association Francaise des Banques in September 1994 as 'Base Exact/Exact' * in 'Definitions Communes plusieurs Additifs Techniques'. * <p> * OpenGamma implements this day count based on the original French documentation * without the ISDA clarification. The ISDA document translates "Periode d'Application" * to "Calculation Period" and then assigns the regular ISDA meaning of "Calculation Period". * Examination of the original French indicates that "Periode d'Application" simply means * the period that the day count is applied to, not a regular periodic schedule. * <p> * In addition, the ISDA document adds a roll back rule stating that if the period ends * on the 28th February it should be rolled back to the 28th, or to the 29th in a leap year. * Unfortunately, this rule has a strange effect when implemented, with one day receiving * two days interest and the next receiving no interest: * <pre> * From 2004-02-28 to 2008-02-27, ISDA rule = 3 + 365 / 366 * From 2004-02-28 to 2008-02-28, ISDA rule = 4 + 1 / 366 * From 2004-02-28 to 2008-02-29, ISDA rule = 4 + 1 / 366 * </pre> * (Other strange examples occur from 2004-02-29 and 2003-03-01). * <p> * OpenGamma interprets the roll back rule to be that if the period ends on the <i>29th</i> February * it should be rolled back to the 28th, or to the 29th in a leap year. * This change (which can be argued is closer to the original French than the ISDA "clarification") * results in the following: * <pre> * From 2004-02-28 to 2008-02-27, OpenGamma interpretation = 3 + 365 / 366 * From 2004-02-28 to 2008-02-28, OpenGamma interpretation = 4 * From 2004-02-28 to 2008-02-29, OpenGamma interpretation = 4 + 1 / 366 * </pre> * <p> * Original French (from 1999 as 1994 version cannot be found): * http://www.banque-france.fr/fileadmin/user_upload/banque_de_france/archipel/publications/bdf_bof/bdf_bof_1999/bdf_bof_01.pdf * ISDA "clarification": * http://www.isda.org/c_and_a/pdf/ACT-ACT-ISDA-1999.pdf */ public static final DayCount ACT_ACT_AFB = DayCount.of(StandardDayCounts.ACT_ACT_AFB.getName()); /** * The 'Act/Act Year' day count, which divides the actual number of days * by the number of days in the year from the start date. * <p> * The result is calculated as follows in two parts - a number of whole years and the remaining part. * <p> * If the period is over one year, a number of years is added to the start date to reduce * the remaining period to less than a year. If the start date is February 29th, then each * time a year is added the last valid day in February is chosen. * <p> * The remaining period is then processed by a simple division. * The numerator is the actual number of days in the remaining period. * The denominator is the actual number of days in the year from the adjusted start date. * The first day in the period is included, the last day is excluded. * The result is the number of whole years plus the result of the division. * <p> * For example, the consider the period 2016-01-10 to 2016-01-20. * The numerator is 10, as there are 10 days between the dates. * The denominator is 366, as there are 366 days between 2016-01-10 and 2017-01-10. * <p> * This is a variation of the 'Act/Act ICMA' day count. * If 'Act/Act ICMA is called with a frequency of yearly, the next coupon date equal to the * start date plus one year and the end-of-month flag set to false, then the result will * be the same for periods less than a year. */ public static final DayCount ACT_ACT_YEAR = DayCount.of(StandardDayCounts.ACT_ACT_YEAR.getName()); /** * The 'Act/365 Actual' day count, which divides the actual number of days by 366 * if a leap day is contained, or by 365 if not. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is 366 if the period contains February 29th, if not it is 365. * The first day in the period is excluded, the last day is included. * <p> * Also known as 'Act/365A'. */ public static final DayCount ACT_365_ACTUAL = DayCount.of(StandardDayCounts.ACT_365_ACTUAL.getName()); /** * The 'Act/365L' day count, which divides the actual number of days by 365 or 366. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is determined by examining the frequency and the period end date (the date of the next coupon). * If the frequency is annual then the denominator is 366 if the period contains February 29th, * if not it is 365. The first day in the period is excluded, the last day is included. * If the frequency is not annual, the denominator is 366 if the period end date * is in a leap year, if not it is 365. * <p> * The method {@link DayCount#yearFraction(LocalDate, LocalDate)} will throw an * exception because schedule information is required for this day count. * <p> * Also known as 'Act/365 Leap year'. * Defined by the 2006 ISDA definitions 4.16i and ICMA rule 251.1(i) part 2 * as later clarified by ICMA and Swiss Exchange. */ public static final DayCount ACT_365L = DayCount.of(StandardDayCounts.ACT_365L.getName()); /** * The 'Act/360' day count, which divides the actual number of days by 360. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is always 360. * <p> * Also known as 'Actual/360' or 'French'. * Defined by the 2006 ISDA definitions 4.16e and ICMA rule 251.1(i) part 1. */ public static final DayCount ACT_360 = DayCount.of(StandardDayCounts.ACT_360.getName()); /** * The 'Act/364' day count, which divides the actual number of days by 364. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is always 364. * <p> * Also known as 'Actual/364'. */ public static final DayCount ACT_364 = DayCount.of(StandardDayCounts.ACT_364.getName()); /** * The 'Act/365F' day count, which divides the actual number of days by 365 (fixed). * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is always 365. * <p> * Also known as 'Act/365', 'Actual/365 Fixed' or 'English'. * Defined by the 2006 ISDA definitions 4.16d. */ public static final DayCount ACT_365F = DayCount.of(StandardDayCounts.ACT_365F.getName()); /** * The 'Act/365.25' day count, which divides the actual number of days by 365.25. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period. * The denominator is always 365.25. */ public static final DayCount ACT_365_25 = DayCount.of(StandardDayCounts.ACT_365_25.getName()); /** * The 'NL/365' day count, which divides the actual number of days omitting leap days by 365. * <p> * The result is a simple division. * The numerator is the actual number of days in the requested period minus the number of occurrences of February 29. * The denominator is always 365. * The first day in the period is excluded, the last day is included. * <p> * Also known as 'Actual/365 No Leap'. */ public static final DayCount NL_365 = DayCount.of(StandardDayCounts.NL_365.getName()); /** * The '30/360 ISDA' day count, which treats input day-of-month 31 specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If the second day-of-month is 31 and the first day-of-month is 30 or 31, change the second day-of-month to 30. * If the first day-of-month is 31, change the first day-of-month to 30. * <p> * Also known as '30/360 U.S. Municipal' or '30/360 Bond Basis'. * Defined by the 2006 ISDA definitions 4.16f. */ public static final DayCount THIRTY_360_ISDA = DayCount.of(StandardDayCounts.THIRTY_360_ISDA.getName()); /** * The '30U/360' day count, which treats input day-of-month 31 and end of February specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If the schedule uses EOM convention and both dates are the last day of February, * change the second day-of-month to 30. * If the schedule uses EOM convention and the first date is the last day of February, * change the first day-of-month to 30. * If the second day-of-month is 31 and the first day-of-month is 30 or 31, change the second day-of-month to 30. * If the first day-of-month is 31, change the first day-of-month to 30. * <p> * This day count has different rules depending on whether the EOM rule applies or not. * The EOM rule is set in the {@link ScheduleInfo}. The default value for EOM is true, * as used by {@link DayCount#yearFraction(LocalDate, LocalDate)}. * <p> * There are two related day counts. * The '30U/360 EOM' rule is identical to this rule when the EOM convention applies. * The '30/360 ISDA' rule is identical to this rule when the EOM convention does not apply. * <p> * Also known as '30/360 US', '30US/360' or '30/360 SIA'. * <p> * History note. It appears that the US 30/360 day count originally started with just the two rules * of '30/360 ISDA'. At some later point, the last day of February EOM rules were added. */ public static final DayCount THIRTY_U_360 = DayCount.of(StandardDayCounts.THIRTY_U_360.getName()); /** * The '30U/360 EOM' day count, which treats input day-of-month 31 and end of February specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If both dates are the last day of February, change the second day-of-month to 30. * If the first date is the last day of February, change the first day-of-month to 30. * If the second day-of-month is 31 and the first day-of-month is 30 or 31, change the second day-of-month to 30. * If the first day-of-month is 31, change the first day-of-month to 30. * <p> * This day count is not dependent on the EOM flag in {@link ScheduleInfo}. * <p> * This is the same as '30U/360' when the EOM convention applies. * This day count would typically be used to be explicit about the EOM rule applying. * In most cases, '30U/360' should be used in preference to this day count. * <p> * The method {@link DayCount#yearFraction(LocalDate, LocalDate)} will assume * that the end-of-month rule applies. * * @see #THIRTY_U_360 */ public static final DayCount THIRTY_U_360_EOM = DayCount.of(StandardDayCounts.THIRTY_U_360_EOM.getName()); /** * The '30/360 PSA' day count, which treats input day-of-month 31 and end of February specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If the first date is the last day of February, change the first day-of-month to 30. * If the second day-of-month is 31 and the first day-of-month is 30 or 31, change the second day-of-month to 30. * If the first day-of-month is 31, change the first day-of-month to 30. * <p> * Also known as '30/360 PSA' (PSA is the Public Securites Association, BMA is the Bond Market Association). */ public static final DayCount THIRTY_360_PSA = DayCount.of(StandardDayCounts.THIRTY_360_PSA.getName()); /** * The '30E/360 ISDA' day count, which treats input day-of-month 31 and end of February specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If the first day-of-month is 31, change the first day-of-month to 30. * If the second day-of-month is 31, change the second day-of-month to 30. * If the first date is the last day of February, change the first day-of-month to 30. * If the second date is the last day of February and it is not the maturity date, * change the second day-of-month to 30. * <p> * The method {@link DayCount#yearFraction(LocalDate, LocalDate)} will throw an * exception because schedule information is required for this day count. * <p> * Also known as '30E/360 German' or 'German'. * Defined by the 2006 ISDA definitions 4.16h. */ public static final DayCount THIRTY_E_360_ISDA = DayCount.of(StandardDayCounts.THIRTY_E_360_ISDA.getName()); /** * The '30E/360' day count, which treats input day-of-month 31 specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay is calculated once day-of-month adjustments have occurred. * If the first day-of-month is 31, it is changed to 30. * If the second day-of-month is 31, it is changed to 30. * <p> * Also known as '30/360 ISMA', '30/360 European', '30S/360 Special German' or 'Eurobond'. * Defined by the 2006 ISDA definitions 4.16g and ICMA rule 251.1(ii) and 252.2. */ public static final DayCount THIRTY_E_360 = DayCount.of(StandardDayCounts.THIRTY_E_360.getName()); /** * The '30E+/360' day count, which treats input day-of-month 31 specially. * <p> * The result is calculated as {@code (360 * deltaYear + 30 * deltaMonth + deltaDay) / 360}. * The deltaDay and deltaMonth are calculated once adjustments have occurred. * If the first day-of-month is 31, it is changed to 30. * If the second day-of-month is 31, it is changed to 1 and the second month is incremented. */ public static final DayCount THIRTY_EPLUS_360 = DayCount.of(StandardDayCounts.THIRTY_EPLUS_360.getName()); //------------------------------------------------------------------------- /** * Restricted constructor. */ private DayCounts() { } }