Skip to main content

nautilus_bitmex/python/
mod.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 from `pyo3`.
17
18pub mod canceller;
19pub mod config;
20pub mod enums;
21pub mod factories;
22pub mod http;
23pub mod submitter;
24
25use nautilus_common::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
26use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
27use nautilus_system::get_global_pyo3_registry;
28use pyo3::prelude::*;
29
30use crate::{
31    common::consts::{BITMEX, BITMEX_CLIENT_ID, BITMEX_VENUE},
32    config::{BitmexDataClientConfig, BitmexExecutionClientConfig},
33    factories::{BitmexDataClientFactory, BitmexExecutionClientFactory},
34};
35
36#[expect(clippy::needless_pass_by_value)]
37fn extract_bitmex_data_factory(
38    py: Python<'_>,
39    factory: Py<PyAny>,
40) -> PyResult<Box<dyn DataClientFactory>> {
41    match factory.extract::<BitmexDataClientFactory>(py) {
42        Ok(f) => Ok(Box::new(f)),
43        Err(e) => Err(to_pyvalue_err(format!(
44            "Failed to extract BitmexDataClientFactory: {e}"
45        ))),
46    }
47}
48
49#[expect(clippy::needless_pass_by_value)]
50fn extract_bitmex_exec_factory(
51    py: Python<'_>,
52    factory: Py<PyAny>,
53) -> PyResult<Box<dyn ExecutionClientFactory>> {
54    match factory.extract::<BitmexExecutionClientFactory>(py) {
55        Ok(f) => Ok(Box::new(f)),
56        Err(e) => Err(to_pyvalue_err(format!(
57            "Failed to extract BitmexExecutionClientFactory: {e}"
58        ))),
59    }
60}
61
62#[expect(clippy::needless_pass_by_value)]
63fn extract_bitmex_data_config(
64    py: Python<'_>,
65    config: Py<PyAny>,
66) -> PyResult<Box<dyn ClientConfig>> {
67    match config.extract::<BitmexDataClientConfig>(py) {
68        Ok(c) => Ok(Box::new(c)),
69        Err(e) => Err(to_pyvalue_err(format!(
70            "Failed to extract BitmexDataClientConfig: {e}"
71        ))),
72    }
73}
74
75#[expect(clippy::needless_pass_by_value)]
76fn extract_bitmex_exec_config(
77    py: Python<'_>,
78    config: Py<PyAny>,
79) -> PyResult<Box<dyn ClientConfig>> {
80    match config.extract::<BitmexExecutionClientConfig>(py) {
81        Ok(c) => Ok(Box::new(c)),
82        Err(e) => Err(to_pyvalue_err(format!(
83            "Failed to extract BitmexExecutionClientConfig: {e}"
84        ))),
85    }
86}
87
88/// Exposed through `nautilus_trader.adapters.bitmex`.
89///
90/// # Errors
91///
92/// Returns an error if the module registration fails or if adding functions/classes fails.
93#[pymodule]
94pub fn bitmex(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
95    m.add(stringify!(BITMEX), BITMEX)?;
96    m.add(stringify!(BITMEX_CLIENT_ID), *BITMEX_CLIENT_ID)?;
97    m.add(stringify!(BITMEX_VENUE), *BITMEX_VENUE)?;
98    m.add_class::<crate::common::enums::BitmexEnvironment>()?;
99    m.add_class::<crate::http::client::BitmexHttpClient>()?;
100    m.add_class::<crate::broadcast::canceller::CancelBroadcaster>()?;
101    m.add_class::<crate::broadcast::submitter::SubmitBroadcaster>()?;
102    m.add_class::<BitmexDataClientConfig>()?;
103    m.add_class::<BitmexDataClientFactory>()?;
104    m.add_class::<BitmexExecutionClientConfig>()?;
105    m.add_class::<BitmexExecutionClientFactory>()?;
106
107    let registry = get_global_pyo3_registry();
108
109    if let Err(e) =
110        registry.register_factory_extractor(BITMEX.to_string(), extract_bitmex_data_factory)
111    {
112        return Err(to_pyruntime_err(format!(
113            "Failed to register BitMEX data factory extractor: {e}"
114        )));
115    }
116
117    if let Err(e) =
118        registry.register_exec_factory_extractor(BITMEX.to_string(), extract_bitmex_exec_factory)
119    {
120        return Err(to_pyruntime_err(format!(
121            "Failed to register BitMEX exec factory extractor: {e}"
122        )));
123    }
124
125    if let Err(e) = registry.register_config_extractor(
126        "BitmexDataClientConfig".to_string(),
127        extract_bitmex_data_config,
128    ) {
129        return Err(to_pyruntime_err(format!(
130            "Failed to register BitMEX data config extractor: {e}"
131        )));
132    }
133
134    if let Err(e) = registry.register_config_extractor(
135        "BitmexExecutionClientConfig".to_string(),
136        extract_bitmex_exec_config,
137    ) {
138        return Err(to_pyruntime_err(format!(
139            "Failed to register BitMEX exec config extractor: {e}"
140        )));
141    }
142
143    Ok(())
144}