Skip to main content

nautilus_model/python/types/
currency.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::str::FromStr;
17
18use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
19use pyo3::{IntoPyObjectExt, prelude::*};
20
21use crate::{enums::CurrencyType, types::Currency};
22
23#[pymethods]
24impl Currency {
25    #[new]
26    fn py_new(
27        code: &str,
28        precision: u8,
29        iso4217: u16,
30        name: &str,
31        currency_type: CurrencyType,
32    ) -> PyResult<Self> {
33        Self::new_checked(code, precision, iso4217, name, currency_type).map_err(to_pyvalue_err)
34    }
35
36    fn __reduce__(&self, py: Python) -> PyResult<Py<PyAny>> {
37        let unpickle = py.get_type::<Self>().getattr("_unpickle")?;
38        let args = (
39            self.code.to_string(),
40            self.precision,
41            self.iso4217,
42            self.name.to_string(),
43            self.currency_type.to_string(),
44        )
45            .into_py_any(py)?;
46        (unpickle, args).into_py_any(py)
47    }
48
49    #[staticmethod]
50    fn _unpickle(
51        code: &str,
52        precision: u8,
53        iso4217: u16,
54        name: &str,
55        currency_type_str: &str,
56    ) -> PyResult<Self> {
57        let currency_type = CurrencyType::from_str(currency_type_str).map_err(to_pyvalue_err)?;
58        Self::new_checked(code, precision, iso4217, name, currency_type).map_err(to_pyvalue_err)
59    }
60
61    fn __repr__(&self) -> String {
62        format!("{self:?}")
63    }
64
65    fn __str__(&self) -> &'static str {
66        self.code.as_str()
67    }
68
69    #[getter]
70    #[pyo3(name = "code")]
71    fn py_code(&self) -> &'static str {
72        self.code.as_str()
73    }
74
75    #[getter]
76    #[pyo3(name = "precision")]
77    fn py_precision(&self) -> u8 {
78        self.precision
79    }
80
81    #[getter]
82    #[pyo3(name = "iso4217")]
83    fn py_iso4217(&self) -> u16 {
84        self.iso4217
85    }
86
87    #[getter]
88    #[pyo3(name = "name")]
89    fn py_name(&self) -> &'static str {
90        self.name.as_str()
91    }
92
93    #[getter]
94    #[pyo3(name = "currency_type")]
95    fn py_currency_type(&self) -> CurrencyType {
96        self.currency_type
97    }
98
99    #[staticmethod]
100    #[pyo3(name = "is_fiat")]
101    fn py_is_fiat(code: &str) -> PyResult<bool> {
102        Self::is_fiat(code).map_err(to_pyvalue_err)
103    }
104
105    #[staticmethod]
106    #[pyo3(name = "is_crypto")]
107    fn py_is_crypto(code: &str) -> PyResult<bool> {
108        Self::is_crypto(code).map_err(to_pyvalue_err)
109    }
110
111    #[staticmethod]
112    #[pyo3(name = "is_commodity_backed")]
113    fn py_is_commodidity_backed(code: &str) -> PyResult<bool> {
114        Self::is_commodity_backed(code).map_err(to_pyvalue_err)
115    }
116
117    #[staticmethod]
118    #[pyo3(name = "from_str")]
119    #[pyo3(signature = (value, strict = false))]
120    fn py_from_str(value: &str, strict: bool) -> PyResult<Self> {
121        match Self::from_str(value) {
122            Ok(currency) => Ok(currency),
123            Err(e) => {
124                if strict {
125                    Err(to_pyvalue_err(e))
126                } else {
127                    Self::new_checked(value, 8, 0, value, CurrencyType::Crypto)
128                        .map_err(to_pyvalue_err)
129                }
130            }
131        }
132    }
133
134    #[staticmethod]
135    #[pyo3(name = "register")]
136    #[pyo3(signature = (currency, overwrite = false))]
137    fn py_register(currency: Self, overwrite: bool) -> PyResult<()> {
138        Self::register(currency, overwrite).map_err(to_pyruntime_err)
139    }
140}