nautilus_bitmex/config.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//! Configuration types for the BitMEX adapter clients.
17
18use nautilus_model::identifiers::AccountId;
19
20use crate::common::consts::{
21 BITMEX_HTTP_TESTNET_URL, BITMEX_HTTP_URL, BITMEX_WS_TESTNET_URL, BITMEX_WS_URL,
22};
23
24/// Configuration for the BitMEX live data client.
25#[derive(Clone, Debug)]
26pub struct BitmexDataClientConfig {
27 /// Optional API key used for authenticated REST/WebSocket requests.
28 pub api_key: Option<String>,
29 /// Optional API secret used for authenticated REST/WebSocket requests.
30 pub api_secret: Option<String>,
31 /// Optional override for the REST base URL.
32 pub base_url_http: Option<String>,
33 /// Optional override for the WebSocket URL.
34 pub base_url_ws: Option<String>,
35 /// Optional REST timeout in seconds.
36 pub http_timeout_secs: Option<u64>,
37 /// Optional maximum retry attempts for REST requests.
38 pub max_retries: Option<u32>,
39 /// Optional initial retry backoff in milliseconds.
40 pub retry_delay_initial_ms: Option<u64>,
41 /// Optional maximum retry backoff in milliseconds.
42 pub retry_delay_max_ms: Option<u64>,
43 /// Optional heartbeat interval (seconds) for the WebSocket client.
44 pub heartbeat_interval_secs: Option<u64>,
45 /// Optional receive window in milliseconds for signed requests (default 10_000).
46 ///
47 /// This value determines how far in the future the `api-expires` timestamp will be set
48 /// for signed REST requests. BitMEX uses seconds-granularity Unix timestamps in the
49 /// `api-expires` header, calculated as: `current_timestamp + (recv_window_ms / 1000)`.
50 ///
51 /// **Note**: This parameter is specified in milliseconds for consistency with other
52 /// adapter configurations (e.g., Bybit's `recv_window_ms`), but BitMEX only supports
53 /// seconds-granularity timestamps. The value is converted via integer division, so
54 /// 10000ms becomes 10 seconds, 15500ms becomes 15 seconds, etc.
55 ///
56 /// A larger window provides more tolerance for clock skew and network latency, but
57 /// increases the replay attack window. The default of 10 seconds should be sufficient
58 /// for most deployments. Consider increasing this value (e.g., to 30_000ms = 30s) if you
59 /// experience request expiration errors due to clock drift or high network latency.
60 pub recv_window_ms: Option<u64>,
61 /// When `true`, only active instruments are requested during bootstrap.
62 pub active_only: bool,
63 /// Optional interval (minutes) for instrument refresh from REST.
64 pub update_instruments_interval_mins: Option<u64>,
65 /// When `true`, use BitMEX testnet endpoints by default.
66 pub use_testnet: bool,
67 /// Maximum number of requests per second (burst limit).
68 pub max_requests_per_second: Option<u32>,
69 /// Maximum number of requests per minute (rolling window).
70 pub max_requests_per_minute: Option<u32>,
71}
72
73impl Default for BitmexDataClientConfig {
74 fn default() -> Self {
75 Self {
76 api_key: None,
77 api_secret: None,
78 base_url_http: None,
79 base_url_ws: None,
80 http_timeout_secs: Some(60),
81 max_retries: Some(3),
82 retry_delay_initial_ms: Some(1_000),
83 retry_delay_max_ms: Some(10_000),
84 heartbeat_interval_secs: None,
85 recv_window_ms: Some(10_000),
86 active_only: true,
87 update_instruments_interval_mins: None,
88 use_testnet: false,
89 max_requests_per_second: Some(10),
90 max_requests_per_minute: Some(120),
91 }
92 }
93}
94
95impl BitmexDataClientConfig {
96 /// Creates a configuration with default values.
97 #[must_use]
98 pub fn new() -> Self {
99 Self::default()
100 }
101
102 /// Returns `true` if both API key and secret are available.
103 #[must_use]
104 pub fn has_api_credentials(&self) -> bool {
105 self.api_key.is_some() && self.api_secret.is_some()
106 }
107
108 /// Returns the REST base URL, considering overrides and the testnet flag.
109 #[must_use]
110 pub fn http_base_url(&self) -> String {
111 self.base_url_http.clone().unwrap_or_else(|| {
112 if self.use_testnet {
113 BITMEX_HTTP_TESTNET_URL.to_string()
114 } else {
115 BITMEX_HTTP_URL.to_string()
116 }
117 })
118 }
119
120 /// Returns the WebSocket URL, considering overrides and the testnet flag.
121 #[must_use]
122 pub fn ws_url(&self) -> String {
123 self.base_url_ws.clone().unwrap_or_else(|| {
124 if self.use_testnet {
125 BITMEX_WS_TESTNET_URL.to_string()
126 } else {
127 BITMEX_WS_URL.to_string()
128 }
129 })
130 }
131}
132
133/// Configuration for the BitMEX live execution client.
134#[derive(Clone, Debug)]
135pub struct BitmexExecClientConfig {
136 /// API key used for authenticated requests.
137 pub api_key: Option<String>,
138 /// API secret used for authenticated requests.
139 pub api_secret: Option<String>,
140 /// Optional override for the REST base URL.
141 pub base_url_http: Option<String>,
142 /// Optional override for the WebSocket URL.
143 pub base_url_ws: Option<String>,
144 /// Optional REST timeout in seconds.
145 pub http_timeout_secs: Option<u64>,
146 /// Optional maximum retry attempts for REST requests.
147 pub max_retries: Option<u32>,
148 /// Optional initial retry backoff in milliseconds.
149 pub retry_delay_initial_ms: Option<u64>,
150 /// Optional maximum retry backoff in milliseconds.
151 pub retry_delay_max_ms: Option<u64>,
152 /// Optional heartbeat interval (seconds) for the WebSocket client.
153 pub heartbeat_interval_secs: Option<u64>,
154 /// Optional receive window in milliseconds for signed requests (default 10000).
155 ///
156 /// This value determines how far in the future the `api-expires` timestamp will be set
157 /// for signed REST requests. BitMEX uses seconds-granularity Unix timestamps in the
158 /// `api-expires` header, calculated as: `current_timestamp + (recv_window_ms / 1000)`.
159 ///
160 /// **Note**: This parameter is specified in milliseconds for consistency with other
161 /// adapter configurations (e.g., Bybit's `recv_window_ms`), but BitMEX only supports
162 /// seconds-granularity timestamps. The value is converted via integer division, so
163 /// 10000ms becomes 10 seconds, 15500ms becomes 15 seconds, etc.
164 ///
165 /// A larger window provides more tolerance for clock skew and network latency, but
166 /// increases the replay attack window. The default of 10 seconds should be sufficient
167 /// for most deployments. Consider increasing this value (e.g., to 30000ms = 30s) if you
168 /// experience request expiration errors due to clock drift or high network latency.
169 pub recv_window_ms: Option<u64>,
170 /// When `true`, only active instruments are requested during bootstrap.
171 pub active_only: bool,
172 /// When `true`, use BitMEX testnet endpoints by default.
173 pub use_testnet: bool,
174 /// Optional account identifier to associate with the execution client.
175 pub account_id: Option<AccountId>,
176 /// Maximum number of requests per second (burst limit).
177 pub max_requests_per_second: Option<u32>,
178 /// Maximum number of requests per minute (rolling window).
179 pub max_requests_per_minute: Option<u32>,
180}
181
182impl Default for BitmexExecClientConfig {
183 fn default() -> Self {
184 Self {
185 api_key: None,
186 api_secret: None,
187 base_url_http: None,
188 base_url_ws: None,
189 http_timeout_secs: Some(60),
190 max_retries: Some(3),
191 retry_delay_initial_ms: Some(1_000),
192 retry_delay_max_ms: Some(10_000),
193 heartbeat_interval_secs: Some(5),
194 recv_window_ms: Some(10_000),
195 active_only: true,
196 use_testnet: false,
197 account_id: None,
198 max_requests_per_second: Some(10),
199 max_requests_per_minute: Some(120),
200 }
201 }
202}
203
204impl BitmexExecClientConfig {
205 /// Creates a configuration with default values.
206 #[must_use]
207 pub fn new() -> Self {
208 Self::default()
209 }
210
211 /// Returns `true` if both API key and secret are available.
212 #[must_use]
213 pub fn has_api_credentials(&self) -> bool {
214 self.api_key.is_some() && self.api_secret.is_some()
215 }
216
217 /// Returns the REST base URL, considering overrides and the testnet flag.
218 #[must_use]
219 pub fn http_base_url(&self) -> String {
220 self.base_url_http.clone().unwrap_or_else(|| {
221 if self.use_testnet {
222 BITMEX_HTTP_TESTNET_URL.to_string()
223 } else {
224 BITMEX_HTTP_URL.to_string()
225 }
226 })
227 }
228
229 /// Returns the WebSocket URL, considering overrides and the testnet flag.
230 #[must_use]
231 pub fn ws_url(&self) -> String {
232 self.base_url_ws.clone().unwrap_or_else(|| {
233 if self.use_testnet {
234 BITMEX_WS_TESTNET_URL.to_string()
235 } else {
236 BITMEX_WS_URL.to_string()
237 }
238 })
239 }
240}