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