1use std::num::NonZeroUsize;
17
18use nautilus_core::{Params, UUID4, UnixNanos};
19use nautilus_model::{
20 data::{BarType, DataType, option_chain::StrikeRange},
21 enums::BookType,
22 identifiers::{ClientId, InstrumentId, OptionSeriesId, Venue},
23};
24use serde::{Deserialize, Serialize};
25
26use super::{
27 IntoBarTypes, IntoInstrumentIds, check_client_id_or_venue,
28 identifiers::{
29 deserialize_bar_types, deserialize_instrument_ids, single_bar_type, single_instrument_id,
30 },
31};
32
33#[derive(Clone, Debug, Serialize, Deserialize)]
34#[cfg_attr(
35 feature = "python",
36 pyo3::pyclass(module = "nautilus_trader.live", frozen)
37)]
38#[cfg_attr(
39 feature = "python",
40 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
41)]
42pub struct SubscribeCustomData {
43 pub client_id: Option<ClientId>,
44 pub venue: Option<Venue>,
45 pub data_type: DataType,
46 pub command_id: UUID4,
47 pub ts_init: UnixNanos,
48 pub correlation_id: Option<UUID4>,
49 pub params: Option<Params>,
50}
51
52impl SubscribeCustomData {
53 pub fn new(
55 client_id: Option<ClientId>,
56 venue: Option<Venue>,
57 data_type: DataType,
58 command_id: UUID4,
59 ts_init: UnixNanos,
60 correlation_id: Option<UUID4>,
61 params: Option<Params>,
62 ) -> Self {
63 check_client_id_or_venue(&client_id, &venue);
64 Self {
65 client_id,
66 venue,
67 data_type,
68 command_id,
69 ts_init,
70 correlation_id,
71 params,
72 }
73 }
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize)]
77#[cfg_attr(
78 feature = "python",
79 pyo3::pyclass(module = "nautilus_trader.live", frozen)
80)]
81#[cfg_attr(
82 feature = "python",
83 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
84)]
85pub struct SubscribeInstrument {
86 #[serde(deserialize_with = "deserialize_instrument_ids")]
87 pub instrument_ids: Vec<InstrumentId>,
88 pub client_id: Option<ClientId>,
89 pub venue: Option<Venue>,
90 pub command_id: UUID4,
91 pub ts_init: UnixNanos,
92 pub correlation_id: Option<UUID4>,
93 pub params: Option<Params>,
94}
95
96impl SubscribeInstrument {
97 pub fn new(
107 instrument_ids: impl IntoInstrumentIds,
108 client_id: Option<ClientId>,
109 venue: Option<Venue>,
110 command_id: UUID4,
111 ts_init: UnixNanos,
112 correlation_id: Option<UUID4>,
113 params: Option<Params>,
114 ) -> Self {
115 let instrument_ids = instrument_ids
116 .into_instrument_ids()
117 .expect("invalid instrument identifier list");
118 check_client_id_or_venue(&client_id, &venue);
119 Self {
120 instrument_ids,
121 client_id,
122 venue,
123 command_id,
124 ts_init,
125 correlation_id,
126 params,
127 }
128 }
129
130 #[must_use]
136 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
137 let instrument_ids = instrument_ids
138 .into_instrument_ids()
139 .expect("invalid instrument identifier list");
140
141 Self {
142 instrument_ids,
143 client_id: self.client_id,
144 venue: self.venue,
145 command_id: self.command_id,
146 ts_init: self.ts_init,
147 correlation_id: self.correlation_id,
148 params: self.params.clone(),
149 }
150 }
151
152 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
158 single_instrument_id(&self.instrument_ids, "subscription")
159 }
160}
161
162#[derive(Clone, Debug, Serialize, Deserialize)]
163#[cfg_attr(
164 feature = "python",
165 pyo3::pyclass(module = "nautilus_trader.live", frozen)
166)]
167#[cfg_attr(
168 feature = "python",
169 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
170)]
171pub struct SubscribeInstruments {
172 pub client_id: Option<ClientId>,
173 pub venue: Venue,
174 pub command_id: UUID4,
175 pub ts_init: UnixNanos,
176 pub correlation_id: Option<UUID4>,
177 pub params: Option<Params>,
178}
179
180impl SubscribeInstruments {
181 pub fn new(
183 client_id: Option<ClientId>,
184 venue: Venue,
185 command_id: UUID4,
186 ts_init: UnixNanos,
187 correlation_id: Option<UUID4>,
188 params: Option<Params>,
189 ) -> Self {
190 Self {
191 client_id,
192 venue,
193 command_id,
194 ts_init,
195 correlation_id,
196 params,
197 }
198 }
199}
200
201#[derive(Clone, Debug, Serialize, Deserialize)]
202#[cfg_attr(
203 feature = "python",
204 pyo3::pyclass(module = "nautilus_trader.live", frozen)
205)]
206#[cfg_attr(
207 feature = "python",
208 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
209)]
210pub struct SubscribeBookDeltas {
211 #[serde(deserialize_with = "deserialize_instrument_ids")]
212 pub instrument_ids: Vec<InstrumentId>,
213 pub book_type: BookType,
214 pub client_id: Option<ClientId>,
215 pub venue: Option<Venue>,
216 pub command_id: UUID4,
217 pub ts_init: UnixNanos,
218 pub depth: Option<NonZeroUsize>,
219 pub managed: bool,
220 pub correlation_id: Option<UUID4>,
221 pub params: Option<Params>,
222}
223
224impl SubscribeBookDeltas {
225 #[expect(clippy::too_many_arguments)]
235 pub fn new(
236 instrument_ids: impl IntoInstrumentIds,
237 book_type: BookType,
238 client_id: Option<ClientId>,
239 venue: Option<Venue>,
240 command_id: UUID4,
241 ts_init: UnixNanos,
242 depth: Option<NonZeroUsize>,
243 managed: bool,
244 correlation_id: Option<UUID4>,
245 params: Option<Params>,
246 ) -> Self {
247 let instrument_ids = instrument_ids
248 .into_instrument_ids()
249 .expect("invalid instrument identifier list");
250 check_client_id_or_venue(&client_id, &venue);
251 Self {
252 instrument_ids,
253 book_type,
254 client_id,
255 venue,
256 command_id,
257 ts_init,
258 depth,
259 managed,
260 correlation_id,
261 params,
262 }
263 }
264
265 #[must_use]
271 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
272 let instrument_ids = instrument_ids
273 .into_instrument_ids()
274 .expect("invalid instrument identifier list");
275
276 Self {
277 instrument_ids,
278 book_type: self.book_type,
279 client_id: self.client_id,
280 venue: self.venue,
281 command_id: self.command_id,
282 ts_init: self.ts_init,
283 depth: self.depth,
284 managed: self.managed,
285 correlation_id: self.correlation_id,
286 params: self.params.clone(),
287 }
288 }
289
290 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
296 single_instrument_id(&self.instrument_ids, "subscription")
297 }
298}
299
300#[derive(Clone, Debug, Serialize, Deserialize)]
301#[cfg_attr(
302 feature = "python",
303 pyo3::pyclass(module = "nautilus_trader.live", frozen)
304)]
305#[cfg_attr(
306 feature = "python",
307 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
308)]
309pub struct SubscribeBookDepth {
310 #[serde(deserialize_with = "deserialize_instrument_ids")]
311 pub instrument_ids: Vec<InstrumentId>,
312 pub book_type: BookType,
313 pub client_id: Option<ClientId>,
314 pub venue: Option<Venue>,
315 pub command_id: UUID4,
316 pub ts_init: UnixNanos,
317 pub depth: Option<NonZeroUsize>,
318 pub managed: bool,
319 pub correlation_id: Option<UUID4>,
320 pub params: Option<Params>,
321}
322
323impl SubscribeBookDepth {
324 #[expect(clippy::too_many_arguments)]
334 pub fn new(
335 instrument_ids: impl IntoInstrumentIds,
336 book_type: BookType,
337 client_id: Option<ClientId>,
338 venue: Option<Venue>,
339 command_id: UUID4,
340 ts_init: UnixNanos,
341 depth: Option<NonZeroUsize>,
342 managed: bool,
343 correlation_id: Option<UUID4>,
344 params: Option<Params>,
345 ) -> Self {
346 let instrument_ids = instrument_ids
347 .into_instrument_ids()
348 .expect("invalid instrument identifier list");
349 check_client_id_or_venue(&client_id, &venue);
350 Self {
351 instrument_ids,
352 book_type,
353 client_id,
354 venue,
355 command_id,
356 ts_init,
357 depth,
358 managed,
359 correlation_id,
360 params,
361 }
362 }
363
364 #[must_use]
370 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
371 let instrument_ids = instrument_ids
372 .into_instrument_ids()
373 .expect("invalid instrument identifier list");
374
375 Self {
376 instrument_ids,
377 book_type: self.book_type,
378 client_id: self.client_id,
379 venue: self.venue,
380 command_id: self.command_id,
381 ts_init: self.ts_init,
382 depth: self.depth,
383 managed: self.managed,
384 correlation_id: self.correlation_id,
385 params: self.params.clone(),
386 }
387 }
388
389 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
395 single_instrument_id(&self.instrument_ids, "subscription")
396 }
397}
398
399#[derive(Clone, Debug, Serialize, Deserialize)]
400pub struct SubscribeBookSnapshots {
401 #[serde(deserialize_with = "deserialize_instrument_ids")]
402 pub instrument_ids: Vec<InstrumentId>,
403 pub book_type: BookType,
404 pub client_id: Option<ClientId>,
405 pub venue: Option<Venue>,
406 pub command_id: UUID4,
407 pub ts_init: UnixNanos,
408 pub depth: Option<NonZeroUsize>,
409 pub interval_ms: NonZeroUsize,
410 pub correlation_id: Option<UUID4>,
411 pub params: Option<Params>,
412}
413
414impl SubscribeBookSnapshots {
415 #[expect(clippy::too_many_arguments)]
425 pub fn new(
426 instrument_ids: impl IntoInstrumentIds,
427 book_type: BookType,
428 client_id: Option<ClientId>,
429 venue: Option<Venue>,
430 command_id: UUID4,
431 ts_init: UnixNanos,
432 depth: Option<NonZeroUsize>,
433 interval_ms: NonZeroUsize,
434 correlation_id: Option<UUID4>,
435 params: Option<Params>,
436 ) -> Self {
437 let instrument_ids = instrument_ids
438 .into_instrument_ids()
439 .expect("invalid instrument identifier list");
440 check_client_id_or_venue(&client_id, &venue);
441 Self {
442 instrument_ids,
443 book_type,
444 client_id,
445 venue,
446 command_id,
447 ts_init,
448 depth,
449 interval_ms,
450 correlation_id,
451 params,
452 }
453 }
454
455 #[must_use]
461 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
462 let instrument_ids = instrument_ids
463 .into_instrument_ids()
464 .expect("invalid instrument identifier list");
465
466 Self {
467 instrument_ids,
468 book_type: self.book_type,
469 client_id: self.client_id,
470 venue: self.venue,
471 command_id: self.command_id,
472 ts_init: self.ts_init,
473 depth: self.depth,
474 interval_ms: self.interval_ms,
475 correlation_id: self.correlation_id,
476 params: self.params.clone(),
477 }
478 }
479
480 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
486 single_instrument_id(&self.instrument_ids, "subscription")
487 }
488}
489
490#[derive(Clone, Debug, Serialize, Deserialize)]
491#[cfg_attr(
492 feature = "python",
493 pyo3::pyclass(module = "nautilus_trader.live", frozen)
494)]
495#[cfg_attr(
496 feature = "python",
497 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
498)]
499pub struct SubscribeQuotes {
500 #[serde(deserialize_with = "deserialize_instrument_ids")]
501 pub instrument_ids: Vec<InstrumentId>,
502 pub client_id: Option<ClientId>,
503 pub venue: Option<Venue>,
504 pub command_id: UUID4,
505 pub ts_init: UnixNanos,
506 pub correlation_id: Option<UUID4>,
507 pub params: Option<Params>,
508}
509
510impl SubscribeQuotes {
511 pub fn new(
521 instrument_ids: impl IntoInstrumentIds,
522 client_id: Option<ClientId>,
523 venue: Option<Venue>,
524 command_id: UUID4,
525 ts_init: UnixNanos,
526 correlation_id: Option<UUID4>,
527 params: Option<Params>,
528 ) -> Self {
529 let instrument_ids = instrument_ids
530 .into_instrument_ids()
531 .expect("invalid instrument identifier list");
532 check_client_id_or_venue(&client_id, &venue);
533 Self {
534 instrument_ids,
535 client_id,
536 venue,
537 command_id,
538 ts_init,
539 correlation_id,
540 params,
541 }
542 }
543
544 #[must_use]
550 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
551 let instrument_ids = instrument_ids
552 .into_instrument_ids()
553 .expect("invalid instrument identifier list");
554
555 Self {
556 instrument_ids,
557 client_id: self.client_id,
558 venue: self.venue,
559 command_id: self.command_id,
560 ts_init: self.ts_init,
561 correlation_id: self.correlation_id,
562 params: self.params.clone(),
563 }
564 }
565
566 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
572 single_instrument_id(&self.instrument_ids, "subscription")
573 }
574}
575
576#[derive(Debug, thiserror::Error)]
582#[error("{source}")]
583#[non_exhaustive]
584pub struct SubscriptionError {
585 pub instrument_ids_accepted: Vec<InstrumentId>,
586 pub bar_types_accepted: Vec<BarType>,
587 #[source]
588 pub source: anyhow::Error,
589}
590
591impl SubscriptionError {
592 #[must_use]
594 pub fn instruments(instrument_ids_accepted: Vec<InstrumentId>, source: anyhow::Error) -> Self {
595 Self {
596 instrument_ids_accepted,
597 bar_types_accepted: Vec::new(),
598 source,
599 }
600 }
601
602 #[must_use]
604 pub fn bars(bar_types_accepted: Vec<BarType>, source: anyhow::Error) -> Self {
605 Self {
606 instrument_ids_accepted: Vec::new(),
607 bar_types_accepted,
608 source,
609 }
610 }
611}
612
613#[derive(Clone, Debug, Serialize, Deserialize)]
614#[cfg_attr(
615 feature = "python",
616 pyo3::pyclass(module = "nautilus_trader.live", frozen)
617)]
618#[cfg_attr(
619 feature = "python",
620 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
621)]
622pub struct SubscribeTrades {
623 #[serde(deserialize_with = "deserialize_instrument_ids")]
624 pub instrument_ids: Vec<InstrumentId>,
625 pub client_id: Option<ClientId>,
626 pub venue: Option<Venue>,
627 pub command_id: UUID4,
628 pub ts_init: UnixNanos,
629 pub correlation_id: Option<UUID4>,
630 pub params: Option<Params>,
631}
632
633impl SubscribeTrades {
634 pub fn new(
644 instrument_ids: impl IntoInstrumentIds,
645 client_id: Option<ClientId>,
646 venue: Option<Venue>,
647 command_id: UUID4,
648 ts_init: UnixNanos,
649 correlation_id: Option<UUID4>,
650 params: Option<Params>,
651 ) -> Self {
652 let instrument_ids = instrument_ids
653 .into_instrument_ids()
654 .expect("invalid instrument identifier list");
655 check_client_id_or_venue(&client_id, &venue);
656 Self {
657 instrument_ids,
658 client_id,
659 venue,
660 command_id,
661 ts_init,
662 correlation_id,
663 params,
664 }
665 }
666
667 #[must_use]
673 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
674 let instrument_ids = instrument_ids
675 .into_instrument_ids()
676 .expect("invalid instrument identifier list");
677
678 Self {
679 instrument_ids,
680 client_id: self.client_id,
681 venue: self.venue,
682 command_id: self.command_id,
683 ts_init: self.ts_init,
684 correlation_id: self.correlation_id,
685 params: self.params.clone(),
686 }
687 }
688
689 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
695 single_instrument_id(&self.instrument_ids, "subscription")
696 }
697}
698
699#[derive(Clone, Debug, Serialize, Deserialize)]
700#[cfg_attr(
701 feature = "python",
702 pyo3::pyclass(module = "nautilus_trader.live", frozen)
703)]
704#[cfg_attr(
705 feature = "python",
706 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
707)]
708pub struct SubscribeBars {
709 #[serde(deserialize_with = "deserialize_bar_types")]
710 pub bar_types: Vec<BarType>,
711 pub client_id: Option<ClientId>,
712 pub venue: Option<Venue>,
713 pub command_id: UUID4,
714 pub ts_init: UnixNanos,
715 pub correlation_id: Option<UUID4>,
716 pub params: Option<Params>,
717}
718
719impl SubscribeBars {
720 pub fn new(
730 bar_types: impl IntoBarTypes,
731 client_id: Option<ClientId>,
732 venue: Option<Venue>,
733 command_id: UUID4,
734 ts_init: UnixNanos,
735 correlation_id: Option<UUID4>,
736 params: Option<Params>,
737 ) -> Self {
738 let bar_types = bar_types.into_bar_types().expect("invalid bar type list");
739 check_client_id_or_venue(&client_id, &venue);
740 Self {
741 bar_types,
742 client_id,
743 venue,
744 command_id,
745 ts_init,
746 correlation_id,
747 params,
748 }
749 }
750
751 #[must_use]
757 pub fn with_bar_types(&self, bar_types: impl IntoBarTypes) -> Self {
758 let bar_types = bar_types.into_bar_types().expect("invalid bar type list");
759
760 Self {
761 bar_types,
762 client_id: self.client_id,
763 venue: self.venue,
764 command_id: self.command_id,
765 ts_init: self.ts_init,
766 correlation_id: self.correlation_id,
767 params: self.params.clone(),
768 }
769 }
770
771 pub fn single_bar_type(&self) -> anyhow::Result<BarType> {
777 single_bar_type(&self.bar_types, "subscription")
778 }
779}
780
781#[derive(Clone, Debug, Serialize, Deserialize)]
782#[cfg_attr(
783 feature = "python",
784 pyo3::pyclass(module = "nautilus_trader.live", frozen)
785)]
786#[cfg_attr(
787 feature = "python",
788 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
789)]
790pub struct SubscribeMarkPrices {
791 #[serde(deserialize_with = "deserialize_instrument_ids")]
792 pub instrument_ids: Vec<InstrumentId>,
793 pub client_id: Option<ClientId>,
794 pub venue: Option<Venue>,
795 pub command_id: UUID4,
796 pub ts_init: UnixNanos,
797 pub correlation_id: Option<UUID4>,
798 pub params: Option<Params>,
799}
800
801impl SubscribeMarkPrices {
802 pub fn new(
812 instrument_ids: impl IntoInstrumentIds,
813 client_id: Option<ClientId>,
814 venue: Option<Venue>,
815 command_id: UUID4,
816 ts_init: UnixNanos,
817 correlation_id: Option<UUID4>,
818 params: Option<Params>,
819 ) -> Self {
820 let instrument_ids = instrument_ids
821 .into_instrument_ids()
822 .expect("invalid instrument identifier list");
823 check_client_id_or_venue(&client_id, &venue);
824 Self {
825 instrument_ids,
826 client_id,
827 venue,
828 command_id,
829 ts_init,
830 correlation_id,
831 params,
832 }
833 }
834
835 #[must_use]
841 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
842 let instrument_ids = instrument_ids
843 .into_instrument_ids()
844 .expect("invalid instrument identifier list");
845
846 Self {
847 instrument_ids,
848 client_id: self.client_id,
849 venue: self.venue,
850 command_id: self.command_id,
851 ts_init: self.ts_init,
852 correlation_id: self.correlation_id,
853 params: self.params.clone(),
854 }
855 }
856
857 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
863 single_instrument_id(&self.instrument_ids, "subscription")
864 }
865}
866
867#[derive(Clone, Debug, Serialize, Deserialize)]
868#[cfg_attr(
869 feature = "python",
870 pyo3::pyclass(module = "nautilus_trader.live", frozen)
871)]
872#[cfg_attr(
873 feature = "python",
874 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
875)]
876pub struct SubscribeIndexPrices {
877 #[serde(deserialize_with = "deserialize_instrument_ids")]
878 pub instrument_ids: Vec<InstrumentId>,
879 pub client_id: Option<ClientId>,
880 pub venue: Option<Venue>,
881 pub command_id: UUID4,
882 pub ts_init: UnixNanos,
883 pub correlation_id: Option<UUID4>,
884 pub params: Option<Params>,
885}
886
887impl SubscribeIndexPrices {
888 pub fn new(
898 instrument_ids: impl IntoInstrumentIds,
899 client_id: Option<ClientId>,
900 venue: Option<Venue>,
901 command_id: UUID4,
902 ts_init: UnixNanos,
903 correlation_id: Option<UUID4>,
904 params: Option<Params>,
905 ) -> Self {
906 let instrument_ids = instrument_ids
907 .into_instrument_ids()
908 .expect("invalid instrument identifier list");
909 check_client_id_or_venue(&client_id, &venue);
910 Self {
911 instrument_ids,
912 client_id,
913 venue,
914 command_id,
915 ts_init,
916 correlation_id,
917 params,
918 }
919 }
920
921 #[must_use]
927 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
928 let instrument_ids = instrument_ids
929 .into_instrument_ids()
930 .expect("invalid instrument identifier list");
931
932 Self {
933 instrument_ids,
934 client_id: self.client_id,
935 venue: self.venue,
936 command_id: self.command_id,
937 ts_init: self.ts_init,
938 correlation_id: self.correlation_id,
939 params: self.params.clone(),
940 }
941 }
942
943 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
949 single_instrument_id(&self.instrument_ids, "subscription")
950 }
951}
952
953#[derive(Clone, Debug, Serialize, Deserialize)]
954#[cfg_attr(
955 feature = "python",
956 pyo3::pyclass(module = "nautilus_trader.live", frozen)
957)]
958#[cfg_attr(
959 feature = "python",
960 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
961)]
962pub struct SubscribeFundingRates {
963 #[serde(deserialize_with = "deserialize_instrument_ids")]
964 pub instrument_ids: Vec<InstrumentId>,
965 pub client_id: Option<ClientId>,
966 pub venue: Option<Venue>,
967 pub command_id: UUID4,
968 pub ts_init: UnixNanos,
969 pub correlation_id: Option<UUID4>,
970 pub params: Option<Params>,
971}
972
973impl SubscribeFundingRates {
974 pub fn new(
984 instrument_ids: impl IntoInstrumentIds,
985 client_id: Option<ClientId>,
986 venue: Option<Venue>,
987 command_id: UUID4,
988 ts_init: UnixNanos,
989 correlation_id: Option<UUID4>,
990 params: Option<Params>,
991 ) -> Self {
992 let instrument_ids = instrument_ids
993 .into_instrument_ids()
994 .expect("invalid instrument identifier list");
995 check_client_id_or_venue(&client_id, &venue);
996 Self {
997 instrument_ids,
998 client_id,
999 venue,
1000 command_id,
1001 ts_init,
1002 correlation_id,
1003 params,
1004 }
1005 }
1006
1007 #[must_use]
1013 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
1014 let instrument_ids = instrument_ids
1015 .into_instrument_ids()
1016 .expect("invalid instrument identifier list");
1017
1018 Self {
1019 instrument_ids,
1020 client_id: self.client_id,
1021 venue: self.venue,
1022 command_id: self.command_id,
1023 ts_init: self.ts_init,
1024 correlation_id: self.correlation_id,
1025 params: self.params.clone(),
1026 }
1027 }
1028
1029 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
1035 single_instrument_id(&self.instrument_ids, "subscription")
1036 }
1037}
1038
1039#[derive(Clone, Debug, Serialize, Deserialize)]
1040#[cfg_attr(
1041 feature = "python",
1042 pyo3::pyclass(module = "nautilus_trader.live", frozen)
1043)]
1044#[cfg_attr(
1045 feature = "python",
1046 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
1047)]
1048pub struct SubscribeInstrumentStatus {
1049 #[serde(deserialize_with = "deserialize_instrument_ids")]
1050 pub instrument_ids: Vec<InstrumentId>,
1051 pub client_id: Option<ClientId>,
1052 pub venue: Option<Venue>,
1053 pub command_id: UUID4,
1054 pub ts_init: UnixNanos,
1055 pub correlation_id: Option<UUID4>,
1056 pub params: Option<Params>,
1057}
1058
1059impl SubscribeInstrumentStatus {
1060 pub fn new(
1070 instrument_ids: impl IntoInstrumentIds,
1071 client_id: Option<ClientId>,
1072 venue: Option<Venue>,
1073 command_id: UUID4,
1074 ts_init: UnixNanos,
1075 correlation_id: Option<UUID4>,
1076 params: Option<Params>,
1077 ) -> Self {
1078 let instrument_ids = instrument_ids
1079 .into_instrument_ids()
1080 .expect("invalid instrument identifier list");
1081 check_client_id_or_venue(&client_id, &venue);
1082 Self {
1083 instrument_ids,
1084 client_id,
1085 venue,
1086 command_id,
1087 ts_init,
1088 correlation_id,
1089 params,
1090 }
1091 }
1092
1093 #[must_use]
1099 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
1100 let instrument_ids = instrument_ids
1101 .into_instrument_ids()
1102 .expect("invalid instrument identifier list");
1103
1104 Self {
1105 instrument_ids,
1106 client_id: self.client_id,
1107 venue: self.venue,
1108 command_id: self.command_id,
1109 ts_init: self.ts_init,
1110 correlation_id: self.correlation_id,
1111 params: self.params.clone(),
1112 }
1113 }
1114
1115 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
1121 single_instrument_id(&self.instrument_ids, "subscription")
1122 }
1123}
1124
1125#[derive(Clone, Debug, Serialize, Deserialize)]
1126#[cfg_attr(
1127 feature = "python",
1128 pyo3::pyclass(module = "nautilus_trader.live", frozen)
1129)]
1130#[cfg_attr(
1131 feature = "python",
1132 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
1133)]
1134pub struct SubscribeOptionGreeks {
1135 #[serde(deserialize_with = "deserialize_instrument_ids")]
1136 pub instrument_ids: Vec<InstrumentId>,
1137 pub client_id: Option<ClientId>,
1138 pub venue: Option<Venue>,
1139 pub command_id: UUID4,
1140 pub ts_init: UnixNanos,
1141 pub correlation_id: Option<UUID4>,
1142 pub params: Option<Params>,
1143}
1144
1145impl SubscribeOptionGreeks {
1146 pub fn new(
1156 instrument_ids: impl IntoInstrumentIds,
1157 client_id: Option<ClientId>,
1158 venue: Option<Venue>,
1159 command_id: UUID4,
1160 ts_init: UnixNanos,
1161 correlation_id: Option<UUID4>,
1162 params: Option<Params>,
1163 ) -> Self {
1164 let instrument_ids = instrument_ids
1165 .into_instrument_ids()
1166 .expect("invalid instrument identifier list");
1167 check_client_id_or_venue(&client_id, &venue);
1168 Self {
1169 instrument_ids,
1170 client_id,
1171 venue,
1172 command_id,
1173 ts_init,
1174 correlation_id,
1175 params,
1176 }
1177 }
1178
1179 #[must_use]
1185 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
1186 let instrument_ids = instrument_ids
1187 .into_instrument_ids()
1188 .expect("invalid instrument identifier list");
1189
1190 Self {
1191 instrument_ids,
1192 client_id: self.client_id,
1193 venue: self.venue,
1194 command_id: self.command_id,
1195 ts_init: self.ts_init,
1196 correlation_id: self.correlation_id,
1197 params: self.params.clone(),
1198 }
1199 }
1200
1201 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
1207 single_instrument_id(&self.instrument_ids, "subscription")
1208 }
1209}
1210
1211#[derive(Clone, Debug, Serialize, Deserialize)]
1212#[cfg_attr(
1213 feature = "python",
1214 pyo3::pyclass(module = "nautilus_trader.live", frozen)
1215)]
1216#[cfg_attr(
1217 feature = "python",
1218 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")
1219)]
1220pub struct SubscribeInstrumentClose {
1221 #[serde(deserialize_with = "deserialize_instrument_ids")]
1222 pub instrument_ids: Vec<InstrumentId>,
1223 pub client_id: Option<ClientId>,
1224 pub venue: Option<Venue>,
1225 pub command_id: UUID4,
1226 pub ts_init: UnixNanos,
1227 pub correlation_id: Option<UUID4>,
1228 pub params: Option<Params>,
1229}
1230
1231impl SubscribeInstrumentClose {
1232 pub fn new(
1242 instrument_ids: impl IntoInstrumentIds,
1243 client_id: Option<ClientId>,
1244 venue: Option<Venue>,
1245 command_id: UUID4,
1246 ts_init: UnixNanos,
1247 correlation_id: Option<UUID4>,
1248 params: Option<Params>,
1249 ) -> Self {
1250 let instrument_ids = instrument_ids
1251 .into_instrument_ids()
1252 .expect("invalid instrument identifier list");
1253 check_client_id_or_venue(&client_id, &venue);
1254 Self {
1255 instrument_ids,
1256 client_id,
1257 venue,
1258 command_id,
1259 ts_init,
1260 correlation_id,
1261 params,
1262 }
1263 }
1264
1265 #[must_use]
1271 pub fn with_instrument_ids(&self, instrument_ids: impl IntoInstrumentIds) -> Self {
1272 let instrument_ids = instrument_ids
1273 .into_instrument_ids()
1274 .expect("invalid instrument identifier list");
1275
1276 Self {
1277 instrument_ids,
1278 client_id: self.client_id,
1279 venue: self.venue,
1280 command_id: self.command_id,
1281 ts_init: self.ts_init,
1282 correlation_id: self.correlation_id,
1283 params: self.params.clone(),
1284 }
1285 }
1286
1287 pub fn single_instrument_id(&self) -> anyhow::Result<InstrumentId> {
1293 single_instrument_id(&self.instrument_ids, "subscription")
1294 }
1295}
1296
1297#[derive(Clone, Debug, Serialize, Deserialize)]
1298pub struct SubscribeOptionChain {
1299 pub series_id: OptionSeriesId,
1300 pub strike_range: StrikeRange,
1301 pub snapshot_interval_ms: Option<u64>,
1302 pub command_id: UUID4,
1303 pub ts_init: UnixNanos,
1304 pub client_id: Option<ClientId>,
1305 pub venue: Option<Venue>,
1306 #[serde(default)]
1307 pub correlation_id: Option<UUID4>,
1308 pub params: Option<Params>,
1309}
1310
1311impl SubscribeOptionChain {
1312 #[expect(
1314 clippy::too_many_arguments,
1315 reason = "constructor exposes the option chain subscription fields"
1316 )]
1317 pub fn new(
1318 series_id: OptionSeriesId,
1319 strike_range: StrikeRange,
1320 snapshot_interval_ms: Option<u64>,
1321 command_id: UUID4,
1322 ts_init: UnixNanos,
1323 client_id: Option<ClientId>,
1324 venue: Option<Venue>,
1325 params: Option<Params>,
1326 ) -> Self {
1327 check_client_id_or_venue(&client_id, &venue);
1328 Self {
1329 series_id,
1330 strike_range,
1331 snapshot_interval_ms,
1332 command_id,
1333 ts_init,
1334 client_id,
1335 venue,
1336 correlation_id: None,
1337 params,
1338 }
1339 }
1340}