nautilus_execution/client/
mod.rs1use std::{
19 fmt::Debug,
20 ops::{Deref, DerefMut},
21};
22
23use async_trait::async_trait;
24use nautilus_common::messages::execution::{
25 BatchCancelOrders, CancelAllOrders, CancelOrder, GenerateFillReports,
26 GenerateOrderStatusReport, GenerateOrderStatusReports, GeneratePositionStatusReports,
27 ModifyOrder, QueryAccount, QueryOrder, SubmitOrder, SubmitOrderList,
28};
29use nautilus_core::UnixNanos;
30use nautilus_model::{
31 accounts::AccountAny,
32 enums::OmsType,
33 identifiers::{AccountId, ClientId, Venue},
34 reports::{ExecutionMassStatus, FillReport, OrderStatusReport, PositionStatusReport},
35 types::{AccountBalance, MarginBalance},
36};
37
38pub mod base;
39
40#[async_trait(?Send)]
47pub trait ExecutionClient {
48 fn is_connected(&self) -> bool;
49 fn client_id(&self) -> ClientId;
50 fn account_id(&self) -> AccountId;
51 fn venue(&self) -> Venue;
52 fn oms_type(&self) -> OmsType;
53 fn get_account(&self) -> Option<AccountAny>;
54
55 fn generate_account_state(
61 &self,
62 balances: Vec<AccountBalance>,
63 margins: Vec<MarginBalance>,
64 reported: bool,
65 ts_event: UnixNanos,
66 ) -> anyhow::Result<()>;
67
68 fn start(&mut self) -> anyhow::Result<()>;
74
75 fn stop(&mut self) -> anyhow::Result<()>;
81
82 async fn connect(&mut self) -> anyhow::Result<()> {
88 Ok(())
89 }
90
91 async fn disconnect(&mut self) -> anyhow::Result<()> {
97 Ok(())
98 }
99
100 fn submit_order(&self, cmd: &SubmitOrder) -> anyhow::Result<()> {
106 log_not_implemented(cmd);
107 Ok(())
108 }
109
110 fn submit_order_list(&self, cmd: &SubmitOrderList) -> anyhow::Result<()> {
116 log_not_implemented(cmd);
117 Ok(())
118 }
119
120 fn modify_order(&self, cmd: &ModifyOrder) -> anyhow::Result<()> {
126 log_not_implemented(cmd);
127 Ok(())
128 }
129
130 fn cancel_order(&self, cmd: &CancelOrder) -> anyhow::Result<()> {
136 log_not_implemented(cmd);
137 Ok(())
138 }
139
140 fn cancel_all_orders(&self, cmd: &CancelAllOrders) -> anyhow::Result<()> {
146 log_not_implemented(cmd);
147 Ok(())
148 }
149
150 fn batch_cancel_orders(&self, cmd: &BatchCancelOrders) -> anyhow::Result<()> {
156 log_not_implemented(cmd);
157 Ok(())
158 }
159
160 fn query_account(&self, cmd: &QueryAccount) -> anyhow::Result<()> {
166 log_not_implemented(cmd);
167 Ok(())
168 }
169
170 fn query_order(&self, cmd: &QueryOrder) -> anyhow::Result<()> {
176 log_not_implemented(cmd);
177 Ok(())
178 }
179
180 async fn generate_order_status_report(
186 &self,
187 cmd: &GenerateOrderStatusReport,
188 ) -> anyhow::Result<Option<OrderStatusReport>> {
189 log_not_implemented(cmd);
190 Ok(None)
191 }
192
193 async fn generate_order_status_reports(
199 &self,
200 cmd: &GenerateOrderStatusReports,
201 ) -> anyhow::Result<Vec<OrderStatusReport>> {
202 log_not_implemented(cmd);
203 Ok(Vec::new())
204 }
205
206 async fn generate_fill_reports(
212 &self,
213 cmd: GenerateFillReports,
214 ) -> anyhow::Result<Vec<FillReport>> {
215 log_not_implemented(&cmd);
216 Ok(Vec::new())
217 }
218
219 async fn generate_position_status_reports(
225 &self,
226 cmd: &GeneratePositionStatusReports,
227 ) -> anyhow::Result<Vec<PositionStatusReport>> {
228 log_not_implemented(cmd);
229 Ok(Vec::new())
230 }
231
232 async fn generate_mass_status(
238 &self,
239 lookback_mins: Option<u64>,
240 ) -> anyhow::Result<Option<ExecutionMassStatus>> {
241 log_not_implemented(&lookback_mins);
242 Ok(None)
243 }
244}
245
246#[inline(always)]
247fn log_not_implemented<T: Debug>(cmd: &T) {
248 log::warn!("{cmd:?} – handler not implemented");
249}
250
251pub struct ExecutionClientAdapter {
253 pub(crate) client: Box<dyn ExecutionClient>,
254 pub client_id: ClientId,
255 pub venue: Venue,
256 pub account_id: AccountId,
257 pub oms_type: OmsType,
258}
259
260impl Deref for ExecutionClientAdapter {
261 type Target = Box<dyn ExecutionClient>;
262
263 fn deref(&self) -> &Self::Target {
264 &self.client
265 }
266}
267
268impl DerefMut for ExecutionClientAdapter {
269 fn deref_mut(&mut self) -> &mut Self::Target {
270 &mut self.client
271 }
272}
273
274impl Debug for ExecutionClientAdapter {
275 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
276 f.debug_struct(stringify!(ExecutionClientAdapter))
277 .field("client_id", &self.client_id)
278 .field("venue", &self.venue)
279 .field("account_id", &self.account_id)
280 .field("oms_type", &self.oms_type)
281 .finish()
282 }
283}
284
285impl ExecutionClientAdapter {
286 #[must_use]
288 pub fn new(client: Box<dyn ExecutionClient>) -> Self {
289 let client_id = client.client_id();
290 let venue = client.venue();
291 let account_id = client.account_id();
292 let oms_type = client.oms_type();
293
294 Self {
295 client,
296 client_id,
297 venue,
298 account_id,
299 oms_type,
300 }
301 }
302
303 pub async fn connect(&mut self) -> anyhow::Result<()> {
309 self.client.connect().await
310 }
311
312 pub async fn disconnect(&mut self) -> anyhow::Result<()> {
318 self.client.disconnect().await
319 }
320
321 pub async fn generate_order_status_report(
327 &self,
328 cmd: &GenerateOrderStatusReport,
329 ) -> anyhow::Result<Option<OrderStatusReport>> {
330 self.client.generate_order_status_report(cmd).await
331 }
332
333 pub async fn generate_order_status_reports(
339 &self,
340 cmd: &GenerateOrderStatusReports,
341 ) -> anyhow::Result<Vec<OrderStatusReport>> {
342 self.client.generate_order_status_reports(cmd).await
343 }
344
345 pub async fn generate_fill_reports(
351 &self,
352 cmd: GenerateFillReports,
353 ) -> anyhow::Result<Vec<FillReport>> {
354 self.client.generate_fill_reports(cmd).await
355 }
356
357 pub async fn generate_position_status_reports(
363 &self,
364 cmd: &GeneratePositionStatusReports,
365 ) -> anyhow::Result<Vec<PositionStatusReport>> {
366 self.client.generate_position_status_reports(cmd).await
367 }
368
369 pub async fn generate_mass_status(
375 &self,
376 lookback_mins: Option<u64>,
377 ) -> anyhow::Result<Option<ExecutionMassStatus>> {
378 self.client.generate_mass_status(lookback_mins).await
379 }
380}