Skip to main content

nautilus_bitmex/python/
config.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//! Python bindings for BitMEX configuration.
17
18use nautilus_core::{python::to_pyvalue_err, string::secret::SecretString};
19use nautilus_model::identifiers::AccountId;
20use nautilus_network::websocket::TransportBackend;
21use pyo3::prelude::*;
22
23use crate::{
24    common::enums::BitmexEnvironment,
25    config::{BitmexDataClientConfig, BitmexExecutionClientConfig},
26};
27
28#[pymethods]
29#[pyo3_stub_gen::derive::gen_stub_pymethods]
30impl BitmexDataClientConfig {
31    /// Configuration for the BitMEX live data client.
32    #[new]
33    #[pyo3(signature = (
34        api_key = None,
35        api_secret = None,
36        base_url_http = None,
37        base_url_ws = None,
38        proxy_url = None,
39        http_timeout_secs = None,
40        max_retries = None,
41        retry_delay_initial_ms = None,
42        retry_delay_max_ms = None,
43        heartbeat_interval_secs = None,
44        auth_timeout_secs = None,
45        recv_window_ms = None,
46        active_only = None,
47        update_instruments_interval_mins = None,
48        environment = None,
49        max_requests_per_second = None,
50        max_requests_per_minute = None,
51        transport_backend = None,
52    ))]
53    #[expect(clippy::too_many_arguments)]
54    fn py_new(
55        api_key: Option<String>,
56        api_secret: Option<String>,
57        base_url_http: Option<String>,
58        base_url_ws: Option<String>,
59        proxy_url: Option<String>,
60        http_timeout_secs: Option<u64>,
61        max_retries: Option<u32>,
62        retry_delay_initial_ms: Option<u64>,
63        retry_delay_max_ms: Option<u64>,
64        heartbeat_interval_secs: Option<u64>,
65        auth_timeout_secs: Option<u64>,
66        recv_window_ms: Option<u64>,
67        active_only: Option<bool>,
68        update_instruments_interval_mins: Option<u64>,
69        environment: Option<BitmexEnvironment>,
70        max_requests_per_second: Option<u32>,
71        max_requests_per_minute: Option<u32>,
72        transport_backend: Option<TransportBackend>,
73    ) -> Self {
74        let defaults = Self::default();
75        Self {
76            api_key: api_key.map(SecretString::from),
77            api_secret: api_secret.map(SecretString::from),
78            base_url_http,
79            base_url_ws,
80            proxy_url: proxy_url.map(SecretString::from),
81            http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
82            max_retries: max_retries.unwrap_or(defaults.max_retries),
83            retry_delay_initial_ms: retry_delay_initial_ms
84                .unwrap_or(defaults.retry_delay_initial_ms),
85            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
86            heartbeat_interval_secs,
87            auth_timeout_secs,
88            recv_window_ms: recv_window_ms.unwrap_or(defaults.recv_window_ms),
89            active_only: active_only.unwrap_or(defaults.active_only),
90            update_instruments_interval_mins,
91            environment: environment.unwrap_or(defaults.environment),
92            max_requests_per_second: max_requests_per_second
93                .unwrap_or(defaults.max_requests_per_second),
94            max_requests_per_minute: max_requests_per_minute
95                .unwrap_or(defaults.max_requests_per_minute),
96            transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
97        }
98    }
99
100    #[getter]
101    const fn has_proxy_url(&self) -> bool {
102        self.proxy_url.is_some()
103    }
104
105    fn __repr__(&self) -> String {
106        stringify!(BitmexDataClientConfig).to_string()
107    }
108}
109
110#[pymethods]
111#[pyo3_stub_gen::derive::gen_stub_pymethods]
112impl BitmexExecutionClientConfig {
113    /// Configuration for the BitMEX live execution client.
114    ///
115    /// The submit and cancel broadcaster pools must each contain `[1, 15]` clients, with a combined
116    /// size in `[2, 16]`.
117    #[new]
118    #[pyo3(signature = (
119        api_key = None,
120        api_secret = None,
121        base_url_http = None,
122        base_url_ws = None,
123        proxy_url = None,
124        http_timeout_secs = None,
125        max_retries = None,
126        retry_delay_initial_ms = None,
127        retry_delay_max_ms = None,
128        heartbeat_interval_secs = None,
129        auth_timeout_secs = None,
130        recv_window_ms = None,
131        active_only = None,
132        environment = None,
133        account_id = None,
134        max_requests_per_second = None,
135        max_requests_per_minute = None,
136        submitter_pool_size = None,
137        canceller_pool_size = None,
138        submitter_proxy_urls = None,
139        canceller_proxy_urls = None,
140        deadmans_switch_timeout_secs = None,
141        transport_backend = None,
142    ))]
143    #[expect(clippy::too_many_arguments)]
144    fn py_new(
145        api_key: Option<String>,
146        api_secret: Option<String>,
147        base_url_http: Option<String>,
148        base_url_ws: Option<String>,
149        proxy_url: Option<String>,
150        http_timeout_secs: Option<u64>,
151        max_retries: Option<u32>,
152        retry_delay_initial_ms: Option<u64>,
153        retry_delay_max_ms: Option<u64>,
154        heartbeat_interval_secs: Option<u64>,
155        auth_timeout_secs: Option<u64>,
156        recv_window_ms: Option<u64>,
157        active_only: Option<bool>,
158        environment: Option<BitmexEnvironment>,
159        account_id: Option<AccountId>,
160        max_requests_per_second: Option<u32>,
161        max_requests_per_minute: Option<u32>,
162        submitter_pool_size: Option<usize>,
163        canceller_pool_size: Option<usize>,
164        submitter_proxy_urls: Option<Vec<String>>,
165        canceller_proxy_urls: Option<Vec<String>>,
166        deadmans_switch_timeout_secs: Option<u64>,
167        transport_backend: Option<TransportBackend>,
168    ) -> PyResult<Self> {
169        let defaults = Self::default();
170        let config = Self {
171            api_key: api_key.map(SecretString::from),
172            api_secret: api_secret.map(SecretString::from),
173            base_url_http,
174            base_url_ws,
175            proxy_url: proxy_url.map(SecretString::from),
176            http_timeout_secs: http_timeout_secs.unwrap_or(defaults.http_timeout_secs),
177            max_retries: max_retries.unwrap_or(defaults.max_retries),
178            retry_delay_initial_ms: retry_delay_initial_ms
179                .unwrap_or(defaults.retry_delay_initial_ms),
180            retry_delay_max_ms: retry_delay_max_ms.unwrap_or(defaults.retry_delay_max_ms),
181            heartbeat_interval_secs: heartbeat_interval_secs
182                .unwrap_or(defaults.heartbeat_interval_secs),
183            auth_timeout_secs,
184            recv_window_ms: recv_window_ms.unwrap_or(defaults.recv_window_ms),
185            active_only: active_only.unwrap_or(defaults.active_only),
186            environment: environment.unwrap_or(defaults.environment),
187            account_id,
188            max_requests_per_second: max_requests_per_second
189                .unwrap_or(defaults.max_requests_per_second),
190            max_requests_per_minute: max_requests_per_minute
191                .unwrap_or(defaults.max_requests_per_minute),
192            submitter_pool_size,
193            canceller_pool_size,
194            submitter_proxy_urls: submitter_proxy_urls
195                .map(|values| values.into_iter().map(SecretString::from).collect()),
196            canceller_proxy_urls: canceller_proxy_urls
197                .map(|values| values.into_iter().map(SecretString::from).collect()),
198            deadmans_switch_timeout_secs,
199            transport_backend: transport_backend.unwrap_or(defaults.transport_backend),
200        };
201        config
202            .validate_broadcaster_pool_sizes()
203            .map_err(to_pyvalue_err)?;
204        Ok(config)
205    }
206
207    #[getter]
208    const fn has_proxy_url(&self) -> bool {
209        self.proxy_url.is_some()
210    }
211
212    #[getter]
213    const fn has_submitter_proxy_urls(&self) -> bool {
214        self.submitter_proxy_urls.is_some()
215    }
216
217    #[getter]
218    const fn has_canceller_proxy_urls(&self) -> bool {
219        self.canceller_proxy_urls.is_some()
220    }
221
222    fn __repr__(&self) -> String {
223        stringify!(BitmexExecutionClientConfig).to_string()
224    }
225}