nautilus_model/python/types/
balance.rs1use std::str::FromStr;
17
18use nautilus_core::python::{IntoPyObjectNautilusExt, to_pyvalue_err};
19use pyo3::{basic::CompareOp, prelude::*, types::PyDict};
20
21use crate::{
22 identifiers::InstrumentId,
23 types::{AccountBalance, Currency, MarginBalance, Money},
24};
25
26#[pymethods]
27impl AccountBalance {
28 #[new]
29 fn py_new(total: Money, locked: Money, free: Money) -> PyResult<Self> {
30 Self::new_checked(total, locked, free).map_err(to_pyvalue_err)
31 }
32
33 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
34 match op {
35 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
36 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
37 _ => py.NotImplemented(),
38 }
39 }
40
41 fn __repr__(&self) -> String {
42 format!("{self:?}")
43 }
44
45 fn __str__(&self) -> String {
46 self.to_string()
47 }
48
49 #[staticmethod]
59 #[pyo3(name = "from_dict")]
60 pub fn py_from_dict(values: &Bound<'_, PyDict>) -> PyResult<Self> {
61 let dict = values.as_ref();
62 let currency: String = dict.get_item("currency")?.extract()?;
63 let total_str: String = dict.get_item("total")?.extract()?;
64 let total: f64 = total_str.parse::<f64>().unwrap();
65 let free_str: String = dict.get_item("free")?.extract()?;
66 let free: f64 = free_str.parse::<f64>().unwrap();
67 let locked_str: String = dict.get_item("locked")?.extract()?;
68 let locked: f64 = locked_str.parse::<f64>().unwrap();
69 let currency = Currency::from_str(currency.as_str()).map_err(to_pyvalue_err)?;
70 Self::new_checked(
71 Money::new(total, currency),
72 Money::new(locked, currency),
73 Money::new(free, currency),
74 )
75 .map_err(to_pyvalue_err)
76 }
77
78 #[pyo3(name = "to_dict")]
84 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
85 let dict = PyDict::new(py);
86 dict.set_item("type", stringify!(AccountBalance))?;
87 dict.set_item(
88 "total",
89 format!(
90 "{:.*}",
91 self.total.currency.precision as usize,
92 self.total.as_f64()
93 ),
94 )?;
95 dict.set_item(
96 "locked",
97 format!(
98 "{:.*}",
99 self.locked.currency.precision as usize,
100 self.locked.as_f64()
101 ),
102 )?;
103 dict.set_item(
104 "free",
105 format!(
106 "{:.*}",
107 self.free.currency.precision as usize,
108 self.free.as_f64()
109 ),
110 )?;
111 dict.set_item("currency", self.currency.code.to_string())?;
112 Ok(dict.into())
113 }
114}
115
116#[pymethods]
117impl MarginBalance {
118 #[new]
119 fn py_new(initial: Money, maintenance: Money, instrument: InstrumentId) -> Self {
120 Self::new(initial, maintenance, instrument)
121 }
122 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
123 match op {
124 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
125 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
126 _ => py.NotImplemented(),
127 }
128 }
129
130 fn __repr__(&self) -> String {
131 format!("{self:?}")
132 }
133
134 fn __str__(&self) -> String {
135 self.to_string()
136 }
137
138 #[staticmethod]
148 #[pyo3(name = "from_dict")]
149 pub fn py_from_dict(values: &Bound<'_, PyDict>) -> PyResult<Self> {
150 let dict = values.as_ref();
151 let currency: String = dict.get_item("currency")?.extract()?;
152 let initial_str: String = dict.get_item("initial")?.extract()?;
153 let initial: f64 = initial_str.parse::<f64>().unwrap();
154 let maintenance_str: String = dict.get_item("maintenance")?.extract()?;
155 let maintenance: f64 = maintenance_str.parse::<f64>().unwrap();
156 let instrument_id_str: String = dict.get_item("instrument_id")?.extract()?;
157 let currency = Currency::from_str(currency.as_str()).map_err(to_pyvalue_err)?;
158 let account_balance = Self::new(
159 Money::new(initial, currency),
160 Money::new(maintenance, currency),
161 InstrumentId::from(instrument_id_str.as_str()),
162 );
163 Ok(account_balance)
164 }
165
166 #[pyo3(name = "to_dict")]
176 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
177 let dict = PyDict::new(py);
178 dict.set_item("type", stringify!(MarginBalance))?;
179 dict.set_item(
180 "initial",
181 format!(
182 "{:.*}",
183 self.initial.currency.precision as usize,
184 self.initial.as_f64()
185 ),
186 )?;
187 dict.set_item(
188 "maintenance",
189 format!(
190 "{:.*}",
191 self.maintenance.currency.precision as usize,
192 self.maintenance.as_f64()
193 ),
194 )?;
195 dict.set_item("currency", self.currency.code.to_string())?;
196 dict.set_item("instrument_id", self.instrument_id.to_string())?;
197 Ok(dict.into())
198 }
199}