Skip to main content

nautilus_kraken/websocket/spot_v2/
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 for Kraken WebSocket v2 API.
17
18use nautilus_model::enums::{LiquiditySide, OrderStatus};
19use serde::{Deserialize, Serialize};
20use strum::{AsRefStr, Display, EnumString, FromRepr};
21
22#[derive(
23    Clone,
24    Copy,
25    Debug,
26    Display,
27    AsRefStr,
28    EnumString,
29    FromRepr,
30    PartialEq,
31    Eq,
32    Hash,
33    Serialize,
34    Deserialize,
35)]
36#[serde(rename_all = "lowercase")]
37#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
38pub enum KrakenWsMethod {
39    Subscribe,
40    Unsubscribe,
41    Ping,
42    Pong,
43    #[serde(rename = "add_order")]
44    #[strum(serialize = "add_order")]
45    AddOrder,
46    #[serde(rename = "amend_order")]
47    #[strum(serialize = "amend_order")]
48    AmendOrder,
49    #[serde(rename = "cancel_order")]
50    #[strum(serialize = "cancel_order")]
51    CancelOrder,
52    #[serde(rename = "batch_add")]
53    #[strum(serialize = "batch_add")]
54    BatchAdd,
55}
56
57#[derive(
58    Clone,
59    Copy,
60    Debug,
61    Display,
62    AsRefStr,
63    EnumString,
64    FromRepr,
65    PartialEq,
66    Eq,
67    Hash,
68    Serialize,
69    Deserialize,
70)]
71#[serde(rename_all = "lowercase")]
72#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
73pub enum KrakenWsChannel {
74    Ticker,
75    #[serde(rename = "trade")]
76    #[strum(serialize = "trade")]
77    Trade,
78    #[serde(rename = "book")]
79    #[strum(serialize = "book")]
80    Book,
81    #[serde(rename = "ohlc")]
82    #[strum(serialize = "ohlc")]
83    Ohlc,
84    #[serde(rename = "spread")]
85    #[strum(serialize = "spread")]
86    Spread,
87    // Private channels
88    #[serde(rename = "executions")]
89    #[strum(serialize = "executions")]
90    Executions,
91    #[serde(rename = "balances")]
92    #[strum(serialize = "balances")]
93    Balances,
94    #[serde(rename = "level3")]
95    #[strum(serialize = "level3")]
96    Level3,
97}
98
99#[derive(
100    Clone,
101    Copy,
102    Debug,
103    Display,
104    AsRefStr,
105    EnumString,
106    FromRepr,
107    PartialEq,
108    Eq,
109    Hash,
110    Serialize,
111    Deserialize,
112)]
113#[serde(rename_all = "lowercase")]
114#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
115pub enum KrakenWsMessageType {
116    Heartbeat,
117    Status,
118    Subscribe,
119    Unsubscribe,
120    Update,
121    Snapshot,
122    Error,
123}
124
125/// Execution type from the Kraken executions channel.
126#[derive(
127    Clone,
128    Copy,
129    Debug,
130    Display,
131    AsRefStr,
132    EnumString,
133    FromRepr,
134    PartialEq,
135    Eq,
136    Hash,
137    Serialize,
138    Deserialize,
139)]
140#[serde(rename_all = "snake_case")]
141#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
142pub enum KrakenExecType {
143    /// Order is pending submission to the exchange.
144    #[serde(rename = "pending_new")]
145    #[strum(serialize = "pending_new")]
146    PendingNew,
147    /// Order has been accepted by the exchange.
148    New,
149    /// Order has been partially or fully filled.
150    Trade,
151    /// Order has been completely filled.
152    Filled,
153    /// Iceberg order refill.
154    #[serde(rename = "iceberg_refill")]
155    #[strum(serialize = "iceberg_refill")]
156    IcebergRefill,
157    /// Order has been canceled.
158    Canceled,
159    /// Order has expired.
160    Expired,
161    /// Order has been amended (user-initiated modification).
162    Amended,
163    /// Order has been restated (engine-initiated adjustment).
164    Restated,
165    /// Order status update without state change.
166    Status,
167}
168
169/// Order status from the Kraken WebSocket v2 executions channel.
170#[derive(
171    Clone,
172    Copy,
173    Debug,
174    Display,
175    AsRefStr,
176    EnumString,
177    FromRepr,
178    PartialEq,
179    Eq,
180    Hash,
181    Serialize,
182    Deserialize,
183)]
184#[serde(rename_all = "snake_case")]
185#[strum(ascii_case_insensitive, serialize_all = "snake_case")]
186pub enum KrakenWsOrderStatus {
187    /// Order is pending submission.
188    #[serde(rename = "pending_new")]
189    #[strum(serialize = "pending_new")]
190    PendingNew,
191    /// Order has been accepted.
192    New,
193    /// Order has been partially filled.
194    #[serde(rename = "partially_filled")]
195    #[strum(serialize = "partially_filled")]
196    PartiallyFilled,
197    /// Order has been completely filled.
198    Filled,
199    /// Order has been canceled.
200    Canceled,
201    /// Order has expired.
202    Expired,
203    /// Conditional order has been triggered.
204    Triggered,
205}
206
207/// Liquidity indicator from trade executions.
208#[derive(
209    Clone,
210    Copy,
211    Debug,
212    Display,
213    AsRefStr,
214    EnumString,
215    FromRepr,
216    PartialEq,
217    Eq,
218    Hash,
219    Serialize,
220    Deserialize,
221)]
222#[serde(rename_all = "lowercase")]
223#[strum(ascii_case_insensitive, serialize_all = "lowercase")]
224pub enum KrakenLiquidityInd {
225    /// Maker (limit order that added liquidity).
226    #[serde(rename = "m")]
227    #[strum(serialize = "m")]
228    Maker,
229    /// Taker (order that removed liquidity).
230    #[serde(rename = "t")]
231    #[strum(serialize = "t")]
232    Taker,
233}
234
235impl From<KrakenWsOrderStatus> for OrderStatus {
236    fn from(value: KrakenWsOrderStatus) -> Self {
237        match value {
238            KrakenWsOrderStatus::PendingNew => Self::Submitted,
239            KrakenWsOrderStatus::New => Self::Accepted,
240            KrakenWsOrderStatus::PartiallyFilled => Self::PartiallyFilled,
241            KrakenWsOrderStatus::Filled => Self::Filled,
242            KrakenWsOrderStatus::Canceled => Self::Canceled,
243            KrakenWsOrderStatus::Expired => Self::Expired,
244            KrakenWsOrderStatus::Triggered => Self::Triggered,
245        }
246    }
247}
248
249impl From<KrakenLiquidityInd> for LiquiditySide {
250    fn from(value: KrakenLiquidityInd) -> Self {
251        match value {
252            KrakenLiquidityInd::Maker => Self::Maker,
253            KrakenLiquidityInd::Taker => Self::Taker,
254        }
255    }
256}
257
258#[cfg(test)]
259mod tests {
260    use rstest::rstest;
261
262    use super::*;
263
264    #[rstest]
265    #[case(KrakenWsMethod::AddOrder, "\"add_order\"")]
266    #[case(KrakenWsMethod::AmendOrder, "\"amend_order\"")]
267    #[case(KrakenWsMethod::CancelOrder, "\"cancel_order\"")]
268    #[case(KrakenWsMethod::BatchAdd, "\"batch_add\"")]
269    fn test_ws_method_order_variants_serde(#[case] m: KrakenWsMethod, #[case] expected: &str) {
270        let json = serde_json::to_string(&m).unwrap();
271        assert_eq!(json, expected);
272        let back: KrakenWsMethod = serde_json::from_str(&json).unwrap();
273        assert_eq!(back, m);
274    }
275
276    #[rstest]
277    fn test_ws_channel_level3_serde() {
278        let json = serde_json::to_string(&KrakenWsChannel::Level3).unwrap();
279        assert_eq!(json, "\"level3\"");
280        let back: KrakenWsChannel = serde_json::from_str(&json).unwrap();
281        assert_eq!(back, KrakenWsChannel::Level3);
282    }
283}