nautilus_execution/python/
reconciliation.rs1use nautilus_core::python::to_pyvalue_err;
19use nautilus_model::{
20 python::instruments::pyobject_to_instrument_any, reports::ExecutionMassStatus,
21};
22use pyo3::{
23 IntoPyObjectExt,
24 prelude::*,
25 types::{PyDict, PyTuple},
26};
27use rust_decimal::Decimal;
28
29use crate::reconciliation::{
30 calculate_reconciliation_price, process_mass_status_for_reconciliation,
31};
32
33#[pyfunction(name = "adjust_fills_for_partial_window")]
46#[pyo3(signature = (mass_status, instrument, tolerance=None))]
47pub fn py_adjust_fills_for_partial_window(
48 py: Python<'_>,
49 mass_status: &Bound<'_, PyAny>,
50 instrument: Py<PyAny>,
51 tolerance: Option<String>,
52) -> PyResult<Py<PyTuple>> {
53 let instrument_any = pyobject_to_instrument_any(py, instrument)?;
54 let mass_status_obj: ExecutionMassStatus = mass_status.extract()?;
55
56 let tol = tolerance
57 .map(|s| Decimal::from_str_exact(&s).map_err(to_pyvalue_err))
58 .transpose()?;
59
60 let result = process_mass_status_for_reconciliation(&mass_status_obj, &instrument_any, tol)
61 .map_err(to_pyvalue_err)?;
62
63 let orders_dict = PyDict::new(py);
64 for (id, order) in result.orders {
65 orders_dict.set_item(id.to_string(), order.into_py_any(py)?)?;
66 }
67
68 let fills_dict = PyDict::new(py);
69 for (id, fills) in result.fills {
70 let fills_list: Result<Vec<_>, _> = fills.into_iter().map(|f| f.into_py_any(py)).collect();
71 fills_dict.set_item(id.to_string(), fills_list?)?;
72 }
73
74 Ok(PyTuple::new(
75 py,
76 [orders_dict.into_py_any(py)?, fills_dict.into_py_any(py)?],
77 )?
78 .into())
79}
80
81#[pyfunction(name = "calculate_reconciliation_price")]
83#[pyo3(signature = (current_position_qty, current_position_avg_px, target_position_qty, target_position_avg_px))]
84pub fn py_calculate_reconciliation_price(
85 current_position_qty: Decimal,
86 current_position_avg_px: Option<Decimal>,
87 target_position_qty: Decimal,
88 target_position_avg_px: Option<Decimal>,
89) -> Option<Decimal> {
90 calculate_reconciliation_price(
91 current_position_qty,
92 current_position_avg_px,
93 target_position_qty,
94 target_position_avg_px,
95 )
96}