nautilus_execution/python/
reconciliation.rs1use nautilus_core::{UnixNanos, python::to_pyvalue_err};
19use nautilus_model::{
20 enums::{OrderSide, OrderType},
21 identifiers::{AccountId, ClientOrderId, InstrumentId, PositionId, TradeId, VenueOrderId},
22 python::instruments::pyobject_to_instrument_any,
23 reports::ExecutionMassStatus,
24 types::{Price, Quantity},
25};
26use pyo3::{
27 IntoPyObjectExt,
28 prelude::*,
29 types::{PyDict, PyTuple},
30};
31use rust_decimal::Decimal;
32
33use crate::reconciliation::{
34 calculate_reconciliation_price, create_inferred_reconciliation_trade_id,
35 create_position_reconciliation_venue_order_id, process_mass_status_for_reconciliation,
36};
37
38#[pyfunction(name = "process_mass_status_for_reconciliation")]
45#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
46#[pyo3(signature = (mass_status, instrument, tolerance=None))]
47#[expect(clippy::missing_errors_doc)]
48pub fn py_process_mass_status_for_reconciliation(
49 py: Python<'_>,
50 mass_status: &Bound<'_, PyAny>,
51 instrument: Py<PyAny>,
52 tolerance: Option<String>,
53) -> PyResult<Py<PyTuple>> {
54 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
55 let mass_status_obj: ExecutionMassStatus = mass_status.extract()?;
56
57 let tol = tolerance
58 .map(|s| Decimal::from_str_exact(&s).map_err(to_pyvalue_err))
59 .transpose()?;
60
61 let result = process_mass_status_for_reconciliation(&mass_status_obj, &instrument_any, tol)
62 .map_err(to_pyvalue_err)?;
63
64 let orders_dict = PyDict::new(py);
65 for (id, order) in result.orders {
66 orders_dict.set_item(id.to_string(), order.into_py_any(py)?)?;
67 }
68
69 let fills_dict = PyDict::new(py);
70 for (id, fills) in result.fills {
71 let fills_list: Result<Vec<_>, _> = fills.into_iter().map(|f| f.into_py_any(py)).collect();
72 fills_dict.set_item(id.to_string(), fills_list?)?;
73 }
74
75 Ok(PyTuple::new(
76 py,
77 [orders_dict.into_py_any(py)?, fills_dict.into_py_any(py)?],
78 )?
79 .into())
80}
81
82#[pyfunction(name = "calculate_reconciliation_price")]
100#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
101#[pyo3(signature = (current_position_qty, current_position_avg_px, target_position_qty, target_position_avg_px))]
102pub fn py_calculate_reconciliation_price(
103 current_position_qty: Decimal,
104 current_position_avg_px: Option<Decimal>,
105 target_position_qty: Decimal,
106 target_position_avg_px: Option<Decimal>,
107) -> Option<Decimal> {
108 calculate_reconciliation_price(
109 current_position_qty,
110 current_position_avg_px,
111 target_position_qty,
112 target_position_avg_px,
113 )
114}
115
116#[pyfunction(name = "create_inferred_reconciliation_trade_id")]
123#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
124#[pyo3(signature = (account_id, instrument_id, client_order_id, venue_order_id, order_side, order_type, filled_qty, last_qty, last_px, position_id, ts_last))]
125#[expect(clippy::too_many_arguments)]
126pub fn py_create_inferred_reconciliation_trade_id(
127 account_id: AccountId,
128 instrument_id: InstrumentId,
129 client_order_id: ClientOrderId,
130 venue_order_id: Option<VenueOrderId>,
131 order_side: OrderSide,
132 order_type: OrderType,
133 filled_qty: Quantity,
134 last_qty: Quantity,
135 last_px: Price,
136 position_id: PositionId,
137 ts_last: u64,
138) -> TradeId {
139 create_inferred_reconciliation_trade_id(
140 account_id,
141 instrument_id,
142 client_order_id,
143 venue_order_id,
144 order_side,
145 order_type,
146 filled_qty,
147 last_qty,
148 last_px,
149 position_id,
150 UnixNanos::from(ts_last),
151 )
152}
153
154#[pyfunction(name = "create_position_reconciliation_venue_order_id")]
160#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
161#[pyo3(signature = (account_id, instrument_id, order_side, order_type, quantity, price=None, venue_position_id=None, ts_last=0, tag=None))]
162#[expect(clippy::needless_pass_by_value, clippy::too_many_arguments)]
163pub fn py_create_position_reconciliation_venue_order_id(
164 account_id: AccountId,
165 instrument_id: InstrumentId,
166 order_side: OrderSide,
167 order_type: OrderType,
168 quantity: Quantity,
169 price: Option<Price>,
170 venue_position_id: Option<PositionId>,
171 ts_last: u64,
172 tag: Option<String>,
173) -> VenueOrderId {
174 create_position_reconciliation_venue_order_id(
175 account_id,
176 instrument_id,
177 order_side,
178 order_type,
179 quantity,
180 price,
181 venue_position_id,
182 tag.as_deref(),
183 UnixNanos::from(ts_last),
184 )
185}