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