Skip to main content

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