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]
50 #[pyo3(name = "from_dict")]
51 pub fn py_from_dict(values: &Bound<'_, PyDict>) -> PyResult<Self> {
52 let dict = values.as_ref();
53 let currency: String = dict.get_item("currency")?.extract()?;
54 let total_str: String = dict.get_item("total")?.extract()?;
55 let total: f64 = total_str.parse::<f64>().unwrap();
56 let free_str: String = dict.get_item("free")?.extract()?;
57 let free: f64 = free_str.parse::<f64>().unwrap();
58 let locked_str: String = dict.get_item("locked")?.extract()?;
59 let locked: f64 = locked_str.parse::<f64>().unwrap();
60 let currency = Currency::from_str(currency.as_str()).map_err(to_pyvalue_err)?;
61 Self::new_checked(
62 Money::new(total, currency),
63 Money::new(locked, currency),
64 Money::new(free, currency),
65 )
66 .map_err(to_pyvalue_err)
67 }
68
69 #[pyo3(name = "to_dict")]
70 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
71 let dict = PyDict::new(py);
72 dict.set_item("type", stringify!(AccountBalance))?;
73 dict.set_item(
74 "total",
75 format!(
76 "{:.*}",
77 self.total.currency.precision as usize,
78 self.total.as_f64()
79 ),
80 )?;
81 dict.set_item(
82 "locked",
83 format!(
84 "{:.*}",
85 self.locked.currency.precision as usize,
86 self.locked.as_f64()
87 ),
88 )?;
89 dict.set_item(
90 "free",
91 format!(
92 "{:.*}",
93 self.free.currency.precision as usize,
94 self.free.as_f64()
95 ),
96 )?;
97 dict.set_item("currency", self.currency.code.to_string())?;
98 Ok(dict.into())
99 }
100}
101
102#[pymethods]
103impl MarginBalance {
104 #[new]
105 fn py_new(initial: Money, maintenance: Money, instrument: InstrumentId) -> Self {
106 Self::new(initial, maintenance, instrument)
107 }
108 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
109 match op {
110 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
111 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
112 _ => py.NotImplemented(),
113 }
114 }
115
116 fn __repr__(&self) -> String {
117 format!("{self:?}")
118 }
119
120 fn __str__(&self) -> String {
121 self.to_string()
122 }
123
124 #[staticmethod]
125 #[pyo3(name = "from_dict")]
126 pub fn py_from_dict(values: &Bound<'_, PyDict>) -> PyResult<Self> {
127 let dict = values.as_ref();
128 let currency: String = dict.get_item("currency")?.extract()?;
129 let initial_str: String = dict.get_item("initial")?.extract()?;
130 let initial: f64 = initial_str.parse::<f64>().unwrap();
131 let maintenance_str: String = dict.get_item("maintenance")?.extract()?;
132 let maintenance: f64 = maintenance_str.parse::<f64>().unwrap();
133 let instrument_id_str: String = dict.get_item("instrument_id")?.extract()?;
134 let currency = Currency::from_str(currency.as_str()).map_err(to_pyvalue_err)?;
135 let account_balance = Self::new(
136 Money::new(initial, currency),
137 Money::new(maintenance, currency),
138 InstrumentId::from(instrument_id_str.as_str()),
139 );
140 Ok(account_balance)
141 }
142
143 #[pyo3(name = "to_dict")]
144 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
145 let dict = PyDict::new(py);
146 dict.set_item("type", stringify!(MarginBalance))?;
147 dict.set_item(
148 "initial",
149 format!(
150 "{:.*}",
151 self.initial.currency.precision as usize,
152 self.initial.as_f64()
153 ),
154 )?;
155 dict.set_item(
156 "maintenance",
157 format!(
158 "{:.*}",
159 self.maintenance.currency.precision as usize,
160 self.maintenance.as_f64()
161 ),
162 )?;
163 dict.set_item("currency", self.currency.code.to_string())?;
164 dict.set_item("instrument_id", self.instrument_id.to_string())?;
165 Ok(dict.into())
166 }
167}