Skip to main content

nautilus_common/messages/
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//! Message types for system communication.
17//!
18//! This module provides message types used for communication between different
19//! parts of the NautilusTrader system, including data requests, execution commands,
20//! and system control messages.
21
22use nautilus_model::{
23    data::Data,
24    events::{
25        AccountState, OrderAcceptedBatch, OrderCanceledBatch, OrderEventAny, OrderSubmittedBatch,
26    },
27};
28use strum::Display;
29
30pub mod data;
31pub mod execution;
32pub mod system;
33
34#[cfg(feature = "defi")]
35pub mod defi;
36
37// Re-exports
38pub use data::{DataResponse, SubscribeCommand, UnsubscribeCommand};
39pub use execution::ExecutionReport;
40
41// TODO: Refine this to reduce disparity between enum sizes
42#[allow(
43    clippy::large_enum_variant,
44    reason = "event enum keeps all data variants in one routing type"
45)]
46#[derive(Debug, Display)]
47pub enum DataEvent {
48    Data(Data),
49    Response(DataResponse),
50    RequestFailed(data::DataRequestFailed),
51    ResponseEnvelope(data::DataResponseEnvelope),
52    // nautilus-import-ok: conditional compilation import
53    #[cfg(feature = "defi")]
54    DeFi(nautilus_model::defi::data::DefiData),
55    #[cfg(feature = "defi")]
56    PoolSnapshotResponse(defi::PoolSnapshotResponse),
57}
58
59/// System command variants routed to a live node.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Display)]
61pub enum SystemCommand {
62    #[strum(transparent)]
63    ReconnectSocket(system::ReconnectSocket),
64}
65
66/// System event variants routed to a live node.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Display)]
68pub enum SystemEvent {
69    #[strum(transparent)]
70    SocketState(system::SocketStateChange),
71}
72
73/// Execution event variants for order events and reports.
74#[allow(clippy::large_enum_variant)]
75#[derive(Debug, Display)]
76pub enum ExecutionEvent {
77    #[strum(transparent)]
78    Order(OrderEventAny),
79    #[strum(transparent)]
80    OrderSubmittedBatch(OrderSubmittedBatch),
81    #[strum(transparent)]
82    OrderAcceptedBatch(OrderAcceptedBatch),
83    #[strum(transparent)]
84    OrderCanceledBatch(OrderCanceledBatch),
85    #[strum(transparent)]
86    Report(ExecutionReport),
87    #[strum(transparent)]
88    Account(AccountState),
89}
90
91#[cfg(test)]
92mod tests {
93    use nautilus_core::{UUID4, UnixNanos};
94    use nautilus_model::{
95        enums::AccountType,
96        events::OrderInitialized,
97        identifiers::{AccountId, ClientId, TraderId, Venue},
98        reports::ExecutionMassStatus,
99    };
100    use rstest::rstest;
101    use ustr::Ustr;
102
103    use super::*;
104    use crate::messages::system::{ReconnectSocket, SocketState, SocketStateChange};
105
106    #[rstest]
107    fn system_messages_delegate_display_to_inner() {
108        let command = ReconnectSocket::new(
109            TraderId::from("TRADER-001"),
110            ClientId::from("BINANCE"),
111            Ustr::from("orders"),
112            UnixNanos::from(1),
113        );
114        let event = SocketStateChange::new(
115            ClientId::from("BINANCE"),
116            Some(Venue::from("BINANCE")),
117            Ustr::from("orders"),
118            SocketState::Connected,
119        );
120        let command_expected = command.to_string();
121        let event_expected = event.to_string();
122
123        assert_eq!(
124            SystemCommand::ReconnectSocket(command).to_string(),
125            command_expected
126        );
127        assert_eq!(SystemEvent::SocketState(event).to_string(), event_expected);
128    }
129
130    #[rstest]
131    fn execution_events_delegate_display_to_inner() {
132        let order = OrderEventAny::Initialized(OrderInitialized::default());
133        let submitted_batch = OrderSubmittedBatch::new(Vec::new());
134        let accepted_batch = OrderAcceptedBatch::new(Vec::new());
135        let canceled_batch = OrderCanceledBatch::new(Vec::new());
136        let report = ExecutionReport::MassStatus(Box::new(ExecutionMassStatus::new(
137            ClientId::from("BINANCE"),
138            AccountId::from("BINANCE-001"),
139            Venue::from("BINANCE"),
140            UnixNanos::from(2),
141            Some(UUID4::from("00000000-0000-4000-8000-000000000001")),
142        )));
143        let account = AccountState::new(
144            AccountId::from("BINANCE-001"),
145            AccountType::Cash,
146            Vec::new(),
147            Vec::new(),
148            true,
149            UUID4::from("00000000-0000-4000-8000-000000000002"),
150            UnixNanos::from(3),
151            UnixNanos::from(4),
152            None,
153        );
154        let cases = [
155            (ExecutionEvent::Order(order.clone()), order.to_string()),
156            (
157                ExecutionEvent::OrderSubmittedBatch(submitted_batch.clone()),
158                submitted_batch.to_string(),
159            ),
160            (
161                ExecutionEvent::OrderAcceptedBatch(accepted_batch.clone()),
162                accepted_batch.to_string(),
163            ),
164            (
165                ExecutionEvent::OrderCanceledBatch(canceled_batch.clone()),
166                canceled_batch.to_string(),
167            ),
168            (ExecutionEvent::Report(report.clone()), report.to_string()),
169            (
170                ExecutionEvent::Account(account.clone()),
171                account.to_string(),
172            ),
173        ];
174
175        for (event, expected) in cases {
176            assert_eq!(event.to_string(), expected);
177        }
178    }
179}