Skip to main content

nautilus_kraken/common/
consts.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//! Core constants shared across the Kraken adapter components.
17
18use std::{num::NonZeroU32, sync::LazyLock};
19
20use nautilus_model::identifiers::{ClientId, Venue};
21use nautilus_network::ratelimiter::quota::Quota;
22use ustr::Ustr;
23
24/// Venue identifier string.
25pub const KRAKEN: &str = "KRAKEN";
26
27/// Static venue instance.
28pub static KRAKEN_VENUE: LazyLock<Venue> = LazyLock::new(|| Venue::new(Ustr::from(KRAKEN)));
29
30/// Static client ID instance.
31pub static KRAKEN_CLIENT_ID: LazyLock<ClientId> =
32    LazyLock::new(|| ClientId::new(Ustr::from(KRAKEN)));
33
34// API Partner integration identifier
35pub const NAUTILUS_KRAKEN_BROKER_ID: &str = "AA98 N84G GOPN GL6Y";
36
37/// Maximum length of a Kraken Futures client order ID (`cliOrdId`), as the send-order API
38/// documents it.
39pub const KRAKEN_FUTURES_MAX_CLIENT_ORDER_ID_LEN: usize = 100;
40
41// WebSocket-specific constants
42pub const KRAKEN_PONG: &str = "pong";
43pub const KRAKEN_WS_TOPIC_DELIMITER: char = '.';
44
45// Spot API URLs (v2)
46pub const KRAKEN_SPOT_HTTP_URL: &str = "https://api.kraken.com";
47pub const KRAKEN_SPOT_WS_PUBLIC_URL: &str = "wss://ws.kraken.com/v2";
48pub const KRAKEN_SPOT_WS_PRIVATE_URL: &str = "wss://ws-auth.kraken.com/v2";
49pub const KRAKEN_SPOT_WS_L3_URL: &str = "wss://ws-l3.kraken.com/v2";
50
51// Futures API URLs
52pub const KRAKEN_FUTURES_HTTP_URL: &str = "https://futures.kraken.com";
53pub const KRAKEN_FUTURES_WS_URL: &str = "wss://futures.kraken.com/ws/v1";
54
55// Demo URLs
56pub const KRAKEN_FUTURES_DEMO_HTTP_URL: &str = "https://demo-futures.kraken.com";
57pub const KRAKEN_FUTURES_DEMO_WS_URL: &str = "wss://demo-futures.kraken.com/ws/v1";
58
59// Spot order flags (oflags parameter values)
60pub const KRAKEN_OFLAG_POST_ONLY: &str = "post";
61pub const KRAKEN_OFLAG_QUOTE_QUANTITY: &str = "viqc";
62
63/// Kraken Futures WebSocket request rate limit: 100 requests per 1 second.
64///
65/// Set to 90/sec (10% margin below the documented 100/sec hard cap).
66///
67/// <https://docs.kraken.com/api/docs/guides/futures-rate-limits/#websocket-limits>
68pub static KRAKEN_FUTURES_WS_SUBSCRIPTION_QUOTA: LazyLock<Quota> = LazyLock::new(|| {
69    Quota::per_second(NonZeroU32::new(90).expect("non-zero")).expect("valid constant")
70});
71
72/// Kraken Spot WebSocket request rate limit (conservative).
73///
74/// The Spot WS message rate limit is dynamic and varies depending on system load.
75/// No fixed number is documented - the server returns `{"Error": "Exceeded msg rate"}`
76/// when exceeded. This conservative quota should avoid hitting the limit under normal use.
77///
78/// <https://docs.kraken.com/api/docs/guides/spot-ratelimits>
79pub static KRAKEN_SPOT_WS_SUBSCRIPTION_QUOTA: LazyLock<Quota> = LazyLock::new(|| {
80    Quota::per_second(NonZeroU32::new(20).expect("non-zero"))
81        .expect("valid constant")
82        .allow_burst(NonZeroU32::new(10).expect("non-zero"))
83});
84
85/// Kraken Spot WebSocket order rate limit (conservative).
86///
87/// Shares the same dynamic connection-level message budget as subscriptions.
88/// The matching engine enforces additional per-pair rate limits with decay
89/// (thresholds: 60 Starter / 125 Intermediate / 180 Pro).
90///
91/// <https://docs.kraken.com/api/docs/guides/spot-ratelimits>
92pub static KRAKEN_SPOT_WS_ORDER_QUOTA: LazyLock<Quota> = LazyLock::new(|| {
93    Quota::per_second(NonZeroU32::new(10).expect("non-zero"))
94        .expect("valid constant")
95        .allow_burst(NonZeroU32::new(10).expect("non-zero"))
96});
97
98/// Pre-interned rate limit key for WebSocket subscription operations.
99pub static KRAKEN_RATE_LIMIT_KEY_SUBSCRIPTION: LazyLock<[Ustr; 1]> =
100    LazyLock::new(|| [Ustr::from("subscription")]);
101
102/// Pre-interned rate limit key for WebSocket order operations.
103pub static KRAKEN_RATE_LIMIT_KEY_ORDER: LazyLock<[Ustr; 1]> =
104    LazyLock::new(|| [Ustr::from("order")]);
105
106// Post-only rejection reason strings
107pub const KRAKEN_FUTURES_POST_ONLY_REJECT: &str = "post_order_failed_because_it_would_filled";
108pub const KRAKEN_SPOT_POST_ONLY_REJECT: &str = "Post only order";
109pub const KRAKEN_SPOT_POST_ONLY_ERROR: &str = "EOrder:Post only order";
110
111/// Key under which a spot instrument carries Kraken's `altname` in its `info` map.
112///
113/// Present only when the altname differs from the `AssetPairs` key that is the instrument
114/// `raw_symbol`, so a client fed through the cache APIs can index the alias without the
115/// `AssetPairs` response.
116pub(crate) const KRAKEN_ALTNAME_KEY: &str = "kraken_altname";
117
118/// Instrument `info` key for the scale at which Kraken sends a Spot pair's prices on the wire.
119///
120/// `AssetPairs` declares it as `pair_decimals`. The instrument's price precision comes from
121/// `tick_size`, and for a handful of pairs that is one digit below the wire scale, so the key is
122/// present only when the two differ. The `book` checksum is computed over wire-scale strings.
123pub(crate) const KRAKEN_PAIR_DECIMALS_KEY: &str = "kraken_pair_decimals";