1use std::str::FromStr;
19
20use serde::{Deserialize, Deserializer, Serialize, Serializer};
21use strum::{AsRefStr, Display, EnumIter, EnumString, FromRepr};
22
23use crate::enum_strum_serde;
24
25pub trait FromU8 {
27 fn from_u8(value: u8) -> Option<Self>
31 where
32 Self: Sized;
33}
34
35pub trait FromU16 {
37 fn from_u16(value: u16) -> Option<Self>
41 where
42 Self: Sized;
43}
44
45#[repr(C)]
47#[derive(
48 Copy,
49 Clone,
50 Debug,
51 Display,
52 Hash,
53 PartialEq,
54 Eq,
55 PartialOrd,
56 Ord,
57 AsRefStr,
58 FromRepr,
59 EnumIter,
60 EnumString,
61)]
62#[strum(ascii_case_insensitive)]
63#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
64#[cfg_attr(
65 feature = "python",
66 pyo3::pyclass(
67 frozen,
68 eq,
69 eq_int,
70 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
71 from_py_object,
72 rename_all = "SCREAMING_SNAKE_CASE",
73 )
74)]
75#[cfg_attr(
76 feature = "python",
77 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
78)]
79pub enum AccountType {
80 Cash = 1,
82 Margin = 2,
84 Betting = 3,
86 Wallet = 4,
88}
89
90#[repr(C)]
92#[derive(
93 Copy,
94 Clone,
95 Debug,
96 Display,
97 Hash,
98 PartialEq,
99 Eq,
100 PartialOrd,
101 Ord,
102 AsRefStr,
103 FromRepr,
104 EnumIter,
105 EnumString,
106)]
107#[strum(ascii_case_insensitive)]
108#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
109#[cfg_attr(
110 feature = "python",
111 pyo3::pyclass(
112 frozen,
113 eq,
114 eq_int,
115 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
116 from_py_object,
117 rename_all = "SCREAMING_SNAKE_CASE",
118 )
119)]
120#[cfg_attr(
121 feature = "python",
122 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
123)]
124pub enum AggregationSource {
125 External = 1,
127 Internal = 2,
129}
130
131#[repr(C)]
133#[derive(
134 Copy,
135 Clone,
136 Debug,
137 Default,
138 Display,
139 Hash,
140 PartialEq,
141 Eq,
142 PartialOrd,
143 Ord,
144 AsRefStr,
145 FromRepr,
146 EnumIter,
147 EnumString,
148)]
149#[strum(ascii_case_insensitive)]
150#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
151#[cfg_attr(
152 feature = "python",
153 pyo3::pyclass(
154 frozen,
155 eq,
156 eq_int,
157 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
158 from_py_object,
159 rename_all = "SCREAMING_SNAKE_CASE",
160 )
161)]
162#[cfg_attr(
163 feature = "python",
164 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
165)]
166pub enum AggressorSide {
167 #[default]
169 NoAggressor = 0,
170 Buyer = 1,
172 Seller = 2,
174}
175
176impl FromU8 for AggressorSide {
177 fn from_u8(value: u8) -> Option<Self> {
178 match value {
179 0 => Some(Self::NoAggressor),
180 1 => Some(Self::Buyer),
181 2 => Some(Self::Seller),
182 _ => None,
183 }
184 }
185}
186
187#[repr(C)]
189#[derive(
190 Copy,
191 Clone,
192 Debug,
193 Display,
194 Hash,
195 PartialEq,
196 Eq,
197 PartialOrd,
198 Ord,
199 AsRefStr,
200 FromRepr,
201 EnumIter,
202 EnumString,
203)]
204#[strum(ascii_case_insensitive)]
205#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
206#[cfg_attr(
207 feature = "python",
208 pyo3::pyclass(
209 frozen,
210 eq,
211 eq_int,
212 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
213 from_py_object,
214 rename_all = "SCREAMING_SNAKE_CASE",
215 )
216)]
217#[cfg_attr(
218 feature = "python",
219 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
220)]
221#[allow(non_camel_case_types)]
222pub enum AssetClass {
223 FX = 1,
225 Equity = 2,
227 Commodity = 3,
229 Debt = 4,
231 Index = 5,
233 Cryptocurrency = 6,
235 Alternative = 7,
237}
238
239impl FromU8 for AssetClass {
240 fn from_u8(value: u8) -> Option<Self> {
241 match value {
242 1 => Some(Self::FX),
243 2 => Some(Self::Equity),
244 3 => Some(Self::Commodity),
245 4 => Some(Self::Debt),
246 5 => Some(Self::Index),
247 6 => Some(Self::Cryptocurrency),
248 7 => Some(Self::Alternative),
249 _ => None,
250 }
251 }
252}
253
254#[repr(C)]
256#[derive(
257 Copy,
258 Clone,
259 Debug,
260 Display,
261 Hash,
262 PartialEq,
263 Eq,
264 PartialOrd,
265 Ord,
266 AsRefStr,
267 FromRepr,
268 EnumIter,
269 EnumString,
270)]
271#[strum(ascii_case_insensitive)]
272#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
273#[cfg_attr(
274 feature = "python",
275 pyo3::pyclass(
276 frozen,
277 eq,
278 eq_int,
279 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
280 from_py_object,
281 rename_all = "SCREAMING_SNAKE_CASE",
282 )
283)]
284#[cfg_attr(
285 feature = "python",
286 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
287)]
288pub enum BarAggregation {
289 Tick = 1,
291 TickImbalance = 2,
293 TickRuns = 3,
295 Volume = 4,
297 VolumeImbalance = 5,
299 VolumeRuns = 6,
301 Value = 7,
303 ValueImbalance = 8,
305 ValueRuns = 9,
307 Millisecond = 10,
309 Second = 11,
311 Minute = 12,
313 Hour = 13,
315 Day = 14,
317 Week = 15,
319 Month = 16,
321 Year = 17,
323 Renko = 18,
325}
326
327#[repr(C)]
329#[derive(
330 Copy,
331 Clone,
332 Debug,
333 Default,
334 Display,
335 Hash,
336 PartialEq,
337 Eq,
338 PartialOrd,
339 Ord,
340 AsRefStr,
341 FromRepr,
342 EnumIter,
343 EnumString,
344)]
345#[strum(ascii_case_insensitive)]
346#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
347#[cfg_attr(
348 feature = "python",
349 pyo3::pyclass(
350 frozen,
351 eq,
352 eq_int,
353 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
354 from_py_object,
355 rename_all = "SCREAMING_SNAKE_CASE",
356 )
357)]
358#[cfg_attr(
359 feature = "python",
360 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
361)]
362pub enum BarIntervalType {
363 #[default]
365 LeftOpen = 1,
366 RightOpen = 2,
368}
369
370#[repr(C)]
372#[derive(
373 Copy,
374 Clone,
375 Debug,
376 Display,
377 Hash,
378 PartialEq,
379 Eq,
380 PartialOrd,
381 Ord,
382 AsRefStr,
383 FromRepr,
384 EnumIter,
385 EnumString,
386)]
387#[strum(ascii_case_insensitive)]
388#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
389#[cfg_attr(
390 feature = "python",
391 pyo3::pyclass(
392 frozen,
393 eq,
394 eq_int,
395 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
396 from_py_object,
397 rename_all = "SCREAMING_SNAKE_CASE",
398 )
399)]
400#[cfg_attr(
401 feature = "python",
402 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
403)]
404pub enum BetSide {
405 Back = 1,
407 Lay = 2,
409}
410
411impl BetSide {
412 #[must_use]
414 pub fn opposite(&self) -> Self {
415 match self {
416 Self::Back => Self::Lay,
417 Self::Lay => Self::Back,
418 }
419 }
420}
421
422impl From<OrderSide> for BetSide {
423 fn from(side: OrderSide) -> Self {
429 match side {
430 OrderSide::Buy => Self::Back,
431 OrderSide::Sell => Self::Lay,
432 OrderSide::NoOrderSide => panic!("Invalid `OrderSide` for `BetSide`, was {side}"),
433 }
434 }
435}
436
437#[repr(C)]
439#[derive(
440 Copy,
441 Clone,
442 Debug,
443 Display,
444 Hash,
445 PartialEq,
446 Eq,
447 PartialOrd,
448 Ord,
449 AsRefStr,
450 FromRepr,
451 EnumIter,
452 EnumString,
453)]
454#[strum(ascii_case_insensitive)]
455#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
456#[cfg_attr(
457 feature = "python",
458 pyo3::pyclass(
459 frozen,
460 eq,
461 eq_int,
462 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
463 from_py_object,
464 rename_all = "SCREAMING_SNAKE_CASE",
465 )
466)]
467#[cfg_attr(
468 feature = "python",
469 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
470)]
471pub enum BookAction {
472 Add = 1,
474 Update = 2,
476 Delete = 3,
478 Clear = 4,
480}
481
482impl FromU8 for BookAction {
483 fn from_u8(value: u8) -> Option<Self> {
484 match value {
485 1 => Some(Self::Add),
486 2 => Some(Self::Update),
487 3 => Some(Self::Delete),
488 4 => Some(Self::Clear),
489 _ => None,
490 }
491 }
492}
493
494#[repr(C)]
496#[derive(
497 Copy,
498 Clone,
499 Debug,
500 Display,
501 Hash,
502 PartialEq,
503 Eq,
504 PartialOrd,
505 Ord,
506 AsRefStr,
507 FromRepr,
508 EnumIter,
509 EnumString,
510)]
511#[strum(ascii_case_insensitive)]
512#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
513#[cfg_attr(
514 feature = "python",
515 pyo3::pyclass(
516 frozen,
517 eq,
518 eq_int,
519 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
520 from_py_object,
521 rename_all = "SCREAMING_SNAKE_CASE",
522 )
523)]
524#[cfg_attr(
525 feature = "python",
526 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
527)]
528#[allow(non_camel_case_types)]
529pub enum BookType {
530 L1_MBP = 1,
532 L2_MBP = 2,
534 L3_MBO = 3,
536}
537
538impl FromU8 for BookType {
539 fn from_u8(value: u8) -> Option<Self> {
540 match value {
541 1 => Some(Self::L1_MBP),
542 2 => Some(Self::L2_MBP),
543 3 => Some(Self::L3_MBO),
544 _ => None,
545 }
546 }
547}
548
549#[repr(C)]
553#[derive(
554 Copy,
555 Clone,
556 Debug,
557 Default,
558 Display,
559 Hash,
560 PartialEq,
561 Eq,
562 PartialOrd,
563 Ord,
564 AsRefStr,
565 FromRepr,
566 EnumIter,
567 EnumString,
568)]
569#[strum(ascii_case_insensitive)]
570#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
571#[cfg_attr(
572 feature = "python",
573 pyo3::pyclass(
574 frozen,
575 eq,
576 eq_int,
577 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
578 from_py_object,
579 rename_all = "SCREAMING_SNAKE_CASE",
580 )
581)]
582#[cfg_attr(
583 feature = "python",
584 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
585)]
586pub enum ContingencyType {
587 #[default]
589 NoContingency = 0,
590 Oco = 1,
592 Oto = 2,
594 Ouo = 3,
596}
597
598#[repr(C)]
612#[derive(
613 Copy,
614 Clone,
615 Debug,
616 Default,
617 Display,
618 Hash,
619 PartialEq,
620 Eq,
621 PartialOrd,
622 Ord,
623 AsRefStr,
624 FromRepr,
625 EnumIter,
626 EnumString,
627)]
628#[strum(ascii_case_insensitive)]
629#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
630#[cfg_attr(
631 feature = "python",
632 pyo3::pyclass(
633 frozen,
634 eq,
635 eq_int,
636 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
637 from_py_object,
638 rename_all = "SCREAMING_SNAKE_CASE",
639 )
640)]
641#[cfg_attr(
642 feature = "python",
643 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
644)]
645pub enum ContinuousFutureAdjustmentType {
646 #[default]
648 BackwardSpread = 1,
649 ForwardSpread = 2,
651 BackwardRatio = 3,
653 ForwardRatio = 4,
655}
656
657impl ContinuousFutureAdjustmentType {
658 #[must_use]
660 pub const fn is_ratio(&self) -> bool {
661 matches!(self, Self::BackwardRatio | Self::ForwardRatio)
662 }
663
664 #[must_use]
666 pub const fn is_backward(&self) -> bool {
667 matches!(self, Self::BackwardSpread | Self::BackwardRatio)
668 }
669}
670
671#[repr(C)]
673#[derive(
674 Copy,
675 Clone,
676 Debug,
677 Display,
678 Hash,
679 PartialEq,
680 Eq,
681 PartialOrd,
682 Ord,
683 AsRefStr,
684 FromRepr,
685 EnumIter,
686 EnumString,
687)]
688#[strum(ascii_case_insensitive)]
689#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
690#[cfg_attr(
691 feature = "python",
692 pyo3::pyclass(
693 frozen,
694 eq,
695 eq_int,
696 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
697 from_py_object,
698 rename_all = "SCREAMING_SNAKE_CASE",
699 )
700)]
701#[cfg_attr(
702 feature = "python",
703 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
704)]
705pub enum CurrencyType {
706 Crypto = 1,
708 Fiat = 2,
710 CommodityBacked = 3,
712}
713
714#[repr(C)]
716#[derive(
717 Copy,
718 Clone,
719 Debug,
720 Display,
721 Hash,
722 PartialEq,
723 Eq,
724 PartialOrd,
725 Ord,
726 AsRefStr,
727 FromRepr,
728 EnumIter,
729 EnumString,
730)]
731#[strum(ascii_case_insensitive)]
732#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
733#[cfg_attr(
734 feature = "python",
735 pyo3::pyclass(
736 frozen,
737 eq,
738 eq_int,
739 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
740 from_py_object,
741 rename_all = "SCREAMING_SNAKE_CASE",
742 )
743)]
744#[cfg_attr(
745 feature = "python",
746 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
747)]
748pub enum InstrumentClass {
749 Spot = 1,
751 Swap = 2,
753 Future = 3,
755 FuturesSpread = 4,
757 Forward = 5,
759 Cfd = 6,
761 Bond = 7,
763 Option = 8,
765 OptionSpread = 9,
767 Warrant = 10,
769 SportsBetting = 11,
771 BinaryOption = 12,
773}
774
775impl InstrumentClass {
776 #[must_use]
778 pub const fn has_expiration(&self) -> bool {
779 matches!(
780 self,
781 Self::Future | Self::FuturesSpread | Self::Option | Self::OptionSpread
782 )
783 }
784
785 #[must_use]
787 pub const fn allows_negative_price(&self) -> bool {
788 matches!(
789 self,
790 Self::Option | Self::FuturesSpread | Self::OptionSpread
791 )
792 }
793
794 #[must_use]
799 pub fn try_from_parent_suffix(suffix: &str) -> Option<Self> {
800 match suffix {
801 "FUT" | "FUTURE" => Some(Self::Future),
802 "OPT" | "OPTION" => Some(Self::Option),
803 _ => None,
804 }
805 }
806
807 #[must_use]
812 pub const fn parent_suffix(self) -> Option<&'static str> {
813 match self {
814 Self::Future => Some("FUT"),
815 Self::Option => Some("OPT"),
816 _ => None,
817 }
818 }
819}
820
821#[repr(C)]
823#[derive(
824 Copy,
825 Clone,
826 Debug,
827 Display,
828 Hash,
829 PartialEq,
830 Eq,
831 PartialOrd,
832 Ord,
833 AsRefStr,
834 FromRepr,
835 EnumIter,
836 EnumString,
837)]
838#[strum(ascii_case_insensitive)]
839#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
840#[cfg_attr(
841 feature = "python",
842 pyo3::pyclass(
843 frozen,
844 eq,
845 eq_int,
846 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
847 from_py_object,
848 rename_all = "SCREAMING_SNAKE_CASE",
849 )
850)]
851#[cfg_attr(
852 feature = "python",
853 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
854)]
855pub enum InstrumentCloseType {
856 EndOfSession = 1,
858 ContractExpired = 2,
860}
861
862impl FromU8 for InstrumentCloseType {
864 fn from_u8(value: u8) -> Option<Self> {
865 match value {
866 1 => Some(Self::EndOfSession),
867 2 => Some(Self::ContractExpired),
868 _ => None,
869 }
870 }
871}
872
873#[repr(C)]
875#[derive(
876 Copy,
877 Clone,
878 Debug,
879 Display,
880 Hash,
881 PartialEq,
882 Eq,
883 PartialOrd,
884 Ord,
885 AsRefStr,
886 FromRepr,
887 EnumIter,
888 EnumString,
889)]
890#[strum(ascii_case_insensitive)]
891#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
892#[cfg_attr(
893 feature = "python",
894 pyo3::pyclass(
895 frozen,
896 eq,
897 eq_int,
898 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
899 from_py_object,
900 rename_all = "SCREAMING_SNAKE_CASE",
901 )
902)]
903#[cfg_attr(
904 feature = "python",
905 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
906)]
907pub enum LiquiditySide {
908 NoLiquiditySide = 0,
910 Maker = 1,
912 Taker = 2,
914}
915
916#[repr(C)]
918#[derive(
919 Copy,
920 Clone,
921 Debug,
922 Display,
923 Hash,
924 PartialEq,
925 Eq,
926 PartialOrd,
927 Ord,
928 AsRefStr,
929 FromRepr,
930 EnumIter,
931 EnumString,
932)]
933#[strum(ascii_case_insensitive)]
934#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
935#[cfg_attr(
936 feature = "python",
937 pyo3::pyclass(
938 frozen,
939 eq,
940 eq_int,
941 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
942 from_py_object,
943 rename_all = "SCREAMING_SNAKE_CASE",
944 )
945)]
946#[cfg_attr(
947 feature = "python",
948 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
949)]
950pub enum MarketStatus {
951 Open = 1,
953 Closed = 2,
955 Paused = 3,
957 Suspended = 5,
961 NotAvailable = 6,
963}
964
965#[repr(C)]
967#[derive(
968 Copy,
969 Clone,
970 Debug,
971 Display,
972 Hash,
973 PartialEq,
974 Eq,
975 PartialOrd,
976 Ord,
977 AsRefStr,
978 FromRepr,
979 EnumIter,
980 EnumString,
981)]
982#[strum(ascii_case_insensitive)]
983#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
984#[cfg_attr(
985 feature = "python",
986 pyo3::pyclass(
987 frozen,
988 eq,
989 eq_int,
990 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
991 from_py_object,
992 rename_all = "SCREAMING_SNAKE_CASE",
993 )
994)]
995#[cfg_attr(
996 feature = "python",
997 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
998)]
999pub enum MarketStatusAction {
1000 None = 0,
1002 PreOpen = 1,
1004 PreCross = 2,
1006 Quoting = 3,
1008 Cross = 4,
1010 Rotation = 5,
1012 NewPriceIndication = 6,
1014 Trading = 7,
1016 Halt = 8,
1018 Pause = 9,
1020 Suspend = 10,
1022 PreClose = 11,
1024 Close = 12,
1026 PostClose = 13,
1028 ShortSellRestrictionChange = 14,
1030 NotAvailableForTrading = 15,
1032}
1033
1034impl FromU16 for MarketStatusAction {
1036 fn from_u16(value: u16) -> Option<Self> {
1037 match value {
1038 0 => Some(Self::None),
1039 1 => Some(Self::PreOpen),
1040 2 => Some(Self::PreCross),
1041 3 => Some(Self::Quoting),
1042 4 => Some(Self::Cross),
1043 5 => Some(Self::Rotation),
1044 6 => Some(Self::NewPriceIndication),
1045 7 => Some(Self::Trading),
1046 8 => Some(Self::Halt),
1047 9 => Some(Self::Pause),
1048 10 => Some(Self::Suspend),
1049 11 => Some(Self::PreClose),
1050 12 => Some(Self::Close),
1051 13 => Some(Self::PostClose),
1052 14 => Some(Self::ShortSellRestrictionChange),
1053 15 => Some(Self::NotAvailableForTrading),
1054 _ => None,
1055 }
1056 }
1057}
1058
1059#[repr(C)]
1061#[derive(
1062 Copy,
1063 Clone,
1064 Debug,
1065 Default,
1066 Display,
1067 Hash,
1068 PartialEq,
1069 Eq,
1070 PartialOrd,
1071 Ord,
1072 AsRefStr,
1073 FromRepr,
1074 EnumIter,
1075 EnumString,
1076)]
1077#[strum(ascii_case_insensitive)]
1078#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1079#[cfg_attr(
1080 feature = "python",
1081 pyo3::pyclass(
1082 frozen,
1083 eq,
1084 eq_int,
1085 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1086 from_py_object,
1087 rename_all = "SCREAMING_SNAKE_CASE",
1088 )
1089)]
1090#[cfg_attr(
1091 feature = "python",
1092 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1093)]
1094pub enum OmsType {
1095 #[default]
1097 Unspecified = 0,
1098 Netting = 1,
1100 Hedging = 2,
1104}
1105
1106#[repr(C)]
1108#[derive(
1109 Copy,
1110 Clone,
1111 Debug,
1112 Display,
1113 Hash,
1114 PartialEq,
1115 Eq,
1116 PartialOrd,
1117 Ord,
1118 AsRefStr,
1119 FromRepr,
1120 EnumIter,
1121 EnumString,
1122)]
1123#[strum(ascii_case_insensitive)]
1124#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1125#[cfg_attr(
1126 feature = "python",
1127 pyo3::pyclass(
1128 frozen,
1129 eq,
1130 eq_int,
1131 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1132 from_py_object,
1133 rename_all = "SCREAMING_SNAKE_CASE",
1134 )
1135)]
1136#[cfg_attr(
1137 feature = "python",
1138 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1139)]
1140pub enum OptionKind {
1141 Call = 1,
1143 Put = 2,
1145}
1146
1147#[repr(C)]
1159#[derive(
1160 Copy,
1161 Clone,
1162 Debug,
1163 Default,
1164 Display,
1165 Hash,
1166 PartialEq,
1167 Eq,
1168 PartialOrd,
1169 Ord,
1170 AsRefStr,
1171 FromRepr,
1172 EnumIter,
1173 EnumString,
1174)]
1175#[strum(ascii_case_insensitive)]
1176#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1177#[cfg_attr(
1178 feature = "python",
1179 pyo3::pyclass(
1180 frozen,
1181 eq,
1182 eq_int,
1183 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1184 from_py_object,
1185 rename_all = "SCREAMING_SNAKE_CASE",
1186 )
1187)]
1188#[cfg_attr(
1189 feature = "python",
1190 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1191)]
1192pub enum GreeksConvention {
1193 #[default]
1195 BlackScholes = 1,
1196 PriceAdjusted = 2,
1198}
1199
1200#[repr(C)]
1202#[derive(
1203 Copy,
1204 Clone,
1205 Debug,
1206 Default,
1207 Display,
1208 Hash,
1209 PartialEq,
1210 Eq,
1211 PartialOrd,
1212 Ord,
1213 AsRefStr,
1214 FromRepr,
1215 EnumIter,
1216 EnumString,
1217)]
1218#[strum(ascii_case_insensitive)]
1219#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1220#[cfg_attr(
1221 feature = "python",
1222 pyo3::pyclass(
1223 frozen,
1224 eq,
1225 eq_int,
1226 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1227 from_py_object,
1228 rename_all = "SCREAMING_SNAKE_CASE",
1229 )
1230)]
1231#[cfg_attr(
1232 feature = "python",
1233 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1234)]
1235pub enum OtoTriggerMode {
1236 #[default]
1238 Partial = 0,
1239 Full = 1,
1241}
1242
1243#[repr(C)]
1245#[derive(
1246 Copy,
1247 Clone,
1248 Debug,
1249 Default,
1250 Display,
1251 Hash,
1252 PartialEq,
1253 Eq,
1254 PartialOrd,
1255 Ord,
1256 AsRefStr,
1257 FromRepr,
1258 EnumIter,
1259 EnumString,
1260)]
1261#[strum(ascii_case_insensitive)]
1262#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1263#[cfg_attr(
1264 feature = "python",
1265 pyo3::pyclass(
1266 frozen,
1267 eq,
1268 eq_int,
1269 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1270 from_py_object,
1271 rename_all = "SCREAMING_SNAKE_CASE",
1272 )
1273)]
1274#[cfg_attr(
1275 feature = "python",
1276 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1277)]
1278pub enum OrderSide {
1279 #[default]
1281 NoOrderSide = 0,
1282 Buy = 1,
1284 Sell = 2,
1286}
1287
1288impl OrderSide {
1289 #[must_use]
1295 pub fn as_specified(&self) -> OrderSideSpecified {
1296 match &self {
1297 Self::Buy => OrderSideSpecified::Buy,
1298 Self::Sell => OrderSideSpecified::Sell,
1299 Self::NoOrderSide => panic!("Order invariant failed: side must be `Buy` or `Sell`"),
1300 }
1301 }
1302}
1303
1304impl FromU8 for OrderSide {
1306 fn from_u8(value: u8) -> Option<Self> {
1307 match value {
1308 0 => Some(Self::NoOrderSide),
1309 1 => Some(Self::Buy),
1310 2 => Some(Self::Sell),
1311 _ => None,
1312 }
1313 }
1314}
1315
1316#[repr(C)]
1318#[derive(
1319 Copy,
1320 Clone,
1321 Debug,
1322 Display,
1323 Hash,
1324 PartialEq,
1325 Eq,
1326 PartialOrd,
1327 Ord,
1328 AsRefStr,
1329 FromRepr,
1330 EnumIter,
1331 EnumString,
1332)]
1333#[strum(ascii_case_insensitive)]
1334#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1335pub enum OrderSideSpecified {
1336 Buy = 1,
1338 Sell = 2,
1340}
1341
1342impl OrderSideSpecified {
1343 #[must_use]
1345 pub fn opposite(&self) -> Self {
1346 match &self {
1347 Self::Buy => Self::Sell,
1348 Self::Sell => Self::Buy,
1349 }
1350 }
1351
1352 #[must_use]
1354 pub fn as_order_side(&self) -> OrderSide {
1355 match &self {
1356 Self::Buy => OrderSide::Buy,
1357 Self::Sell => OrderSide::Sell,
1358 }
1359 }
1360}
1361
1362#[repr(C)]
1384#[derive(
1385 Copy,
1386 Clone,
1387 Debug,
1388 Display,
1389 Hash,
1390 PartialEq,
1391 Eq,
1392 PartialOrd,
1393 Ord,
1394 AsRefStr,
1395 FromRepr,
1396 EnumIter,
1397 EnumString,
1398)]
1399#[strum(ascii_case_insensitive)]
1400#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1401#[cfg_attr(
1402 feature = "python",
1403 pyo3::pyclass(
1404 frozen,
1405 eq,
1406 eq_int,
1407 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1408 from_py_object,
1409 rename_all = "SCREAMING_SNAKE_CASE",
1410 )
1411)]
1412#[cfg_attr(
1413 feature = "python",
1414 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1415)]
1416pub enum OrderStatus {
1417 Initialized = 1,
1419 Denied = 2,
1421 Emulated = 3,
1423 Released = 4,
1425 Submitted = 5,
1427 Accepted = 6,
1429 Rejected = 7,
1431 Canceled = 8,
1433 Expired = 9,
1435 Triggered = 10,
1437 PendingUpdate = 11,
1439 PendingCancel = 12,
1441 PartiallyFilled = 13,
1443 Filled = 14,
1445 Voided = 15,
1447}
1448
1449impl OrderStatus {
1450 #[must_use]
1452 pub const fn is_open(self) -> bool {
1453 matches!(
1454 self,
1455 Self::Submitted
1456 | Self::Accepted
1457 | Self::Triggered
1458 | Self::PendingUpdate
1459 | Self::PendingCancel
1460 | Self::PartiallyFilled
1461 )
1462 }
1463
1464 #[must_use]
1466 pub const fn is_closed(self) -> bool {
1467 matches!(
1468 self,
1469 Self::Denied
1470 | Self::Rejected
1471 | Self::Canceled
1472 | Self::Expired
1473 | Self::Filled
1474 | Self::Voided
1475 )
1476 }
1477
1478 #[must_use]
1480 pub const fn is_cancellable(self) -> bool {
1481 matches!(
1482 self,
1483 Self::Accepted | Self::Triggered | Self::PendingUpdate | Self::PartiallyFilled
1484 )
1485 }
1486}
1487
1488#[repr(C)]
1490#[derive(
1491 Copy,
1492 Clone,
1493 Debug,
1494 Display,
1495 Hash,
1496 PartialEq,
1497 Eq,
1498 PartialOrd,
1499 Ord,
1500 AsRefStr,
1501 FromRepr,
1502 EnumIter,
1503 EnumString,
1504)]
1505#[strum(ascii_case_insensitive)]
1506#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1507#[cfg_attr(
1508 feature = "python",
1509 pyo3::pyclass(
1510 frozen,
1511 eq,
1512 eq_int,
1513 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1514 from_py_object,
1515 rename_all = "SCREAMING_SNAKE_CASE",
1516 )
1517)]
1518#[cfg_attr(
1519 feature = "python",
1520 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1521)]
1522pub enum OrderType {
1523 Market = 1,
1525 Limit = 2,
1527 StopMarket = 3,
1529 StopLimit = 4,
1531 MarketToLimit = 5,
1533 MarketIfTouched = 6,
1535 LimitIfTouched = 7,
1537 TrailingStopMarket = 8,
1539 TrailingStopLimit = 9,
1541}
1542
1543#[repr(C)]
1545#[derive(
1546 Copy,
1547 Clone,
1548 Debug,
1549 Display,
1550 Hash,
1551 PartialEq,
1552 Eq,
1553 PartialOrd,
1554 Ord,
1555 AsRefStr,
1556 FromRepr,
1557 EnumIter,
1558 EnumString,
1559)]
1560#[strum(ascii_case_insensitive)]
1561#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1562#[cfg_attr(
1563 feature = "python",
1564 pyo3::pyclass(
1565 frozen,
1566 eq,
1567 eq_int,
1568 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1569 from_py_object,
1570 rename_all = "SCREAMING_SNAKE_CASE",
1571 )
1572)]
1573#[cfg_attr(
1574 feature = "python",
1575 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1576)]
1577pub enum PositionAdjustmentType {
1578 Commission = 1,
1580 Funding = 2,
1582}
1583
1584impl FromU8 for PositionAdjustmentType {
1585 fn from_u8(value: u8) -> Option<Self> {
1586 match value {
1587 1 => Some(Self::Commission),
1588 2 => Some(Self::Funding),
1589 _ => None,
1590 }
1591 }
1592}
1593
1594#[repr(C)]
1596#[derive(
1597 Copy,
1598 Clone,
1599 Debug,
1600 Default,
1601 Display,
1602 Hash,
1603 PartialEq,
1604 Eq,
1605 PartialOrd,
1606 Ord,
1607 AsRefStr,
1608 FromRepr,
1609 EnumIter,
1610 EnumString,
1611)]
1612#[strum(ascii_case_insensitive)]
1613#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1614#[cfg_attr(
1615 feature = "python",
1616 pyo3::pyclass(
1617 frozen,
1618 eq,
1619 eq_int,
1620 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1621 from_py_object,
1622 rename_all = "SCREAMING_SNAKE_CASE",
1623 )
1624)]
1625#[cfg_attr(
1626 feature = "python",
1627 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1628)]
1629pub enum PositionSide {
1630 #[default]
1632 NoPositionSide = 0,
1633 Flat = 1,
1635 Long = 2,
1637 Short = 3,
1639}
1640
1641impl PositionSide {
1642 #[must_use]
1648 pub fn as_specified(&self) -> PositionSideSpecified {
1649 match &self {
1650 Self::Long => PositionSideSpecified::Long,
1651 Self::Short => PositionSideSpecified::Short,
1652 Self::Flat => PositionSideSpecified::Flat,
1653 Self::NoPositionSide => {
1654 panic!("Position invariant failed: side must be `Long`, `Short`, or `Flat`")
1655 }
1656 }
1657 }
1658}
1659
1660#[repr(C)]
1662#[derive(
1663 Copy,
1664 Clone,
1665 Debug,
1666 Display,
1667 Hash,
1668 PartialEq,
1669 Eq,
1670 PartialOrd,
1671 Ord,
1672 AsRefStr,
1673 FromRepr,
1674 EnumIter,
1675 EnumString,
1676)]
1677#[strum(ascii_case_insensitive)]
1678#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1679#[cfg_attr(
1680 feature = "python",
1681 pyo3::pyclass(
1682 frozen,
1683 eq,
1684 eq_int,
1685 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1686 from_py_object,
1687 rename_all = "SCREAMING_SNAKE_CASE",
1688 )
1689)]
1690#[cfg_attr(
1691 feature = "python",
1692 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1693)]
1694pub enum PositionSideSpecified {
1695 Flat = 1,
1697 Long = 2,
1699 Short = 3,
1701}
1702
1703impl PositionSideSpecified {
1704 #[must_use]
1706 pub fn as_position_side(&self) -> PositionSide {
1707 match &self {
1708 Self::Long => PositionSide::Long,
1709 Self::Short => PositionSide::Short,
1710 Self::Flat => PositionSide::Flat,
1711 }
1712 }
1713}
1714
1715#[repr(C)]
1717#[derive(
1718 Copy,
1719 Clone,
1720 Debug,
1721 Display,
1722 Hash,
1723 PartialEq,
1724 Eq,
1725 PartialOrd,
1726 Ord,
1727 AsRefStr,
1728 FromRepr,
1729 EnumIter,
1730 EnumString,
1731)]
1732#[strum(ascii_case_insensitive)]
1733#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1734#[cfg_attr(
1735 feature = "python",
1736 pyo3::pyclass(
1737 frozen,
1738 eq,
1739 eq_int,
1740 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1741 from_py_object,
1742 rename_all = "SCREAMING_SNAKE_CASE",
1743 )
1744)]
1745#[cfg_attr(
1746 feature = "python",
1747 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1748)]
1749pub enum PriceType {
1750 Bid = 1,
1756 Ask = 2,
1759 Mid = 3,
1761 Last = 4,
1763 Mark = 5,
1766}
1767
1768#[repr(C)]
1770#[derive(
1771 Copy,
1772 Clone,
1773 Debug,
1774 Display,
1775 Hash,
1776 PartialEq,
1777 Eq,
1778 PartialOrd,
1779 Ord,
1780 AsRefStr,
1781 FromRepr,
1782 EnumIter,
1783 EnumString,
1784)]
1785#[strum(ascii_case_insensitive)]
1786#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1787#[cfg_attr(
1788 feature = "python",
1789 pyo3::pyclass(
1790 frozen,
1791 eq,
1792 eq_int,
1793 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1794 from_py_object,
1795 rename_all = "SCREAMING_SNAKE_CASE",
1796 )
1797)]
1798#[cfg_attr(
1799 feature = "python",
1800 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1801)]
1802#[allow(non_camel_case_types)]
1803pub enum RecordFlag {
1804 F_LAST = 1 << 7, F_TOB = 1 << 6, F_SNAPSHOT = 1 << 5, F_MBP = 1 << 4, RESERVED_2 = 1 << 3, RESERVED_1 = 1 << 2, }
1817
1818impl RecordFlag {
1819 #[must_use]
1821 pub fn matches(self, value: u8) -> bool {
1822 (self as u8) & value != 0
1823 }
1824}
1825
1826#[repr(C)]
1828#[derive(
1829 Copy,
1830 Clone,
1831 Debug,
1832 Display,
1833 Hash,
1834 PartialEq,
1835 Eq,
1836 PartialOrd,
1837 Ord,
1838 AsRefStr,
1839 FromRepr,
1840 EnumIter,
1841 EnumString,
1842)]
1843#[strum(ascii_case_insensitive)]
1844#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1845#[cfg_attr(
1846 feature = "python",
1847 pyo3::pyclass(
1848 frozen,
1849 eq,
1850 eq_int,
1851 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1852 from_py_object,
1853 rename_all = "SCREAMING_SNAKE_CASE",
1854 )
1855)]
1856#[cfg_attr(
1857 feature = "python",
1858 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1859)]
1860pub enum TimeInForce {
1861 Gtc = 1,
1863 Ioc = 2,
1865 Fok = 3,
1867 Gtd = 4,
1869 Day = 5,
1871 AtTheOpen = 6,
1873 AtTheClose = 7,
1875}
1876
1877#[repr(C)]
1879#[derive(
1880 Copy,
1881 Clone,
1882 Debug,
1883 Display,
1884 Hash,
1885 PartialEq,
1886 Eq,
1887 PartialOrd,
1888 Ord,
1889 AsRefStr,
1890 FromRepr,
1891 EnumIter,
1892 EnumString,
1893)]
1894#[strum(ascii_case_insensitive)]
1895#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1896#[cfg_attr(
1897 feature = "python",
1898 pyo3::pyclass(
1899 frozen,
1900 eq,
1901 eq_int,
1902 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1903 from_py_object,
1904 rename_all = "SCREAMING_SNAKE_CASE",
1905 )
1906)]
1907#[cfg_attr(
1908 feature = "python",
1909 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1910)]
1911pub enum TradingState {
1912 Active = 1,
1914 Halted = 2,
1916 Reducing = 3,
1918}
1919
1920#[repr(C)]
1922#[derive(
1923 Copy,
1924 Clone,
1925 Debug,
1926 Default,
1927 Display,
1928 Hash,
1929 PartialEq,
1930 Eq,
1931 PartialOrd,
1932 Ord,
1933 AsRefStr,
1934 FromRepr,
1935 EnumIter,
1936 EnumString,
1937)]
1938#[strum(ascii_case_insensitive)]
1939#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1940#[cfg_attr(
1941 feature = "python",
1942 pyo3::pyclass(
1943 frozen,
1944 eq,
1945 eq_int,
1946 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1947 from_py_object,
1948 rename_all = "SCREAMING_SNAKE_CASE",
1949 )
1950)]
1951#[cfg_attr(
1952 feature = "python",
1953 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
1954)]
1955pub enum TrailingOffsetType {
1956 #[default]
1958 NoTrailingOffset = 0,
1959 Price = 1,
1961 BasisPoints = 2,
1963 Ticks = 3,
1965 PriceTier = 4,
1967}
1968
1969#[repr(C)]
1971#[derive(
1972 Copy,
1973 Clone,
1974 Debug,
1975 Default,
1976 Display,
1977 Hash,
1978 PartialEq,
1979 Eq,
1980 PartialOrd,
1981 Ord,
1982 AsRefStr,
1983 FromRepr,
1984 EnumIter,
1985 EnumString,
1986)]
1987#[strum(ascii_case_insensitive)]
1988#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1989#[cfg_attr(
1990 feature = "python",
1991 pyo3::pyclass(
1992 frozen,
1993 eq,
1994 eq_int,
1995 module = "nautilus_trader.core.nautilus_pyo3.model.enums",
1996 from_py_object,
1997 rename_all = "SCREAMING_SNAKE_CASE",
1998 )
1999)]
2000#[cfg_attr(
2001 feature = "python",
2002 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.model")
2003)]
2004pub enum TriggerType {
2005 #[default]
2007 NoTrigger = 0,
2008 Default = 1,
2010 LastPrice = 2,
2012 MarkPrice = 3,
2014 IndexPrice = 4,
2016 BidAsk = 5,
2018 DoubleLast = 6,
2020 DoubleBidAsk = 7,
2022 LastOrBidAsk = 8,
2024 MidPoint = 9,
2026}
2027
2028enum_strum_serde!(AccountType);
2029enum_strum_serde!(AggregationSource);
2030enum_strum_serde!(AggressorSide);
2031enum_strum_serde!(AssetClass);
2032enum_strum_serde!(BarAggregation);
2033enum_strum_serde!(BarIntervalType);
2034enum_strum_serde!(BookAction);
2035enum_strum_serde!(BookType);
2036enum_strum_serde!(ContingencyType);
2037enum_strum_serde!(ContinuousFutureAdjustmentType);
2038enum_strum_serde!(CurrencyType);
2039enum_strum_serde!(GreeksConvention);
2040enum_strum_serde!(InstrumentClass);
2041enum_strum_serde!(InstrumentCloseType);
2042enum_strum_serde!(LiquiditySide);
2043enum_strum_serde!(MarketStatus);
2044enum_strum_serde!(MarketStatusAction);
2045enum_strum_serde!(OmsType);
2046enum_strum_serde!(OptionKind);
2047enum_strum_serde!(OrderSide);
2048enum_strum_serde!(OrderSideSpecified);
2049enum_strum_serde!(OrderStatus);
2050enum_strum_serde!(OrderType);
2051enum_strum_serde!(PositionAdjustmentType);
2052enum_strum_serde!(PositionSide);
2053enum_strum_serde!(PositionSideSpecified);
2054enum_strum_serde!(PriceType);
2055enum_strum_serde!(RecordFlag);
2056enum_strum_serde!(TimeInForce);
2057enum_strum_serde!(TradingState);
2058enum_strum_serde!(TrailingOffsetType);
2059enum_strum_serde!(TriggerType);
2060
2061#[cfg(test)]
2062mod tests {
2063 use rstest::rstest;
2064
2065 use super::*;
2066
2067 #[rstest]
2068 #[case::no_aggressor(0, Some(AggressorSide::NoAggressor))]
2069 #[case::buyer(1, Some(AggressorSide::Buyer))]
2070 #[case::seller(2, Some(AggressorSide::Seller))]
2071 #[case::invalid(3, None)]
2072 #[case::max_u8(255, None)]
2073 fn test_aggressor_side_from_u8(#[case] value: u8, #[case] expected: Option<AggressorSide>) {
2074 assert_eq!(AggressorSide::from_u8(value), expected);
2075 }
2076
2077 #[rstest]
2078 #[case(GreeksConvention::BlackScholes, "\"BLACK_SCHOLES\"")]
2079 #[case(GreeksConvention::PriceAdjusted, "\"PRICE_ADJUSTED\"")]
2080 fn test_greeks_convention_serde_roundtrip(
2081 #[case] input: GreeksConvention,
2082 #[case] expected: &str,
2083 ) {
2084 let json = serde_json::to_string(&input).unwrap();
2085 assert_eq!(json, expected);
2086 let parsed: GreeksConvention = serde_json::from_str(expected).unwrap();
2087 assert_eq!(parsed, input);
2088 }
2089
2090 #[rstest]
2091 fn test_greeks_convention_default_is_black_scholes() {
2092 assert_eq!(GreeksConvention::default(), GreeksConvention::BlackScholes);
2093 }
2094
2095 #[rstest]
2096 #[case(ContinuousFutureAdjustmentType::BackwardSpread, false, true)]
2097 #[case(ContinuousFutureAdjustmentType::ForwardSpread, false, false)]
2098 #[case(ContinuousFutureAdjustmentType::BackwardRatio, true, true)]
2099 #[case(ContinuousFutureAdjustmentType::ForwardRatio, true, false)]
2100 fn test_continuous_future_adjustment_type_predicates(
2101 #[case] mode: ContinuousFutureAdjustmentType,
2102 #[case] expected_is_ratio: bool,
2103 #[case] expected_is_backward: bool,
2104 ) {
2105 assert_eq!(mode.is_ratio(), expected_is_ratio);
2106 assert_eq!(mode.is_backward(), expected_is_backward);
2107 }
2108
2109 #[rstest]
2110 #[case(ContinuousFutureAdjustmentType::BackwardSpread, "\"BACKWARD_SPREAD\"")]
2111 #[case(ContinuousFutureAdjustmentType::ForwardSpread, "\"FORWARD_SPREAD\"")]
2112 #[case(ContinuousFutureAdjustmentType::BackwardRatio, "\"BACKWARD_RATIO\"")]
2113 #[case(ContinuousFutureAdjustmentType::ForwardRatio, "\"FORWARD_RATIO\"")]
2114 fn test_continuous_future_adjustment_type_serde_roundtrip(
2115 #[case] input: ContinuousFutureAdjustmentType,
2116 #[case] expected: &str,
2117 ) {
2118 let json = serde_json::to_string(&input).unwrap();
2119 assert_eq!(json, expected);
2120 let parsed: ContinuousFutureAdjustmentType = serde_json::from_str(expected).unwrap();
2121 assert_eq!(parsed, input);
2122 }
2123
2124 #[rstest]
2125 fn test_continuous_future_adjustment_type_default_is_backward_spread() {
2126 assert_eq!(
2127 ContinuousFutureAdjustmentType::default(),
2128 ContinuousFutureAdjustmentType::BackwardSpread,
2129 );
2130 }
2131
2132 #[rstest]
2133 #[case(InstrumentClass::Option, true)]
2134 #[case(InstrumentClass::FuturesSpread, true)]
2135 #[case(InstrumentClass::OptionSpread, true)]
2136 #[case(InstrumentClass::Spot, false)]
2137 #[case(InstrumentClass::Swap, false)]
2138 #[case(InstrumentClass::Future, false)]
2139 #[case(InstrumentClass::Forward, false)]
2140 #[case(InstrumentClass::Cfd, false)]
2141 #[case(InstrumentClass::Bond, false)]
2142 #[case(InstrumentClass::Warrant, false)]
2143 #[case(InstrumentClass::SportsBetting, false)]
2144 #[case(InstrumentClass::BinaryOption, false)]
2145 fn test_instrument_class_allows_negative_price(
2146 #[case] class: InstrumentClass,
2147 #[case] expected: bool,
2148 ) {
2149 assert_eq!(class.allows_negative_price(), expected);
2150 }
2151
2152 #[rstest]
2153 #[case("FUT", Some(InstrumentClass::Future))]
2154 #[case("FUTURE", Some(InstrumentClass::Future))]
2155 #[case("OPT", Some(InstrumentClass::Option))]
2156 #[case("OPTION", Some(InstrumentClass::Option))]
2157 #[case("fut", None)]
2158 #[case("Fut", None)]
2159 #[case("option", None)]
2160 #[case("Option", None)]
2161 #[case("SPREAD", None)]
2162 #[case("UNKNOWN", None)]
2163 #[case("", None)]
2164 fn test_instrument_class_try_from_parent_suffix(
2165 #[case] suffix: &str,
2166 #[case] expected: Option<InstrumentClass>,
2167 ) {
2168 assert_eq!(InstrumentClass::try_from_parent_suffix(suffix), expected);
2169 }
2170
2171 #[rstest]
2172 #[case(InstrumentClass::Future, Some("FUT"))]
2173 #[case(InstrumentClass::Option, Some("OPT"))]
2174 #[case(InstrumentClass::Spot, None)]
2175 #[case(InstrumentClass::Swap, None)]
2176 #[case(InstrumentClass::FuturesSpread, None)]
2177 #[case(InstrumentClass::Forward, None)]
2178 #[case(InstrumentClass::Cfd, None)]
2179 #[case(InstrumentClass::Bond, None)]
2180 #[case(InstrumentClass::OptionSpread, None)]
2181 #[case(InstrumentClass::Warrant, None)]
2182 #[case(InstrumentClass::SportsBetting, None)]
2183 #[case(InstrumentClass::BinaryOption, None)]
2184 fn test_instrument_class_parent_suffix(
2185 #[case] class: InstrumentClass,
2186 #[case] expected: Option<&'static str>,
2187 ) {
2188 assert_eq!(class.parent_suffix(), expected);
2189 }
2190
2191 #[rstest]
2192 #[case(InstrumentClass::Future)]
2193 #[case(InstrumentClass::Option)]
2194 fn test_instrument_class_parent_suffix_roundtrip(#[case] class: InstrumentClass) {
2195 let suffix = class.parent_suffix().unwrap();
2196 assert_eq!(InstrumentClass::try_from_parent_suffix(suffix), Some(class));
2197 }
2198}