Implementation:Avhz RustQuant DayCountConventions
| Knowledge Sources | |
|---|---|
| Domains | Calendar, Time_Value_of_Money |
| Last Updated | 2026-02-07 19:00 GMT |
Overview
Concrete tool for computing day count factors (year fractions) under various financial day count conventions provided by the RustQuant library.
Description
The DayCountConventions module defines the DayCountConvention enum and its associated calculation methods. In finance, day count conventions determine how interest accrues over time for bonds, notes, loans, mortgages, swaps, and forward rate agreements (FRAs). The convention specifies how to compute the fraction of a year between two dates, which directly affects coupon amounts, accrued interest, and present value discounting.
The DayCountConvention enum supports 19 distinct conventions:
Actual-based conventions:
- One_One -- always returns 1.0 regardless of dates
- Actual_360 -- actual days / 360
- Actual_364 -- actual days / 364
- Actual_366 -- actual days / 366
- Actual_365_25 -- actual days / 365.25
- Actual_365_Actual -- actual days / 366 if the period contains a leap year, otherwise / 365
- Actual_365_Fixed -- actual days / 365 (fixed)
- Actual_365_Leap -- actual days / 366 if leap year contained, otherwise / 365
- Actual_Actual_AFB -- AFB variant with stub period handling and leap year detection
- Actual_Actual_ICMA -- ICMA variant (currently unimplemented, marked with
todo!()) - Actual_Actual_ISDA -- splits the period at year boundaries, dividing each year's portion by 365 or 366 as appropriate
No-Leap conventions:
- No_Leap_360 -- (actual days minus leap days) / 360
- No_Leap_365 -- (actual days minus leap days) / 365
30/360 family conventions:
- Thirty_360_ISDA -- 30/360 ISDA with day-31 adjustment
- Thirty_E_360 -- 30E/360 European with day-31 capping to 30
- Thirty_E_360_ISDA -- 30E/360 ISDA with end-of-February special handling
- Thirty_E_365 -- 30E/365 with end-of-February special handling, denominator 365
- Thirty_E_Plus_360 -- 30E+/360 where day-31 on end date rolls to next month's 1st
- Thirty_U_360 -- 30U/360 US variant with end-of-February special handling
The main entry point is day_count_factor(&self, start_date, end_date) -> f64, which dispatches to the appropriate calculation method. Internal helper methods thirty_360_numerator and thirty_360_unpack_date provide shared logic for the 30/360 family. The module relies on utility functions contains_leap_year, days_between, is_last_day_of_february, and leap_year_count from the utilities module.
The enum is annotated with #[pyclass] for Python interoperability via PyO3.
Usage
Use this when you need to compute the year fraction between two dates for interest accrual, bond pricing, swap valuation, or any financial calculation that requires a day count factor. Select the appropriate convention based on the instrument's market convention (e.g., Actual/360 for money markets, 30/360 for corporate bonds, Actual/Actual ISDA for government bonds).
Code Reference
Source Location
- Repository: RustQuant
- File: crates/RustQuant_time/src/day_counting.rs
- Lines: 1-524
Signature
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
#[pyclass]
pub enum DayCountConvention {
One_One,
Actual_360,
Actual_364,
Actual_366,
Actual_365_25,
Actual_365_Actual,
Actual_365_Fixed,
Actual_365_Leap,
Actual_Actual_AFB,
Actual_Actual_ICMA,
Actual_Actual_ISDA,
No_Leap_360,
No_Leap_365,
Thirty_360_ISDA,
Thirty_E_360,
Thirty_E_360_ISDA,
Thirty_E_365,
Thirty_E_Plus_360,
Thirty_U_360,
}
impl DayCountConvention {
pub fn day_count_factor(&self, start_date: Date, end_date: Date) -> f64;
}
Import
use RustQuant::time::day_counting::DayCountConvention;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| start_date | Date | Yes | The beginning date of the accrual period |
| end_date | Date | Yes | The ending date of the accrual period |
Outputs
| Name | Type | Description |
|---|---|---|
| day_count_factor | f64 | The year fraction between the two dates according to the selected convention |
Usage Examples
use time::macros::date;
use RustQuant::time::day_counting::DayCountConvention;
let start = date!(2023-01-01);
let end = date!(2024-01-01);
// Actual/365 Fixed: 365 / 365 = 1.0
let dcf_fixed = DayCountConvention::Actual_365_Fixed.day_count_factor(start, end);
assert_eq!(dcf_fixed, 1.0);
// Actual/360: 365 / 360 = 1.01388...
let dcf_360 = DayCountConvention::Actual_360.day_count_factor(start, end);
// Actual/Actual ISDA for a period spanning a year boundary
let date1 = date!(2003-11-01);
let date2 = date!(2004-05-01);
let dcf_isda = DayCountConvention::Actual_Actual_ISDA.day_count_factor(date1, date2);
// Approximately 0.4977
// 30E/365 convention
let start_30e = date!(2011-06-17);
let end_30e = date!(2012-12-30);
let dcf_30e365 = DayCountConvention::Thirty_E_365.day_count_factor(start_30e, end_30e);
// Approximately 1.5151