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