diff --git a/financepy/utils/day_count.py b/financepy/utils/day_count.py index 7865ebeb..e0414fd2 100644 --- a/financepy/utils/day_count.py +++ b/financepy/utils/day_count.py @@ -255,9 +255,9 @@ def year_frac( frequency = annual_frequency(freq_type) if dt3 is None: - y3 = y2 - else: - y3 = dt3.y + dt3 = dt2 + + y3 = dt3.y num = dt2 - dt1 den = 365 diff --git a/unit_tests/test_FinDayCount.py b/unit_tests/test_FinDayCount.py index 307fee00..cf22eab0 100644 --- a/unit_tests/test_FinDayCount.py +++ b/unit_tests/test_FinDayCount.py @@ -120,6 +120,52 @@ def test_year_frace_act_365_l(): ######################################################################################## +def test_act_365_l_without_reference_end_date(): + + day_count = DayCount(DayCountTypes.ACT_365L) + period_start = Date(1, 12, 2023) + period_end = Date(1, 3, 2024) + + implicit_period_end = day_count.year_frac( + period_start, + period_end, + freq_type=FrequencyTypes.ANNUAL, + ) + explicit_period_end = day_count.year_frac( + period_start, + period_end, + period_end, + FrequencyTypes.ANNUAL, + ) + + assert implicit_period_end == explicit_period_end + assert implicit_period_end == (91.0 / 366.0, 91.0, 366) + + # A separately supplied coupon-period end must still control the + # denominator for an accrued fraction. + accrued_start = Date(1, 3, 2023) + accrued_end = Date(1, 12, 2023) + next_coupon = Date(1, 3, 2024) + + full_period_mode = day_count.year_frac( + accrued_start, + accrued_end, + freq_type=FrequencyTypes.ANNUAL, + ) + accrued_mode = day_count.year_frac( + accrued_start, + accrued_end, + next_coupon, + FrequencyTypes.ANNUAL, + ) + + assert full_period_mode == (275.0 / 365.0, 275.0, 365) + assert accrued_mode == (275.0 / 366.0, 275.0, 366) + + +######################################################################################## + + def test_year_frace_simple(): dc_type = DayCountTypes.JULIAN