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