1use nautilus_model::enums::{MarketStatusAction, OrderSide, OrderStatus, OrderType};
19use serde::{Deserialize, Serialize};
20use strum::{AsRefStr, Display, EnumString, FromRepr};
21
22#[derive(
24 Clone,
25 Copy,
26 Debug,
27 Default,
28 Display,
29 AsRefStr,
30 EnumString,
31 FromRepr,
32 PartialEq,
33 Eq,
34 Hash,
35 Serialize,
36 Deserialize,
37)]
38#[cfg_attr(
39 feature = "python",
40 pyo3::pyclass(
41 module = "nautilus_trader.core.nautilus_pyo3.kraken",
42 eq,
43 eq_int,
44 frozen,
45 hash,
46 from_py_object,
47 rename_all = "SCREAMING_SNAKE_CASE",
48 )
49)]
50#[cfg_attr(
51 feature = "python",
52 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
53)]
54#[serde(rename_all = "lowercase")]
55#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
56pub enum KrakenEnvironment {
57 #[default]
58 Live,
59 Demo,
60}
61
62#[derive(
64 Clone,
65 Copy,
66 Debug,
67 Default,
68 Display,
69 AsRefStr,
70 EnumString,
71 FromRepr,
72 PartialEq,
73 Eq,
74 Hash,
75 Serialize,
76 Deserialize,
77)]
78#[cfg_attr(
79 feature = "python",
80 pyo3::pyclass(
81 module = "nautilus_trader.core.nautilus_pyo3.kraken",
82 eq,
83 eq_int,
84 frozen,
85 hash,
86 from_py_object,
87 rename_all = "SCREAMING_SNAKE_CASE",
88 )
89)]
90#[cfg_attr(
91 feature = "python",
92 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
93)]
94#[serde(rename_all = "lowercase")]
95#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
96pub enum KrakenProductType {
97 #[default]
98 Spot,
99 Futures,
100}
101
102#[derive(
104 Clone,
105 Copy,
106 Debug,
107 Display,
108 AsRefStr,
109 EnumString,
110 FromRepr,
111 PartialEq,
112 Eq,
113 Hash,
114 Serialize,
115 Deserialize,
116)]
117#[cfg_attr(
118 feature = "python",
119 pyo3::pyclass(
120 module = "nautilus_trader.core.nautilus_pyo3.kraken",
121 eq,
122 eq_int,
123 from_py_object
124 )
125)]
126#[cfg_attr(
127 feature = "python",
128 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
129)]
130#[serde(rename_all = "lowercase")]
131#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
132pub enum KrakenOrderType {
133 Market,
134 Limit,
135 #[serde(rename = "stop-loss")]
136 #[strum(serialize = "stop-loss")]
137 StopLoss,
138 #[serde(rename = "take-profit")]
139 #[strum(serialize = "take-profit")]
140 TakeProfit,
141 #[serde(rename = "stop-loss-limit")]
142 #[strum(serialize = "stop-loss-limit")]
143 StopLossLimit,
144 #[serde(rename = "take-profit-limit")]
145 #[strum(serialize = "take-profit-limit")]
146 TakeProfitLimit,
147 #[serde(rename = "trailing-stop")]
148 #[strum(serialize = "trailing-stop")]
149 TrailingStop,
150 #[serde(rename = "trailing-stop-limit")]
151 #[strum(serialize = "trailing-stop-limit")]
152 TrailingStopLimit,
153 #[serde(rename = "settle-position")]
154 #[strum(serialize = "settle-position")]
155 SettlePosition,
156}
157
158#[derive(
160 Clone,
161 Copy,
162 Debug,
163 Display,
164 AsRefStr,
165 EnumString,
166 FromRepr,
167 PartialEq,
168 Eq,
169 Hash,
170 Serialize,
171 Deserialize,
172)]
173#[cfg_attr(
174 feature = "python",
175 pyo3::pyclass(
176 module = "nautilus_trader.core.nautilus_pyo3.kraken",
177 eq,
178 eq_int,
179 from_py_object
180 )
181)]
182#[cfg_attr(
183 feature = "python",
184 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
185)]
186#[serde(rename_all = "lowercase")]
187#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
188pub enum KrakenOrderSide {
189 Buy,
190 Sell,
191}
192
193#[derive(
195 Clone,
196 Copy,
197 Debug,
198 Display,
199 AsRefStr,
200 EnumString,
201 FromRepr,
202 PartialEq,
203 Eq,
204 Hash,
205 Serialize,
206 Deserialize,
207)]
208#[cfg_attr(
209 feature = "python",
210 pyo3::pyclass(
211 module = "nautilus_trader.core.nautilus_pyo3.kraken",
212 eq,
213 eq_int,
214 from_py_object
215 )
216)]
217#[cfg_attr(
218 feature = "python",
219 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
220)]
221#[serde(rename_all = "UPPERCASE")]
222#[strum(ascii_case_insensitive, serialize_all = "UPPERCASE")]
223pub enum KrakenTimeInForce {
224 #[serde(rename = "IOC")]
225 #[strum(serialize = "IOC")]
226 ImmediateOrCancel,
227 #[serde(rename = "FOK")]
228 #[strum(serialize = "FOK")]
229 FillOrKill,
230 #[serde(rename = "GTC")]
231 #[strum(serialize = "GTC")]
232 GoodTilCancelled,
233 #[serde(rename = "GTD")]
234 #[strum(serialize = "GTD")]
235 GoodTilDate,
236}
237
238#[derive(
240 Clone,
241 Copy,
242 Debug,
243 Display,
244 AsRefStr,
245 EnumString,
246 FromRepr,
247 PartialEq,
248 Eq,
249 Hash,
250 Serialize,
251 Deserialize,
252)]
253#[cfg_attr(
254 feature = "python",
255 pyo3::pyclass(
256 module = "nautilus_trader.core.nautilus_pyo3.kraken",
257 eq,
258 eq_int,
259 from_py_object
260 )
261)]
262#[cfg_attr(
263 feature = "python",
264 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
265)]
266#[serde(rename_all = "lowercase")]
267#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
268pub enum KrakenOrderStatus {
269 Pending,
270 Open,
271 Closed,
272 Canceled,
273 Expired,
274}
275
276#[derive(
278 Clone,
279 Copy,
280 Debug,
281 Display,
282 AsRefStr,
283 EnumString,
284 FromRepr,
285 PartialEq,
286 Eq,
287 Hash,
288 Serialize,
289 Deserialize,
290)]
291#[cfg_attr(
292 feature = "python",
293 pyo3::pyclass(
294 module = "nautilus_trader.core.nautilus_pyo3.kraken",
295 eq,
296 eq_int,
297 from_py_object
298 )
299)]
300#[cfg_attr(
301 feature = "python",
302 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
303)]
304#[serde(rename_all = "lowercase")]
305#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
306pub enum KrakenPositionSide {
307 Long,
308 Short,
309}
310
311#[derive(
313 Clone,
314 Copy,
315 Debug,
316 Display,
317 AsRefStr,
318 EnumString,
319 FromRepr,
320 PartialEq,
321 Eq,
322 Hash,
323 Serialize,
324 Deserialize,
325)]
326#[cfg_attr(
327 feature = "python",
328 pyo3::pyclass(
329 module = "nautilus_trader.core.nautilus_pyo3.kraken",
330 eq,
331 eq_int,
332 from_py_object
333 )
334)]
335#[cfg_attr(
336 feature = "python",
337 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
338)]
339#[serde(rename_all = "snake_case")]
340#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
341pub enum KrakenPairStatus {
342 Online,
343 #[serde(rename = "cancel_only")]
344 #[strum(serialize = "cancel_only")]
345 CancelOnly,
346 #[serde(rename = "post_only")]
347 #[strum(serialize = "post_only")]
348 PostOnly,
349 #[serde(rename = "limit_only")]
350 #[strum(serialize = "limit_only")]
351 LimitOnly,
352 #[serde(rename = "reduce_only")]
353 #[strum(serialize = "reduce_only")]
354 ReduceOnly,
355}
356
357#[derive(
359 Clone,
360 Copy,
361 Debug,
362 Display,
363 AsRefStr,
364 EnumString,
365 FromRepr,
366 PartialEq,
367 Eq,
368 Hash,
369 Serialize,
370 Deserialize,
371)]
372#[cfg_attr(
373 feature = "python",
374 pyo3::pyclass(
375 module = "nautilus_trader.core.nautilus_pyo3.kraken",
376 eq,
377 eq_int,
378 from_py_object
379 )
380)]
381#[cfg_attr(
382 feature = "python",
383 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
384)]
385#[serde(rename_all = "lowercase")]
386#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
387pub enum KrakenSystemStatus {
388 Online,
389 Maintenance,
390 #[serde(rename = "cancel_only")]
391 #[strum(serialize = "cancel_only")]
392 CancelOnly,
393 #[serde(rename = "post_only")]
394 #[strum(serialize = "post_only")]
395 PostOnly,
396}
397
398#[derive(
400 Clone,
401 Copy,
402 Debug,
403 Display,
404 AsRefStr,
405 EnumString,
406 FromRepr,
407 PartialEq,
408 Eq,
409 Hash,
410 Serialize,
411 Deserialize,
412)]
413#[cfg_attr(
414 feature = "python",
415 pyo3::pyclass(
416 module = "nautilus_trader.core.nautilus_pyo3.kraken",
417 eq,
418 eq_int,
419 from_py_object
420 )
421)]
422#[cfg_attr(
423 feature = "python",
424 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
425)]
426#[serde(rename_all = "lowercase")]
427#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
428pub enum KrakenAssetClass {
429 Currency,
430 #[serde(rename = "tokenized_asset")]
431 #[strum(serialize = "tokenized_asset")]
432 TokenizedAsset,
433}
434
435#[derive(
437 Clone,
438 Copy,
439 Debug,
440 Display,
441 AsRefStr,
442 EnumString,
443 FromRepr,
444 PartialEq,
445 Eq,
446 Hash,
447 Serialize,
448 Deserialize,
449)]
450#[cfg_attr(
451 feature = "python",
452 pyo3::pyclass(
453 module = "nautilus_trader.core.nautilus_pyo3.kraken",
454 eq,
455 eq_int,
456 from_py_object
457 )
458)]
459#[cfg_attr(
460 feature = "python",
461 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
462)]
463#[serde(rename_all = "lowercase")]
464#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
465pub enum KrakenFuturesOrderType {
466 #[serde(rename = "lmt", alias = "limit")]
467 #[strum(serialize = "lmt")]
468 Limit,
469 #[serde(rename = "ioc")]
470 #[strum(serialize = "ioc")]
471 Ioc,
472 #[serde(rename = "post")]
473 #[strum(serialize = "post")]
474 Post,
475 #[serde(rename = "mkt", alias = "market")]
476 #[strum(serialize = "mkt")]
477 Market,
478 #[serde(rename = "stp")]
479 #[strum(serialize = "stp")]
480 Stop,
481 #[serde(rename = "stop")]
482 #[strum(serialize = "stop")]
483 StopLower,
484 #[serde(rename = "take_profit")]
485 #[strum(serialize = "take_profit")]
486 TakeProfit,
487 #[serde(rename = "stop_loss")]
488 #[strum(serialize = "stop_loss")]
489 StopLoss,
490 #[serde(rename = "unknown")]
491 Unknown,
492}
493
494#[derive(
496 Clone,
497 Copy,
498 Debug,
499 Display,
500 AsRefStr,
501 EnumString,
502 FromRepr,
503 PartialEq,
504 Eq,
505 Hash,
506 Serialize,
507 Deserialize,
508)]
509#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
510#[strum(ascii_case_insensitive, serialize_all = "SCREAMING_SNAKE_CASE")]
511pub enum KrakenFuturesOrderEventType {
512 Place,
514 Fill,
516 Execution,
518 Reject,
520 Cancel,
522 Edit,
524 #[serde(alias = "EXPIRED")]
526 #[strum(serialize = "EXPIRED")]
527 Expire,
528}
529
530#[derive(
532 Clone,
533 Copy,
534 Debug,
535 Display,
536 AsRefStr,
537 EnumString,
538 FromRepr,
539 PartialEq,
540 Eq,
541 Hash,
542 Serialize,
543 Deserialize,
544)]
545#[cfg_attr(
546 feature = "python",
547 pyo3::pyclass(
548 module = "nautilus_trader.core.nautilus_pyo3.kraken",
549 eq,
550 eq_int,
551 from_py_object
552 )
553)]
554#[cfg_attr(
555 feature = "python",
556 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
557)]
558#[serde(rename_all = "camelCase")]
559#[strum(ascii_case_insensitive, serialize_all = "camelCase")]
560pub enum KrakenFuturesOrderStatus {
561 Untouched,
562 PartiallyFilled,
563 Filled,
564 Cancelled,
565 Expired,
566}
567
568#[derive(
570 Clone,
571 Copy,
572 Debug,
573 Display,
574 AsRefStr,
575 EnumString,
576 FromRepr,
577 PartialEq,
578 Eq,
579 Hash,
580 Serialize,
581 Deserialize,
582)]
583#[cfg_attr(
584 feature = "python",
585 pyo3::pyclass(
586 module = "nautilus_trader.core.nautilus_pyo3.kraken",
587 eq,
588 eq_int,
589 from_py_object
590 )
591)]
592#[cfg_attr(
593 feature = "python",
594 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
595)]
596#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
597pub enum KrakenTriggerSignal {
598 #[serde(rename = "last", alias = "last_price")]
599 Last,
600 #[serde(rename = "mark", alias = "mark_price")]
601 Mark,
602 #[serde(
603 rename = "spot",
604 alias = "spot_price",
605 alias = "index",
606 alias = "index_price"
607 )]
608 #[strum(
609 serialize = "spot",
610 serialize = "spot_price",
611 serialize = "index",
612 serialize = "index_price"
613 )]
614 Index,
615 #[serde(rename = "unknown")]
616 Unknown,
617}
618
619#[derive(
621 Clone,
622 Copy,
623 Debug,
624 Display,
625 AsRefStr,
626 EnumString,
627 FromRepr,
628 PartialEq,
629 Eq,
630 Hash,
631 Serialize,
632 Deserialize,
633)]
634#[cfg_attr(
635 feature = "python",
636 pyo3::pyclass(
637 module = "nautilus_trader.core.nautilus_pyo3.kraken",
638 eq,
639 eq_int,
640 from_py_object
641 )
642)]
643#[cfg_attr(
644 feature = "python",
645 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
646)]
647#[serde(rename_all = "lowercase")]
648#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
649pub enum KrakenSpotTrigger {
650 Last,
652 Index,
654}
655
656#[derive(
658 Clone,
659 Copy,
660 Debug,
661 Display,
662 AsRefStr,
663 EnumString,
664 FromRepr,
665 PartialEq,
666 Eq,
667 Hash,
668 Serialize,
669 Deserialize,
670)]
671#[cfg_attr(
672 feature = "python",
673 pyo3::pyclass(
674 module = "nautilus_trader.core.nautilus_pyo3.kraken",
675 eq,
676 eq_int,
677 from_py_object
678 )
679)]
680#[cfg_attr(
681 feature = "python",
682 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
683)]
684#[serde(rename_all = "lowercase")]
685#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
686pub enum KrakenFillType {
687 Maker,
688 Taker,
689}
690
691#[derive(
693 Clone,
694 Copy,
695 Debug,
696 Display,
697 AsRefStr,
698 EnumString,
699 FromRepr,
700 PartialEq,
701 Eq,
702 Hash,
703 Serialize,
704 Deserialize,
705)]
706#[cfg_attr(
707 feature = "python",
708 pyo3::pyclass(
709 module = "nautilus_trader.core.nautilus_pyo3.kraken",
710 eq,
711 eq_int,
712 from_py_object
713 )
714)]
715#[cfg_attr(
716 feature = "python",
717 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
718)]
719#[serde(rename_all = "lowercase")]
720#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
721pub enum KrakenApiResult {
722 Success,
723 Error,
724}
725
726#[derive(
728 Clone,
729 Copy,
730 Debug,
731 Display,
732 AsRefStr,
733 EnumString,
734 FromRepr,
735 PartialEq,
736 Eq,
737 Hash,
738 Serialize,
739 Deserialize,
740)]
741#[cfg_attr(
742 feature = "python",
743 pyo3::pyclass(
744 module = "nautilus_trader.core.nautilus_pyo3.kraken",
745 eq,
746 eq_int,
747 from_py_object
748 )
749)]
750#[cfg_attr(
751 feature = "python",
752 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
753)]
754#[serde(rename_all = "snake_case")]
755#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
756pub enum KrakenInstrumentType {
757 FuturesInverse,
759 FlexibleFutures,
761}
762
763#[derive(
765 Clone,
766 Copy,
767 Debug,
768 Display,
769 AsRefStr,
770 EnumString,
771 FromRepr,
772 PartialEq,
773 Eq,
774 Hash,
775 Serialize,
776 Deserialize,
777)]
778#[cfg_attr(
779 feature = "python",
780 pyo3::pyclass(
781 module = "nautilus_trader.core.nautilus_pyo3.kraken",
782 eq,
783 eq_int,
784 from_py_object
785 )
786)]
787#[cfg_attr(
788 feature = "python",
789 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
790)]
791#[serde(rename_all = "camelCase")]
792#[strum(ascii_case_insensitive, serialize_all = "camelCase")]
793pub enum KrakenSendStatus {
794 Placed,
796 Cancelled,
798 Edited,
800 NotFound,
802 NoOrdersToCancel,
810 InsufficientAvailableFunds,
812 InvalidOrderType,
814 InvalidSize,
816 WouldCauseLiquidation,
818 PostWouldExecute,
820 ReduceOnlyWouldIncreasePosition,
822}
823
824#[derive(
826 Clone,
827 Copy,
828 Debug,
829 Display,
830 AsRefStr,
831 EnumString,
832 FromRepr,
833 PartialEq,
834 Eq,
835 Hash,
836 Serialize,
837 Deserialize,
838)]
839#[cfg_attr(
840 feature = "python",
841 pyo3::pyclass(
842 module = "nautilus_trader.core.nautilus_pyo3.kraken",
843 eq,
844 eq_int,
845 from_py_object
846 )
847)]
848#[cfg_attr(
849 feature = "python",
850 pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.adapters.kraken")
851)]
852#[serde(rename_all = "snake_case")]
853#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
854pub enum KrakenTriggerSide {
855 #[serde(rename = "trigger_above")]
857 #[strum(serialize = "trigger_above")]
858 TriggerAbove,
859 #[serde(rename = "trigger_below")]
861 #[strum(serialize = "trigger_below")]
862 TriggerBelow,
863 #[serde(rename = "unknown")]
865 Unknown,
866}
867
868impl From<KrakenOrderSide> for OrderSide {
869 fn from(value: KrakenOrderSide) -> Self {
870 match value {
871 KrakenOrderSide::Buy => Self::Buy,
872 KrakenOrderSide::Sell => Self::Sell,
873 }
874 }
875}
876
877impl From<KrakenOrderType> for OrderType {
878 fn from(value: KrakenOrderType) -> Self {
884 match value {
885 KrakenOrderType::Market => Self::Market,
886 KrakenOrderType::Limit => Self::Limit,
887 KrakenOrderType::StopLoss => Self::StopMarket,
888 KrakenOrderType::TakeProfit => Self::MarketIfTouched,
889 KrakenOrderType::StopLossLimit => Self::StopLimit,
890 KrakenOrderType::TakeProfitLimit => Self::LimitIfTouched,
891 KrakenOrderType::TrailingStop => Self::StopMarket,
892 KrakenOrderType::TrailingStopLimit => Self::StopLimit,
893 KrakenOrderType::SettlePosition => Self::Market,
894 }
895 }
896}
897
898impl From<KrakenOrderStatus> for OrderStatus {
899 fn from(value: KrakenOrderStatus) -> Self {
900 match value {
901 KrakenOrderStatus::Pending => Self::Initialized,
902 KrakenOrderStatus::Open => Self::Accepted,
903 KrakenOrderStatus::Closed => Self::Filled,
904 KrakenOrderStatus::Canceled => Self::Canceled,
905 KrakenOrderStatus::Expired => Self::Expired,
906 }
907 }
908}
909
910impl From<KrakenFuturesOrderType> for OrderType {
911 fn from(value: KrakenFuturesOrderType) -> Self {
912 match value {
913 KrakenFuturesOrderType::Limit
914 | KrakenFuturesOrderType::Ioc
915 | KrakenFuturesOrderType::Post => Self::Limit,
916 KrakenFuturesOrderType::Market => Self::Market,
917 KrakenFuturesOrderType::Stop | KrakenFuturesOrderType::StopLower => Self::StopMarket,
918 KrakenFuturesOrderType::TakeProfit => Self::MarketIfTouched,
919 KrakenFuturesOrderType::StopLoss => Self::StopMarket,
920 KrakenFuturesOrderType::Unknown => {
921 log::warn!(
922 "KrakenFuturesOrderType::Unknown received from venue, defaulting to Market"
923 );
924 Self::Market
925 }
926 }
927 }
928}
929
930impl TryFrom<OrderSide> for KrakenOrderSide {
931 type Error = &'static str;
932
933 fn try_from(value: OrderSide) -> Result<Self, Self::Error> {
934 match value {
935 OrderSide::Buy => Ok(Self::Buy),
936 OrderSide::Sell => Ok(Self::Sell),
937 OrderSide::NoOrderSide => Err("Cannot convert NoOrderSide to KrakenOrderSide"),
938 }
939 }
940}
941
942impl From<KrakenFuturesOrderStatus> for OrderStatus {
943 fn from(value: KrakenFuturesOrderStatus) -> Self {
944 match value {
945 KrakenFuturesOrderStatus::Untouched => Self::Accepted,
946 KrakenFuturesOrderStatus::PartiallyFilled => Self::PartiallyFilled,
947 KrakenFuturesOrderStatus::Filled => Self::Filled,
948 KrakenFuturesOrderStatus::Cancelled => Self::Canceled,
949 KrakenFuturesOrderStatus::Expired => Self::Expired,
950 }
951 }
952}
953
954impl From<KrakenPairStatus> for MarketStatusAction {
955 fn from(value: KrakenPairStatus) -> Self {
956 match value {
957 KrakenPairStatus::Online => Self::Trading,
958 KrakenPairStatus::CancelOnly => Self::Halt,
959 KrakenPairStatus::PostOnly => Self::Pause,
960 KrakenPairStatus::LimitOnly => Self::Pause,
961 KrakenPairStatus::ReduceOnly => Self::Pause,
962 }
963 }
964}
965
966#[must_use]
977pub fn product_type_from_symbol(symbol: &str) -> KrakenProductType {
978 if symbol.starts_with("PI_")
979 || symbol.starts_with("PF_")
980 || symbol.starts_with("PV_")
981 || symbol.starts_with("FI_")
982 || symbol.starts_with("FF_")
983 {
984 KrakenProductType::Futures
985 } else {
986 KrakenProductType::Spot
987 }
988}
989
990#[cfg(test)]
991mod tests {
992 use nautilus_model::enums::{MarketStatusAction, OrderType};
993 use rstest::rstest;
994
995 use super::*;
996
997 #[rstest]
998 #[case::online(KrakenPairStatus::Online, MarketStatusAction::Trading)]
999 #[case::cancel_only(KrakenPairStatus::CancelOnly, MarketStatusAction::Halt)]
1000 #[case::post_only(KrakenPairStatus::PostOnly, MarketStatusAction::Pause)]
1001 #[case::limit_only(KrakenPairStatus::LimitOnly, MarketStatusAction::Pause)]
1002 #[case::reduce_only(KrakenPairStatus::ReduceOnly, MarketStatusAction::Pause)]
1003 fn test_pair_status_to_market_status_action(
1004 #[case] input: KrakenPairStatus,
1005 #[case] expected: MarketStatusAction,
1006 ) {
1007 assert_eq!(MarketStatusAction::from(input), expected);
1008 }
1009
1010 #[rstest]
1011 #[case::trailing_stop(KrakenOrderType::TrailingStop, OrderType::StopMarket)]
1012 #[case::trailing_stop_limit(KrakenOrderType::TrailingStopLimit, OrderType::StopLimit)]
1013 fn test_trailing_stop_order_type_mapping(
1014 #[case] input: KrakenOrderType,
1015 #[case] expected: OrderType,
1016 ) {
1017 assert_eq!(OrderType::from(input), expected);
1018 }
1019
1020 #[rstest]
1021 fn test_time_in_force_deserializes_fok() {
1022 let tif: KrakenTimeInForce = serde_json::from_str("\"FOK\"").unwrap();
1025 assert_eq!(tif, KrakenTimeInForce::FillOrKill);
1026 }
1027
1028 #[rstest]
1029 #[case("\"placed\"", KrakenSendStatus::Placed)]
1030 #[case("\"cancelled\"", KrakenSendStatus::Cancelled)]
1031 #[case("\"edited\"", KrakenSendStatus::Edited)]
1032 #[case("\"notFound\"", KrakenSendStatus::NotFound)]
1033 #[case("\"noOrdersToCancel\"", KrakenSendStatus::NoOrdersToCancel)]
1034 #[case(
1035 "\"insufficientAvailableFunds\"",
1036 KrakenSendStatus::InsufficientAvailableFunds
1037 )]
1038 #[case("\"invalidOrderType\"", KrakenSendStatus::InvalidOrderType)]
1039 #[case("\"invalidSize\"", KrakenSendStatus::InvalidSize)]
1040 #[case("\"wouldCauseLiquidation\"", KrakenSendStatus::WouldCauseLiquidation)]
1041 #[case("\"postWouldExecute\"", KrakenSendStatus::PostWouldExecute)]
1042 #[case(
1043 "\"reduceOnlyWouldIncreasePosition\"",
1044 KrakenSendStatus::ReduceOnlyWouldIncreasePosition
1045 )]
1046 fn test_send_status_deserialization(#[case] raw: &str, #[case] expected: KrakenSendStatus) {
1047 let parsed: KrakenSendStatus = serde_json::from_str(raw).unwrap();
1048 assert_eq!(parsed, expected);
1049 }
1050
1051 #[rstest]
1052 #[case("\"last\"", KrakenTriggerSignal::Last)]
1053 #[case("\"last_price\"", KrakenTriggerSignal::Last)]
1054 #[case("\"mark\"", KrakenTriggerSignal::Mark)]
1055 #[case("\"mark_price\"", KrakenTriggerSignal::Mark)]
1056 #[case("\"spot\"", KrakenTriggerSignal::Index)]
1057 #[case("\"spot_price\"", KrakenTriggerSignal::Index)]
1058 #[case("\"index\"", KrakenTriggerSignal::Index)]
1059 #[case("\"index_price\"", KrakenTriggerSignal::Index)]
1060 #[case("\"unknown\"", KrakenTriggerSignal::Unknown)]
1061 fn test_trigger_signal_deserialization(
1062 #[case] raw: &str,
1063 #[case] expected: KrakenTriggerSignal,
1064 ) {
1065 let parsed: KrakenTriggerSignal = serde_json::from_str(raw).unwrap();
1066 assert_eq!(parsed, expected);
1067 }
1068
1069 #[rstest]
1070 #[case("\"trigger_above\"", KrakenTriggerSide::TriggerAbove)]
1071 #[case("\"trigger_below\"", KrakenTriggerSide::TriggerBelow)]
1072 #[case("\"unknown\"", KrakenTriggerSide::Unknown)]
1073 fn test_trigger_side_deserialization(#[case] raw: &str, #[case] expected: KrakenTriggerSide) {
1074 let parsed: KrakenTriggerSide = serde_json::from_str(raw).unwrap();
1075 assert_eq!(parsed, expected);
1076 }
1077
1078 #[rstest]
1079 #[case("\"lmt\"", KrakenFuturesOrderType::Limit)]
1080 #[case("\"limit\"", KrakenFuturesOrderType::Limit)]
1081 #[case("\"ioc\"", KrakenFuturesOrderType::Ioc)]
1082 #[case("\"post\"", KrakenFuturesOrderType::Post)]
1083 #[case("\"mkt\"", KrakenFuturesOrderType::Market)]
1084 #[case("\"market\"", KrakenFuturesOrderType::Market)]
1085 #[case("\"stp\"", KrakenFuturesOrderType::Stop)]
1086 #[case("\"stop\"", KrakenFuturesOrderType::StopLower)]
1087 #[case("\"take_profit\"", KrakenFuturesOrderType::TakeProfit)]
1088 #[case("\"stop_loss\"", KrakenFuturesOrderType::StopLoss)]
1089 #[case("\"unknown\"", KrakenFuturesOrderType::Unknown)]
1090 fn test_futures_order_type_deserialization(
1091 #[case] raw: &str,
1092 #[case] expected: KrakenFuturesOrderType,
1093 ) {
1094 let parsed: KrakenFuturesOrderType = serde_json::from_str(raw).unwrap();
1095 assert_eq!(parsed, expected);
1096 }
1097
1098 #[rstest]
1099 fn test_order_metadata_enums_fail_loud_on_unmodeled_value() {
1100 assert!(serde_json::from_str::<KrakenFuturesOrderType>("\"iceberg\"").is_err());
1103 assert!(serde_json::from_str::<KrakenTriggerSignal>("\"vwap\"").is_err());
1104 assert!(serde_json::from_str::<KrakenTriggerSide>("\"sideways\"").is_err());
1105 }
1106
1107 #[rstest]
1108 fn test_futures_order_type_unknown_maps_to_market_default() {
1109 assert_eq!(
1110 OrderType::from(KrakenFuturesOrderType::Unknown),
1111 OrderType::Market,
1112 );
1113 }
1114
1115 #[rstest]
1116 #[case("\"PLACE\"", KrakenFuturesOrderEventType::Place)]
1117 #[case("\"FILL\"", KrakenFuturesOrderEventType::Fill)]
1118 #[case("\"EXECUTION\"", KrakenFuturesOrderEventType::Execution)]
1119 #[case("\"REJECT\"", KrakenFuturesOrderEventType::Reject)]
1120 #[case("\"CANCEL\"", KrakenFuturesOrderEventType::Cancel)]
1121 #[case("\"EDIT\"", KrakenFuturesOrderEventType::Edit)]
1122 #[case("\"EXPIRE\"", KrakenFuturesOrderEventType::Expire)]
1123 #[case("\"EXPIRED\"", KrakenFuturesOrderEventType::Expire)]
1124 fn test_futures_order_event_type_deserialization(
1125 #[case] raw: &str,
1126 #[case] expected: KrakenFuturesOrderEventType,
1127 ) {
1128 let parsed: KrakenFuturesOrderEventType = serde_json::from_str(raw).unwrap();
1129 assert_eq!(parsed, expected);
1130 }
1131}