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