nautilus_common/messages/
data.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 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
16use std::{any::Any, collections::HashMap, num::NonZeroUsize, sync::Arc};
17
18use chrono::{DateTime, Utc};
19use nautilus_core::{UUID4, UnixNanos};
20use nautilus_model::{
21    data::{Bar, BarType, DataType, QuoteTick, TradeTick},
22    enums::BookType,
23    identifiers::{ClientId, InstrumentId, Venue},
24    instruments::InstrumentAny,
25    orderbook::OrderBook,
26};
27
28#[derive(Clone, Debug)]
29pub enum DataCommand {
30    Request(RequestCommand),
31    Subscribe(SubscribeCommand),
32    Unsubscribe(UnsubscribeCommand),
33}
34
35impl DataCommand {
36    /// Converts the command to a dyn Any trait object for messaging.
37    pub fn as_any(&self) -> &dyn Any {
38        self
39    }
40}
41
42#[derive(Clone, Debug)]
43pub enum SubscribeCommand {
44    Data(SubscribeData),
45    Instruments(SubscribeInstruments),
46    Instrument(SubscribeInstrument),
47    BookDeltas(SubscribeBookDeltas),
48    BookDepth10(SubscribeBookDepth10),
49    BookSnapshots(SubscribeBookSnapshots),
50    Quotes(SubscribeQuotes),
51    Trades(SubscribeTrades),
52    Bars(SubscribeBars),
53    MarkPrices(SubscribeMarkPrices),
54    IndexPrices(SubscribeIndexPrices),
55    InstrumentStatus(SubscribeInstrumentStatus),
56    InstrumentClose(SubscribeInstrumentClose),
57}
58
59impl SubscribeCommand {
60    pub fn client_id(&self) -> Option<&ClientId> {
61        match self {
62            Self::Data(cmd) => cmd.client_id.as_ref(),
63            Self::Instruments(cmd) => cmd.client_id.as_ref(),
64            Self::Instrument(cmd) => cmd.client_id.as_ref(),
65            Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
66            Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
67            Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
68            Self::Quotes(cmd) => cmd.client_id.as_ref(),
69            Self::Trades(cmd) => cmd.client_id.as_ref(),
70            Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
71            Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
72            Self::Bars(cmd) => cmd.client_id.as_ref(),
73            Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
74            Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
75        }
76    }
77
78    pub fn venue(&self) -> Option<&Venue> {
79        match self {
80            Self::Data(cmd) => cmd.venue.as_ref(),
81            Self::Instruments(cmd) => Some(&cmd.venue),
82            Self::Instrument(cmd) => cmd.venue.as_ref(),
83            Self::BookDeltas(cmd) => cmd.venue.as_ref(),
84            Self::BookDepth10(cmd) => cmd.venue.as_ref(),
85            Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
86            Self::Quotes(cmd) => cmd.venue.as_ref(),
87            Self::Trades(cmd) => cmd.venue.as_ref(),
88            Self::MarkPrices(cmd) => cmd.venue.as_ref(),
89            Self::IndexPrices(cmd) => cmd.venue.as_ref(),
90            Self::Bars(cmd) => cmd.venue.as_ref(),
91            Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
92            Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
93        }
94    }
95}
96
97#[derive(Clone, Debug)]
98pub enum UnsubscribeCommand {
99    Data(UnsubscribeData),
100    Instruments(UnsubscribeInstruments),
101    Instrument(UnsubscribeInstrument),
102    BookDeltas(UnsubscribeBookDeltas),
103    BookDepth10(UnsubscribeBookDepth10),
104    BookSnapshots(UnsubscribeBookSnapshots),
105    Quotes(UnsubscribeQuotes),
106    Trades(UnsubscribeTrades),
107    Bars(UnsubscribeBars),
108    MarkPrices(UnsubscribeMarkPrices),
109    IndexPrices(UnsubscribeIndexPrices),
110    InstrumentStatus(UnsubscribeInstrumentStatus),
111    InstrumentClose(UnsubscribeInstrumentClose),
112}
113
114impl UnsubscribeCommand {
115    pub fn client_id(&self) -> Option<&ClientId> {
116        match self {
117            Self::Data(cmd) => cmd.client_id.as_ref(),
118            Self::Instruments(cmd) => cmd.client_id.as_ref(),
119            Self::Instrument(cmd) => cmd.client_id.as_ref(),
120            Self::BookDeltas(cmd) => cmd.client_id.as_ref(),
121            Self::BookDepth10(cmd) => cmd.client_id.as_ref(),
122            Self::BookSnapshots(cmd) => cmd.client_id.as_ref(),
123            Self::Quotes(cmd) => cmd.client_id.as_ref(),
124            Self::Trades(cmd) => cmd.client_id.as_ref(),
125            Self::Bars(cmd) => cmd.client_id.as_ref(),
126            Self::MarkPrices(cmd) => cmd.client_id.as_ref(),
127            Self::IndexPrices(cmd) => cmd.client_id.as_ref(),
128            Self::InstrumentStatus(cmd) => cmd.client_id.as_ref(),
129            Self::InstrumentClose(cmd) => cmd.client_id.as_ref(),
130        }
131    }
132
133    pub fn venue(&self) -> Option<&Venue> {
134        match self {
135            Self::Data(cmd) => cmd.venue.as_ref(),
136            Self::Instruments(cmd) => Some(&cmd.venue),
137            Self::Instrument(cmd) => cmd.venue.as_ref(),
138            Self::BookDeltas(cmd) => cmd.venue.as_ref(),
139            Self::BookDepth10(cmd) => cmd.venue.as_ref(),
140            Self::BookSnapshots(cmd) => cmd.venue.as_ref(),
141            Self::Quotes(cmd) => cmd.venue.as_ref(),
142            Self::Trades(cmd) => cmd.venue.as_ref(),
143            Self::Bars(cmd) => cmd.venue.as_ref(),
144            Self::MarkPrices(cmd) => cmd.venue.as_ref(),
145            Self::IndexPrices(cmd) => cmd.venue.as_ref(),
146            Self::InstrumentStatus(cmd) => cmd.venue.as_ref(),
147            Self::InstrumentClose(cmd) => cmd.venue.as_ref(),
148        }
149    }
150}
151
152fn check_client_id_or_venue(client_id: &Option<ClientId>, venue: &Option<Venue>) {
153    assert!(
154        client_id.is_some() || venue.is_some(),
155        "Both `client_id` and `venue` were None"
156    );
157}
158
159#[derive(Clone, Debug)]
160pub struct SubscribeData {
161    pub client_id: Option<ClientId>,
162    pub venue: Option<Venue>,
163    pub data_type: DataType,
164    pub command_id: UUID4,
165    pub ts_init: UnixNanos,
166    pub params: Option<HashMap<String, String>>,
167}
168
169impl SubscribeData {
170    pub fn new(
171        client_id: Option<ClientId>,
172        venue: Option<Venue>,
173        data_type: DataType,
174        command_id: UUID4,
175        ts_init: UnixNanos,
176        params: Option<HashMap<String, String>>,
177    ) -> Self {
178        check_client_id_or_venue(&client_id, &venue);
179        Self {
180            client_id,
181            venue,
182            data_type,
183            command_id,
184            ts_init,
185            params,
186        }
187    }
188}
189
190#[derive(Clone, Debug)]
191pub struct SubscribeInstruments {
192    pub client_id: Option<ClientId>,
193    pub venue: Venue,
194    pub command_id: UUID4,
195    pub ts_init: UnixNanos,
196    pub params: Option<HashMap<String, String>>,
197}
198
199impl SubscribeInstruments {
200    pub fn new(
201        client_id: Option<ClientId>,
202        venue: Venue,
203        command_id: UUID4,
204        ts_init: UnixNanos,
205        params: Option<HashMap<String, String>>,
206    ) -> Self {
207        Self {
208            client_id,
209            venue,
210            command_id,
211            ts_init,
212            params,
213        }
214    }
215}
216
217#[derive(Clone, Debug)]
218pub struct SubscribeInstrument {
219    pub instrument_id: InstrumentId,
220    pub client_id: Option<ClientId>,
221    pub venue: Option<Venue>,
222    pub command_id: UUID4,
223    pub ts_init: UnixNanos,
224    pub params: Option<HashMap<String, String>>,
225}
226
227impl SubscribeInstrument {
228    pub fn new(
229        instrument_id: InstrumentId,
230        client_id: Option<ClientId>,
231        venue: Option<Venue>,
232        command_id: UUID4,
233        ts_init: UnixNanos,
234        params: Option<HashMap<String, String>>,
235    ) -> Self {
236        check_client_id_or_venue(&client_id, &venue);
237        Self {
238            instrument_id,
239            client_id,
240            venue,
241            command_id,
242            ts_init,
243            params,
244        }
245    }
246}
247
248#[derive(Clone, Debug)]
249pub struct SubscribeBookDeltas {
250    pub instrument_id: InstrumentId,
251    pub book_type: BookType,
252    pub client_id: Option<ClientId>,
253    pub venue: Option<Venue>,
254    pub command_id: UUID4,
255    pub ts_init: UnixNanos,
256    pub depth: Option<NonZeroUsize>,
257    pub managed: bool,
258    pub params: Option<HashMap<String, String>>,
259}
260
261impl SubscribeBookDeltas {
262    #[allow(clippy::too_many_arguments)]
263    pub fn new(
264        instrument_id: InstrumentId,
265        book_type: BookType,
266        client_id: Option<ClientId>,
267        venue: Option<Venue>,
268        command_id: UUID4,
269        ts_init: UnixNanos,
270        depth: Option<NonZeroUsize>,
271        managed: bool,
272        params: Option<HashMap<String, String>>,
273    ) -> Self {
274        check_client_id_or_venue(&client_id, &venue);
275        Self {
276            instrument_id,
277            book_type,
278            client_id,
279            venue,
280            command_id,
281            ts_init,
282            depth,
283            managed,
284            params,
285        }
286    }
287}
288
289#[derive(Clone, Debug)]
290pub struct SubscribeBookDepth10 {
291    pub instrument_id: InstrumentId,
292    pub book_type: BookType,
293    pub client_id: Option<ClientId>,
294    pub venue: Option<Venue>,
295    pub command_id: UUID4,
296    pub ts_init: UnixNanos,
297    pub depth: Option<NonZeroUsize>,
298    pub managed: bool,
299    pub params: Option<HashMap<String, String>>,
300}
301
302impl SubscribeBookDepth10 {
303    #[allow(clippy::too_many_arguments)]
304    pub fn new(
305        instrument_id: InstrumentId,
306        book_type: BookType,
307        client_id: Option<ClientId>,
308        venue: Option<Venue>,
309        command_id: UUID4,
310        ts_init: UnixNanos,
311        depth: Option<NonZeroUsize>,
312        managed: bool,
313        params: Option<HashMap<String, String>>,
314    ) -> Self {
315        check_client_id_or_venue(&client_id, &venue);
316        Self {
317            instrument_id,
318            book_type,
319            client_id,
320            venue,
321            command_id,
322            ts_init,
323            depth,
324            managed,
325            params,
326        }
327    }
328}
329
330#[derive(Clone, Debug)]
331pub struct SubscribeBookSnapshots {
332    pub instrument_id: InstrumentId,
333    pub book_type: BookType,
334    pub client_id: Option<ClientId>,
335    pub venue: Option<Venue>,
336    pub command_id: UUID4,
337    pub ts_init: UnixNanos,
338    pub depth: Option<NonZeroUsize>,
339    pub interval_ms: NonZeroUsize,
340    pub params: Option<HashMap<String, String>>,
341}
342
343impl SubscribeBookSnapshots {
344    #[allow(clippy::too_many_arguments)]
345    pub fn new(
346        instrument_id: InstrumentId,
347        book_type: BookType,
348        client_id: Option<ClientId>,
349        venue: Option<Venue>,
350        command_id: UUID4,
351        ts_init: UnixNanos,
352        depth: Option<NonZeroUsize>,
353        interval_ms: NonZeroUsize,
354        params: Option<HashMap<String, String>>,
355    ) -> Self {
356        check_client_id_or_venue(&client_id, &venue);
357        Self {
358            instrument_id,
359            book_type,
360            client_id,
361            venue,
362            command_id,
363            ts_init,
364            depth,
365            interval_ms,
366            params,
367        }
368    }
369}
370
371#[derive(Clone, Debug)]
372pub struct SubscribeQuotes {
373    pub instrument_id: InstrumentId,
374    pub client_id: Option<ClientId>,
375    pub venue: Option<Venue>,
376    pub command_id: UUID4,
377    pub ts_init: UnixNanos,
378    pub params: Option<HashMap<String, String>>,
379}
380
381impl SubscribeQuotes {
382    pub fn new(
383        instrument_id: InstrumentId,
384        client_id: Option<ClientId>,
385        venue: Option<Venue>,
386        command_id: UUID4,
387        ts_init: UnixNanos,
388        params: Option<HashMap<String, String>>,
389    ) -> Self {
390        check_client_id_or_venue(&client_id, &venue);
391        Self {
392            instrument_id,
393            client_id,
394            venue,
395            command_id,
396            ts_init,
397            params,
398        }
399    }
400}
401
402#[derive(Clone, Debug)]
403pub struct SubscribeTrades {
404    pub instrument_id: InstrumentId,
405    pub client_id: Option<ClientId>,
406    pub venue: Option<Venue>,
407    pub command_id: UUID4,
408    pub ts_init: UnixNanos,
409    pub params: Option<HashMap<String, String>>,
410}
411
412impl SubscribeTrades {
413    pub fn new(
414        instrument_id: InstrumentId,
415        client_id: Option<ClientId>,
416        venue: Option<Venue>,
417        command_id: UUID4,
418        ts_init: UnixNanos,
419        params: Option<HashMap<String, String>>,
420    ) -> Self {
421        check_client_id_or_venue(&client_id, &venue);
422        Self {
423            instrument_id,
424            client_id,
425            venue,
426            command_id,
427            ts_init,
428            params,
429        }
430    }
431}
432
433#[derive(Clone, Debug)]
434pub struct SubscribeBars {
435    pub bar_type: BarType,
436    pub client_id: Option<ClientId>,
437    pub venue: Option<Venue>,
438    pub command_id: UUID4,
439    pub ts_init: UnixNanos,
440    pub await_partial: bool,
441    pub params: Option<HashMap<String, String>>,
442}
443
444impl SubscribeBars {
445    pub fn new(
446        bar_type: BarType,
447        client_id: Option<ClientId>,
448        venue: Option<Venue>,
449        command_id: UUID4,
450        ts_init: UnixNanos,
451        await_partial: bool,
452        params: Option<HashMap<String, String>>,
453    ) -> Self {
454        check_client_id_or_venue(&client_id, &venue);
455        Self {
456            bar_type,
457            client_id,
458            venue,
459            command_id,
460            ts_init,
461            await_partial,
462            params,
463        }
464    }
465}
466
467#[derive(Clone, Debug)]
468pub struct SubscribeMarkPrices {
469    pub instrument_id: InstrumentId,
470    pub client_id: Option<ClientId>,
471    pub venue: Option<Venue>,
472    pub command_id: UUID4,
473    pub ts_init: UnixNanos,
474    pub params: Option<HashMap<String, String>>,
475}
476
477impl SubscribeMarkPrices {
478    pub fn new(
479        instrument_id: InstrumentId,
480        client_id: Option<ClientId>,
481        venue: Option<Venue>,
482        command_id: UUID4,
483        ts_init: UnixNanos,
484        params: Option<HashMap<String, String>>,
485    ) -> Self {
486        check_client_id_or_venue(&client_id, &venue);
487        Self {
488            instrument_id,
489            client_id,
490            venue,
491            command_id,
492            ts_init,
493            params,
494        }
495    }
496}
497
498#[derive(Clone, Debug)]
499pub struct SubscribeIndexPrices {
500    pub instrument_id: InstrumentId,
501    pub client_id: Option<ClientId>,
502    pub venue: Option<Venue>,
503    pub command_id: UUID4,
504    pub ts_init: UnixNanos,
505    pub params: Option<HashMap<String, String>>,
506}
507
508impl SubscribeIndexPrices {
509    pub fn new(
510        instrument_id: InstrumentId,
511        client_id: Option<ClientId>,
512        venue: Option<Venue>,
513        command_id: UUID4,
514        ts_init: UnixNanos,
515        params: Option<HashMap<String, String>>,
516    ) -> Self {
517        check_client_id_or_venue(&client_id, &venue);
518        Self {
519            instrument_id,
520            client_id,
521            venue,
522            command_id,
523            ts_init,
524            params,
525        }
526    }
527}
528
529#[derive(Clone, Debug)]
530pub struct SubscribeInstrumentStatus {
531    pub instrument_id: InstrumentId,
532    pub client_id: Option<ClientId>,
533    pub venue: Option<Venue>,
534    pub command_id: UUID4,
535    pub ts_init: UnixNanos,
536    pub params: Option<HashMap<String, String>>,
537}
538
539impl SubscribeInstrumentStatus {
540    pub fn new(
541        instrument_id: InstrumentId,
542        client_id: Option<ClientId>,
543        venue: Option<Venue>,
544        command_id: UUID4,
545        ts_init: UnixNanos,
546        params: Option<HashMap<String, String>>,
547    ) -> Self {
548        check_client_id_or_venue(&client_id, &venue);
549        Self {
550            instrument_id,
551            client_id,
552            venue,
553            command_id,
554            ts_init,
555            params,
556        }
557    }
558}
559
560#[derive(Clone, Debug)]
561pub struct SubscribeInstrumentClose {
562    pub instrument_id: InstrumentId,
563    pub client_id: Option<ClientId>,
564    pub venue: Option<Venue>,
565    pub command_id: UUID4,
566    pub ts_init: UnixNanos,
567    pub params: Option<HashMap<String, String>>,
568}
569
570impl SubscribeInstrumentClose {
571    pub fn new(
572        instrument_id: InstrumentId,
573        client_id: Option<ClientId>,
574        venue: Option<Venue>,
575        command_id: UUID4,
576        ts_init: UnixNanos,
577        params: Option<HashMap<String, String>>,
578    ) -> Self {
579        check_client_id_or_venue(&client_id, &venue);
580        Self {
581            instrument_id,
582            client_id,
583            venue,
584            command_id,
585            ts_init,
586            params,
587        }
588    }
589}
590
591#[derive(Clone, Debug)]
592pub struct UnsubscribeData {
593    pub client_id: Option<ClientId>,
594    pub venue: Option<Venue>,
595    pub data_type: DataType,
596    pub command_id: UUID4,
597    pub ts_init: UnixNanos,
598    pub params: Option<HashMap<String, String>>,
599}
600
601impl UnsubscribeData {
602    pub fn new(
603        client_id: Option<ClientId>,
604        venue: Option<Venue>,
605        data_type: DataType,
606        command_id: UUID4,
607        ts_init: UnixNanos,
608        params: Option<HashMap<String, String>>,
609    ) -> Self {
610        check_client_id_or_venue(&client_id, &venue);
611        Self {
612            client_id,
613            venue,
614            data_type,
615            command_id,
616            ts_init,
617            params,
618        }
619    }
620}
621
622// Unsubscribe commands
623#[derive(Clone, Debug)]
624pub struct UnsubscribeInstruments {
625    pub client_id: Option<ClientId>,
626    pub venue: Venue,
627    pub command_id: UUID4,
628    pub ts_init: UnixNanos,
629    pub params: Option<HashMap<String, String>>,
630}
631
632impl UnsubscribeInstruments {
633    pub fn new(
634        client_id: Option<ClientId>,
635        venue: Venue,
636        command_id: UUID4,
637        ts_init: UnixNanos,
638        params: Option<HashMap<String, String>>,
639    ) -> Self {
640        Self {
641            client_id,
642            venue,
643            command_id,
644            ts_init,
645            params,
646        }
647    }
648}
649
650#[derive(Clone, Debug)]
651pub struct UnsubscribeInstrument {
652    pub instrument_id: InstrumentId,
653    pub client_id: Option<ClientId>,
654    pub venue: Option<Venue>,
655    pub command_id: UUID4,
656    pub ts_init: UnixNanos,
657    pub params: Option<HashMap<String, String>>,
658}
659
660impl UnsubscribeInstrument {
661    pub fn new(
662        instrument_id: InstrumentId,
663        client_id: Option<ClientId>,
664        venue: Option<Venue>,
665        command_id: UUID4,
666        ts_init: UnixNanos,
667        params: Option<HashMap<String, String>>,
668    ) -> Self {
669        check_client_id_or_venue(&client_id, &venue);
670        Self {
671            instrument_id,
672            client_id,
673            venue,
674            command_id,
675            ts_init,
676            params,
677        }
678    }
679}
680
681#[derive(Clone, Debug)]
682pub struct UnsubscribeBookDeltas {
683    pub instrument_id: InstrumentId,
684    pub client_id: Option<ClientId>,
685    pub venue: Option<Venue>,
686    pub command_id: UUID4,
687    pub ts_init: UnixNanos,
688    pub params: Option<HashMap<String, String>>,
689}
690
691impl UnsubscribeBookDeltas {
692    #[allow(clippy::too_many_arguments)]
693    pub fn new(
694        instrument_id: InstrumentId,
695        client_id: Option<ClientId>,
696        venue: Option<Venue>,
697        command_id: UUID4,
698        ts_init: UnixNanos,
699        params: Option<HashMap<String, String>>,
700    ) -> Self {
701        check_client_id_or_venue(&client_id, &venue);
702        Self {
703            instrument_id,
704            client_id,
705            venue,
706            command_id,
707            ts_init,
708            params,
709        }
710    }
711}
712
713#[derive(Clone, Debug)]
714pub struct UnsubscribeBookDepth10 {
715    pub instrument_id: InstrumentId,
716    pub client_id: Option<ClientId>,
717    pub venue: Option<Venue>,
718    pub command_id: UUID4,
719    pub ts_init: UnixNanos,
720    pub params: Option<HashMap<String, String>>,
721}
722
723impl UnsubscribeBookDepth10 {
724    #[allow(clippy::too_many_arguments)]
725    pub fn new(
726        instrument_id: InstrumentId,
727        client_id: Option<ClientId>,
728        venue: Option<Venue>,
729        command_id: UUID4,
730        ts_init: UnixNanos,
731        params: Option<HashMap<String, String>>,
732    ) -> Self {
733        check_client_id_or_venue(&client_id, &venue);
734        Self {
735            instrument_id,
736            client_id,
737            venue,
738            command_id,
739            ts_init,
740            params,
741        }
742    }
743}
744
745#[derive(Clone, Debug)]
746pub struct UnsubscribeBookSnapshots {
747    pub instrument_id: InstrumentId,
748    pub client_id: Option<ClientId>,
749    pub venue: Option<Venue>,
750    pub command_id: UUID4,
751    pub ts_init: UnixNanos,
752    pub params: Option<HashMap<String, String>>,
753}
754
755impl UnsubscribeBookSnapshots {
756    #[allow(clippy::too_many_arguments)]
757    pub fn new(
758        instrument_id: InstrumentId,
759        client_id: Option<ClientId>,
760        venue: Option<Venue>,
761        command_id: UUID4,
762        ts_init: UnixNanos,
763        params: Option<HashMap<String, String>>,
764    ) -> Self {
765        check_client_id_or_venue(&client_id, &venue);
766        Self {
767            instrument_id,
768            client_id,
769            venue,
770            command_id,
771            ts_init,
772            params,
773        }
774    }
775}
776
777#[derive(Clone, Debug)]
778pub struct UnsubscribeQuotes {
779    pub instrument_id: InstrumentId,
780    pub client_id: Option<ClientId>,
781    pub venue: Option<Venue>,
782    pub command_id: UUID4,
783    pub ts_init: UnixNanos,
784    pub params: Option<HashMap<String, String>>,
785}
786
787impl UnsubscribeQuotes {
788    #[allow(clippy::too_many_arguments)]
789    pub fn new(
790        instrument_id: InstrumentId,
791        client_id: Option<ClientId>,
792        venue: Option<Venue>,
793        command_id: UUID4,
794        ts_init: UnixNanos,
795        params: Option<HashMap<String, String>>,
796    ) -> Self {
797        check_client_id_or_venue(&client_id, &venue);
798        Self {
799            instrument_id,
800            client_id,
801            venue,
802            command_id,
803            ts_init,
804            params,
805        }
806    }
807}
808
809#[derive(Clone, Debug)]
810pub struct UnsubscribeTrades {
811    pub instrument_id: InstrumentId,
812    pub client_id: Option<ClientId>,
813    pub venue: Option<Venue>,
814    pub command_id: UUID4,
815    pub ts_init: UnixNanos,
816    pub params: Option<HashMap<String, String>>,
817}
818
819impl UnsubscribeTrades {
820    #[allow(clippy::too_many_arguments)]
821    pub fn new(
822        instrument_id: InstrumentId,
823        client_id: Option<ClientId>,
824        venue: Option<Venue>,
825        command_id: UUID4,
826        ts_init: UnixNanos,
827        params: Option<HashMap<String, String>>,
828    ) -> Self {
829        check_client_id_or_venue(&client_id, &venue);
830        Self {
831            instrument_id,
832            client_id,
833            venue,
834            command_id,
835            ts_init,
836            params,
837        }
838    }
839}
840
841#[derive(Clone, Debug)]
842pub struct UnsubscribeBars {
843    pub bar_type: BarType,
844    pub client_id: Option<ClientId>,
845    pub venue: Option<Venue>,
846    pub command_id: UUID4,
847    pub ts_init: UnixNanos,
848    pub params: Option<HashMap<String, String>>,
849}
850
851impl UnsubscribeBars {
852    #[allow(clippy::too_many_arguments)]
853    pub fn new(
854        bar_type: BarType,
855        client_id: Option<ClientId>,
856        venue: Option<Venue>,
857        command_id: UUID4,
858        ts_init: UnixNanos,
859        params: Option<HashMap<String, String>>,
860    ) -> Self {
861        check_client_id_or_venue(&client_id, &venue);
862        Self {
863            bar_type,
864            client_id,
865            venue,
866            command_id,
867            ts_init,
868            params,
869        }
870    }
871}
872
873#[derive(Clone, Debug)]
874pub struct UnsubscribeMarkPrices {
875    pub instrument_id: InstrumentId,
876    pub client_id: Option<ClientId>,
877    pub venue: Option<Venue>,
878    pub command_id: UUID4,
879    pub ts_init: UnixNanos,
880    pub params: Option<HashMap<String, String>>,
881}
882
883impl UnsubscribeMarkPrices {
884    #[allow(clippy::too_many_arguments)]
885    pub fn new(
886        instrument_id: InstrumentId,
887        client_id: Option<ClientId>,
888        venue: Option<Venue>,
889        command_id: UUID4,
890        ts_init: UnixNanos,
891        params: Option<HashMap<String, String>>,
892    ) -> Self {
893        check_client_id_or_venue(&client_id, &venue);
894        Self {
895            instrument_id,
896            client_id,
897            venue,
898            command_id,
899            ts_init,
900            params,
901        }
902    }
903}
904
905#[derive(Clone, Debug)]
906pub struct UnsubscribeIndexPrices {
907    pub instrument_id: InstrumentId,
908    pub client_id: Option<ClientId>,
909    pub venue: Option<Venue>,
910    pub command_id: UUID4,
911    pub ts_init: UnixNanos,
912    pub params: Option<HashMap<String, String>>,
913}
914
915impl UnsubscribeIndexPrices {
916    #[allow(clippy::too_many_arguments)]
917    pub fn new(
918        instrument_id: InstrumentId,
919        client_id: Option<ClientId>,
920        venue: Option<Venue>,
921        command_id: UUID4,
922        ts_init: UnixNanos,
923        params: Option<HashMap<String, String>>,
924    ) -> Self {
925        check_client_id_or_venue(&client_id, &venue);
926        Self {
927            instrument_id,
928            client_id,
929            venue,
930            command_id,
931            ts_init,
932            params,
933        }
934    }
935}
936
937#[derive(Clone, Debug)]
938pub struct UnsubscribeInstrumentStatus {
939    pub instrument_id: InstrumentId,
940    pub client_id: Option<ClientId>,
941    pub venue: Option<Venue>,
942    pub command_id: UUID4,
943    pub ts_init: UnixNanos,
944    pub params: Option<HashMap<String, String>>,
945}
946
947impl UnsubscribeInstrumentStatus {
948    #[allow(clippy::too_many_arguments)]
949    pub fn new(
950        instrument_id: InstrumentId,
951        client_id: Option<ClientId>,
952        venue: Option<Venue>,
953        command_id: UUID4,
954        ts_init: UnixNanos,
955        params: Option<HashMap<String, String>>,
956    ) -> Self {
957        check_client_id_or_venue(&client_id, &venue);
958        Self {
959            instrument_id,
960            client_id,
961            venue,
962            command_id,
963            ts_init,
964            params,
965        }
966    }
967}
968
969#[derive(Clone, Debug)]
970pub struct UnsubscribeInstrumentClose {
971    pub instrument_id: InstrumentId,
972    pub client_id: Option<ClientId>,
973    pub venue: Option<Venue>,
974    pub command_id: UUID4,
975    pub ts_init: UnixNanos,
976    pub params: Option<HashMap<String, String>>,
977}
978
979impl UnsubscribeInstrumentClose {
980    #[allow(clippy::too_many_arguments)]
981    pub fn new(
982        instrument_id: InstrumentId,
983        client_id: Option<ClientId>,
984        venue: Option<Venue>,
985        command_id: UUID4,
986        ts_init: UnixNanos,
987        params: Option<HashMap<String, String>>,
988    ) -> Self {
989        check_client_id_or_venue(&client_id, &venue);
990        Self {
991            instrument_id,
992            client_id,
993            venue,
994            command_id,
995            ts_init,
996            params,
997        }
998    }
999}
1000
1001#[derive(Clone, Debug)]
1002pub enum RequestCommand {
1003    Data(RequestData),
1004    Instrument(RequestInstrument),
1005    Instruments(RequestInstruments),
1006    BookSnapshot(RequestBookSnapshot),
1007    Quotes(RequestQuotes),
1008    Trades(RequestTrades),
1009    Bars(RequestBars),
1010}
1011
1012impl RequestCommand {
1013    /// Converts the command to a dyn Any trait object for messaging.
1014    pub fn as_any(&self) -> &dyn Any {
1015        self
1016    }
1017
1018    pub fn request_id(&self) -> &UUID4 {
1019        match self {
1020            Self::Data(cmd) => &cmd.request_id,
1021            Self::Instruments(cmd) => &cmd.request_id,
1022            Self::Instrument(cmd) => &cmd.request_id,
1023            Self::BookSnapshot(cmd) => &cmd.request_id,
1024            Self::Quotes(cmd) => &cmd.request_id,
1025            Self::Trades(cmd) => &cmd.request_id,
1026            Self::Bars(cmd) => &cmd.request_id,
1027        }
1028    }
1029
1030    pub fn client_id(&self) -> Option<&ClientId> {
1031        match self {
1032            Self::Data(cmd) => Some(&cmd.client_id),
1033            Self::Instruments(cmd) => cmd.client_id.as_ref(),
1034            Self::Instrument(cmd) => cmd.client_id.as_ref(),
1035            Self::BookSnapshot(cmd) => cmd.client_id.as_ref(),
1036            Self::Quotes(cmd) => cmd.client_id.as_ref(),
1037            Self::Trades(cmd) => cmd.client_id.as_ref(),
1038            Self::Bars(cmd) => cmd.client_id.as_ref(),
1039        }
1040    }
1041
1042    pub fn venue(&self) -> Option<&Venue> {
1043        match self {
1044            Self::Data(_) => None,
1045            Self::Instruments(cmd) => cmd.venue.as_ref(),
1046            Self::Instrument(cmd) => Some(&cmd.instrument_id.venue),
1047            Self::BookSnapshot(cmd) => Some(&cmd.instrument_id.venue),
1048            Self::Quotes(cmd) => Some(&cmd.instrument_id.venue),
1049            Self::Trades(cmd) => Some(&cmd.instrument_id.venue),
1050            // TODO: Extract the below somewhere
1051            Self::Bars(cmd) => match &cmd.bar_type {
1052                BarType::Standard { instrument_id, .. } => Some(&instrument_id.venue),
1053                BarType::Composite { instrument_id, .. } => Some(&instrument_id.venue),
1054            },
1055        }
1056    }
1057}
1058
1059// Request data structures
1060#[derive(Clone, Debug)]
1061pub struct RequestInstrument {
1062    pub instrument_id: InstrumentId,
1063    pub start: Option<DateTime<Utc>>,
1064    pub end: Option<DateTime<Utc>>,
1065    pub client_id: Option<ClientId>,
1066    pub request_id: UUID4,
1067    pub ts_init: UnixNanos,
1068    pub params: Option<HashMap<String, String>>,
1069}
1070
1071#[derive(Clone, Debug)]
1072pub struct RequestData {
1073    pub client_id: ClientId,
1074    pub data_type: DataType,
1075    pub request_id: UUID4,
1076    pub ts_init: UnixNanos,
1077    pub params: Option<HashMap<String, String>>,
1078}
1079
1080impl RequestInstrument {
1081    #[allow(clippy::too_many_arguments)]
1082    pub fn new(
1083        instrument_id: InstrumentId,
1084        start: Option<DateTime<Utc>>,
1085        end: Option<DateTime<Utc>>,
1086        client_id: Option<ClientId>,
1087        request_id: UUID4,
1088        ts_init: UnixNanos,
1089        params: Option<HashMap<String, String>>,
1090    ) -> Self {
1091        Self {
1092            instrument_id,
1093            start,
1094            end,
1095            client_id,
1096            request_id,
1097            ts_init,
1098            params,
1099        }
1100    }
1101}
1102
1103#[derive(Clone, Debug)]
1104pub struct RequestInstruments {
1105    pub start: Option<DateTime<Utc>>,
1106    pub end: Option<DateTime<Utc>>,
1107    pub client_id: Option<ClientId>,
1108    pub venue: Option<Venue>,
1109    pub request_id: UUID4,
1110    pub ts_init: UnixNanos,
1111    pub params: Option<HashMap<String, String>>,
1112}
1113
1114impl RequestInstruments {
1115    #[allow(clippy::too_many_arguments)]
1116    pub fn new(
1117        start: Option<DateTime<Utc>>,
1118        end: Option<DateTime<Utc>>,
1119        client_id: Option<ClientId>,
1120        venue: Option<Venue>,
1121        request_id: UUID4,
1122        ts_init: UnixNanos,
1123        params: Option<HashMap<String, String>>,
1124    ) -> Self {
1125        check_client_id_or_venue(&client_id, &venue);
1126        Self {
1127            start,
1128            end,
1129            client_id,
1130            venue,
1131            request_id,
1132            ts_init,
1133            params,
1134        }
1135    }
1136}
1137
1138#[derive(Clone, Debug)]
1139pub struct RequestBookSnapshot {
1140    pub instrument_id: InstrumentId,
1141    pub depth: Option<NonZeroUsize>,
1142    pub client_id: Option<ClientId>,
1143    pub request_id: UUID4,
1144    pub ts_init: UnixNanos,
1145    pub params: Option<HashMap<String, String>>,
1146}
1147
1148impl RequestBookSnapshot {
1149    #[allow(clippy::too_many_arguments)]
1150    pub fn new(
1151        instrument_id: InstrumentId,
1152        depth: Option<NonZeroUsize>,
1153        client_id: Option<ClientId>,
1154        request_id: UUID4,
1155        ts_init: UnixNanos,
1156        params: Option<HashMap<String, String>>,
1157    ) -> Self {
1158        Self {
1159            instrument_id,
1160            depth,
1161            client_id,
1162            request_id,
1163            ts_init,
1164            params,
1165        }
1166    }
1167}
1168
1169#[derive(Clone, Debug)]
1170pub struct RequestQuotes {
1171    pub instrument_id: InstrumentId,
1172    pub start: Option<DateTime<Utc>>,
1173    pub end: Option<DateTime<Utc>>,
1174    pub limit: Option<NonZeroUsize>,
1175    pub client_id: Option<ClientId>,
1176    pub request_id: UUID4,
1177    pub ts_init: UnixNanos,
1178    pub params: Option<HashMap<String, String>>,
1179}
1180
1181impl RequestQuotes {
1182    #[allow(clippy::too_many_arguments)]
1183    pub fn new(
1184        instrument_id: InstrumentId,
1185        start: Option<DateTime<Utc>>,
1186        end: Option<DateTime<Utc>>,
1187        limit: Option<NonZeroUsize>,
1188        client_id: Option<ClientId>,
1189        request_id: UUID4,
1190        ts_init: UnixNanos,
1191        params: Option<HashMap<String, String>>,
1192    ) -> Self {
1193        Self {
1194            instrument_id,
1195            start,
1196            end,
1197            limit,
1198            client_id,
1199            request_id,
1200            ts_init,
1201            params,
1202        }
1203    }
1204}
1205
1206#[derive(Clone, Debug)]
1207pub struct RequestTrades {
1208    pub instrument_id: InstrumentId,
1209    pub start: Option<DateTime<Utc>>,
1210    pub end: Option<DateTime<Utc>>,
1211    pub limit: Option<NonZeroUsize>,
1212    pub client_id: Option<ClientId>,
1213    pub request_id: UUID4,
1214    pub ts_init: UnixNanos,
1215    pub params: Option<HashMap<String, String>>,
1216}
1217
1218impl RequestTrades {
1219    #[allow(clippy::too_many_arguments)]
1220    pub fn new(
1221        instrument_id: InstrumentId,
1222        start: Option<DateTime<Utc>>,
1223        end: Option<DateTime<Utc>>,
1224        limit: Option<NonZeroUsize>,
1225        client_id: Option<ClientId>,
1226        request_id: UUID4,
1227        ts_init: UnixNanos,
1228        params: Option<HashMap<String, String>>,
1229    ) -> Self {
1230        Self {
1231            instrument_id,
1232            start,
1233            end,
1234            limit,
1235            client_id,
1236            request_id,
1237            ts_init,
1238            params,
1239        }
1240    }
1241}
1242
1243#[derive(Clone, Debug)]
1244pub struct RequestBars {
1245    pub bar_type: BarType,
1246    pub start: Option<DateTime<Utc>>,
1247    pub end: Option<DateTime<Utc>>,
1248    pub limit: Option<NonZeroUsize>,
1249    pub client_id: Option<ClientId>,
1250    pub request_id: UUID4,
1251    pub ts_init: UnixNanos,
1252    pub params: Option<HashMap<String, String>>,
1253}
1254
1255impl RequestBars {
1256    #[allow(clippy::too_many_arguments)]
1257    pub fn new(
1258        bar_type: BarType,
1259        start: Option<DateTime<Utc>>,
1260        end: Option<DateTime<Utc>>,
1261        limit: Option<NonZeroUsize>,
1262        client_id: Option<ClientId>,
1263        request_id: UUID4,
1264        ts_init: UnixNanos,
1265        params: Option<HashMap<String, String>>,
1266    ) -> Self {
1267        Self {
1268            bar_type,
1269            start,
1270            end,
1271            limit,
1272            client_id,
1273            request_id,
1274            ts_init,
1275            params,
1276        }
1277    }
1278}
1279
1280#[derive(Clone, Debug)]
1281pub enum DataResponse {
1282    Data(CustomDataResponse),
1283    Instruments(InstrumentsResponse),
1284    Book(BookResponse),
1285    Quotes(QuotesResponse),
1286    Trades(TradesResponse),
1287    Bars(BarsResponse),
1288}
1289
1290impl DataResponse {
1291    /// Converts the command to a dyn Any trait object for messaging.
1292    pub fn as_any(&self) -> &dyn Any {
1293        self
1294    }
1295
1296    pub fn correlation_id(&self) -> &UUID4 {
1297        match self {
1298            Self::Data(resp) => &resp.correlation_id,
1299            Self::Instruments(resp) => &resp.correlation_id,
1300            Self::Book(resp) => &resp.correlation_id,
1301            Self::Quotes(resp) => &resp.correlation_id,
1302            Self::Trades(resp) => &resp.correlation_id,
1303            Self::Bars(resp) => &resp.correlation_id,
1304        }
1305    }
1306}
1307
1308pub type Payload = Arc<dyn Any + Send + Sync>;
1309
1310#[derive(Clone, Debug)]
1311pub struct CustomDataResponse {
1312    pub correlation_id: UUID4,
1313    pub client_id: ClientId,
1314    pub venue: Venue,
1315    pub data_type: DataType,
1316    pub data: Payload,
1317    pub ts_init: UnixNanos,
1318    pub params: Option<HashMap<String, String>>,
1319}
1320
1321impl CustomDataResponse {
1322    pub fn new<T: Any + Send + Sync>(
1323        correlation_id: UUID4,
1324        client_id: ClientId,
1325        venue: Venue,
1326        data_type: DataType,
1327        data: T,
1328        ts_init: UnixNanos,
1329        params: Option<HashMap<String, String>>,
1330    ) -> Self {
1331        Self {
1332            correlation_id,
1333            client_id,
1334            venue,
1335            data_type,
1336            data: Arc::new(data),
1337            ts_init,
1338            params,
1339        }
1340    }
1341}
1342
1343#[derive(Clone, Debug)]
1344pub struct InstrumentsResponse {
1345    pub correlation_id: UUID4,
1346    pub client_id: ClientId,
1347    pub instrument_id: InstrumentId,
1348    pub data: Vec<InstrumentAny>,
1349    pub ts_init: UnixNanos,
1350    pub params: Option<HashMap<String, String>>,
1351}
1352
1353impl InstrumentsResponse {
1354    /// Converts to a dyn Any trait object for messaging.
1355    pub fn as_any(&self) -> &dyn Any {
1356        self
1357    }
1358
1359    pub fn new(
1360        correlation_id: UUID4,
1361        client_id: ClientId,
1362        instrument_id: InstrumentId,
1363        data: Vec<InstrumentAny>,
1364        ts_init: UnixNanos,
1365        params: Option<HashMap<String, String>>,
1366    ) -> Self {
1367        Self {
1368            correlation_id,
1369            client_id,
1370            instrument_id,
1371            data,
1372            ts_init,
1373            params,
1374        }
1375    }
1376}
1377
1378#[derive(Clone, Debug)]
1379pub struct BookResponse {
1380    pub correlation_id: UUID4,
1381    pub client_id: ClientId,
1382    pub instrument_id: InstrumentId,
1383    pub data: OrderBook,
1384    pub ts_init: UnixNanos,
1385    pub params: Option<HashMap<String, String>>,
1386}
1387
1388impl BookResponse {
1389    /// Converts to a dyn Any trait object for messaging.
1390    pub fn as_any(&self) -> &dyn Any {
1391        self
1392    }
1393
1394    pub fn new(
1395        correlation_id: UUID4,
1396        client_id: ClientId,
1397        instrument_id: InstrumentId,
1398        data: OrderBook,
1399        ts_init: UnixNanos,
1400        params: Option<HashMap<String, String>>,
1401    ) -> Self {
1402        Self {
1403            correlation_id,
1404            client_id,
1405            instrument_id,
1406            data,
1407            ts_init,
1408            params,
1409        }
1410    }
1411}
1412
1413#[derive(Clone, Debug)]
1414pub struct QuotesResponse {
1415    pub correlation_id: UUID4,
1416    pub client_id: ClientId,
1417    pub instrument_id: InstrumentId,
1418    pub data: Vec<QuoteTick>,
1419    pub ts_init: UnixNanos,
1420    pub params: Option<HashMap<String, String>>,
1421}
1422
1423impl QuotesResponse {
1424    /// Converts to a dyn Any trait object for messaging.
1425    pub fn as_any(&self) -> &dyn Any {
1426        self
1427    }
1428
1429    pub fn new(
1430        correlation_id: UUID4,
1431        client_id: ClientId,
1432        instrument_id: InstrumentId,
1433        data: Vec<QuoteTick>,
1434        ts_init: UnixNanos,
1435        params: Option<HashMap<String, String>>,
1436    ) -> Self {
1437        Self {
1438            correlation_id,
1439            client_id,
1440            instrument_id,
1441            data,
1442            ts_init,
1443            params,
1444        }
1445    }
1446}
1447
1448#[derive(Clone, Debug)]
1449pub struct TradesResponse {
1450    pub correlation_id: UUID4,
1451    pub client_id: ClientId,
1452    pub instrument_id: InstrumentId,
1453    pub data: Vec<TradeTick>,
1454    pub ts_init: UnixNanos,
1455    pub params: Option<HashMap<String, String>>,
1456}
1457
1458impl TradesResponse {
1459    /// Converts to a dyn Any trait object for messaging.
1460    pub fn as_any(&self) -> &dyn Any {
1461        self
1462    }
1463
1464    pub fn new(
1465        correlation_id: UUID4,
1466        client_id: ClientId,
1467        instrument_id: InstrumentId,
1468        data: Vec<TradeTick>,
1469        ts_init: UnixNanos,
1470        params: Option<HashMap<String, String>>,
1471    ) -> Self {
1472        Self {
1473            correlation_id,
1474            client_id,
1475            instrument_id,
1476            data,
1477            ts_init,
1478            params,
1479        }
1480    }
1481}
1482
1483#[derive(Clone, Debug)]
1484pub struct BarsResponse {
1485    pub correlation_id: UUID4,
1486    pub client_id: ClientId,
1487    pub bar_type: BarType,
1488    pub data: Vec<Bar>,
1489    pub ts_init: UnixNanos,
1490    pub params: Option<HashMap<String, String>>,
1491}
1492
1493impl BarsResponse {
1494    /// Converts to a dyn Any trait object for messaging.
1495    pub fn as_any(&self) -> &dyn Any {
1496        self
1497    }
1498
1499    pub fn new(
1500        correlation_id: UUID4,
1501        client_id: ClientId,
1502        bar_type: BarType,
1503        data: Vec<Bar>,
1504        ts_init: UnixNanos,
1505        params: Option<HashMap<String, String>>,
1506    ) -> Self {
1507        Self {
1508            correlation_id,
1509            client_id,
1510            bar_type,
1511            data,
1512            ts_init,
1513            params,
1514        }
1515    }
1516}