From 4fb16f425973d8215402f4eb112d4a8c8185e338 Mon Sep 17 00:00:00 2001 From: Eric Forgy Date: Thu, 24 Jan 2019 17:41:58 +0800 Subject: [PATCH 1/3] Add Excel module Add a default yearfrac (Excel.Thirty360) --- src/excel.jl | 92 +++++++++++++++++++++++++++++++++++++++++++----- test/excel.jl | 8 ++--- test/runtests.jl | 8 ++--- 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/src/excel.jl b/src/excel.jl index 56b3428..014b87f 100644 --- a/src/excel.jl +++ b/src/excel.jl @@ -1,5 +1,11 @@ +module Excel + +using ..DayCounts, ..Dates + """ - Thirty360Excel() + Excel.Thirty360() + +Excel Basis = 0 or omitted **US (NASD) 30/360** day count convention, as computed via Microsoft Excel `YEARFRAC` with the basis option of `0`. @@ -12,9 +18,8 @@ This differs from [`Thirty360`](@ref) when: - [Microsoft Excel `YEARFRAC` function](https://support.office.com/en-us/article/yearfrac-function-3844141e-c76d-4143-82b6-208454ddc6a8) - [David A. Wheeler (2008) "YEARFRAC Incompatibilities between Excel 2007 and OOXML (OXML), and the Definitions Actually Used by Excel 2007"](https://dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf) """ -struct Thirty360Excel <: DayCount -end -function yearfrac(startdate::Date, enddate::Date, dc::Thirty360Excel) +struct Thirty360 <: DayCounts.DayCount end +function DayCounts.yearfrac(startdate::Date, enddate::Date, dc::Thirty360) if startdate > enddate return -yearfrac(enddate, startdate, dc) end @@ -36,11 +41,14 @@ function yearfrac(startdate::Date, enddate::Date, dc::Thirty360Excel) d2 = 30 end end - return thirty360(y2-y1,m2-m1,d2-d1) + return DayCounts.thirty360(y2-y1,m2-m1,d2-d1) end +DayCounts.yearfrac(startdate::Date, enddate::Date) = DayCounts.yearfrac(startdate::Date, enddate::Date, Thirty360()) """ - ActualActualExcel() + Excel.ActualActual() + +Excel Basis = 1 **Actual/Actual** day count convention, as computed via Microsoft Excel `YEARFRAC` with the basis option of `1`. @@ -59,9 +67,8 @@ where: - [Microsoft Excel `YEARFRAC` function](https://support.office.com/en-us/article/yearfrac-function-3844141e-c76d-4143-82b6-208454ddc6a8) - [David A. Wheeler (2008) "YEARFRAC Incompatibilities between Excel 2007 and OOXML (OXML), and the Definitions Actually Used by Excel 2007"](https://dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf) """ -struct ActualActualExcel <: DayCount -end -function yearfrac(startdate::Date, enddate::Date, dc::ActualActualExcel) +struct ActualActual <: DayCounts.DayCount end +function DayCounts.yearfrac(startdate::Date, enddate::Date, dc::ActualActual) if startdate > enddate return -yearfrac(enddate, startdate, dc) end @@ -81,3 +88,70 @@ function yearfrac(startdate::Date, enddate::Date, dc::ActualActualExcel) return Dates.value(enddate-startdate) / (sum(daysinyear, yrange) / length(yrange)) end end + +""" + Excel.Actual360() + +Excel Basis = 2 + +Same as DayCounts.Actual360. + +**Actual/360** day count convention. + +The year fraction is computed as: +```math +\\frac{\\text{# of days}}{360} +``` + +# Reference + - 2006 ISDA definitions, §4.16 (e) + +""" +const Actual360 = DayCounts.Actual360 + +""" + Excel.Actual365() + +Excel Basis = 3 + +Same as DayCounts.Actual365Fixed. + +**Actual/365 (Fixed)** day count convention. + +The year fraction is computed as: +```math +\\frac{\\text{# of days}}{365} +``` + +# Reference + - 2006 ISDA definitions, §4.16 (d) +""" +const Actual365 = DayCounts.Actual365Fixed + +""" + Excel.ThirtyE360() + +Excel Basis = 4 + +Same as DayCounts.ThirtyE360. + +**30E/360** or **Eurobond Basis** day count convention. + +The year fraction is computed as: +```math +\\frac{360 \\times (y_2 - y_1) + 30 \\times (m_2 - m_1) + (d_2 - d_1)}{360} +``` +where +- ``y_1`` and ``y_2`` are the years of the start and end date, respectively. +- ``m_1`` and ``m_2`` are the months of the start and end date, respectively. +- ``d_1`` is the day of the month at the start date, unless it is 31st day of the month, + in which case it is 30. +- ``d_2`` is the day of the month at the end date, unless it is 31st day of the month, + in which case it is 30. + +# Reference + - 2006 ISDA definitions, §4.16 (g) +""" +const ThirtyE360 = DayCounts.ThirtyE360 + +end \ No newline at end of file diff --git a/test/excel.jl b/test/excel.jl index 1223654..2ed3c09 100644 --- a/test/excel.jl +++ b/test/excel.jl @@ -2,7 +2,7 @@ using Test, DayCounts, Dates, ExcelFiles @testset "Excel basis 0" begin table = load("yearfrac.xlsx","basis0") - dc = DayCounts.Thirty360Excel() + dc = DayCounts.Excel.Thirty360() for r in ExcelFiles.getiterator(table) @test yearfrac(Date(r.startdate), Date(r.enddate), dc) == r.yearfrac end @@ -10,7 +10,7 @@ end @testset "Excel basis 1" begin table = load("yearfrac.xlsx","basis1") - dc = DayCounts.ActualActualExcel() + dc = DayCounts.Excel.ActualActual() for r in ExcelFiles.getiterator(table) @test yearfrac(Date(r.startdate), Date(r.enddate), dc) == r.yearfrac end @@ -18,7 +18,7 @@ end @testset "Excel basis 2" begin table = load("yearfrac.xlsx","basis2") - dc = DayCounts.Actual360() + dc = DayCounts.Excel.Actual360() for r in ExcelFiles.getiterator(table) @test yearfrac(Date(r.startdate), Date(r.enddate), dc) == r.yearfrac end @@ -26,7 +26,7 @@ end @testset "Excel basis 3" begin table = load("yearfrac.xlsx","basis3") - dc = DayCounts.Actual365Fixed() + dc = DayCounts.Excel.Actual365() for r in ExcelFiles.getiterator(table) @test yearfrac(Date(r.startdate), Date(r.enddate), dc) == r.yearfrac end diff --git a/test/runtests.jl b/test/runtests.jl index 578f9a3..4ee8470 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -289,8 +289,8 @@ end end -@testset "Thirty360Excel" begin - dc = DayCounts.Thirty360Excel() +@testset "Excel.Thirty360" begin + dc = DayCounts.Excel.Thirty360() # usual rule: ((d2-d1) + (m2-m1)*30 + (y2-y1)*360)/360 @test yearfrac(Date(2011,12,28), Date(2012, 2,28), dc) == ((28-28) + (2-12)*30 + (2012-2011)*360)/360 @test yearfrac(Date(2011,12,28), Date(2012, 2,29), dc) == ((29-28) + (2-12)*30 + (2012-2011)*360)/360 @@ -325,8 +325,8 @@ end -@testset "ActualActualExcel" begin - dc = DayCounts.ActualActualExcel() +@testset "Excel.ActualActual" begin + dc = DayCounts.Excel.ActualActual() # calculated from Excel sheet @test yearfrac(Date(2011,12,28), Date(2012, 2,28), dc) == 62/365 @test yearfrac(Date(2011,12,28), Date(2012, 2,29), dc) == 63/366 From b7c27fe7ccb81c610d63e59a951b1d9c1cd3d1d3 Mon Sep 17 00:00:00 2001 From: Eric Forgy Date: Thu, 24 Jan 2019 18:29:43 +0800 Subject: [PATCH 2/3] Moved Excel.Thirty360 to ThirtyU360 and set Excel.Thirty360 = ThirtyU360. Made this the default daycount. --- src/DayCounts.jl | 41 +++++++++++++++++++++++++++++++++++++++++ src/excel.jl | 27 +-------------------------- test/excel.jl | 2 +- test/runtests.jl | 4 ++-- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/DayCounts.jl b/src/DayCounts.jl index 649b57e..6f43f10 100644 --- a/src/DayCounts.jl +++ b/src/DayCounts.jl @@ -194,6 +194,47 @@ function yearfrac(startdate::Date, enddate::Date, dc::Thirty360) return thirty360(dy,dm,d2-d1) end +""" + ThirtyU360() + +**US (NASD) 30/360** day count convention, as computed via Microsoft Excel `YEARFRAC` with the basis option of `0`. + +This differs from [`Thirty360`](@ref) when: +* if the start date is the last day of February, then + - ``d_1`` is 30, and + - if the end date is also the last day of February ``d_2`` is also 30. + +# Reference +- [Microsoft Excel `YEARFRAC` function](https://support.office.com/en-us/article/yearfrac-function-3844141e-c76d-4143-82b6-208454ddc6a8) +- [David A. Wheeler (2008) "YEARFRAC Incompatibilities between Excel 2007 and OOXML (OXML), and the Definitions Actually Used by Excel 2007"](https://dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf) +""" +struct ThirtyU360 <: DayCount end +function yearfrac(startdate::Date, enddate::Date, dc::ThirtyU360) + if startdate > enddate + return -yearfrac(enddate, startdate, dc) + end + + y1 = year(startdate) + y2 = year(enddate) + m1 = month(startdate) + m2 = month(enddate) + d1 = day(startdate) + d2 = day(enddate) + if d1 >= 30 + d1 = 30 + if d2 >= 30 + d2 = 30 + end + elseif m1 == 2 && startdate == lastdayofmonth(startdate) + d1 = 30 + if m2 == 2 && enddate == lastdayofmonth(enddate) + d2 = 30 + end + end + return DayCounts.thirty360(y2-y1,m2-m1,d2-d1) +end +yearfrac(startdate::Date, enddate::Date) = DayCounts.yearfrac(startdate::Date, enddate::Date, ThirtyU360()) # Defaul DayCount + """ ThirtyE360() diff --git a/src/excel.jl b/src/excel.jl index 014b87f..751d447 100644 --- a/src/excel.jl +++ b/src/excel.jl @@ -18,32 +18,7 @@ This differs from [`Thirty360`](@ref) when: - [Microsoft Excel `YEARFRAC` function](https://support.office.com/en-us/article/yearfrac-function-3844141e-c76d-4143-82b6-208454ddc6a8) - [David A. Wheeler (2008) "YEARFRAC Incompatibilities between Excel 2007 and OOXML (OXML), and the Definitions Actually Used by Excel 2007"](https://dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf) """ -struct Thirty360 <: DayCounts.DayCount end -function DayCounts.yearfrac(startdate::Date, enddate::Date, dc::Thirty360) - if startdate > enddate - return -yearfrac(enddate, startdate, dc) - end - - y1 = year(startdate) - y2 = year(enddate) - m1 = month(startdate) - m2 = month(enddate) - d1 = day(startdate) - d2 = day(enddate) - if d1 >= 30 - d1 = 30 - if d2 >= 30 - d2 = 30 - end - elseif m1 == 2 && startdate == lastdayofmonth(startdate) - d1 = 30 - if m2 == 2 && enddate == lastdayofmonth(enddate) - d2 = 30 - end - end - return DayCounts.thirty360(y2-y1,m2-m1,d2-d1) -end -DayCounts.yearfrac(startdate::Date, enddate::Date) = DayCounts.yearfrac(startdate::Date, enddate::Date, Thirty360()) +const Thirty360 = DayCounts.ThirtyU360 """ Excel.ActualActual() diff --git a/test/excel.jl b/test/excel.jl index 2ed3c09..1883c18 100644 --- a/test/excel.jl +++ b/test/excel.jl @@ -34,7 +34,7 @@ end @testset "Excel basis 4" begin table = load("yearfrac.xlsx","basis4") - dc = DayCounts.ThirtyE360() + dc = DayCounts.Excel.ThirtyE360() for r in ExcelFiles.getiterator(table) @test yearfrac(Date(r.startdate), Date(r.enddate), dc) == r.yearfrac end diff --git a/test/runtests.jl b/test/runtests.jl index 4ee8470..9c62309 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -289,8 +289,8 @@ end end -@testset "Excel.Thirty360" begin - dc = DayCounts.Excel.Thirty360() +@testset "ThirtyU360" begin + dc = DayCounts.ThirtyU360() # usual rule: ((d2-d1) + (m2-m1)*30 + (y2-y1)*360)/360 @test yearfrac(Date(2011,12,28), Date(2012, 2,28), dc) == ((28-28) + (2-12)*30 + (2012-2011)*360)/360 @test yearfrac(Date(2011,12,28), Date(2012, 2,29), dc) == ((29-28) + (2-12)*30 + (2012-2011)*360)/360 From ebcb65929cb8afc1e997d725e9a271e62ecb9077 Mon Sep 17 00:00:00 2001 From: Eric Forgy Date: Wed, 6 Feb 2019 15:57:34 +0800 Subject: [PATCH 3/3] Remove redundant docs and export Excel. --- src/DayCounts.jl | 6 ++-- src/excel.jl | 79 +++--------------------------------------------- 2 files changed, 7 insertions(+), 78 deletions(-) diff --git a/src/DayCounts.jl b/src/DayCounts.jl index 6f43f10..4195bb4 100644 --- a/src/DayCounts.jl +++ b/src/DayCounts.jl @@ -4,7 +4,7 @@ module DayCounts # https://www.isda.org/2008/12/22/30-360-day-count-conventions/ using Dates -export yearfrac +export yearfrac, Excel """ yearfrac(startdate::Date, enddate::Date, dc::DayCount) @@ -22,7 +22,7 @@ end abstract type DayCount end """ - Actual365Fixed() + Actual365Fixed() or Excel.Actual365 **Actual/365 (Fixed)** day count convention. @@ -195,7 +195,7 @@ function yearfrac(startdate::Date, enddate::Date, dc::Thirty360) end """ - ThirtyU360() + ThirtyU360() or Excel.Thirty360 **US (NASD) 30/360** day count convention, as computed via Microsoft Excel `YEARFRAC` with the basis option of `0`. diff --git a/src/excel.jl b/src/excel.jl index 751d447..e55a627 100644 --- a/src/excel.jl +++ b/src/excel.jl @@ -2,22 +2,7 @@ module Excel using ..DayCounts, ..Dates -""" - Excel.Thirty360() - -Excel Basis = 0 or omitted - -**US (NASD) 30/360** day count convention, as computed via Microsoft Excel `YEARFRAC` with the basis option of `0`. - -This differs from [`Thirty360`](@ref) when: -* if the start date is the last day of February, then - - ``d_1`` is 30, and - - if the end date is also the last day of February ``d_2`` is also 30. - -# Reference -- [Microsoft Excel `YEARFRAC` function](https://support.office.com/en-us/article/yearfrac-function-3844141e-c76d-4143-82b6-208454ddc6a8) -- [David A. Wheeler (2008) "YEARFRAC Incompatibilities between Excel 2007 and OOXML (OXML), and the Definitions Actually Used by Excel 2007"](https://dwheeler.com/yearfrac/excel-ooxml-yearfrac.pdf) -""" +@doc (@doc DayCounts.ThirtyU360) const Thirty360 = DayCounts.ThirtyU360 """ @@ -64,69 +49,13 @@ function DayCounts.yearfrac(startdate::Date, enddate::Date, dc::ActualActual) end end -""" - Excel.Actual360() - -Excel Basis = 2 - -Same as DayCounts.Actual360. - -**Actual/360** day count convention. - -The year fraction is computed as: -```math -\\frac{\\text{# of days}}{360} -``` - -# Reference - - 2006 ISDA definitions, §4.16 (e) - -""" +@doc (@doc DayCounts.Actual360) const Actual360 = DayCounts.Actual360 -""" - Excel.Actual365() - -Excel Basis = 3 - -Same as DayCounts.Actual365Fixed. - -**Actual/365 (Fixed)** day count convention. - -The year fraction is computed as: -```math -\\frac{\\text{# of days}}{365} -``` - -# Reference - - 2006 ISDA definitions, §4.16 (d) -""" +@doc (@doc DayCounts.Actual365Fixed) const Actual365 = DayCounts.Actual365Fixed -""" - Excel.ThirtyE360() - -Excel Basis = 4 - -Same as DayCounts.ThirtyE360. - -**30E/360** or **Eurobond Basis** day count convention. - -The year fraction is computed as: -```math -\\frac{360 \\times (y_2 - y_1) + 30 \\times (m_2 - m_1) + (d_2 - d_1)}{360} -``` -where -- ``y_1`` and ``y_2`` are the years of the start and end date, respectively. -- ``m_1`` and ``m_2`` are the months of the start and end date, respectively. -- ``d_1`` is the day of the month at the start date, unless it is 31st day of the month, - in which case it is 30. -- ``d_2`` is the day of the month at the end date, unless it is 31st day of the month, - in which case it is 30. - -# Reference - - 2006 ISDA definitions, §4.16 (g) -""" +@doc (@doc DayCounts.ThirtyE360) const ThirtyE360 = DayCounts.ThirtyE360 end \ No newline at end of file