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 => OptionKind::Call,
340 OKXOptionType::Put => OptionKind::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(Copy, Clone, Debug, PartialEq, Eq)]
578pub enum OKXBookChannel {
579 Book,
581 BookL2Tbt,
583 Books50L2Tbt,
585}
586
587#[derive(
601 Copy,
602 Clone,
603 Debug,
604 Display,
605 PartialEq,
606 Eq,
607 PartialOrd,
608 Ord,
609 Hash,
610 AsRefStr,
611 EnumIter,
612 EnumString,
613 Serialize,
614 Deserialize,
615)]
616#[cfg_attr(
617 feature = "python",
618 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.adapters")
619)]
620pub enum OKXVipLevel {
621 #[serde(rename = "0")]
623 #[strum(serialize = "0")]
624 Vip0 = 0,
625 #[serde(rename = "1")]
627 #[strum(serialize = "1")]
628 Vip1 = 1,
629 #[serde(rename = "2")]
631 #[strum(serialize = "2")]
632 Vip2 = 2,
633 #[serde(rename = "3")]
635 #[strum(serialize = "3")]
636 Vip3 = 3,
637 #[serde(rename = "4")]
639 #[strum(serialize = "4")]
640 Vip4 = 4,
641 #[serde(rename = "5")]
643 #[strum(serialize = "5")]
644 Vip5 = 5,
645 #[serde(rename = "6")]
647 #[strum(serialize = "6")]
648 Vip6 = 6,
649 #[serde(rename = "7")]
651 #[strum(serialize = "7")]
652 Vip7 = 7,
653 #[serde(rename = "8")]
655 #[strum(serialize = "8")]
656 Vip8 = 8,
657 #[serde(rename = "9")]
659 #[strum(serialize = "9")]
660 Vip9 = 9,
661}
662
663impl From<u8> for OKXVipLevel {
664 fn from(value: u8) -> Self {
665 match value {
666 0 => Self::Vip0,
667 1 => Self::Vip1,
668 2 => Self::Vip2,
669 3 => Self::Vip3,
670 4 => Self::Vip4,
671 5 => Self::Vip5,
672 6 => Self::Vip6,
673 7 => Self::Vip7,
674 8 => Self::Vip8,
675 9 => Self::Vip9,
676 _ => {
677 tracing::warn!("Invalid VIP level {value}, defaulting to Vip0");
678 Self::Vip0
679 }
680 }
681 }
682}
683
684impl From<OKXSide> for OrderSide {
685 fn from(side: OKXSide) -> Self {
686 match side {
687 OKXSide::Buy => Self::Buy,
688 OKXSide::Sell => Self::Sell,
689 }
690 }
691}
692
693impl From<OKXExecType> for LiquiditySide {
694 fn from(exec: OKXExecType) -> Self {
695 match exec {
696 OKXExecType::Maker => Self::Maker,
697 OKXExecType::Taker => Self::Taker,
698 OKXExecType::None => Self::NoLiquiditySide,
699 }
700 }
701}
702
703impl From<OKXPositionSide> for PositionSide {
704 fn from(side: OKXPositionSide) -> Self {
705 match side {
706 OKXPositionSide::Long => Self::Long,
707 OKXPositionSide::Short => Self::Short,
708 _ => Self::Flat,
709 }
710 }
711}
712
713impl From<OKXOrderStatus> for OrderStatus {
714 fn from(status: OKXOrderStatus) -> Self {
715 match status {
716 OKXOrderStatus::Live => Self::Accepted,
717 OKXOrderStatus::Effective => Self::Triggered,
718 OKXOrderStatus::PartiallyFilled => Self::PartiallyFilled,
719 OKXOrderStatus::Filled => Self::Filled,
720 OKXOrderStatus::Canceled | OKXOrderStatus::MmpCanceled => Self::Canceled,
721 OKXOrderStatus::OrderPlaced => Self::Triggered,
722 }
723 }
724}
725
726impl From<OKXOrderType> for OrderType {
727 fn from(ord_type: OKXOrderType) -> Self {
728 match ord_type {
729 OKXOrderType::Market => Self::Market,
730 OKXOrderType::Limit
731 | OKXOrderType::PostOnly
732 | OKXOrderType::OptimalLimitIoc
733 | OKXOrderType::Mmp
734 | OKXOrderType::MmpAndPostOnly => Self::Limit,
735 OKXOrderType::Fok | OKXOrderType::Ioc => Self::MarketToLimit,
736 OKXOrderType::Trigger => Self::StopMarket,
737 }
738 }
739}
740
741impl From<OrderType> for OKXOrderType {
742 fn from(value: OrderType) -> Self {
743 match value {
744 OrderType::Market => Self::Market,
745 OrderType::Limit => Self::Limit,
746 OrderType::MarketToLimit => Self::Ioc,
747 OrderType::StopMarket
749 | OrderType::StopLimit
750 | OrderType::MarketIfTouched
751 | OrderType::LimitIfTouched => {
752 panic!("Conditional order types must use OKXAlgoOrderType")
753 }
754 _ => panic!("Invalid `OrderType` cannot be represented on OKX"),
755 }
756 }
757}
758
759impl From<PositionSide> for OKXPositionSide {
760 fn from(value: PositionSide) -> Self {
761 match value {
762 PositionSide::Long => Self::Long,
763 PositionSide::Short => Self::Short,
764 _ => Self::None,
765 }
766 }
767}
768
769#[derive(
770 Copy,
771 Clone,
772 Debug,
773 Display,
774 PartialEq,
775 Eq,
776 Hash,
777 AsRefStr,
778 EnumIter,
779 EnumString,
780 Serialize,
781 Deserialize,
782)]
783#[serde(rename_all = "snake_case")]
784pub enum OKXAlgoOrderType {
785 Conditional,
786 Oco,
787 Trigger,
788 MoveOrderStop,
789 Iceberg,
790 Twap,
791}
792
793pub fn is_conditional_order(order_type: OrderType) -> bool {
795 OKX_CONDITIONAL_ORDER_TYPES.contains(&order_type)
796}
797
798pub fn conditional_order_to_algo_type(order_type: OrderType) -> anyhow::Result<OKXAlgoOrderType> {
804 match order_type {
805 OrderType::StopMarket
806 | OrderType::StopLimit
807 | OrderType::MarketIfTouched
808 | OrderType::LimitIfTouched => Ok(OKXAlgoOrderType::Trigger),
809 _ => anyhow::bail!("Not a conditional order type: {order_type:?}"),
810 }
811}
812
813#[derive(
814 Copy,
815 Clone,
816 Debug,
817 Display,
818 PartialEq,
819 Eq,
820 Hash,
821 AsRefStr,
822 EnumIter,
823 EnumString,
824 Serialize,
825 Deserialize,
826)]
827#[serde(rename_all = "snake_case")]
828pub enum OKXAlgoOrderStatus {
829 Live,
830 Pause,
831 PartiallyEffective,
832 Effective,
833 Canceled,
834 OrderFailed,
835 PartiallyFailed,
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)]
852pub enum OKXTransactionType {
853 #[serde(rename = "1")]
854 Buy,
855 #[serde(rename = "2")]
856 Sell,
857 #[serde(rename = "3")]
858 OpenLong,
859 #[serde(rename = "4")]
860 OpenShort,
861 #[serde(rename = "5")]
862 CloseLong,
863 #[serde(rename = "6")]
864 CloseShort,
865 #[serde(rename = "100")]
866 PartialLiquidationCloseLong,
867 #[serde(rename = "101")]
868 PartialLiquidationCloseShort,
869 #[serde(rename = "102")]
870 PartialLiquidationBuy,
871 #[serde(rename = "103")]
872 PartialLiquidationSell,
873 #[serde(rename = "104")]
874 LiquidationLong,
875 #[serde(rename = "105")]
876 LiquidationShort,
877 #[serde(rename = "106")]
878 LiquidationBuy,
879 #[serde(rename = "107")]
880 LiquidationSell,
881 #[serde(rename = "110")]
882 LiquidationTransferIn,
883 #[serde(rename = "111")]
884 LiquidationTransferOut,
885 #[serde(rename = "118")]
886 SystemTokenConversionTransferIn,
887 #[serde(rename = "119")]
888 SystemTokenConversionTransferOut,
889 #[serde(rename = "125")]
890 AdlCloseLong,
891 #[serde(rename = "126")]
892 AdlCloseShort,
893 #[serde(rename = "127")]
894 AdlBuy,
895 #[serde(rename = "128")]
896 AdlSell,
897 #[serde(rename = "212")]
898 AutoBorrowOfQuickMargin,
899 #[serde(rename = "213")]
900 AutoRepayOfQuickMargin,
901 #[serde(rename = "204")]
902 BlockTradeBuy,
903 #[serde(rename = "205")]
904 BlockTradeSell,
905 #[serde(rename = "206")]
906 BlockTradeOpenLong,
907 #[serde(rename = "207")]
908 BlockTradeOpenShort,
909 #[serde(rename = "208")]
910 BlockTradeCloseOpen,
911 #[serde(rename = "209")]
912 BlockTradeCloseShort,
913 #[serde(rename = "270")]
914 SpreadTradingBuy,
915 #[serde(rename = "271")]
916 SpreadTradingSell,
917 #[serde(rename = "272")]
918 SpreadTradingOpenLong,
919 #[serde(rename = "273")]
920 SpreadTradingOpenShort,
921 #[serde(rename = "274")]
922 SpreadTradingCloseLong,
923 #[serde(rename = "275")]
924 SpreadTradingCloseShort,
925}
926
927#[derive(
928 Copy,
929 Clone,
930 Debug,
931 Display,
932 PartialEq,
933 Eq,
934 Hash,
935 AsRefStr,
936 EnumIter,
937 EnumString,
938 Serialize,
939 Deserialize,
940)]
941pub enum OKXBarSize {
942 #[serde(rename = "1s")]
943 Second1,
944 #[serde(rename = "1m")]
945 Minute1,
946 #[serde(rename = "3m")]
947 Minute3,
948 #[serde(rename = "5m")]
949 Minute5,
950 #[serde(rename = "15m")]
951 Minute15,
952 #[serde(rename = "30m")]
953 Minute30,
954 #[serde(rename = "1H")]
955 Hour1,
956 #[serde(rename = "2H")]
957 Hour2,
958 #[serde(rename = "4H")]
959 Hour4,
960 #[serde(rename = "6H")]
961 Hour6,
962 #[serde(rename = "12H")]
963 Hour12,
964 #[serde(rename = "1D")]
965 Day1,
966 #[serde(rename = "2D")]
967 Day2,
968 #[serde(rename = "3D")]
969 Day3,
970 #[serde(rename = "5D")]
971 Day5,
972 #[serde(rename = "1W")]
973 Week1,
974 #[serde(rename = "1M")]
975 Month1,
976 #[serde(rename = "3M")]
977 Month3,
978}