nautilus_binance/python/
mod.rs1pub mod arrow;
19pub mod config;
20pub mod enums;
21pub mod factories;
22pub mod types;
23
24use nautilus_common::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
25use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
26use nautilus_model::data::ensure_rust_extractor_registered;
27use nautilus_serialization::ensure_custom_data_registered;
28use nautilus_system::get_global_pyo3_registry;
29use pyo3::prelude::*;
30
31use crate::{
32 common::{
33 bar::BinanceBar,
34 consts::{BINANCE_NAUTILUS_FUTURES_BROKER_ID, BINANCE_NAUTILUS_SPOT_BROKER_ID},
35 encoder::decode_broker_id,
36 enums::{BinanceEnvironment, BinanceMarginType, BinancePositionSide, BinanceProductType},
37 },
38 config::{BinanceDataClientConfig, BinanceExecClientConfig},
39 factories::{BinanceDataClientFactory, BinanceExecutionClientFactory},
40};
41
42#[expect(clippy::needless_pass_by_value)]
43fn extract_binance_data_factory(
44 py: Python<'_>,
45 factory: Py<PyAny>,
46) -> PyResult<Box<dyn DataClientFactory>> {
47 match factory.extract::<BinanceDataClientFactory>(py) {
48 Ok(f) => Ok(Box::new(f)),
49 Err(e) => Err(to_pyvalue_err(format!(
50 "Failed to extract BinanceDataClientFactory: {e}"
51 ))),
52 }
53}
54
55#[expect(clippy::needless_pass_by_value)]
56fn extract_binance_exec_factory(
57 py: Python<'_>,
58 factory: Py<PyAny>,
59) -> PyResult<Box<dyn ExecutionClientFactory>> {
60 match factory.extract::<BinanceExecutionClientFactory>(py) {
61 Ok(f) => Ok(Box::new(f)),
62 Err(e) => Err(to_pyvalue_err(format!(
63 "Failed to extract BinanceExecutionClientFactory: {e}"
64 ))),
65 }
66}
67
68#[expect(clippy::needless_pass_by_value)]
69fn extract_binance_data_config(
70 py: Python<'_>,
71 config: Py<PyAny>,
72) -> PyResult<Box<dyn ClientConfig>> {
73 match config.extract::<BinanceDataClientConfig>(py) {
74 Ok(c) => Ok(Box::new(c)),
75 Err(e) => Err(to_pyvalue_err(format!(
76 "Failed to extract BinanceDataClientConfig: {e}"
77 ))),
78 }
79}
80
81#[expect(clippy::needless_pass_by_value)]
82fn extract_binance_exec_config(
83 py: Python<'_>,
84 config: Py<PyAny>,
85) -> PyResult<Box<dyn ClientConfig>> {
86 match config.extract::<BinanceExecClientConfig>(py) {
87 Ok(c) => Ok(Box::new(c)),
88 Err(e) => Err(to_pyvalue_err(format!(
89 "Failed to extract BinanceExecClientConfig: {e}"
90 ))),
91 }
92}
93
94#[pyfunction]
102#[pyo3(name = "decode_binance_spot_client_order_id")]
103fn py_decode_binance_spot_client_order_id(encoded: &str) -> String {
104 decode_broker_id(encoded, BINANCE_NAUTILUS_SPOT_BROKER_ID)
105}
106
107#[pyfunction]
115#[pyo3(name = "decode_binance_futures_client_order_id")]
116fn py_decode_binance_futures_client_order_id(encoded: &str) -> String {
117 decode_broker_id(encoded, BINANCE_NAUTILUS_FUTURES_BROKER_ID)
118}
119
120#[pymodule]
128pub fn binance(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
129 m.add_class::<BinanceProductType>()?;
130 m.add_class::<BinanceEnvironment>()?;
131 m.add_class::<BinanceMarginType>()?;
132 m.add_class::<BinancePositionSide>()?;
133 m.add_class::<BinanceBar>()?;
134 m.add_function(wrap_pyfunction!(arrow::get_binance_arrow_schema_map, m)?)?;
135 m.add_function(wrap_pyfunction!(
136 arrow::py_binance_bar_to_arrow_record_batch_bytes,
137 m
138 )?)?;
139 m.add_function(wrap_pyfunction!(
140 arrow::py_binance_bar_from_arrow_record_batch_bytes,
141 m
142 )?)?;
143 m.add_class::<BinanceDataClientConfig>()?;
144 m.add_class::<BinanceExecClientConfig>()?;
145 m.add_class::<BinanceDataClientFactory>()?;
146 m.add_class::<BinanceExecutionClientFactory>()?;
147 m.add_function(wrap_pyfunction!(py_decode_binance_spot_client_order_id, m)?)?;
148 m.add_function(wrap_pyfunction!(
149 py_decode_binance_futures_client_order_id,
150 m
151 )?)?;
152
153 ensure_custom_data_registered::<BinanceBar>();
155 let _ = ensure_rust_extractor_registered::<BinanceBar>();
156
157 let registry = get_global_pyo3_registry();
158
159 if let Err(e) =
160 registry.register_factory_extractor("BINANCE".to_string(), extract_binance_data_factory)
161 {
162 return Err(to_pyruntime_err(format!(
163 "Failed to register Binance data factory extractor: {e}"
164 )));
165 }
166
167 if let Err(e) = registry
168 .register_exec_factory_extractor("BINANCE".to_string(), extract_binance_exec_factory)
169 {
170 return Err(to_pyruntime_err(format!(
171 "Failed to register Binance exec factory extractor: {e}"
172 )));
173 }
174
175 if let Err(e) = registry.register_config_extractor(
176 "BinanceDataClientConfig".to_string(),
177 extract_binance_data_config,
178 ) {
179 return Err(to_pyruntime_err(format!(
180 "Failed to register Binance data config extractor: {e}"
181 )));
182 }
183
184 if let Err(e) = registry.register_config_extractor(
185 "BinanceExecClientConfig".to_string(),
186 extract_binance_exec_config,
187 ) {
188 return Err(to_pyruntime_err(format!(
189 "Failed to register Binance exec config extractor: {e}"
190 )));
191 }
192
193 Ok(())
194}