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