Skip to main content

nautilus_common/messages/execution/
submit.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 std::fmt::Display;
17
18use indexmap::IndexMap;
19use nautilus_core::{UUID4, UnixNanos, correctness::check_equal};
20use nautilus_model::{
21    events::OrderInitialized,
22    identifiers::{
23        ClientId, ClientOrderId, ExecAlgorithmId, InstrumentId, PositionId, StrategyId, TraderId,
24    },
25    orders::{Order, OrderAny, OrderList},
26};
27use serde::{Deserialize, Serialize};
28
29#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
30#[serde(tag = "type")]
31pub struct SubmitOrder {
32    pub trader_id: TraderId,
33    pub client_id: Option<ClientId>,
34    pub strategy_id: StrategyId,
35    pub instrument_id: InstrumentId,
36    pub client_order_id: ClientOrderId,
37    pub order_init: OrderInitialized,
38    pub exec_algorithm_id: Option<ExecAlgorithmId>,
39    pub position_id: Option<PositionId>,
40    pub params: Option<IndexMap<String, String>>,
41    pub command_id: UUID4,
42    pub ts_init: UnixNanos,
43}
44
45impl SubmitOrder {
46    /// Creates a new [`SubmitOrder`] instance.
47    #[allow(clippy::too_many_arguments)]
48    #[must_use]
49    pub const fn new(
50        trader_id: TraderId,
51        client_id: Option<ClientId>,
52        strategy_id: StrategyId,
53        instrument_id: InstrumentId,
54        client_order_id: ClientOrderId,
55        order_init: OrderInitialized,
56        exec_algorithm_id: Option<ExecAlgorithmId>,
57        position_id: Option<PositionId>,
58        params: Option<IndexMap<String, String>>,
59        command_id: UUID4,
60        ts_init: UnixNanos,
61    ) -> Self {
62        Self {
63            trader_id,
64            client_id,
65            strategy_id,
66            instrument_id,
67            client_order_id,
68            order_init,
69            exec_algorithm_id,
70            position_id,
71            params,
72            command_id,
73            ts_init,
74        }
75    }
76
77    /// Creates a new [`SubmitOrder`] from an existing order.
78    #[allow(clippy::too_many_arguments)]
79    #[must_use]
80    pub fn from_order(
81        order: &OrderAny,
82        trader_id: TraderId,
83        client_id: Option<ClientId>,
84        position_id: Option<PositionId>,
85        command_id: UUID4,
86        ts_init: UnixNanos,
87    ) -> Self {
88        Self {
89            trader_id,
90            client_id,
91            strategy_id: order.strategy_id(),
92            instrument_id: order.instrument_id(),
93            client_order_id: order.client_order_id(),
94            order_init: OrderInitialized::from(order),
95            exec_algorithm_id: order.exec_algorithm_id(),
96            position_id,
97            params: None,
98            command_id,
99            ts_init,
100        }
101    }
102}
103
104impl Display for SubmitOrder {
105    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        write!(
107            f,
108            "SubmitOrder(instrument_id={}, client_order_id={}, position_id={})",
109            self.instrument_id,
110            self.client_order_id,
111            self.position_id
112                .map_or("None".to_string(), |position_id| format!("{position_id}")),
113        )
114    }
115}
116
117#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
118#[serde(tag = "type")]
119pub struct SubmitOrderList {
120    pub trader_id: TraderId,
121    pub client_id: Option<ClientId>,
122    pub strategy_id: StrategyId,
123    pub instrument_id: InstrumentId,
124    pub order_list: OrderList,
125    pub order_inits: Vec<OrderInitialized>,
126    pub exec_algorithm_id: Option<ExecAlgorithmId>,
127    pub position_id: Option<PositionId>,
128    pub params: Option<IndexMap<String, String>>,
129    pub command_id: UUID4,
130    pub ts_init: UnixNanos,
131}
132
133impl SubmitOrderList {
134    /// Creates a new [`SubmitOrderList`] instance.
135    ///
136    /// # Panics
137    ///
138    /// Panics if `order_inits` length doesn't match `order_list.client_order_ids`, or if
139    /// the client order IDs don't match in order.
140    #[allow(clippy::too_many_arguments)]
141    #[must_use]
142    pub fn new(
143        trader_id: TraderId,
144        client_id: Option<ClientId>,
145        strategy_id: StrategyId,
146        order_list: OrderList,
147        order_inits: Vec<OrderInitialized>,
148        exec_algorithm_id: Option<ExecAlgorithmId>,
149        position_id: Option<PositionId>,
150        params: Option<IndexMap<String, String>>,
151        command_id: UUID4,
152        ts_init: UnixNanos,
153    ) -> Self {
154        check_equal(
155            &order_inits.len(),
156            &order_list.client_order_ids.len(),
157            "order_inits.len()",
158            "order_list.client_order_ids.len()",
159        )
160        .unwrap();
161
162        for (init, id) in order_inits.iter().zip(order_list.client_order_ids.iter()) {
163            check_equal(
164                &init.client_order_id,
165                id,
166                "order_init.client_order_id",
167                "order_list.client_order_ids id",
168            )
169            .unwrap();
170        }
171
172        Self {
173            trader_id,
174            client_id,
175            strategy_id,
176            instrument_id: order_list.instrument_id,
177            order_list,
178            order_inits,
179            exec_algorithm_id,
180            position_id,
181            params,
182            command_id,
183            ts_init,
184        }
185    }
186}
187
188impl Display for SubmitOrderList {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        write!(
191            f,
192            "SubmitOrderList(instrument_id={}, order_list={}, position_id={})",
193            self.instrument_id,
194            self.order_list.id,
195            self.position_id
196                .map_or("None".to_string(), |position_id| format!("{position_id}")),
197        )
198    }
199}