nautilus_execution/python/
mass_status.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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 indexmap::IndexMap;
17use nautilus_core::{python::serialization::from_dict_pyo3, UUID4};
18use nautilus_model::identifiers::{AccountId, ClientId, InstrumentId, Venue, VenueOrderId};
19use pyo3::{basic::CompareOp, prelude::*, types::PyDict};
20
21use crate::reports::{
22    fill::FillReport, mass_status::ExecutionMassStatus, order::OrderStatusReport,
23    position::PositionStatusReport,
24};
25
26#[pymethods]
27impl ExecutionMassStatus {
28    #[new]
29    #[pyo3(signature = (client_id, account_id, venue, ts_init, report_id=None))]
30    fn py_new(
31        client_id: ClientId,
32        account_id: AccountId,
33        venue: Venue,
34        ts_init: u64,
35        report_id: Option<UUID4>,
36    ) -> PyResult<Self> {
37        Ok(Self::new(
38            client_id,
39            account_id,
40            venue,
41            ts_init.into(),
42            report_id,
43        ))
44    }
45
46    fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
47        match op {
48            CompareOp::Eq => self.eq(other).into_py(py),
49            CompareOp::Ne => self.ne(other).into_py(py),
50            _ => py.NotImplemented(),
51        }
52    }
53
54    fn __repr__(&self) -> String {
55        self.to_string()
56    }
57
58    fn __str__(&self) -> String {
59        self.to_string()
60    }
61
62    #[getter]
63    #[pyo3(name = "client_id")]
64    const fn py_client_id(&self) -> ClientId {
65        self.client_id
66    }
67
68    #[getter]
69    #[pyo3(name = "account_id")]
70    const fn py_account_id(&self) -> AccountId {
71        self.account_id
72    }
73
74    #[getter]
75    #[pyo3(name = "venue")]
76    const fn py_venue(&self) -> Venue {
77        self.venue
78    }
79
80    #[getter]
81    #[pyo3(name = "report_id")]
82    const fn py_report_id(&self) -> UUID4 {
83        self.report_id
84    }
85
86    #[getter]
87    #[pyo3(name = "ts_init")]
88    const fn py_ts_init(&self) -> u64 {
89        self.ts_init.as_u64()
90    }
91
92    #[getter]
93    #[pyo3(name = "order_reports")]
94    fn py_order_reports(&self) -> PyResult<IndexMap<VenueOrderId, OrderStatusReport>> {
95        Ok(self.order_reports())
96    }
97
98    #[getter]
99    #[pyo3(name = "fill_reports")]
100    fn py_fill_reports(&self) -> PyResult<IndexMap<VenueOrderId, Vec<FillReport>>> {
101        Ok(self.fill_reports())
102    }
103
104    #[getter]
105    #[pyo3(name = "position_reports")]
106    fn py_position_reports(&self) -> PyResult<IndexMap<InstrumentId, Vec<PositionStatusReport>>> {
107        Ok(self.position_reports())
108    }
109
110    #[pyo3(name = "add_order_reports")]
111    fn py_add_order_reports(&mut self, reports: Vec<OrderStatusReport>) -> PyResult<()> {
112        self.add_order_reports(reports);
113        Ok(())
114    }
115
116    #[pyo3(name = "add_fill_reports")]
117    fn py_add_fill_reports(&mut self, reports: Vec<FillReport>) -> PyResult<()> {
118        self.add_fill_reports(reports);
119        Ok(())
120    }
121
122    #[pyo3(name = "add_position_reports")]
123    fn py_add_position_reports(&mut self, reports: Vec<PositionStatusReport>) -> PyResult<()> {
124        self.add_position_reports(reports);
125        Ok(())
126    }
127
128    #[staticmethod]
129    #[pyo3(name = "from_dict")]
130    pub fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
131        from_dict_pyo3(py, values)
132    }
133
134    #[pyo3(name = "to_dict")]
135    fn py_to_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
136        let dict = PyDict::new(py);
137        dict.set_item("type", stringify!(ExecutionMassStatus))?;
138        dict.set_item("client_id", self.client_id.to_string())?;
139        dict.set_item("account_id", self.account_id.to_string())?;
140        dict.set_item("venue", self.venue.to_string())?;
141        dict.set_item("report_id", self.report_id.to_string())?;
142        dict.set_item("ts_init", self.ts_init.as_u64())?;
143
144        let order_reports_dict = PyDict::new(py);
145        for (key, value) in &self.order_reports() {
146            order_reports_dict.set_item(key.to_string(), value.py_to_dict(py)?)?;
147        }
148        dict.set_item("order_reports", order_reports_dict)?;
149
150        let fill_reports_dict = PyDict::new(py);
151        for (key, value) in &self.fill_reports() {
152            let reports: PyResult<Vec<_>> = value.iter().map(|r| r.py_to_dict(py)).collect();
153            fill_reports_dict.set_item(key.to_string(), reports?)?;
154        }
155        dict.set_item("fill_reports", fill_reports_dict)?;
156
157        let position_reports_dict = PyDict::new(py);
158        for (key, value) in &self.position_reports() {
159            let reports: PyResult<Vec<_>> = value.iter().map(|r| r.py_to_dict(py)).collect();
160            position_reports_dict.set_item(key.to_string(), reports?)?;
161        }
162        dict.set_item("position_reports", position_reports_dict)?;
163
164        Ok(dict.into())
165    }
166}