nautilus_common/clients/execution.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
16//! Execution client trait definition.
17
18use async_trait::async_trait;
19use nautilus_core::UnixNanos;
20use nautilus_model::{
21 accounts::AccountAny,
22 enums::OmsType,
23 identifiers::{
24 AccountId, ClientId, ClientOrderId, InstrumentId, StrategyId, Venue, VenueOrderId,
25 },
26 instruments::InstrumentAny,
27 reports::{ExecutionMassStatus, FillReport, OrderStatusReport, PositionStatusReport},
28 types::{AccountBalance, MarginBalance},
29};
30
31use super::log_not_implemented;
32use crate::messages::execution::{
33 BatchCancelOrders, CancelAllOrders, CancelOrder, GenerateFillReports,
34 GenerateOrderStatusReport, GenerateOrderStatusReports, GeneratePositionStatusReports,
35 ModifyOrder, QueryAccount, QueryOrder, SubmitOrder, SubmitOrderList,
36};
37
38/// Defines the interface for an execution client managing order operations.
39///
40/// # Thread Safety
41///
42/// Client instances are not intended to be sent across threads. The `?Send` bound
43/// allows implementations to hold non-Send state for any Python interop.
44#[async_trait(?Send)]
45pub trait ExecutionClient {
46 fn is_connected(&self) -> bool;
47 fn client_id(&self) -> ClientId;
48 fn account_id(&self) -> AccountId;
49 fn venue(&self) -> Venue;
50 fn oms_type(&self) -> OmsType;
51 fn get_account(&self) -> Option<AccountAny>;
52
53 /// Generates and publishes the account state event.
54 ///
55 /// # Errors
56 ///
57 /// Returns an error if generating the account state fails.
58 fn generate_account_state(
59 &self,
60 balances: Vec<AccountBalance>,
61 margins: Vec<MarginBalance>,
62 reported: bool,
63 ts_event: UnixNanos,
64 ) -> anyhow::Result<()>;
65
66 /// Starts the execution client.
67 ///
68 /// # Errors
69 ///
70 /// Returns an error if the client fails to start.
71 fn start(&mut self) -> anyhow::Result<()>;
72
73 /// Stops the execution client.
74 ///
75 /// # Errors
76 ///
77 /// Returns an error if the client fails to stop.
78 fn stop(&mut self) -> anyhow::Result<()>;
79
80 /// Connects the client to the execution venue.
81 ///
82 /// # Errors
83 ///
84 /// Returns an error if connection fails.
85 async fn connect(&mut self) -> anyhow::Result<()> {
86 Ok(())
87 }
88
89 /// Disconnects the client from the execution venue.
90 ///
91 /// # Errors
92 ///
93 /// Returns an error if disconnection fails.
94 async fn disconnect(&mut self) -> anyhow::Result<()> {
95 Ok(())
96 }
97
98 /// Submits a single order command to the execution venue.
99 ///
100 /// # Errors
101 ///
102 /// Returns an error if submission fails.
103 fn submit_order(&self, cmd: &SubmitOrder) -> anyhow::Result<()> {
104 log_not_implemented(cmd);
105 Ok(())
106 }
107
108 /// Submits a list of orders to the execution venue.
109 ///
110 /// # Errors
111 ///
112 /// Returns an error if submission fails.
113 fn submit_order_list(&self, cmd: &SubmitOrderList) -> anyhow::Result<()> {
114 log_not_implemented(cmd);
115 Ok(())
116 }
117
118 /// Modifies an existing order.
119 ///
120 /// # Errors
121 ///
122 /// Returns an error if modification fails.
123 fn modify_order(&self, cmd: &ModifyOrder) -> anyhow::Result<()> {
124 log_not_implemented(cmd);
125 Ok(())
126 }
127
128 /// Cancels a specific order.
129 ///
130 /// # Errors
131 ///
132 /// Returns an error if cancellation fails.
133 fn cancel_order(&self, cmd: &CancelOrder) -> anyhow::Result<()> {
134 log_not_implemented(cmd);
135 Ok(())
136 }
137
138 /// Cancels all orders.
139 ///
140 /// # Errors
141 ///
142 /// Returns an error if cancellation fails.
143 fn cancel_all_orders(&self, cmd: &CancelAllOrders) -> anyhow::Result<()> {
144 log_not_implemented(cmd);
145 Ok(())
146 }
147
148 /// Cancels a batch of orders.
149 ///
150 /// # Errors
151 ///
152 /// Returns an error if batch cancellation fails.
153 fn batch_cancel_orders(&self, cmd: &BatchCancelOrders) -> anyhow::Result<()> {
154 log_not_implemented(cmd);
155 Ok(())
156 }
157
158 /// Queries the status of an account.
159 ///
160 /// # Errors
161 ///
162 /// Returns an error if the query fails.
163 fn query_account(&self, cmd: &QueryAccount) -> anyhow::Result<()> {
164 log_not_implemented(cmd);
165 Ok(())
166 }
167
168 /// Queries the status of an order.
169 ///
170 /// # Errors
171 ///
172 /// Returns an error if the query fails.
173 fn query_order(&self, cmd: &QueryOrder) -> anyhow::Result<()> {
174 log_not_implemented(cmd);
175 Ok(())
176 }
177
178 /// Generates a single order status report.
179 ///
180 /// # Errors
181 ///
182 /// Returns an error if report generation fails.
183 async fn generate_order_status_report(
184 &self,
185 cmd: &GenerateOrderStatusReport,
186 ) -> anyhow::Result<Option<OrderStatusReport>> {
187 log_not_implemented(cmd);
188 Ok(None)
189 }
190
191 /// Generates multiple order status reports.
192 ///
193 /// # Errors
194 ///
195 /// Returns an error if report generation fails.
196 async fn generate_order_status_reports(
197 &self,
198 cmd: &GenerateOrderStatusReports,
199 ) -> anyhow::Result<Vec<OrderStatusReport>> {
200 log_not_implemented(cmd);
201 Ok(Vec::new())
202 }
203
204 /// Generates fill reports based on execution results.
205 ///
206 /// # Errors
207 ///
208 /// Returns an error if fill report generation fails.
209 async fn generate_fill_reports(
210 &self,
211 cmd: GenerateFillReports,
212 ) -> anyhow::Result<Vec<FillReport>> {
213 log_not_implemented(&cmd);
214 Ok(Vec::new())
215 }
216
217 /// Generates position status reports.
218 ///
219 /// # Errors
220 ///
221 /// Returns an error if generation fails.
222 async fn generate_position_status_reports(
223 &self,
224 cmd: &GeneratePositionStatusReports,
225 ) -> anyhow::Result<Vec<PositionStatusReport>> {
226 log_not_implemented(cmd);
227 Ok(Vec::new())
228 }
229
230 /// Generates mass status for executions.
231 ///
232 /// # Errors
233 ///
234 /// Returns an error if status generation fails.
235 async fn generate_mass_status(
236 &self,
237 lookback_mins: Option<u64>,
238 ) -> anyhow::Result<Option<ExecutionMassStatus>> {
239 log_not_implemented(&lookback_mins);
240 Ok(None)
241 }
242
243 /// Registers an external order for tracking by the execution client.
244 ///
245 /// This is called after reconciliation creates an external order, allowing the
246 /// execution client to track it for subsequent events (e.g., cancellations).
247 fn register_external_order(
248 &self,
249 _client_order_id: ClientOrderId,
250 _venue_order_id: VenueOrderId,
251 _instrument_id: InstrumentId,
252 _strategy_id: StrategyId,
253 _ts_init: UnixNanos,
254 ) {
255 // Default no-op implementation
256 }
257
258 /// Handles an instrument update received via the message bus.
259 ///
260 /// Exec clients that need live instrument updates (e.g. for internal maps)
261 /// can override this to process instruments for their venue.
262 fn on_instrument(&mut self, _instrument: InstrumentAny) {
263 // Default no-op
264 }
265}