nautilus_kraken/common/
enums.rs

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