Skip to main content

nautilus_execution/client/
mod.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 implementations for trading venue connectivity.
17
18use std::{
19    fmt::Debug,
20    ops::{Deref, DerefMut},
21};
22
23use nautilus_common::messages::execution::{
24    GenerateFillReports, GenerateOrderStatusReport, GenerateOrderStatusReports,
25    GeneratePositionStatusReports,
26};
27use nautilus_core::UnixNanos;
28use nautilus_model::{
29    enums::OmsType,
30    identifiers::{
31        AccountId, ClientId, ClientOrderId, InstrumentId, StrategyId, Venue, VenueOrderId,
32    },
33    reports::{ExecutionMassStatus, FillReport, OrderStatusReport, PositionStatusReport},
34};
35
36pub mod core;
37
38use nautilus_common::clients::ExecutionClient;
39
40/// Wraps an [`ExecutionClient`], managing its lifecycle and providing access to the client.
41pub struct ExecutionClientAdapter {
42    pub(crate) client: Box<dyn ExecutionClient>,
43    pub client_id: ClientId,
44    pub venue: Venue,
45    pub account_id: AccountId,
46    pub oms_type: OmsType,
47}
48
49impl Deref for ExecutionClientAdapter {
50    type Target = Box<dyn ExecutionClient>;
51
52    fn deref(&self) -> &Self::Target {
53        &self.client
54    }
55}
56
57impl DerefMut for ExecutionClientAdapter {
58    fn deref_mut(&mut self) -> &mut Self::Target {
59        &mut self.client
60    }
61}
62
63impl Debug for ExecutionClientAdapter {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        f.debug_struct(stringify!(ExecutionClientAdapter))
66            .field("client_id", &self.client_id)
67            .field("venue", &self.venue)
68            .field("account_id", &self.account_id)
69            .field("oms_type", &self.oms_type)
70            .finish()
71    }
72}
73
74impl ExecutionClientAdapter {
75    /// Creates a new [`ExecutionClientAdapter`] with the given client.
76    #[must_use]
77    pub fn new(client: Box<dyn ExecutionClient>) -> Self {
78        let client_id = client.client_id();
79        let venue = client.venue();
80        let account_id = client.account_id();
81        let oms_type = client.oms_type();
82
83        Self {
84            client,
85            client_id,
86            venue,
87            account_id,
88            oms_type,
89        }
90    }
91
92    /// Connects the execution client to the venue.
93    ///
94    /// # Errors
95    ///
96    /// Returns an error if connection fails.
97    pub async fn connect(&mut self) -> anyhow::Result<()> {
98        self.client.connect().await
99    }
100
101    /// Disconnects the execution client from the venue.
102    ///
103    /// # Errors
104    ///
105    /// Returns an error if disconnection fails.
106    pub async fn disconnect(&mut self) -> anyhow::Result<()> {
107        self.client.disconnect().await
108    }
109
110    /// Generates a single order status report.
111    ///
112    /// # Errors
113    ///
114    /// Returns an error if report generation fails.
115    pub async fn generate_order_status_report(
116        &self,
117        cmd: &GenerateOrderStatusReport,
118    ) -> anyhow::Result<Option<OrderStatusReport>> {
119        self.client.generate_order_status_report(cmd).await
120    }
121
122    /// Generates multiple order status reports.
123    ///
124    /// # Errors
125    ///
126    /// Returns an error if report generation fails.
127    pub async fn generate_order_status_reports(
128        &self,
129        cmd: &GenerateOrderStatusReports,
130    ) -> anyhow::Result<Vec<OrderStatusReport>> {
131        self.client.generate_order_status_reports(cmd).await
132    }
133
134    /// Generates fill reports based on execution results.
135    ///
136    /// # Errors
137    ///
138    /// Returns an error if fill report generation fails.
139    pub async fn generate_fill_reports(
140        &self,
141        cmd: GenerateFillReports,
142    ) -> anyhow::Result<Vec<FillReport>> {
143        self.client.generate_fill_reports(cmd).await
144    }
145
146    /// Generates position status reports.
147    ///
148    /// # Errors
149    ///
150    /// Returns an error if generation fails.
151    pub async fn generate_position_status_reports(
152        &self,
153        cmd: &GeneratePositionStatusReports,
154    ) -> anyhow::Result<Vec<PositionStatusReport>> {
155        self.client.generate_position_status_reports(cmd).await
156    }
157
158    /// Generates mass status for executions.
159    ///
160    /// # Errors
161    ///
162    /// Returns an error if status generation fails.
163    pub async fn generate_mass_status(
164        &self,
165        lookback_mins: Option<u64>,
166    ) -> anyhow::Result<Option<ExecutionMassStatus>> {
167        self.client.generate_mass_status(lookback_mins).await
168    }
169
170    /// Registers an external order for tracking by the execution client.
171    ///
172    /// This is called after reconciliation creates an external order, allowing the
173    /// execution client to track it for subsequent events (e.g., cancellations).
174    pub fn register_external_order(
175        &self,
176        client_order_id: ClientOrderId,
177        venue_order_id: VenueOrderId,
178        instrument_id: InstrumentId,
179        strategy_id: StrategyId,
180        ts_init: UnixNanos,
181    ) {
182        self.client.register_external_order(
183            client_order_id,
184            venue_order_id,
185            instrument_id,
186            strategy_id,
187            ts_init,
188        );
189    }
190}