Skip to main content

nautilus_model/python/orders/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 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 nautilus_core::python::to_pyvalue_err;
17use pyo3::{IntoPyObjectExt, Py, PyAny, PyResult, Python};
18
19use crate::{
20    enums::OrderType,
21    orders::{
22        LimitIfTouchedOrder, LimitOrder, MarketIfTouchedOrder, MarketOrder, MarketToLimitOrder,
23        OrderAny, StopLimitOrder, StopMarketOrder, TrailingStopLimitOrder, TrailingStopMarketOrder,
24    },
25};
26
27pub mod limit;
28pub mod limit_if_touched;
29pub mod market;
30pub mod market_if_touched;
31pub mod market_to_limit;
32pub mod stop_limit;
33pub mod stop_market;
34pub mod trailing_stop_limit;
35pub mod trailing_stop_market;
36
37/// Converts a Python order object into an [`OrderAny`] enum.
38///
39/// # Errors
40///
41/// Returns a `PyErr` if extraction fails or the order type is unsupported.
42#[expect(clippy::needless_pass_by_value)]
43pub fn pyobject_to_order_any(py: Python, order: Py<PyAny>) -> PyResult<OrderAny> {
44    let order_type = order.getattr(py, "order_type")?.extract::<OrderType>(py)?;
45    if order_type == OrderType::Limit {
46        let limit = order.extract::<LimitOrder>(py)?;
47        Ok(OrderAny::Limit(limit))
48    } else if order_type == OrderType::Market {
49        let market = order.extract::<MarketOrder>(py)?;
50        Ok(OrderAny::Market(market))
51    } else if order_type == OrderType::StopLimit {
52        let stop_limit = order.extract::<StopLimitOrder>(py)?;
53        Ok(OrderAny::StopLimit(stop_limit))
54    } else if order_type == OrderType::LimitIfTouched {
55        let limit_if_touched = order.extract::<LimitIfTouchedOrder>(py)?;
56        Ok(OrderAny::LimitIfTouched(limit_if_touched))
57    } else if order_type == OrderType::MarketIfTouched {
58        let market_if_touched = order.extract::<MarketIfTouchedOrder>(py)?;
59        Ok(OrderAny::MarketIfTouched(market_if_touched))
60    } else if order_type == OrderType::MarketToLimit {
61        let market_to_limit = order.extract::<MarketToLimitOrder>(py)?;
62        Ok(OrderAny::MarketToLimit(market_to_limit))
63    } else if order_type == OrderType::StopMarket {
64        let stop_market = order.extract::<StopMarketOrder>(py)?;
65        Ok(OrderAny::StopMarket(stop_market))
66    } else if order_type == OrderType::TrailingStopMarket {
67        let trailing_stop_market = order.extract::<TrailingStopMarketOrder>(py)?;
68        Ok(OrderAny::TrailingStopMarket(trailing_stop_market))
69    } else if order_type == OrderType::TrailingStopLimit {
70        let trailing_stop_limit = order.extract::<TrailingStopLimitOrder>(py)?;
71        Ok(OrderAny::TrailingStopLimit(trailing_stop_limit))
72    } else {
73        Err(to_pyvalue_err("Unsupported order type"))
74    }
75}
76
77/// Converts an [`OrderAny`] enum into a Python object.
78///
79/// # Errors
80///
81/// Returns a `PyErr` if conversion to a Python object fails.
82pub fn order_any_to_pyobject(py: Python, order: OrderAny) -> PyResult<Py<PyAny>> {
83    match order {
84        OrderAny::Limit(limit_order) => limit_order.into_py_any(py),
85        OrderAny::LimitIfTouched(limit_if_touched_order) => limit_if_touched_order.into_py_any(py),
86        OrderAny::Market(market_order) => market_order.into_py_any(py),
87        OrderAny::MarketIfTouched(market_if_touched_order) => {
88            market_if_touched_order.into_py_any(py)
89        }
90        OrderAny::MarketToLimit(market_to_limit_order) => market_to_limit_order.into_py_any(py),
91        OrderAny::StopLimit(stop_limit_order) => stop_limit_order.into_py_any(py),
92        OrderAny::StopMarket(stop_market_order) => stop_market_order.into_py_any(py),
93        OrderAny::TrailingStopLimit(trailing_stop_limit_order) => {
94            trailing_stop_limit_order.into_py_any(py)
95        }
96        OrderAny::TrailingStopMarket(trailing_stop_market_order) => {
97            trailing_stop_market_order.into_py_any(py)
98        }
99    }
100}