1use nautilus_model::enums::{
19 AggressorSide, LiquiditySide, OptionKind, OrderSide, OrderStatus, OrderType, PositionSide,
20 TriggerType,
21};
22use serde::{Deserialize, Serialize};
23use strum::{AsRefStr, Display, EnumIter, EnumString};
24
25use crate::common::consts::OKX_CONDITIONAL_ORDER_TYPES;
26
27#[derive(
29 Copy,
30 Clone,
31 Debug,
32 Display,
33 PartialEq,
34 Eq,
35 Hash,
36 AsRefStr,
37 EnumIter,
38 EnumString,
39 Serialize,
40 Deserialize,
41)]
42#[serde(rename_all = "lowercase")]
43pub enum OKXBookAction {
44 Update,
46 Snapshot,
48}
49
50#[derive(
52 Copy,
53 Clone,
54 Debug,
55 Display,
56 PartialEq,
57 Eq,
58 Hash,
59 AsRefStr,
60 EnumIter,
61 EnumString,
62 Serialize,
63 Deserialize,
64)]
65pub enum OKXCandleConfirm {
66 #[serde(rename = "0")]
68 Partial,
69 #[serde(rename = "1")]
71 Closed,
72}
73
74#[derive(
76 Copy,
77 Clone,
78 Debug,
79 Display,
80 PartialEq,
81 Eq,
82 Hash,
83 AsRefStr,
84 EnumIter,
85 EnumString,
86 Serialize,
87 Deserialize,
88)]
89#[serde(rename_all = "snake_case")]
90pub enum OKXSide {
91 Buy,
93 Sell,
95}
96
97impl From<OrderSide> for OKXSide {
98 fn from(value: OrderSide) -> Self {
99 match value {
100 OrderSide::Buy => Self::Buy,
101 OrderSide::Sell => Self::Sell,
102 _ => panic!("Invalid `OrderSide`"),
103 }
104 }
105}
106
107impl From<OKXSide> for AggressorSide {
108 fn from(value: OKXSide) -> Self {
109 match value {
110 OKXSide::Buy => Self::Buyer,
111 OKXSide::Sell => Self::Seller,
112 }
113 }
114}
115
116#[derive(
118 Copy,
119 Clone,
120 Debug,
121 Display,
122 PartialEq,
123 Eq,
124 Hash,
125 AsRefStr,
126 EnumIter,
127 EnumString,
128 Serialize,
129 Deserialize,
130)]
131#[serde(rename_all = "snake_case")]
132pub enum OKXOrderType {
133 Market,
135 Limit,
137 PostOnly, Fok, Ioc, OptimalLimitIoc, Mmp, MmpAndPostOnly, Trigger, }
145
146#[derive(
148 Copy,
149 Clone,
150 Debug,
151 Display,
152 PartialEq,
153 Eq,
154 Hash,
155 AsRefStr,
156 EnumIter,
157 EnumString,
158 Serialize,
159 Deserialize,
160)]
161#[serde(rename_all = "snake_case")]
162#[cfg_attr(
163 feature = "python",
164 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
165)]
166pub enum OKXOrderStatus {
167 Canceled,
168 Live,
169 Effective,
170 PartiallyFilled,
171 Filled,
172 MmpCanceled,
173 OrderPlaced,
174}
175
176impl From<OrderStatus> for OKXOrderStatus {
177 fn from(value: OrderStatus) -> Self {
178 match value {
179 OrderStatus::Canceled => Self::Canceled,
180 OrderStatus::Accepted => Self::Live,
181 OrderStatus::PartiallyFilled => Self::PartiallyFilled,
182 OrderStatus::Filled => Self::Filled,
183 _ => panic!("Invalid `OrderStatus`"),
184 }
185 }
186}
187
188#[derive(
190 Copy,
191 Clone,
192 Debug,
193 Default,
194 Display,
195 PartialEq,
196 Eq,
197 Hash,
198 AsRefStr,
199 EnumIter,
200 EnumString,
201 Serialize,
202 Deserialize,
203)]
204pub enum OKXExecType {
205 #[serde(rename = "")]
206 #[default]
207 None,
208 #[serde(rename = "T")]
209 Taker,
210 #[serde(rename = "M")]
211 Maker,
212}
213
214impl From<LiquiditySide> for OKXExecType {
215 fn from(value: LiquiditySide) -> Self {
216 match value {
217 LiquiditySide::NoLiquiditySide => Self::None,
218 LiquiditySide::Taker => Self::Taker,
219 LiquiditySide::Maker => Self::Maker,
220 }
221 }
222}
223
224#[derive(
226 Copy,
227 Clone,
228 Debug,
229 Display,
230 Default,
231 PartialEq,
232 Eq,
233 Hash,
234 AsRefStr,
235 EnumIter,
236 EnumString,
237 Serialize,
238 Deserialize,
239)]
240#[serde(rename_all = "UPPERCASE")]
241#[cfg_attr(
242 feature = "python",
243 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
244)]
245pub enum OKXInstrumentType {
246 #[default]
247 Any,
248 Spot,
250 Margin,
252 Swap,
254 Futures,
256 Option,
258}
259
260#[derive(
262 Copy,
263 Clone,
264 Debug,
265 Display,
266 PartialEq,
267 Eq,
268 Hash,
269 AsRefStr,
270 EnumIter,
271 EnumString,
272 Serialize,
273 Deserialize,
274)]
275#[serde(rename_all = "snake_case")]
276pub enum OKXInstrumentStatus {
277 Live,
278 Suspend,
279 Preopen,
280 Test,
281}
282
283#[derive(
285 Copy,
286 Clone,
287 Default,
288 Debug,
289 Display,
290 PartialEq,
291 Eq,
292 Hash,
293 AsRefStr,
294 EnumIter,
295 EnumString,
296 Serialize,
297 Deserialize,
298)]
299#[serde(rename_all = "snake_case")]
300#[cfg_attr(
301 feature = "python",
302 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
303)]
304pub enum OKXContractType {
305 #[serde(rename = "")]
306 #[default]
307 None,
308 Linear,
309 Inverse,
310}
311
312#[derive(
314 Copy,
315 Clone,
316 Debug,
317 Display,
318 PartialEq,
319 Eq,
320 Hash,
321 AsRefStr,
322 EnumIter,
323 EnumString,
324 Serialize,
325 Deserialize,
326)]
327pub enum OKXOptionType {
328 #[serde(rename = "")]
329 None,
330 #[serde(rename = "C")]
331 Call,
332 #[serde(rename = "P")]
333 Put,
334}
335
336impl From<OKXOptionType> for OptionKind {
337 fn from(option_type: OKXOptionType) -> Self {
338 match option_type {
339 OKXOptionType::Call => Self::Call,
340 OKXOptionType::Put => Self::Put,
341 _ => panic!("Invalid `option_type`, was None"),
342 }
343 }
344}
345
346#[derive(
348 Copy,
349 Clone,
350 Debug,
351 Display,
352 Default,
353 PartialEq,
354 Eq,
355 Hash,
356 AsRefStr,
357 EnumIter,
358 EnumString,
359 Serialize,
360 Deserialize,
361)]
362#[serde(rename_all = "snake_case")]
363#[strum(ascii_case_insensitive)]
364#[cfg_attr(
365 feature = "python",
366 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
367)]
368pub enum OKXTradeMode {
369 #[default]
370 Cash,
371 Isolated,
372 Cross,
373 #[strum(serialize = "spot_isolated")]
374 SpotIsolated,
375}
376
377#[derive(
383 Copy,
384 Clone,
385 Debug,
386 Display,
387 PartialEq,
388 Eq,
389 Hash,
390 AsRefStr,
391 EnumIter,
392 EnumString,
393 Serialize,
394 Deserialize,
395)]
396pub enum OKXAccountMode {
397 #[serde(rename = "Spot mode")]
398 Spot,
399 #[serde(rename = "Spot and futures mode")]
400 SpotAndFutures,
401 #[serde(rename = "Multi-currency margin mode")]
402 MultiCurrencyMarginMode,
403 #[serde(rename = "Portfolio margin mode")]
404 PortfolioMarginMode,
405}
406
407#[derive(
415 Copy,
416 Clone,
417 Default,
418 Debug,
419 Display,
420 PartialEq,
421 Eq,
422 Hash,
423 AsRefStr,
424 EnumIter,
425 EnumString,
426 Serialize,
427 Deserialize,
428)]
429#[serde(rename_all = "snake_case")]
430#[cfg_attr(
431 feature = "python",
432 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
433)]
434pub enum OKXMarginMode {
435 #[serde(rename = "")]
436 #[default]
437 None,
438 Isolated,
439 Cross,
440}
441
442#[derive(
448 Copy,
449 Clone,
450 Default,
451 Debug,
452 Display,
453 PartialEq,
454 Eq,
455 Hash,
456 AsRefStr,
457 EnumIter,
458 EnumString,
459 Serialize,
460 Deserialize,
461)]
462#[cfg_attr(
463 feature = "python",
464 pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.okx")
465)]
466pub enum OKXPositionMode {
467 #[default]
468 #[serde(rename = "net_mode")]
469 NetMode,
470 #[serde(rename = "long_short_mode")]
471 LongShortMode,
472}
473
474#[derive(
475 Copy,
476 Clone,
477 Debug,
478 Display,
479 PartialEq,
480 Eq,
481 Hash,
482 AsRefStr,
483 EnumIter,
484 EnumString,
485 Serialize,
486 Deserialize,
487)]
488#[serde(rename_all = "snake_case")]
489pub enum OKXPositionSide {
490 #[serde(rename = "")]
491 None,
492 Net,
493 Long,
494 Short,
495}
496
497#[derive(
498 Copy,
499 Clone,
500 Debug,
501 Display,
502 PartialEq,
503 Eq,
504 Hash,
505 AsRefStr,
506 EnumIter,
507 EnumString,
508 Serialize,
509 Deserialize,
510)]
511#[serde(rename_all = "snake_case")]
512pub enum OKXSelfTradePreventionMode {
513 #[serde(rename = "")]
514 None,
515 CancelMaker,
516 CancelTaker,
517 CancelBoth,
518}
519
520#[derive(
521 Copy,
522 Clone,
523 Debug,
524 Display,
525 PartialEq,
526 Eq,
527 Hash,
528 AsRefStr,
529 EnumIter,
530 EnumString,
531 Serialize,
532 Deserialize,
533)]
534#[serde(rename_all = "snake_case")]
535pub enum OKXTakeProfitKind {
536 #[serde(rename = "")]
537 None,
538 Condition,
539 Limit,
540}
541
542#[derive(
543 Copy,
544 Clone,
545 Debug,
546 Display,
547 PartialEq,
548 Eq,
549 Hash,
550 AsRefStr,
551 EnumIter,
552 EnumString,
553 Serialize,
554 Deserialize,
555)]
556#[serde(rename_all = "snake_case")]
557pub enum OKXTriggerType {
558 #[serde(rename = "")]
559 None,
560 Last,
561 Index,
562 Mark,
563}
564
565impl From<TriggerType> for OKXTriggerType {
566 fn from(value: TriggerType) -> Self {
567 match value {
568 TriggerType::LastPrice => Self::Last,
569 TriggerType::MarkPrice => Self::Mark,
570 TriggerType::IndexPrice => Self::Index,
571 _ => Self::Last,
572 }
573 }
574}
575
576#[derive(
578 Copy,
579 Clone,
580 Debug,
581 Display,
582 PartialEq,
583 Eq,
584 Hash,
585 AsRefStr,
586 EnumIter,
587 EnumString,
588 Serialize,
589 Deserialize,
590)]
591#[serde(rename_all = "snake_case")]
592#[strum(serialize_all = "snake_case")]
593pub enum OKXTargetCurrency {
594 BaseCcy,
596 QuoteCcy,
598}
599
600#[derive(Copy, Clone, Debug, PartialEq, Eq)]
602pub enum OKXBookChannel {
603 Book,
605 BookL2Tbt,
607 Books50L2Tbt,
609}
610
611#[derive(
625 Copy,
626 Clone,
627 Debug,
628 Display,
629 PartialEq,
630 Eq,
631 PartialOrd,
632 Ord,
633 Hash,
634 AsRefStr,
635 EnumIter,
636 EnumString,
637 Serialize,
638 Deserialize,
639)]
640#[cfg_attr(
641 feature = "python",
642 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.adapters")
643)]
644pub enum OKXVipLevel {
645 #[serde(rename = "0")]
647 #[strum(serialize = "0")]
648 Vip0 = 0,
649 #[serde(rename = "1")]
651 #[strum(serialize = "1")]
652 Vip1 = 1,
653 #[serde(rename = "2")]
655 #[strum(serialize = "2")]
656 Vip2 = 2,
657 #[serde(rename = "3")]
659 #[strum(serialize = "3")]
660 Vip3 = 3,
661 #[serde(rename = "4")]
663 #[strum(serialize = "4")]
664 Vip4 = 4,
665 #[serde(rename = "5")]
667 #[strum(serialize = "5")]
668 Vip5 = 5,
669 #[serde(rename = "6")]
671 #[strum(serialize = "6")]
672 Vip6 = 6,
673 #[serde(rename = "7")]
675 #[strum(serialize = "7")]
676 Vip7 = 7,
677 #[serde(rename = "8")]
679 #[strum(serialize = "8")]
680 Vip8 = 8,
681 #[serde(rename = "9")]
683 #[strum(serialize = "9")]
684 Vip9 = 9,
685}
686
687impl From<u8> for OKXVipLevel {
688 fn from(value: u8) -> Self {
689 match value {
690 0 => Self::Vip0,
691 1 => Self::Vip1,
692 2 => Self::Vip2,
693 3 => Self::Vip3,
694 4 => Self::Vip4,
695 5 => Self::Vip5,
696 6 => Self::Vip6,
697 7 => Self::Vip7,
698 8 => Self::Vip8,
699 9 => Self::Vip9,
700 _ => {
701 tracing::warn!("Invalid VIP level {value}, defaulting to Vip0");
702 Self::Vip0
703 }
704 }
705 }
706}
707
708impl From<OKXSide> for OrderSide {
709 fn from(side: OKXSide) -> Self {
710 match side {
711 OKXSide::Buy => Self::Buy,
712 OKXSide::Sell => Self::Sell,
713 }
714 }
715}
716
717impl From<OKXExecType> for LiquiditySide {
718 fn from(exec: OKXExecType) -> Self {
719 match exec {
720 OKXExecType::Maker => Self::Maker,
721 OKXExecType::Taker => Self::Taker,
722 OKXExecType::None => Self::NoLiquiditySide,
723 }
724 }
725}
726
727impl From<OKXPositionSide> for PositionSide {
728 fn from(side: OKXPositionSide) -> Self {
729 match side {
730 OKXPositionSide::Long => Self::Long,
731 OKXPositionSide::Short => Self::Short,
732 _ => Self::Flat,
733 }
734 }
735}
736
737impl From<OKXOrderStatus> for OrderStatus {
738 fn from(status: OKXOrderStatus) -> Self {
739 match status {
740 OKXOrderStatus::Live => Self::Accepted,
741 OKXOrderStatus::Effective => Self::Triggered,
742 OKXOrderStatus::PartiallyFilled => Self::PartiallyFilled,
743 OKXOrderStatus::Filled => Self::Filled,
744 OKXOrderStatus::Canceled | OKXOrderStatus::MmpCanceled => Self::Canceled,
745 OKXOrderStatus::OrderPlaced => Self::Triggered,
746 }
747 }
748}
749
750impl From<OKXOrderType> for OrderType {
751 fn from(ord_type: OKXOrderType) -> Self {
752 match ord_type {
753 OKXOrderType::Market => Self::Market,
754 OKXOrderType::Limit
755 | OKXOrderType::PostOnly
756 | OKXOrderType::OptimalLimitIoc
757 | OKXOrderType::Mmp
758 | OKXOrderType::MmpAndPostOnly
759 | OKXOrderType::Fok
760 | OKXOrderType::Ioc => Self::Limit,
761 OKXOrderType::Trigger => Self::StopMarket,
762 }
763 }
764}
765
766impl From<OrderType> for OKXOrderType {
767 fn from(value: OrderType) -> Self {
768 match value {
769 OrderType::Market => Self::Market,
770 OrderType::Limit => Self::Limit,
771 OrderType::MarketToLimit => Self::Ioc,
772 OrderType::StopMarket
774 | OrderType::StopLimit
775 | OrderType::MarketIfTouched
776 | OrderType::LimitIfTouched => {
777 panic!("Conditional order types must use OKXAlgoOrderType")
778 }
779 _ => panic!("Invalid `OrderType` cannot be represented on OKX"),
780 }
781 }
782}
783
784impl From<PositionSide> for OKXPositionSide {
785 fn from(value: PositionSide) -> Self {
786 match value {
787 PositionSide::Long => Self::Long,
788 PositionSide::Short => Self::Short,
789 _ => Self::None,
790 }
791 }
792}
793
794#[derive(
795 Copy,
796 Clone,
797 Debug,
798 Display,
799 PartialEq,
800 Eq,
801 Hash,
802 AsRefStr,
803 EnumIter,
804 EnumString,
805 Serialize,
806 Deserialize,
807)]
808#[serde(rename_all = "snake_case")]
809pub enum OKXAlgoOrderType {
810 Conditional,
811 Oco,
812 Trigger,
813 MoveOrderStop,
814 Iceberg,
815 Twap,
816}
817
818pub fn is_conditional_order(order_type: OrderType) -> bool {
820 OKX_CONDITIONAL_ORDER_TYPES.contains(&order_type)
821}
822
823pub fn conditional_order_to_algo_type(order_type: OrderType) -> anyhow::Result<OKXAlgoOrderType> {
829 match order_type {
830 OrderType::StopMarket
831 | OrderType::StopLimit
832 | OrderType::MarketIfTouched
833 | OrderType::LimitIfTouched => Ok(OKXAlgoOrderType::Trigger),
834 _ => anyhow::bail!("Not a conditional order type: {order_type:?}"),
835 }
836}
837
838#[derive(
839 Copy,
840 Clone,
841 Debug,
842 Display,
843 PartialEq,
844 Eq,
845 Hash,
846 AsRefStr,
847 EnumIter,
848 EnumString,
849 Serialize,
850 Deserialize,
851)]
852#[serde(rename_all = "snake_case")]
853pub enum OKXAlgoOrderStatus {
854 Live,
855 Pause,
856 PartiallyEffective,
857 Effective,
858 Canceled,
859 OrderFailed,
860 PartiallyFailed,
861}
862
863#[derive(
864 Copy,
865 Clone,
866 Debug,
867 Display,
868 PartialEq,
869 Eq,
870 Hash,
871 AsRefStr,
872 EnumIter,
873 EnumString,
874 Serialize,
875 Deserialize,
876)]
877pub enum OKXTransactionType {
878 #[serde(rename = "1")]
879 Buy,
880 #[serde(rename = "2")]
881 Sell,
882 #[serde(rename = "3")]
883 OpenLong,
884 #[serde(rename = "4")]
885 OpenShort,
886 #[serde(rename = "5")]
887 CloseLong,
888 #[serde(rename = "6")]
889 CloseShort,
890 #[serde(rename = "100")]
891 PartialLiquidationCloseLong,
892 #[serde(rename = "101")]
893 PartialLiquidationCloseShort,
894 #[serde(rename = "102")]
895 PartialLiquidationBuy,
896 #[serde(rename = "103")]
897 PartialLiquidationSell,
898 #[serde(rename = "104")]
899 LiquidationLong,
900 #[serde(rename = "105")]
901 LiquidationShort,
902 #[serde(rename = "106")]
903 LiquidationBuy,
904 #[serde(rename = "107")]
905 LiquidationSell,
906 #[serde(rename = "110")]
907 LiquidationTransferIn,
908 #[serde(rename = "111")]
909 LiquidationTransferOut,
910 #[serde(rename = "118")]
911 SystemTokenConversionTransferIn,
912 #[serde(rename = "119")]
913 SystemTokenConversionTransferOut,
914 #[serde(rename = "125")]
915 AdlCloseLong,
916 #[serde(rename = "126")]
917 AdlCloseShort,
918 #[serde(rename = "127")]
919 AdlBuy,
920 #[serde(rename = "128")]
921 AdlSell,
922 #[serde(rename = "212")]
923 AutoBorrowOfQuickMargin,
924 #[serde(rename = "213")]
925 AutoRepayOfQuickMargin,
926 #[serde(rename = "204")]
927 BlockTradeBuy,
928 #[serde(rename = "205")]
929 BlockTradeSell,
930 #[serde(rename = "206")]
931 BlockTradeOpenLong,
932 #[serde(rename = "207")]
933 BlockTradeOpenShort,
934 #[serde(rename = "208")]
935 BlockTradeCloseOpen,
936 #[serde(rename = "209")]
937 BlockTradeCloseShort,
938 #[serde(rename = "270")]
939 SpreadTradingBuy,
940 #[serde(rename = "271")]
941 SpreadTradingSell,
942 #[serde(rename = "272")]
943 SpreadTradingOpenLong,
944 #[serde(rename = "273")]
945 SpreadTradingOpenShort,
946 #[serde(rename = "274")]
947 SpreadTradingCloseLong,
948 #[serde(rename = "275")]
949 SpreadTradingCloseShort,
950}
951
952#[derive(
962 Copy,
963 Clone,
964 Debug,
965 Display,
966 PartialEq,
967 Eq,
968 Hash,
969 AsRefStr,
970 EnumIter,
971 EnumString,
972 Serialize,
973 Deserialize,
974)]
975#[serde(rename_all = "snake_case")]
976pub enum OKXOrderCategory {
977 Normal,
979 FullLiquidation,
981 PartialLiquidation,
983 Adl,
985 Twap,
987 Iceberg,
989 Oco,
991 Conditional,
993 MoveOrderStop,
995 Ddh,
997 #[serde(other)]
999 Other,
1000}
1001
1002#[derive(
1003 Copy,
1004 Clone,
1005 Debug,
1006 Display,
1007 PartialEq,
1008 Eq,
1009 Hash,
1010 AsRefStr,
1011 EnumIter,
1012 EnumString,
1013 Serialize,
1014 Deserialize,
1015)]
1016pub enum OKXBarSize {
1017 #[serde(rename = "1s")]
1018 Second1,
1019 #[serde(rename = "1m")]
1020 Minute1,
1021 #[serde(rename = "3m")]
1022 Minute3,
1023 #[serde(rename = "5m")]
1024 Minute5,
1025 #[serde(rename = "15m")]
1026 Minute15,
1027 #[serde(rename = "30m")]
1028 Minute30,
1029 #[serde(rename = "1H")]
1030 Hour1,
1031 #[serde(rename = "2H")]
1032 Hour2,
1033 #[serde(rename = "4H")]
1034 Hour4,
1035 #[serde(rename = "6H")]
1036 Hour6,
1037 #[serde(rename = "12H")]
1038 Hour12,
1039 #[serde(rename = "1D")]
1040 Day1,
1041 #[serde(rename = "2D")]
1042 Day2,
1043 #[serde(rename = "3D")]
1044 Day3,
1045 #[serde(rename = "5D")]
1046 Day5,
1047 #[serde(rename = "1W")]
1048 Week1,
1049 #[serde(rename = "1M")]
1050 Month1,
1051 #[serde(rename = "3M")]
1052 Month3,
1053}