1use std::{any::Any, sync::Arc};
19
20use nautilus_core::{UUID4, UnixNanos};
21use nautilus_model::{
22 data::BarType,
23 identifiers::{ClientId, Venue},
24};
25
26pub mod request;
27pub mod response;
28pub mod subscribe;
29pub mod unsubscribe;
30
31pub use request::{
33 RequestBars, RequestBookSnapshot, RequestCustomData, RequestInstrument, RequestInstruments,
34 RequestQuotes, RequestTrades,
35};
36pub use response::{
37 BarsResponse, BookResponse, CustomDataResponse, InstrumentResponse, InstrumentsResponse,
38 QuotesResponse, TradesResponse,
39};
40pub use subscribe::{
41 SubscribeBars, SubscribeBookDeltas, SubscribeBookDepth10, SubscribeBookSnapshots,
42 SubscribeCustomData, SubscribeIndexPrices, SubscribeInstrument, SubscribeInstrumentClose,
43 SubscribeInstrumentStatus, SubscribeInstruments, SubscribeMarkPrices, SubscribeQuotes,
44 SubscribeTrades,
45};
46pub use unsubscribe::{
47 UnsubscribeBars, UnsubscribeBookDeltas, UnsubscribeBookDepth10, UnsubscribeBookSnapshots,
48 UnsubscribeCustomData, UnsubscribeIndexPrices, UnsubscribeInstrument,
49 UnsubscribeInstrumentClose, UnsubscribeInstrumentStatus, UnsubscribeInstruments,
50 UnsubscribeMarkPrices, UnsubscribeQuotes, UnsubscribeTrades,
51};
52
53#[cfg(feature = "defi")]
54use crate::messages::defi::{DefiSubscribeCommand, DefiUnsubscribeCommand};
55
56#[derive(Clone, Debug, PartialEq)]
57pub enum DataCommand {
58 Request(RequestCommand),
59 Subscribe(SubscribeCommand),
60 Unsubscribe(UnsubscribeCommand),
61 #[cfg(feature = "defi")]
62 DefiSubscribe(DefiSubscribeCommand),
63 #[cfg(feature = "defi")]
64 DefiUnsubscribe(DefiUnsubscribeCommand),
65}
66
67impl DataCommand {
68 pub fn as_any(&self) -> &dyn Any {
70 self
71 }
72}
73
74#[derive(Clone, Debug)]
75pub enum SubscribeCommand {
76 Data(SubscribeCustomData),
77 Instrument(SubscribeInstrument),
78 Instruments(SubscribeInstruments),
79 BookDeltas(SubscribeBookDeltas),
80 BookDepth10(SubscribeBookDepth10),
81 BookSnapshots(SubscribeBookSnapshots),
82 Quotes(SubscribeQuotes),
83 Trades(SubscribeTrades),
84 Bars(SubscribeBars),
85 MarkPrices(SubscribeMarkPrices),
86 IndexPrices(SubscribeIndexPrices),
87 InstrumentStatus(SubscribeInstrumentStatus),
88 InstrumentClose(SubscribeInstrumentClose),
89}
90
91impl PartialEq for SubscribeCommand {
92 fn eq(&self, other: &Self) -> bool {
93 self.command_id() == other.command_id()
94 }
95}
96
97impl SubscribeCommand {
98 pub fn as_any(&self) -> &dyn Any {
100 self
101 }
102
103 pub fn command_id(&self) -> UUID4 {
104 match self {
105 Self::Data(cmd) => cmd.command_id,
106 Self::Instrument(cmd) => cmd.command_id,
107 Self::Instruments(cmd) => cmd.command_id,
108 Self::BookDeltas(cmd) => cmd.command_id,
109 Self::BookDepth10(cmd) => cmd.command_id,
110 Self::BookSnapshots(cmd) => cmd.command_id,
111 Self::Quotes(cmd) => cmd.command_id,
112 Self::Trades(cmd) => cmd.command_id,
113 Self::Bars(cmd) => cmd.command_id,
114 Self::MarkPrices(cmd) => cmd.command_id,
115 Self::IndexPrices(cmd) => cmd.command_id,
116 Self::InstrumentStatus(cmd) => cmd.command_id,
117 Self::InstrumentClose(cmd) => cmd.command_id,
118 }
119 }
120
121 pub fn client_id(&self) -> Option<&ClientId> {
122 match self {
123 Self::Data(cmd) => cmd.client_id.as_ref(),
124 Self::Instrument(cmd) => cmd.client_id.as_ref(),
125 Self::Instruments(cmd) => cmd.client_id.as_ref(),
126 Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
127 Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
128 Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
129 Self::Quotes(cmd) => cmd.client_id.as_ref(),
130 Self::Trades(cmd) => cmd.client_id.as_ref(),
131 Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
132 Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
133 Self::Bars(cmd) => cmd.client_id.as_ref(),
134 Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
135 Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
136 }
137 }
138
139 pub fn venue(&self) -> Option<&Venue> {
140 match self {
141 Self::Data(cmd) => cmd.venue.as_ref(),
142 Self::Instrument(cmd) => cmd.venue.as_ref(),
143 Self::Instruments(cmd) => Some(&cmd.venue),
144 Self::BookDeltas(cmd) => cmd.venue.as_ref(),
145 Self::BookDepth10(cmd) => cmd.venue.as_ref(),
146 Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
147 Self::Quotes(cmd) => cmd.venue.as_ref(),
148 Self::Trades(cmd) => cmd.venue.as_ref(),
149 Self::MarkPrices(cmd) => cmd.venue.as_ref(),
150 Self::IndexPrices(cmd) => cmd.venue.as_ref(),
151 Self::Bars(cmd) => cmd.venue.as_ref(),
152 Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
153 Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
154 }
155 }
156
157 pub fn ts_init(&self) -> UnixNanos {
158 match self {
159 Self::Data(cmd) => cmd.ts_init,
160 Self::Instrument(cmd) => cmd.ts_init,
161 Self::Instruments(cmd) => cmd.ts_init,
162 Self::BookDeltas(cmd) => cmd.ts_init,
163 Self::BookDepth10(cmd) => cmd.ts_init,
164 Self::BookSnapshots(cmd) => cmd.ts_init,
165 Self::Quotes(cmd) => cmd.ts_init,
166 Self::Trades(cmd) => cmd.ts_init,
167 Self::MarkPrices(cmd) => cmd.ts_init,
168 Self::IndexPrices(cmd) => cmd.ts_init,
169 Self::Bars(cmd) => cmd.ts_init,
170 Self::InstrumentStatus(cmd) => cmd.ts_init,
171 Self::InstrumentClose(cmd) => cmd.ts_init,
172 }
173 }
174}
175
176#[derive(Clone, Debug)]
177pub enum UnsubscribeCommand {
178 Data(UnsubscribeCustomData),
179 Instrument(UnsubscribeInstrument),
180 Instruments(UnsubscribeInstruments),
181 BookDeltas(UnsubscribeBookDeltas),
182 BookDepth10(UnsubscribeBookDepth10),
183 BookSnapshots(UnsubscribeBookSnapshots),
184 Quotes(UnsubscribeQuotes),
185 Trades(UnsubscribeTrades),
186 Bars(UnsubscribeBars),
187 MarkPrices(UnsubscribeMarkPrices),
188 IndexPrices(UnsubscribeIndexPrices),
189 InstrumentStatus(UnsubscribeInstrumentStatus),
190 InstrumentClose(UnsubscribeInstrumentClose),
191}
192
193impl PartialEq for UnsubscribeCommand {
194 fn eq(&self, other: &Self) -> bool {
195 self.command_id() == other.command_id()
196 }
197}
198
199impl UnsubscribeCommand {
200 pub fn as_any(&self) -> &dyn Any {
202 self
203 }
204
205 pub fn command_id(&self) -> UUID4 {
206 match self {
207 Self::Data(cmd) => cmd.command_id,
208 Self::Instrument(cmd) => cmd.command_id,
209 Self::Instruments(cmd) => cmd.command_id,
210 Self::BookDeltas(cmd) => cmd.command_id,
211 Self::BookDepth10(cmd) => cmd.command_id,
212 Self::BookSnapshots(cmd) => cmd.command_id,
213 Self::Quotes(cmd) => cmd.command_id,
214 Self::Trades(cmd) => cmd.command_id,
215 Self::Bars(cmd) => cmd.command_id,
216 Self::MarkPrices(cmd) => cmd.command_id,
217 Self::IndexPrices(cmd) => cmd.command_id,
218 Self::InstrumentStatus(cmd) => cmd.command_id,
219 Self::InstrumentClose(cmd) => cmd.command_id,
220 }
221 }
222
223 pub fn client_id(&self) -> Option<&ClientId> {
224 match self {
225 Self::Data(cmd) => cmd.client_id.as_ref(),
226 Self::Instrument(cmd) => cmd.client_id.as_ref(),
227 Self::Instruments(cmd) => cmd.client_id.as_ref(),
228 Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
229 Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
230 Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
231 Self::Quotes(cmd) => cmd.client_id.as_ref(),
232 Self::Trades(cmd) => cmd.client_id.as_ref(),
233 Self::Bars(cmd) => cmd.client_id.as_ref(),
234 Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
235 Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
236 Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
237 Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
238 }
239 }
240
241 pub fn venue(&self) -> Option<&Venue> {
242 match self {
243 Self::Data(cmd) => cmd.venue.as_ref(),
244 Self::Instrument(cmd) => cmd.venue.as_ref(),
245 Self::Instruments(cmd) => Some(&cmd.venue),
246 Self::BookDeltas(cmd) => cmd.venue.as_ref(),
247 Self::BookDepth10(cmd) => cmd.venue.as_ref(),
248 Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
249 Self::Quotes(cmd) => cmd.venue.as_ref(),
250 Self::Trades(cmd) => cmd.venue.as_ref(),
251 Self::Bars(cmd) => cmd.venue.as_ref(),
252 Self::MarkPrices(cmd) => cmd.venue.as_ref(),
253 Self::IndexPrices(cmd) => cmd.venue.as_ref(),
254 Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
255 Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
256 }
257 }
258
259 pub fn ts_init(&self) -> UnixNanos {
260 match self {
261 Self::Data(cmd) => cmd.ts_init,
262 Self::Instrument(cmd) => cmd.ts_init,
263 Self::Instruments(cmd) => cmd.ts_init,
264 Self::BookDeltas(cmd) => cmd.ts_init,
265 Self::BookDepth10(cmd) => cmd.ts_init,
266 Self::BookSnapshots(cmd) => cmd.ts_init,
267 Self::Quotes(cmd) => cmd.ts_init,
268 Self::Trades(cmd) => cmd.ts_init,
269 Self::MarkPrices(cmd) => cmd.ts_init,
270 Self::IndexPrices(cmd) => cmd.ts_init,
271 Self::Bars(cmd) => cmd.ts_init,
272 Self::InstrumentStatus(cmd) => cmd.ts_init,
273 Self::InstrumentClose(cmd) => cmd.ts_init,
274 }
275 }
276}
277
278fn check_client_id_or_venue(client_id: &Option<ClientId>, venue: &Option<Venue>) {
279 assert!(
280 client_id.is_some() || venue.is_some(),
281 "Both `client_id` and `venue` were None"
282 );
283}
284
285#[derive(Clone, Debug)]
286pub enum RequestCommand {
287 Data(RequestCustomData),
288 Instrument(RequestInstrument),
289 Instruments(RequestInstruments),
290 BookSnapshot(RequestBookSnapshot),
291 Quotes(RequestQuotes),
292 Trades(RequestTrades),
293 Bars(RequestBars),
294}
295
296impl PartialEq for RequestCommand {
297 fn eq(&self, other: &Self) -> bool {
298 self.request_id() == other.request_id()
299 }
300}
301
302impl RequestCommand {
303 pub fn as_any(&self) -> &dyn Any {
305 self
306 }
307
308 pub fn request_id(&self) -> &UUID4 {
309 match self {
310 Self::Data(cmd) => &cmd.request_id,
311 Self::Instrument(cmd) => &cmd.request_id,
312 Self::Instruments(cmd) => &cmd.request_id,
313 Self::BookSnapshot(cmd) => &cmd.request_id,
314 Self::Quotes(cmd) => &cmd.request_id,
315 Self::Trades(cmd) => &cmd.request_id,
316 Self::Bars(cmd) => &cmd.request_id,
317 }
318 }
319
320 pub fn client_id(&self) -> Option<&ClientId> {
321 match self {
322 Self::Data(cmd) => Some(&cmd.client_id),
323 Self::Instrument(cmd) => cmd.client_id.as_ref(),
324 Self::Instruments(cmd) => cmd.client_id.as_ref(),
325 Self::BookSnapshot(cmd) => cmd.client_id.as_ref(),
326 Self::Quotes(cmd) => cmd.client_id.as_ref(),
327 Self::Trades(cmd) => cmd.client_id.as_ref(),
328 Self::Bars(cmd) => cmd.client_id.as_ref(),
329 }
330 }
331
332 pub fn venue(&self) -> Option<&Venue> {
333 match self {
334 Self::Data(_) => None,
335 Self::Instrument(cmd) => Some(&cmd.instrument_id.venue),
336 Self::Instruments(cmd) => cmd.venue.as_ref(),
337 Self::BookSnapshot(cmd) => Some(&cmd.instrument_id.venue),
338 Self::Quotes(cmd) => Some(&cmd.instrument_id.venue),
339 Self::Trades(cmd) => Some(&cmd.instrument_id.venue),
340 Self::Bars(cmd) => match &cmd.bar_type {
342 BarType::Standard { instrument_id, .. } => Some(&instrument_id.venue),
343 BarType::Composite { instrument_id, .. } => Some(&instrument_id.venue),
344 },
345 }
346 }
347
348 pub fn ts_init(&self) -> UnixNanos {
349 match self {
350 Self::Data(cmd) => cmd.ts_init,
351 Self::Instrument(cmd) => cmd.ts_init,
352 Self::Instruments(cmd) => cmd.ts_init,
353 Self::BookSnapshot(cmd) => cmd.ts_init,
354 Self::Quotes(cmd) => cmd.ts_init,
355 Self::Trades(cmd) => cmd.ts_init,
356 Self::Bars(cmd) => cmd.ts_init,
357 }
358 }
359}
360
361#[derive(Clone, Debug)]
362pub enum DataResponse {
363 Data(CustomDataResponse),
364 Instrument(Box<InstrumentResponse>),
365 Instruments(InstrumentsResponse),
366 Book(BookResponse),
367 Quotes(QuotesResponse),
368 Trades(TradesResponse),
369 Bars(BarsResponse),
370}
371
372impl DataResponse {
373 pub fn as_any(&self) -> &dyn Any {
375 self
376 }
377
378 pub fn correlation_id(&self) -> &UUID4 {
379 match self {
380 Self::Data(resp) => &resp.correlation_id,
381 Self::Instrument(resp) => &resp.correlation_id,
382 Self::Instruments(resp) => &resp.correlation_id,
383 Self::Book(resp) => &resp.correlation_id,
384 Self::Quotes(resp) => &resp.correlation_id,
385 Self::Trades(resp) => &resp.correlation_id,
386 Self::Bars(resp) => &resp.correlation_id,
387 }
388 }
389}
390
391pub type Payload = Arc<dyn Any + Send + Sync>;