nautilus_model/python/types/
currency.rs1use std::str::FromStr;
17
18use nautilus_core::python::{IntoPyObjectNautilusExt, to_pyruntime_err, to_pyvalue_err};
19use pyo3::{
20 IntoPyObjectExt,
21 prelude::*,
22 pyclass::CompareOp,
23 types::{PyInt, PyString, PyTuple},
24};
25use ustr::Ustr;
26
27use crate::{enums::CurrencyType, types::Currency};
28
29#[pymethods]
30impl Currency {
31 #[new]
32 fn py_new(
33 code: &str,
34 precision: u8,
35 iso4217: u16,
36 name: &str,
37 currency_type: CurrencyType,
38 ) -> PyResult<Self> {
39 Self::new_checked(code, precision, iso4217, name, currency_type).map_err(to_pyvalue_err)
40 }
41
42 fn __setstate__(&mut self, state: &Bound<'_, PyAny>) -> PyResult<()> {
43 let py_tuple: &Bound<'_, PyTuple> = state.downcast::<PyTuple>()?;
44 self.code = Ustr::from(
45 py_tuple
46 .get_item(0)?
47 .downcast::<PyString>()?
48 .extract::<&str>()?,
49 );
50 self.precision = py_tuple.get_item(1)?.downcast::<PyInt>()?.extract::<u8>()?;
51 self.iso4217 = py_tuple
52 .get_item(2)?
53 .downcast::<PyInt>()?
54 .extract::<u16>()?;
55 self.name = Ustr::from(
56 py_tuple
57 .get_item(3)?
58 .downcast::<PyString>()?
59 .extract::<&str>()?,
60 );
61 self.currency_type = CurrencyType::from_str(
62 py_tuple
63 .get_item(4)?
64 .downcast::<PyString>()?
65 .extract::<&str>()?,
66 )
67 .map_err(to_pyvalue_err)?;
68 Ok(())
69 }
70
71 fn __getstate__(&self, py: Python) -> PyResult<PyObject> {
72 (
73 self.code.to_string(),
74 self.precision,
75 self.iso4217,
76 self.name.to_string(),
77 self.currency_type.to_string(),
78 )
79 .into_py_any(py)
80 }
81
82 fn __reduce__(&self, py: Python) -> PyResult<PyObject> {
83 let safe_constructor = py.get_type::<Self>().getattr("_safe_constructor")?;
84 let state = self.__getstate__(py)?;
85 (safe_constructor, PyTuple::empty(py), state).into_py_any(py)
86 }
87
88 #[staticmethod]
89 fn _safe_constructor() -> PyResult<Self> {
90 Ok(Self::AUD()) }
92
93 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
94 match op {
95 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
96 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
97 _ => py.NotImplemented(),
98 }
99 }
100
101 fn __hash__(&self) -> isize {
102 self.code.precomputed_hash() as isize
103 }
104
105 fn __repr__(&self) -> String {
106 format!("{self:?}")
107 }
108
109 fn __str__(&self) -> &'static str {
110 self.code.as_str()
111 }
112
113 #[getter]
114 #[pyo3(name = "code")]
115 fn py_code(&self) -> &'static str {
116 self.code.as_str()
117 }
118
119 #[getter]
120 #[pyo3(name = "precision")]
121 fn py_precision(&self) -> u8 {
122 self.precision
123 }
124
125 #[getter]
126 #[pyo3(name = "iso4217")]
127 fn py_iso4217(&self) -> u16 {
128 self.iso4217
129 }
130
131 #[getter]
132 #[pyo3(name = "name")]
133 fn py_name(&self) -> &'static str {
134 self.name.as_str()
135 }
136
137 #[getter]
138 #[pyo3(name = "currency_type")]
139 fn py_currency_type(&self) -> CurrencyType {
140 self.currency_type
141 }
142
143 #[staticmethod]
144 #[pyo3(name = "is_fiat")]
145 fn py_is_fiat(code: &str) -> PyResult<bool> {
146 Self::is_fiat(code).map_err(to_pyvalue_err)
147 }
148
149 #[staticmethod]
150 #[pyo3(name = "is_crypto")]
151 fn py_is_crypto(code: &str) -> PyResult<bool> {
152 Self::is_crypto(code).map_err(to_pyvalue_err)
153 }
154
155 #[staticmethod]
156 #[pyo3(name = "is_commodity_backed")]
157 fn py_is_commodidity_backed(code: &str) -> PyResult<bool> {
158 Self::is_commodity_backed(code).map_err(to_pyvalue_err)
159 }
160
161 #[staticmethod]
162 #[pyo3(name = "from_str")]
163 #[pyo3(signature = (value, strict = false))]
164 fn py_from_str(value: &str, strict: bool) -> PyResult<Self> {
165 match Self::from_str(value) {
166 Ok(currency) => Ok(currency),
167 Err(e) => {
168 if strict {
169 Err(to_pyvalue_err(e))
170 } else {
171 Self::new_checked(value, 8, 0, value, CurrencyType::Crypto)
172 .map_err(to_pyvalue_err)
173 }
174 }
175 }
176 }
177
178 #[staticmethod]
179 #[pyo3(name = "register")]
180 #[pyo3(signature = (currency, overwrite = false))]
181 fn py_register(currency: Self, overwrite: bool) -> PyResult<()> {
182 Self::register(currency, overwrite).map_err(to_pyruntime_err)
183 }
184}