nautilus_binance/python/
mod.rs1pub mod config;
19pub mod enums;
20pub mod factories;
21pub mod types;
22
23#[cfg(feature = "arrow")]
24pub mod arrow;
25
26mod data;
27mod instruments;
28
29use nautilus_common::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
30use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
31use nautilus_model::data::ensure_rust_extractor_registered;
32use nautilus_system::get_global_pyo3_registry;
33use pyo3::prelude::*;
34
35use crate::{
36 common::{
37 bar::BinanceBar,
38 consts::{
39 BINANCE, BINANCE_CLIENT_ID, BINANCE_NAUTILUS_FUTURES_BROKER_ID,
40 BINANCE_NAUTILUS_SPOT_BROKER_ID, BINANCE_VENUE,
41 },
42 encoder::decode_broker_id,
43 enums::{BinanceEnvironment, BinanceMarginType, BinancePositionSide, BinanceProductType},
44 },
45 config::{
46 BinanceDataClientConfig, BinanceExecutionClientConfig, BinanceInstrumentProviderConfig,
47 BinanceSpotMarketDataMode,
48 },
49 data_types::{
50 BinanceFuturesLiquidation, BinanceFuturesMarkPriceUpdate, BinanceFuturesOpenInterest,
51 BinanceFuturesOpenInterestHist, BinanceFuturesOpenInterestHistPoint, BinanceFuturesTicker,
52 BinanceSpotTicker, register_binance_custom_data,
53 },
54 factories::{BinanceDataClientFactory, BinanceExecutionClientFactory},
55};
56
57#[expect(clippy::needless_pass_by_value)]
58fn extract_binance_data_factory(
59 py: Python<'_>,
60 factory: Py<PyAny>,
61) -> PyResult<Box<dyn DataClientFactory>> {
62 match factory.extract::<BinanceDataClientFactory>(py) {
63 Ok(f) => Ok(Box::new(f)),
64 Err(e) => Err(to_pyvalue_err(format!(
65 "Failed to extract BinanceDataClientFactory: {e}"
66 ))),
67 }
68}
69
70#[expect(clippy::needless_pass_by_value)]
71fn extract_binance_exec_factory(
72 py: Python<'_>,
73 factory: Py<PyAny>,
74) -> PyResult<Box<dyn ExecutionClientFactory>> {
75 match factory.extract::<BinanceExecutionClientFactory>(py) {
76 Ok(f) => Ok(Box::new(f)),
77 Err(e) => Err(to_pyvalue_err(format!(
78 "Failed to extract BinanceExecutionClientFactory: {e}"
79 ))),
80 }
81}
82
83#[expect(clippy::needless_pass_by_value)]
84fn extract_binance_data_config(
85 py: Python<'_>,
86 config: Py<PyAny>,
87) -> PyResult<Box<dyn ClientConfig>> {
88 match config.extract::<BinanceDataClientConfig>(py) {
89 Ok(c) => Ok(Box::new(c)),
90 Err(e) => Err(to_pyvalue_err(format!(
91 "Failed to extract BinanceDataClientConfig: {e}"
92 ))),
93 }
94}
95
96#[expect(clippy::needless_pass_by_value)]
97fn extract_binance_exec_config(
98 py: Python<'_>,
99 config: Py<PyAny>,
100) -> PyResult<Box<dyn ClientConfig>> {
101 match config.extract::<BinanceExecutionClientConfig>(py) {
102 Ok(c) => Ok(Box::new(c)),
103 Err(e) => Err(to_pyvalue_err(format!(
104 "Failed to extract BinanceExecutionClientConfig: {e}"
105 ))),
106 }
107}
108
109#[pyfunction]
117#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.adapters.binance")]
118#[pyo3(name = "decode_binance_spot_client_order_id")]
119fn py_decode_binance_spot_client_order_id(encoded: &str) -> String {
120 decode_broker_id(encoded, BINANCE_NAUTILUS_SPOT_BROKER_ID)
121}
122
123#[pyfunction]
131#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.adapters.binance")]
132#[pyo3(name = "decode_binance_futures_client_order_id")]
133fn py_decode_binance_futures_client_order_id(encoded: &str) -> String {
134 decode_broker_id(encoded, BINANCE_NAUTILUS_FUTURES_BROKER_ID)
135}
136
137#[pymodule]
145pub fn binance(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
146 m.add(stringify!(BINANCE), BINANCE)?;
147 m.add(stringify!(BINANCE_CLIENT_ID), *BINANCE_CLIENT_ID)?;
148 m.add(stringify!(BINANCE_VENUE), *BINANCE_VENUE)?;
149 m.add_class::<BinanceProductType>()?;
150 m.add_class::<BinanceEnvironment>()?;
151 m.add_class::<BinanceMarginType>()?;
152 m.add_class::<BinancePositionSide>()?;
153 m.add_class::<BinanceBar>()?;
154 m.add_class::<BinanceFuturesLiquidation>()?;
155 m.add_class::<BinanceFuturesTicker>()?;
156 m.add_class::<BinanceSpotTicker>()?;
157 m.add_class::<BinanceFuturesMarkPriceUpdate>()?;
158 m.add_class::<BinanceFuturesOpenInterest>()?;
159 m.add_class::<BinanceFuturesOpenInterestHistPoint>()?;
160 m.add_class::<BinanceFuturesOpenInterestHist>()?;
161
162 #[cfg(feature = "arrow")]
163 {
164 m.add_function(wrap_pyfunction!(arrow::get_binance_arrow_schema_map, m)?)?;
165 m.add_function(wrap_pyfunction!(
166 arrow::py_binance_bar_to_arrow_record_batch_bytes,
167 m
168 )?)?;
169 m.add_function(wrap_pyfunction!(
170 arrow::py_binance_bar_from_arrow_record_batch_bytes,
171 m
172 )?)?;
173 }
174
175 m.add_class::<BinanceDataClientConfig>()?;
176 m.add_class::<BinanceDataClientFactory>()?;
177 m.add_class::<BinanceExecutionClientConfig>()?;
178 m.add_class::<BinanceExecutionClientFactory>()?;
179 m.add_class::<BinanceInstrumentProviderConfig>()?;
180 m.add_class::<BinanceSpotMarketDataMode>()?;
181 m.add_function(wrap_pyfunction!(py_decode_binance_spot_client_order_id, m)?)?;
182 m.add_function(wrap_pyfunction!(
183 py_decode_binance_futures_client_order_id,
184 m
185 )?)?;
186 m.add_function(wrap_pyfunction!(
187 instruments::py_load_binance_instruments,
188 m
189 )?)?;
190 m.add_function(wrap_pyfunction!(
191 data::py_load_binance_order_book_deltas,
192 m
193 )?)?;
194
195 register_binance_custom_data();
196 let _result = ensure_rust_extractor_registered::<BinanceBar>();
197 let _result = ensure_rust_extractor_registered::<BinanceFuturesLiquidation>();
198 let _result = ensure_rust_extractor_registered::<BinanceFuturesTicker>();
199 let _result = ensure_rust_extractor_registered::<BinanceSpotTicker>();
200 let _result = ensure_rust_extractor_registered::<BinanceFuturesMarkPriceUpdate>();
201 let _result = ensure_rust_extractor_registered::<BinanceFuturesOpenInterest>();
202 let _result = ensure_rust_extractor_registered::<BinanceFuturesOpenInterestHist>();
203
204 let registry = get_global_pyo3_registry();
205
206 if let Err(e) =
207 registry.register_factory_extractor(BINANCE.to_string(), extract_binance_data_factory)
208 {
209 return Err(to_pyruntime_err(format!(
210 "Failed to register Binance data factory extractor: {e}"
211 )));
212 }
213
214 if let Err(e) =
215 registry.register_exec_factory_extractor(BINANCE.to_string(), extract_binance_exec_factory)
216 {
217 return Err(to_pyruntime_err(format!(
218 "Failed to register Binance exec factory extractor: {e}"
219 )));
220 }
221
222 if let Err(e) = registry.register_config_extractor(
223 "BinanceDataClientConfig".to_string(),
224 extract_binance_data_config,
225 ) {
226 return Err(to_pyruntime_err(format!(
227 "Failed to register Binance data config extractor: {e}"
228 )));
229 }
230
231 if let Err(e) = registry.register_config_extractor(
232 "BinanceExecutionClientConfig".to_string(),
233 extract_binance_exec_config,
234 ) {
235 return Err(to_pyruntime_err(format!(
236 "Failed to register Binance exec config extractor: {e}"
237 )));
238 }
239
240 Ok(())
241}