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