Skip to main content

nautilus_kraken/common/
enums.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Enumerations that model Kraken string/int enums across HTTP and WebSocket payloads.
17
18use nautilus_model::enums::{OrderSide, OrderStatus, OrderType};
19use serde::{Deserialize, Serialize};
20use strum::{AsRefStr, Display, EnumString, FromRepr};
21
22/// Kraken API environment (mainnet or demo).
23#[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#[serde(rename_all = "lowercase")]
51#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
52pub enum KrakenEnvironment {
53    #[default]
54    Mainnet,
55    Demo,
56}
57
58/// Kraken product type (spot or futures).
59#[derive(
60    Clone,
61    Copy,
62    Debug,
63    Default,
64    Display,
65    AsRefStr,
66    EnumString,
67    FromRepr,
68    PartialEq,
69    Eq,
70    Hash,
71    Serialize,
72    Deserialize,
73)]
74#[cfg_attr(
75    feature = "python",
76    pyo3::pyclass(
77        module = "nautilus_trader.core.nautilus_pyo3.kraken",
78        eq,
79        eq_int,
80        frozen,
81        hash,
82        from_py_object,
83        rename_all = "SCREAMING_SNAKE_CASE",
84    )
85)]
86#[serde(rename_all = "lowercase")]
87#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
88pub enum KrakenProductType {
89    #[default]
90    Spot,
91    Futures,
92}
93
94/// Kraken spot order type.
95#[derive(
96    Clone,
97    Copy,
98    Debug,
99    Display,
100    AsRefStr,
101    EnumString,
102    FromRepr,
103    PartialEq,
104    Eq,
105    Hash,
106    Serialize,
107    Deserialize,
108)]
109#[cfg_attr(
110    feature = "python",
111    pyo3::pyclass(
112        module = "nautilus_trader.core.nautilus_pyo3.kraken",
113        eq,
114        eq_int,
115        from_py_object
116    )
117)]
118#[serde(rename_all = "lowercase")]
119#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
120pub enum KrakenOrderType {
121    Market,
122    Limit,
123    #[serde(rename = "stop-loss")]
124    #[strum(serialize = "stop-loss")]
125    StopLoss,
126    #[serde(rename = "take-profit")]
127    #[strum(serialize = "take-profit")]
128    TakeProfit,
129    #[serde(rename = "stop-loss-limit")]
130    #[strum(serialize = "stop-loss-limit")]
131    StopLossLimit,
132    #[serde(rename = "take-profit-limit")]
133    #[strum(serialize = "take-profit-limit")]
134    TakeProfitLimit,
135    #[serde(rename = "settle-position")]
136    #[strum(serialize = "settle-position")]
137    SettlePosition,
138}
139
140/// Kraken order side (buy or sell).
141#[derive(
142    Clone,
143    Copy,
144    Debug,
145    Display,
146    AsRefStr,
147    EnumString,
148    FromRepr,
149    PartialEq,
150    Eq,
151    Hash,
152    Serialize,
153    Deserialize,
154)]
155#[cfg_attr(
156    feature = "python",
157    pyo3::pyclass(
158        module = "nautilus_trader.core.nautilus_pyo3.kraken",
159        eq,
160        eq_int,
161        from_py_object
162    )
163)]
164#[serde(rename_all = "lowercase")]
165#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
166pub enum KrakenOrderSide {
167    Buy,
168    Sell,
169}
170
171/// Kraken time-in-force for orders.
172#[derive(
173    Clone,
174    Copy,
175    Debug,
176    Display,
177    AsRefStr,
178    EnumString,
179    FromRepr,
180    PartialEq,
181    Eq,
182    Hash,
183    Serialize,
184    Deserialize,
185)]
186#[cfg_attr(
187    feature = "python",
188    pyo3::pyclass(
189        module = "nautilus_trader.core.nautilus_pyo3.kraken",
190        eq,
191        eq_int,
192        from_py_object
193    )
194)]
195#[serde(rename_all = "UPPERCASE")]
196#[strum(ascii_case_insensitive, serialize_all = "UPPERCASE")]
197pub enum KrakenTimeInForce {
198    #[serde(rename = "GTC")]
199    #[strum(serialize = "GTC")]
200    GoodTilCancelled,
201    #[serde(rename = "IOC")]
202    #[strum(serialize = "IOC")]
203    ImmediateOrCancel,
204    #[serde(rename = "GTD")]
205    #[strum(serialize = "GTD")]
206    GoodTilDate,
207}
208
209/// Kraken order status.
210#[derive(
211    Clone,
212    Copy,
213    Debug,
214    Display,
215    AsRefStr,
216    EnumString,
217    FromRepr,
218    PartialEq,
219    Eq,
220    Hash,
221    Serialize,
222    Deserialize,
223)]
224#[cfg_attr(
225    feature = "python",
226    pyo3::pyclass(
227        module = "nautilus_trader.core.nautilus_pyo3.kraken",
228        eq,
229        eq_int,
230        from_py_object
231    )
232)]
233#[serde(rename_all = "lowercase")]
234#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
235pub enum KrakenOrderStatus {
236    Pending,
237    Open,
238    Closed,
239    Canceled,
240    Expired,
241}
242
243/// Kraken position side (long or short).
244#[derive(
245    Clone,
246    Copy,
247    Debug,
248    Display,
249    AsRefStr,
250    EnumString,
251    FromRepr,
252    PartialEq,
253    Eq,
254    Hash,
255    Serialize,
256    Deserialize,
257)]
258#[cfg_attr(
259    feature = "python",
260    pyo3::pyclass(
261        module = "nautilus_trader.core.nautilus_pyo3.kraken",
262        eq,
263        eq_int,
264        from_py_object
265    )
266)]
267#[serde(rename_all = "lowercase")]
268#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
269pub enum KrakenPositionSide {
270    Long,
271    Short,
272}
273
274/// Kraken trading pair status.
275#[derive(
276    Clone,
277    Copy,
278    Debug,
279    Display,
280    AsRefStr,
281    EnumString,
282    FromRepr,
283    PartialEq,
284    Eq,
285    Hash,
286    Serialize,
287    Deserialize,
288)]
289#[cfg_attr(
290    feature = "python",
291    pyo3::pyclass(
292        module = "nautilus_trader.core.nautilus_pyo3.kraken",
293        eq,
294        eq_int,
295        from_py_object
296    )
297)]
298#[serde(rename_all = "snake_case")]
299#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
300pub enum KrakenPairStatus {
301    Online,
302    #[serde(rename = "cancel_only")]
303    #[strum(serialize = "cancel_only")]
304    CancelOnly,
305    #[serde(rename = "post_only")]
306    #[strum(serialize = "post_only")]
307    PostOnly,
308    #[serde(rename = "limit_only")]
309    #[strum(serialize = "limit_only")]
310    LimitOnly,
311    #[serde(rename = "reduce_only")]
312    #[strum(serialize = "reduce_only")]
313    ReduceOnly,
314}
315
316/// Kraken system status.
317#[derive(
318    Clone,
319    Copy,
320    Debug,
321    Display,
322    AsRefStr,
323    EnumString,
324    FromRepr,
325    PartialEq,
326    Eq,
327    Hash,
328    Serialize,
329    Deserialize,
330)]
331#[cfg_attr(
332    feature = "python",
333    pyo3::pyclass(
334        module = "nautilus_trader.core.nautilus_pyo3.kraken",
335        eq,
336        eq_int,
337        from_py_object
338    )
339)]
340#[serde(rename_all = "lowercase")]
341#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
342pub enum KrakenSystemStatus {
343    Online,
344    Maintenance,
345    #[serde(rename = "cancel_only")]
346    #[strum(serialize = "cancel_only")]
347    CancelOnly,
348    #[serde(rename = "post_only")]
349    #[strum(serialize = "post_only")]
350    PostOnly,
351}
352
353/// Kraken asset class.
354#[derive(
355    Clone,
356    Copy,
357    Debug,
358    Display,
359    AsRefStr,
360    EnumString,
361    FromRepr,
362    PartialEq,
363    Eq,
364    Hash,
365    Serialize,
366    Deserialize,
367)]
368#[cfg_attr(
369    feature = "python",
370    pyo3::pyclass(
371        module = "nautilus_trader.core.nautilus_pyo3.kraken",
372        eq,
373        eq_int,
374        from_py_object
375    )
376)]
377#[serde(rename_all = "lowercase")]
378#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
379pub enum KrakenAssetClass {
380    Currency,
381}
382
383/// Kraken futures order type.
384#[derive(
385    Clone,
386    Copy,
387    Debug,
388    Display,
389    AsRefStr,
390    EnumString,
391    FromRepr,
392    PartialEq,
393    Eq,
394    Hash,
395    Serialize,
396    Deserialize,
397)]
398#[cfg_attr(
399    feature = "python",
400    pyo3::pyclass(
401        module = "nautilus_trader.core.nautilus_pyo3.kraken",
402        eq,
403        eq_int,
404        from_py_object
405    )
406)]
407#[serde(rename_all = "lowercase")]
408#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
409pub enum KrakenFuturesOrderType {
410    #[serde(rename = "lmt")]
411    #[strum(serialize = "lmt")]
412    Limit,
413    #[serde(rename = "ioc")]
414    #[strum(serialize = "ioc")]
415    Ioc,
416    #[serde(rename = "post")]
417    #[strum(serialize = "post")]
418    Post,
419    #[serde(rename = "mkt")]
420    #[strum(serialize = "mkt")]
421    Market,
422    #[serde(rename = "stp")]
423    #[strum(serialize = "stp")]
424    Stop,
425    #[serde(rename = "stop")]
426    #[strum(serialize = "stop")]
427    StopLower,
428    #[serde(rename = "take_profit")]
429    #[strum(serialize = "take_profit")]
430    TakeProfit,
431    #[serde(rename = "stop_loss")]
432    #[strum(serialize = "stop_loss")]
433    StopLoss,
434}
435
436/// Event types from Kraken Futures sendorder/editorder responses.
437#[derive(
438    Clone,
439    Copy,
440    Debug,
441    Display,
442    AsRefStr,
443    EnumString,
444    FromRepr,
445    PartialEq,
446    Eq,
447    Hash,
448    Serialize,
449    Deserialize,
450)]
451#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
452#[strum(ascii_case_insensitive, serialize_all = "SCREAMING_SNAKE_CASE")]
453pub enum KrakenFuturesOrderEventType {
454    /// Order was placed.
455    Place,
456    /// Order was executed (filled).
457    Execution,
458    /// Order was rejected.
459    Reject,
460    /// Order was cancelled.
461    Cancel,
462    /// Order was edited.
463    Edit,
464}
465
466/// Kraken futures order status.
467#[derive(
468    Clone,
469    Copy,
470    Debug,
471    Display,
472    AsRefStr,
473    EnumString,
474    FromRepr,
475    PartialEq,
476    Eq,
477    Hash,
478    Serialize,
479    Deserialize,
480)]
481#[cfg_attr(
482    feature = "python",
483    pyo3::pyclass(
484        module = "nautilus_trader.core.nautilus_pyo3.kraken",
485        eq,
486        eq_int,
487        from_py_object
488    )
489)]
490#[serde(rename_all = "camelCase")]
491#[strum(ascii_case_insensitive, serialize_all = "camelCase")]
492pub enum KrakenFuturesOrderStatus {
493    Untouched,
494    PartiallyFilled,
495    Filled,
496    Cancelled,
497    Expired,
498}
499
500/// Kraken futures trigger signal type.
501#[derive(
502    Clone,
503    Copy,
504    Debug,
505    Display,
506    AsRefStr,
507    EnumString,
508    FromRepr,
509    PartialEq,
510    Eq,
511    Hash,
512    Serialize,
513    Deserialize,
514)]
515#[cfg_attr(
516    feature = "python",
517    pyo3::pyclass(
518        module = "nautilus_trader.core.nautilus_pyo3.kraken",
519        eq,
520        eq_int,
521        from_py_object
522    )
523)]
524#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
525pub enum KrakenTriggerSignal {
526    #[serde(rename = "last", alias = "last_price")]
527    Last,
528    #[serde(rename = "mark", alias = "mark_price")]
529    Mark,
530    #[serde(rename = "index", alias = "index_price")]
531    Index,
532}
533
534/// Trigger reference price for Kraken spot conditional orders.
535#[derive(
536    Clone,
537    Copy,
538    Debug,
539    Display,
540    AsRefStr,
541    EnumString,
542    FromRepr,
543    PartialEq,
544    Eq,
545    Hash,
546    Serialize,
547    Deserialize,
548)]
549#[cfg_attr(
550    feature = "python",
551    pyo3::pyclass(
552        module = "nautilus_trader.core.nautilus_pyo3.kraken",
553        eq,
554        eq_int,
555        from_py_object
556    )
557)]
558#[serde(rename_all = "lowercase")]
559#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
560pub enum KrakenSpotTrigger {
561    /// Last traded price in the order book.
562    Last,
563    /// Index price for the broader market.
564    Index,
565}
566
567/// Kraken fill type (maker or taker).
568#[derive(
569    Clone,
570    Copy,
571    Debug,
572    Display,
573    AsRefStr,
574    EnumString,
575    FromRepr,
576    PartialEq,
577    Eq,
578    Hash,
579    Serialize,
580    Deserialize,
581)]
582#[cfg_attr(
583    feature = "python",
584    pyo3::pyclass(
585        module = "nautilus_trader.core.nautilus_pyo3.kraken",
586        eq,
587        eq_int,
588        from_py_object
589    )
590)]
591#[serde(rename_all = "lowercase")]
592#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
593pub enum KrakenFillType {
594    Maker,
595    Taker,
596}
597
598/// Kraken API result status.
599#[derive(
600    Clone,
601    Copy,
602    Debug,
603    Display,
604    AsRefStr,
605    EnumString,
606    FromRepr,
607    PartialEq,
608    Eq,
609    Hash,
610    Serialize,
611    Deserialize,
612)]
613#[cfg_attr(
614    feature = "python",
615    pyo3::pyclass(
616        module = "nautilus_trader.core.nautilus_pyo3.kraken",
617        eq,
618        eq_int,
619        from_py_object
620    )
621)]
622#[serde(rename_all = "lowercase")]
623#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
624pub enum KrakenApiResult {
625    Success,
626    Error,
627}
628
629/// Kraken futures instrument type.
630#[derive(
631    Clone,
632    Copy,
633    Debug,
634    Display,
635    AsRefStr,
636    EnumString,
637    FromRepr,
638    PartialEq,
639    Eq,
640    Hash,
641    Serialize,
642    Deserialize,
643)]
644#[cfg_attr(
645    feature = "python",
646    pyo3::pyclass(
647        module = "nautilus_trader.core.nautilus_pyo3.kraken",
648        eq,
649        eq_int,
650        from_py_object
651    )
652)]
653#[serde(rename_all = "snake_case")]
654#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
655pub enum KrakenInstrumentType {
656    /// Inverse perpetual futures (e.g., PI_XBTUSD).
657    FuturesInverse,
658    /// Flexible/linear perpetual futures (e.g., PF_XBTUSD).
659    FlexibleFutures,
660}
661
662/// Kraken futures send order status.
663#[derive(
664    Clone,
665    Copy,
666    Debug,
667    Display,
668    AsRefStr,
669    EnumString,
670    FromRepr,
671    PartialEq,
672    Eq,
673    Hash,
674    Serialize,
675    Deserialize,
676)]
677#[cfg_attr(
678    feature = "python",
679    pyo3::pyclass(
680        module = "nautilus_trader.core.nautilus_pyo3.kraken",
681        eq,
682        eq_int,
683        from_py_object
684    )
685)]
686#[serde(rename_all = "camelCase")]
687#[strum(ascii_case_insensitive, serialize_all = "camelCase")]
688pub enum KrakenSendStatus {
689    /// Order was successfully placed.
690    Placed,
691    /// Order was cancelled.
692    Cancelled,
693    /// Order was edited.
694    Edited,
695    /// Order not found.
696    NotFound,
697    /// Insufficient available funds.
698    InsufficientAvailableFunds,
699    /// Invalid order type.
700    InvalidOrderType,
701    /// Invalid size.
702    InvalidSize,
703    /// Would cause liquidation.
704    WouldCauseLiquidation,
705    /// Post-only order would have crossed.
706    PostWouldExecute,
707    /// Reduce-only order would increase position.
708    ReduceOnlyWouldIncreasePosition,
709}
710
711/// Kraken futures trigger side for conditional orders.
712#[derive(
713    Clone,
714    Copy,
715    Debug,
716    Display,
717    AsRefStr,
718    EnumString,
719    FromRepr,
720    PartialEq,
721    Eq,
722    Hash,
723    Serialize,
724    Deserialize,
725)]
726#[cfg_attr(
727    feature = "python",
728    pyo3::pyclass(
729        module = "nautilus_trader.core.nautilus_pyo3.kraken",
730        eq,
731        eq_int,
732        from_py_object
733    )
734)]
735#[serde(rename_all = "snake_case")]
736#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
737pub enum KrakenTriggerSide {
738    /// Trigger when price goes above the trigger price.
739    #[serde(rename = "trigger_above")]
740    #[strum(serialize = "trigger_above")]
741    TriggerAbove,
742    /// Trigger when price goes below the trigger price.
743    #[serde(rename = "trigger_below")]
744    #[strum(serialize = "trigger_below")]
745    TriggerBelow,
746}
747
748impl From<KrakenOrderSide> for OrderSide {
749    fn from(value: KrakenOrderSide) -> Self {
750        match value {
751            KrakenOrderSide::Buy => Self::Buy,
752            KrakenOrderSide::Sell => Self::Sell,
753        }
754    }
755}
756
757impl From<KrakenOrderType> for OrderType {
758    fn from(value: KrakenOrderType) -> Self {
759        match value {
760            KrakenOrderType::Market => Self::Market,
761            KrakenOrderType::Limit => Self::Limit,
762            KrakenOrderType::StopLoss => Self::StopMarket,
763            KrakenOrderType::TakeProfit => Self::MarketIfTouched,
764            KrakenOrderType::StopLossLimit => Self::StopLimit,
765            KrakenOrderType::TakeProfitLimit => Self::LimitIfTouched,
766            KrakenOrderType::SettlePosition => Self::Market,
767        }
768    }
769}
770
771impl From<KrakenOrderStatus> for OrderStatus {
772    fn from(value: KrakenOrderStatus) -> Self {
773        match value {
774            KrakenOrderStatus::Pending => Self::Initialized,
775            KrakenOrderStatus::Open => Self::Accepted,
776            KrakenOrderStatus::Closed => Self::Filled,
777            KrakenOrderStatus::Canceled => Self::Canceled,
778            KrakenOrderStatus::Expired => Self::Expired,
779        }
780    }
781}
782
783impl From<KrakenFuturesOrderType> for OrderType {
784    fn from(value: KrakenFuturesOrderType) -> Self {
785        match value {
786            KrakenFuturesOrderType::Limit
787            | KrakenFuturesOrderType::Ioc
788            | KrakenFuturesOrderType::Post => Self::Limit,
789            KrakenFuturesOrderType::Market => Self::Market,
790            KrakenFuturesOrderType::Stop | KrakenFuturesOrderType::StopLower => Self::StopMarket,
791            KrakenFuturesOrderType::TakeProfit => Self::MarketIfTouched,
792            KrakenFuturesOrderType::StopLoss => Self::StopMarket,
793        }
794    }
795}
796
797impl TryFrom<OrderSide> for KrakenOrderSide {
798    type Error = &'static str;
799
800    fn try_from(value: OrderSide) -> Result<Self, Self::Error> {
801        match value {
802            OrderSide::Buy => Ok(Self::Buy),
803            OrderSide::Sell => Ok(Self::Sell),
804            OrderSide::NoOrderSide => Err("Cannot convert NoOrderSide to KrakenOrderSide"),
805        }
806    }
807}
808
809impl From<KrakenFuturesOrderStatus> for OrderStatus {
810    fn from(value: KrakenFuturesOrderStatus) -> Self {
811        match value {
812            KrakenFuturesOrderStatus::Untouched => Self::Accepted,
813            KrakenFuturesOrderStatus::PartiallyFilled => Self::PartiallyFilled,
814            KrakenFuturesOrderStatus::Filled => Self::Filled,
815            KrakenFuturesOrderStatus::Cancelled => Self::Canceled,
816            KrakenFuturesOrderStatus::Expired => Self::Expired,
817        }
818    }
819}
820
821/// Determines the product type from a Kraken symbol.
822///
823/// Futures symbols have the following prefixes:
824/// - `PI_` - Perpetual Inverse futures (e.g., `PI_XBTUSD`)
825/// - `PF_` - Perpetual Fixed-margin futures (e.g., `PF_XBTUSD`)
826/// - `PV_` - Perpetual Vanilla futures (e.g., `PV_XRPXBT`)
827/// - `FI_` - Fixed maturity Inverse futures (e.g., `FI_XBTUSD_230929`)
828/// - `FF_` - Flex futures
829///
830/// All other symbols are considered spot.
831#[must_use]
832pub fn product_type_from_symbol(symbol: &str) -> KrakenProductType {
833    if symbol.starts_with("PI_")
834        || symbol.starts_with("PF_")
835        || symbol.starts_with("PV_")
836        || symbol.starts_with("FI_")
837        || symbol.starts_with("FF_")
838    {
839        KrakenProductType::Futures
840    } else {
841        KrakenProductType::Spot
842    }
843}