nautilus_model/python/orders/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Posei Systems Pty Ltd. All rights reserved.
3//  https://poseitrader.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, PyObject, 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.
42pub fn pyobject_to_order_any(py: Python, order: PyObject) -> PyResult<OrderAny> {
43    let order_type = order.getattr(py, "order_type")?.extract::<OrderType>(py)?;
44    if order_type == OrderType::Limit {
45        let limit = order.extract::<LimitOrder>(py)?;
46        Ok(OrderAny::Limit(limit))
47    } else if order_type == OrderType::Market {
48        let market = order.extract::<MarketOrder>(py)?;
49        Ok(OrderAny::Market(market))
50    } else if order_type == OrderType::StopLimit {
51        let stop_limit = order.extract::<StopLimitOrder>(py)?;
52        Ok(OrderAny::StopLimit(stop_limit))
53    } else if order_type == OrderType::LimitIfTouched {
54        let limit_if_touched = order.extract::<LimitIfTouchedOrder>(py)?;
55        Ok(OrderAny::LimitIfTouched(limit_if_touched))
56    } else if order_type == OrderType::MarketIfTouched {
57        let market_if_touched = order.extract::<MarketIfTouchedOrder>(py)?;
58        Ok(OrderAny::MarketIfTouched(market_if_touched))
59    } else if order_type == OrderType::MarketToLimit {
60        let market_to_limit = order.extract::<MarketToLimitOrder>(py)?;
61        Ok(OrderAny::MarketToLimit(market_to_limit))
62    } else if order_type == OrderType::StopMarket {
63        let stop_market = order.extract::<StopMarketOrder>(py)?;
64        Ok(OrderAny::StopMarket(stop_market))
65    } else if order_type == OrderType::TrailingStopMarket {
66        let trailing_stop_market = order.extract::<TrailingStopMarketOrder>(py)?;
67        Ok(OrderAny::TrailingStopMarket(trailing_stop_market))
68    } else if order_type == OrderType::TrailingStopLimit {
69        let trailing_stop_limit = order.extract::<TrailingStopLimitOrder>(py)?;
70        Ok(OrderAny::TrailingStopLimit(trailing_stop_limit))
71    } else {
72        Err(to_pyvalue_err("Unsupported order type"))
73    }
74}
75
76/// Converts an [`OrderAny`] enum into a Python object.
77///
78/// # Errors
79///
80/// Returns a `PyErr` if conversion to a Python object fails.
81pub fn order_any_to_pyobject(py: Python, order: OrderAny) -> PyResult<PyObject> {
82    match order {
83        OrderAny::Limit(limit_order) => limit_order.into_py_any(py),
84        OrderAny::LimitIfTouched(limit_if_touched_order) => limit_if_touched_order.into_py_any(py),
85        OrderAny::Market(market_order) => market_order.into_py_any(py),
86        OrderAny::MarketIfTouched(market_if_touched_order) => {
87            market_if_touched_order.into_py_any(py)
88        }
89        OrderAny::MarketToLimit(market_to_limit_order) => market_to_limit_order.into_py_any(py),
90        OrderAny::StopLimit(stop_limit_order) => stop_limit_order.into_py_any(py),
91        OrderAny::StopMarket(stop_market_order) => stop_market_order.into_py_any(py),
92        OrderAny::TrailingStopLimit(trailing_stop_limit_order) => {
93            trailing_stop_limit_order.into_py_any(py)
94        }
95        OrderAny::TrailingStopMarket(trailing_stop_market_order) => {
96            trailing_stop_market_order.into_py_any(py)
97        }
98    }
99}