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, 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, BinanceSpotMarketDataMode},
39 data_types::{
40 BinanceFuturesLiquidation, BinanceFuturesOpenInterest, BinanceFuturesOpenInterestHist,
41 BinanceFuturesOpenInterestHistPoint, BinanceFuturesTicker, register_binance_custom_data,
42 },
43 factories::{BinanceDataClientFactory, BinanceExecutionClientFactory},
44};
45
46#[expect(clippy::needless_pass_by_value)]
47fn extract_binance_data_factory(
48 py: Python<'_>,
49 factory: Py<PyAny>,
50) -> PyResult<Box<dyn DataClientFactory>> {
51 match factory.extract::<BinanceDataClientFactory>(py) {
52 Ok(f) => Ok(Box::new(f)),
53 Err(e) => Err(to_pyvalue_err(format!(
54 "Failed to extract BinanceDataClientFactory: {e}"
55 ))),
56 }
57}
58
59#[expect(clippy::needless_pass_by_value)]
60fn extract_binance_exec_factory(
61 py: Python<'_>,
62 factory: Py<PyAny>,
63) -> PyResult<Box<dyn ExecutionClientFactory>> {
64 match factory.extract::<BinanceExecutionClientFactory>(py) {
65 Ok(f) => Ok(Box::new(f)),
66 Err(e) => Err(to_pyvalue_err(format!(
67 "Failed to extract BinanceExecutionClientFactory: {e}"
68 ))),
69 }
70}
71
72#[expect(clippy::needless_pass_by_value)]
73fn extract_binance_data_config(
74 py: Python<'_>,
75 config: Py<PyAny>,
76) -> PyResult<Box<dyn ClientConfig>> {
77 match config.extract::<BinanceDataClientConfig>(py) {
78 Ok(c) => Ok(Box::new(c)),
79 Err(e) => Err(to_pyvalue_err(format!(
80 "Failed to extract BinanceDataClientConfig: {e}"
81 ))),
82 }
83}
84
85#[expect(clippy::needless_pass_by_value)]
86fn extract_binance_exec_config(
87 py: Python<'_>,
88 config: Py<PyAny>,
89) -> PyResult<Box<dyn ClientConfig>> {
90 match config.extract::<BinanceExecClientConfig>(py) {
91 Ok(c) => Ok(Box::new(c)),
92 Err(e) => Err(to_pyvalue_err(format!(
93 "Failed to extract BinanceExecClientConfig: {e}"
94 ))),
95 }
96}
97
98#[pyfunction]
106#[pyo3(name = "decode_binance_spot_client_order_id")]
107fn py_decode_binance_spot_client_order_id(encoded: &str) -> String {
108 decode_broker_id(encoded, BINANCE_NAUTILUS_SPOT_BROKER_ID)
109}
110
111#[pyfunction]
119#[pyo3(name = "decode_binance_futures_client_order_id")]
120fn py_decode_binance_futures_client_order_id(encoded: &str) -> String {
121 decode_broker_id(encoded, BINANCE_NAUTILUS_FUTURES_BROKER_ID)
122}
123
124#[pymodule]
132pub fn binance(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
133 m.add_class::<BinanceProductType>()?;
134 m.add_class::<BinanceEnvironment>()?;
135 m.add_class::<BinanceMarginType>()?;
136 m.add_class::<BinancePositionSide>()?;
137 m.add_class::<BinanceBar>()?;
138 m.add_class::<BinanceFuturesLiquidation>()?;
139 m.add_class::<BinanceFuturesTicker>()?;
140 m.add_class::<BinanceFuturesOpenInterest>()?;
141 m.add_class::<BinanceFuturesOpenInterestHistPoint>()?;
142 m.add_class::<BinanceFuturesOpenInterestHist>()?;
143 m.add_function(wrap_pyfunction!(arrow::get_binance_arrow_schema_map, m)?)?;
144 m.add_function(wrap_pyfunction!(
145 arrow::py_binance_bar_to_arrow_record_batch_bytes,
146 m
147 )?)?;
148 m.add_function(wrap_pyfunction!(
149 arrow::py_binance_bar_from_arrow_record_batch_bytes,
150 m
151 )?)?;
152 m.add_class::<BinanceDataClientConfig>()?;
153 m.add_class::<BinanceExecClientConfig>()?;
154 m.add_class::<BinanceSpotMarketDataMode>()?;
155 m.add_class::<BinanceDataClientFactory>()?;
156 m.add_class::<BinanceExecutionClientFactory>()?;
157 m.add_function(wrap_pyfunction!(py_decode_binance_spot_client_order_id, m)?)?;
158 m.add_function(wrap_pyfunction!(
159 py_decode_binance_futures_client_order_id,
160 m
161 )?)?;
162
163 ensure_custom_data_registered::<BinanceBar>();
165 let _result = ensure_rust_extractor_registered::<BinanceBar>();
166 register_binance_custom_data();
167 let _result = ensure_rust_extractor_registered::<BinanceFuturesLiquidation>();
168 let _result = ensure_rust_extractor_registered::<BinanceFuturesTicker>();
169 let _result = ensure_rust_extractor_registered::<BinanceFuturesOpenInterest>();
170 let _result = ensure_rust_extractor_registered::<BinanceFuturesOpenInterestHist>();
171
172 let registry = get_global_pyo3_registry();
173
174 if let Err(e) =
175 registry.register_factory_extractor(BINANCE.to_string(), extract_binance_data_factory)
176 {
177 return Err(to_pyruntime_err(format!(
178 "Failed to register Binance data factory extractor: {e}"
179 )));
180 }
181
182 if let Err(e) =
183 registry.register_exec_factory_extractor(BINANCE.to_string(), extract_binance_exec_factory)
184 {
185 return Err(to_pyruntime_err(format!(
186 "Failed to register Binance exec factory extractor: {e}"
187 )));
188 }
189
190 if let Err(e) = registry.register_config_extractor(
191 "BinanceDataClientConfig".to_string(),
192 extract_binance_data_config,
193 ) {
194 return Err(to_pyruntime_err(format!(
195 "Failed to register Binance data config extractor: {e}"
196 )));
197 }
198
199 if let Err(e) = registry.register_config_extractor(
200 "BinanceExecClientConfig".to_string(),
201 extract_binance_exec_config,
202 ) {
203 return Err(to_pyruntime_err(format!(
204 "Failed to register Binance exec config extractor: {e}"
205 )));
206 }
207
208 Ok(())
209}