rateslib/scheduling/py/
convention.rs

1use crate::json::{DeserializedObj, JSON};
2use crate::scheduling::{Adjuster, Calendar, Convention, Frequency, PyAdjuster};
3use chrono::prelude::*;
4use pyo3::exceptions::PyValueError;
5use pyo3::prelude::*;
6
7#[pymethods]
8impl Convention {
9    // Pickling
10    #[new]
11    fn new_py(variant: u8) -> PyResult<Convention> {
12        match variant {
13            0_u8 => Ok(Convention::Act365F),
14            1_u8 => Ok(Convention::Act360),
15            2_u8 => Ok(Convention::Thirty360),
16            3_u8 => Ok(Convention::ThirtyU360),
17            4_u8 => Ok(Convention::ThirtyE360),
18            5_u8 => Ok(Convention::ThirtyE360ISDA),
19            6_u8 => Ok(Convention::YearsAct365F),
20            7_u8 => Ok(Convention::YearsAct360),
21            8_u8 => Ok(Convention::YearsMonths),
22            9_u8 => Ok(Convention::One),
23            10_u8 => Ok(Convention::ActActISDA),
24            11_u8 => Ok(Convention::ActActICMA),
25            12_u8 => Ok(Convention::Bus252),
26            13_u8 => Ok(Convention::ActActICMAStubAct365F),
27            14_u8 => Ok(Convention::Act365_25),
28            15_u8 => Ok(Convention::Act364),
29            _ => Err(PyValueError::new_err(
30                "unreachable code on Convention pickle.",
31            )),
32        }
33    }
34
35    /// Calculate the day count fraction of a period.
36    ///
37    /// Parameters
38    /// ----------
39    /// start : datetime
40    ///     The adjusted start date of the calculation period.
41    /// end : datetime
42    ///     The adjusted end date of the calculation period.
43    /// termination : datetime, optional
44    ///     The adjusted termination date of the leg. Required only for some ``convention``.
45    /// frequency : Frequency, str, optional
46    ///     The frequency of the period. Required only for some ``convention``.
47    /// stub : bool, optional
48    ///    Indicates whether the period is a stub or not. Required only for some ``convention``.
49    /// roll : str, int, optional
50    ///     Used only if ``frequency`` is given in string form. Required only for some ``convention``.
51    /// calendar: str, Calendar, optional
52    ///     Used only of ``frequency`` is given in string form. Required only for some ``convention``.
53    /// adjuster: Adjuster, str, optional
54    ///     The :class:`~rateslib.scheduling.Adjuster` used to convert unadjusted dates to
55    ///     adjusted accrual dates on the period. Required only for some ``convention``.
56    ///
57    /// Returns
58    /// --------
59    /// float
60    ///
61    /// Notes
62    /// -----
63    /// Further details on the required arguments can be found under ``Convention`` at the
64    /// lower level Rust docs, see :rust:`rateslib-rs: Scheduling <scheduling>`.
65    #[pyo3(name = "dcf", signature=(start, end, termination=None, frequency=None, stub=None, calendar=None, adjuster=None   ))]
66    fn dcf_py(
67        &self,
68        start: NaiveDateTime,
69        end: NaiveDateTime,
70        termination: Option<NaiveDateTime>,
71        frequency: Option<Frequency>,
72        stub: Option<bool>,
73        calendar: Option<Calendar>,
74        adjuster: Option<PyAdjuster>,
75    ) -> PyResult<f64> {
76        let adjuster_opt: Option<Adjuster> = match adjuster {
77            Some(val) => Some(val.into()),
78            None => None,
79        };
80        self.dcf(
81            &start,
82            &end,
83            termination.as_ref(),
84            frequency.as_ref(),
85            stub,
86            calendar.as_ref(),
87            adjuster_opt.as_ref(),
88        )
89    }
90    fn __getnewargs__<'py>(&self) -> PyResult<(usize,)> {
91        Ok((*self as usize,))
92    }
93
94    fn __repr__(&self) -> String {
95        format!("<rl.Convention.{:?} at {:p}>", self, self)
96    }
97
98    fn __str__(&self) -> String {
99        match self {
100            Convention::Act360 => "Act360".to_string(),
101            Convention::Act365F => "Act365F".to_string(),
102            Convention::YearsAct365F => "YearsAct365F".to_string(),
103            Convention::YearsAct360 => "YearsAct360".to_string(),
104            Convention::YearsMonths => "YearsMonths".to_string(),
105            Convention::Thirty360 => "30360".to_string(),
106            Convention::ThirtyU360 => "30u360".to_string(),
107            Convention::ThirtyE360 => "30e360".to_string(),
108            Convention::ThirtyE360ISDA => "30e360ISDA".to_string(),
109            Convention::One => "One".to_string(),
110            Convention::ActActISDA => "ActActISDA".to_string(),
111            Convention::ActActICMA => "ActActICMA".to_string(),
112            Convention::Bus252 => "Bus252".to_string(),
113            Convention::ActActICMAStubAct365F => "ActActICMAStubAct365F".to_string(),
114            Convention::Act365_25 => "Act365_25".to_string(),
115            Convention::Act364 => "Act364".to_string(),
116        }
117    }
118
119    /// Return a JSON representation of the object.
120    ///
121    /// Returns
122    /// -------
123    /// str
124    #[pyo3(name = "to_json")]
125    fn to_json_py(&self) -> PyResult<String> {
126        match DeserializedObj::Convention(self.clone()).to_json() {
127            Ok(v) => Ok(v),
128            Err(_) => Err(PyValueError::new_err(
129                "Failed to serialize `Convention` to JSON.",
130            )),
131        }
132    }
133}