daycount

Source   Edit  

The daycount module allows you to calculate the duration between two dates according to the calculation convention of your choice. The user is encouraged to see the yearFraction proc for more details.

Types

bdDayCountConvention = enum
  dccThirtyA360 = "30A/360", ## Also known as "30/360 Bond basis" or "30/360 ISDA"
  dccThirtyU360 = "30U/360", ## Also known as "30US/360", "30/360 US" or "30/360 SIA" 
  dccThirtyE360 = "30E/360", ## Also known as "30/360 European", "Eurobond basis", 
                              ## "Special German", "30/360 ISMA" or "30/360 ICMA"
  dccThirtyEPlus360 = "30E+/360", ## No other name known
  dccThirtyG360 = "30/360 German", ## Also known as "30E/360 ISDA"
  dccActual360 = "Actual/360", ## Also known as "French" 
  dccActual365F = "Actual/365 Fixed", ## Also known as "English"
  dccActual366 = "Actual/366", ## No other name known 
  dccActual364 = "Actual/364", ## No other name known 
  dccActual36525 = "Actual/365.25", ## No other name known 
  dccActual365L = "Actual/365L", ## Also known as "ISMA-Year"
  dccActual365A = "Actual/365A", ## No other name known 
  dccNL365 = "NL/365",      ## Also known as "Actual/365 No leap year", "NL365"
  dccActualActual = "Actual/Actual", ## Also known as "Actual/Actual ISDA"	
  dccActualActualAFB = "Actual/Actual AFB", ## No other name known
  dccBusinessDays252 = "BusinessDays/252", ## Also known as "BUS/252" or "BD/252" 
  dccOneOne = "1/1"          ## Also known as "One/One"
Description of each element of the bdDayCountConvention enumeration. Source   Edit  

Procs

proc yearFraction(startDate, endDate: DateTime; dcc: bdDayCountConvention;
                  calendar: bdCalendar = nil;
                  dateInterval: BoundedRealInterval = BoundedRightOpen): float64 {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}

Calculates the duration between the starting date <startDate> and the end date <endDate>, according to the day count convention <dcc>.

Notes:

  • If endDate < startDate the result is equal to -yearFraction(startDate = endDate, endDate = startDate, dcc, calendar, dateInterval).
  • calendar and dateInterval parameters are only use when dcc == dccBusinessDays252.
  • The dateInterval parameter allows you to include/exclude <fromDate> and <toDate> for business day counting.

Main references:

Example:

# Time interval 1:  from  31 January 2008  to  28 February 2008  (leap year)
# --------------------------------------------------------------------------
let startDate1 = dateTime(2008, mJan, 31)
let endDate1 = dateTime(2008, mFeb, 28)

doAssert: yearFraction(startDate1, endDate1, dccActual360) == 28.0/360.0
doAssert: yearFraction(startDate1, endDate1, dccThirtyA360) == 28.0/360.0
doAssert: yearFraction(startDate1, endDate1, dccThirtyU360) == 28.0/360.0
doAssert: yearFraction(startDate1, endDate1, dccThirtyE360) == 28.0/360.0
doAssert: yearFraction(startDate1, endDate1, dccThirtyEPlus360) == 28.0/360.0
doAssert: yearFraction(startDate1, endDate1, dccThirtyG360) == 28.0/360.0

# Day count is 28.0 for all considered day count conventions.

# Time interval 2:  from  28 February 2007  to  31 March 2007  (non-leap year)
# ----------------------------------------------------------------------------
let startDate2 = dateTime(2007, mFeb, 28)
let endDate2 = dateTime(2007, mMar, 31)

doAssert: yearFraction(startDate2, endDate2, dccActual360) == 31.0/360.0
doAssert: yearFraction(startDate2, endDate2, dccThirtyA360) == 33.0/360.0
doAssert: yearFraction(startDate2, endDate2, dccThirtyU360) == 30.0/360.0
doAssert: yearFraction(startDate2, endDate2, dccThirtyE360) == 32.0/360.0
doAssert: yearFraction(startDate2, endDate2, dccThirtyEPlus360) == 33.0/360.0
doAssert: yearFraction(startDate2, endDate2, dccThirtyG360) == 30.0/360.0

# - Depending on the considered day count convention, 
#   the day count varies from 30.0 to 33.0 (4 values).
#
# - The actual number of days is 31.0. But depending on 
#   how the convention manages the end of the month, and 
#   the end of the month of February, we can also obtain 
#   30.0, 32.0 or 33.0 days.


# The following 4 numerical examples are taken from
# http://deltaquants.com/day-count-conventions

# Time interval 3:  from  28 December 2007  to  28 February 2008
# --------------------------------------------------------------
let startDate3 = dateTime(2007, mDec, 28)
let endDate3 = dateTime(2008, mFeb, 28)

doAssert: yearFraction(startDate3, endDate3, dccThirtyA360) == 60.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccThirtyU360) == 60.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccThirtyE360) == 60.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccThirtyEPlus360) == 60.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccThirtyG360) == 60.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccActual360) == 62.0/360.0
doAssert: yearFraction(startDate3, endDate3, dccActual365F) == 62.0/365.0
doAssert: yearFraction(startDate3, endDate3, dccActual365L) == 62.0/366.0
doAssert: yearFraction(startDate3, endDate3, dccActual365A) == 62.0/365.0
doAssert: yearFraction(startDate3, endDate3, dccNL365) == 62.0/365.0
doAssert: yearFraction(startDate3, endDate3, dccActualActual) == 4.0/365.0+58.0/366.0

# Time interval 4:  from  28 December 2007  to  29 February 2008
# --------------------------------------------------------------
let startDate4 = dateTime(2007, mDec, 28)
let endDate4 = dateTime(2008, mFeb, 29)

doAssert: yearFraction(startDate4, endDate4, dccThirtyA360) == 61.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccThirtyU360) == 61.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccThirtyE360) == 61.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccThirtyEPlus360) == 61.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccThirtyG360) == 62.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccActual360) == 63.0/360.0
doAssert: yearFraction(startDate4, endDate4, dccActual365F) == 63.0/365.0
doAssert: yearFraction(startDate4, endDate4, dccActual365L) == 63.0/366.0
doAssert: yearFraction(startDate4, endDate4, dccActual365A) == 63.0/366.0
doAssert: yearFraction(startDate4, endDate4, dccNL365) == 62.0/365.0
doAssert: yearFraction(startDate4, endDate4, dccActualActual) == 4.0/365.0+59.0/366.0

# Time interval 5:  from  31 October 2007  to  30 November 2008
# --------------------------------------------------------------
let startDate5 = dateTime(2007, mOct, 31)
let endDate5 = dateTime(2008, mNov, 30)

doAssert: yearFraction(startDate5, endDate5, dccThirtyA360) == 390.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccThirtyU360) == 390.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccThirtyE360) == 390.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccThirtyEPlus360) == 390.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccThirtyG360) == 390.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccActual360) == 396.0/360.0
doAssert: yearFraction(startDate5, endDate5, dccActual365F) == 396.0/365.0
doAssert: yearFraction(startDate5, endDate5, dccActual365L) == 396.0/366.0
doAssert: yearFraction(startDate5, endDate5, dccActual365A) == 396.0/366.0
doAssert: yearFraction(startDate5, endDate5, dccNL365) == 395.0/365.0
doAssert: yearFraction(startDate5, endDate5, dccActualActual) == 62.0/365.0+334.0/366.0

# Time interval 6:  from  1 February 2008  to  31 May 2009
# --------------------------------------------------------
let startDate6 = dateTime(2008, mFeb, 1)
let endDate6 = dateTime(2009, mMay, 31)

doAssert: yearFraction(startDate6, endDate6, dccThirtyA360) == 480.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccThirtyU360) == 480.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccThirtyE360) == 479.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccThirtyEPlus360) == 480.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccThirtyG360) == 479.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccActual360) == 485.0/360.0
doAssert: yearFraction(startDate6, endDate6, dccActual365F) == 485.0/365.0
doAssert: yearFraction(startDate6, endDate6, dccActual365L) == 485.0/365.0 
doAssert: yearFraction(startDate6, endDate6, dccActual365A) == 485.0/366.0
doAssert: yearFraction(startDate6, endDate6, dccNL365) == 484.0/365.0
doAssert: yearFraction(startDate6, endDate6, dccActualActual) == 335.0/366.0+150.0/365.0

# "Actual/Actual AFB" day count method
# ------------------------------------
# (https://en.wikipedia.org/wiki/Day_count_convention#Actual/Actual_AFB)
let startDate7 = dateTime(2004, mFeb, 28)
let endDate7 = dateTime(2008, mFeb, 27)
let endDate7bis = dateTime(2008, mFeb, 28)
let endDate7ter = dateTime(2008, mFeb, 29)
let startDate8 = dateTime(1994, mFeb, 10)
let endDate8 = dateTime(1997, mJun, 30)

doAssert: yearFraction(startDate7, endDate7, dccActualActualAFB) == 3.0+365.0/366.0
doAssert: yearFraction(startDate7, endDate7bis, dccActualActualAFB) == 4.0
doAssert: yearFraction(startDate7, endDate7ter, dccActualActualAFB) == 4.0+1.0/366.0
doAssert: yearFraction(startDate8, endDate8, dccActualActualAFB) == 3.0+140.0/365.0
Source   Edit  

Exports

klndrStaticHolidays, klndrTARGET, isholidayEngland, bdays, $, holidayUSMemorialDay, isweekendTARGETCalendar, usInaugurationDay, isholidayUSBondMrkt, holidayWhitSunday, boxingDay, holidayUSNYSEElectionDay, klndrNoHolidayOrWeekend, observedHolidays, USVeteransDay, newCalendarGBEngWls, holidayTargetLabourDay, NewYearsDay, holidayGBSctOrangemensDay, holidayGBEarlyMay, bdcFollowing, bdBusinessCalendar, holidayGBSpring, orangemensDay, newCalendarUSFederalGovt, klndrGBEngWls, isweekend, bdHoliday, stPatricksDay, USJuneteenthIndependenceDay, holidayUSWashingtonBirthday, christmasDay, klndrUSFederalGovt, LabourDay, isholiday, holidayUSChristmasDay, klndrGBNir, holidayUSLaborDay, bdcEndOfMonth, holidayTargetDecember31, holidayGBChristmasDay, BoxingDay, holidayAscension, isholidayTARGETCalendar, december31, ChristmasDay, isholiday, bdCalendar, isholiday, holidayEasterNCo, bdcPredecing, holiday, holidayWhitMonday, OrangemensDay, isbday, holidayUSVeteransDay, isholidayUSNYSE, holidayUSIndependenceDay, StPatricksDay, holidayGoodFriday, klndrUSNYSE, holidayEasterSunday, holidayUSThanksgivingDay, holidayGBSctStAndrewsDay, holidayGBSctJanuary2, observedHolidays, newYearsDay, isholidayNorthIreland, holidayGBNirStPatricksDay, nextMondayIfWeekend, holidayUSColumbusDay, holidayEasterMonday, newCalendarGBSct, observedHolidays, bdcModifFollowingFornight, holidayUSNYSENewYearsDay, newCalendarGBNir, holidayUSNewYearsDay, StAndrewsDay, addbdays, USIndependenceDay, bdBusinessDayConvention, isholidayScotland, bdcModifFollowing, newCalendarUSBondMrkt, newCalendarUSNYSE, stAndrewsDay, holidayGBEngNirWlsSummer, December31, info, holidayTargetChristmasDay, newCalendarWeekendsOnly, holidayGBBoxingDay, nearestWeekday, nextbday, klndrWeekendsOnly, holidayTargetNewYearsDay, labourDay, bday, newCalendarTARGET, newCalendar, holidayGBNewYearsDay, holidayUSInaugurationDay, holidayTargetBoxingDay, holidayUSJuneteenthIndependenceDay, newCalendarStaticHolidays, holidayUSMartinLutherKingBirthday, nextWeekday, klndrGBSct, nextMondayIfSunday, holidayGBSctSummer, newCalendarNoHolidayOrWeekend, isholidayUSFederalGovt, klndrUSBondMrkt