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 = "adjust_fills_for_partial_window")]
51#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
52#[pyo3(signature = (mass_status, instrument, tolerance=None))]
53pub fn py_adjust_fills_for_partial_window(
54 py: Python<'_>,
55 mass_status: &Bound<'_, PyAny>,
56 instrument: Py<PyAny>,
57 tolerance: Option<String>,
58) -> PyResult<Py<PyTuple>> {
59 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
60 let mass_status_obj: ExecutionMassStatus = mass_status.extract()?;
61
62 let tol = tolerance
63 .map(|s| Decimal::from_str_exact(&s).map_err(to_pyvalue_err))
64 .transpose()?;
65
66 let result = process_mass_status_for_reconciliation(&mass_status_obj, &instrument_any, tol)
67 .map_err(to_pyvalue_err)?;
68
69 let orders_dict = PyDict::new(py);
70 for (id, order) in result.orders {
71 orders_dict.set_item(id.to_string(), order.into_py_any(py)?)?;
72 }
73
74 let fills_dict = PyDict::new(py);
75 for (id, fills) in result.fills {
76 let fills_list: Result<Vec<_>, _> = fills.into_iter().map(|f| f.into_py_any(py)).collect();
77 fills_dict.set_item(id.to_string(), fills_list?)?;
78 }
79
80 Ok(PyTuple::new(
81 py,
82 [orders_dict.into_py_any(py)?, fills_dict.into_py_any(py)?],
83 )?
84 .into())
85}
86
87#[pyfunction(name = "calculate_reconciliation_price")]
105#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
106#[pyo3(signature = (current_position_qty, current_position_avg_px, target_position_qty, target_position_avg_px))]
107pub fn py_calculate_reconciliation_price(
108 current_position_qty: Decimal,
109 current_position_avg_px: Option<Decimal>,
110 target_position_qty: Decimal,
111 target_position_avg_px: Option<Decimal>,
112) -> Option<Decimal> {
113 calculate_reconciliation_price(
114 current_position_qty,
115 current_position_avg_px,
116 target_position_qty,
117 target_position_avg_px,
118 )
119}
120
121#[pyfunction(name = "create_inferred_reconciliation_trade_id")]
128#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
129#[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))]
130#[expect(clippy::too_many_arguments)]
131pub fn py_create_inferred_reconciliation_trade_id(
132 account_id: AccountId,
133 instrument_id: InstrumentId,
134 client_order_id: ClientOrderId,
135 venue_order_id: Option<VenueOrderId>,
136 order_side: OrderSide,
137 order_type: OrderType,
138 filled_qty: Quantity,
139 last_qty: Quantity,
140 last_px: Price,
141 position_id: PositionId,
142 ts_last: u64,
143) -> TradeId {
144 create_inferred_reconciliation_trade_id(
145 account_id,
146 instrument_id,
147 client_order_id,
148 venue_order_id,
149 order_side,
150 order_type,
151 filled_qty,
152 last_qty,
153 last_px,
154 position_id,
155 UnixNanos::from(ts_last),
156 )
157}
158
159#[pyfunction(name = "create_position_reconciliation_venue_order_id")]
165#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.execution")]
166#[pyo3(signature = (account_id, instrument_id, order_side, order_type, quantity, price=None, venue_position_id=None, ts_last=0, tag=None))]
167#[expect(clippy::needless_pass_by_value, clippy::too_many_arguments)]
168pub fn py_create_position_reconciliation_venue_order_id(
169 account_id: AccountId,
170 instrument_id: InstrumentId,
171 order_side: OrderSide,
172 order_type: OrderType,
173 quantity: Quantity,
174 price: Option<Price>,
175 venue_position_id: Option<PositionId>,
176 ts_last: u64,
177 tag: Option<String>,
178) -> VenueOrderId {
179 create_position_reconciliation_venue_order_id(
180 account_id,
181 instrument_id,
182 order_side,
183 order_type,
184 quantity,
185 price,
186 venue_position_id,
187 tag.as_deref(),
188 UnixNanos::from(ts_last),
189 )
190}