nautilus_binance/
factories.rs1use std::{cell::RefCell, rc::Rc};
19
20use nautilus_common::{
21 cache::Cache,
22 clients::{DataClient, ExecutionClient},
23 clock::Clock,
24};
25use nautilus_live::ExecutionClientCore;
26use nautilus_model::{
27 enums::{AccountType, OmsType},
28 identifiers::ClientId,
29};
30use nautilus_system::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
31
32use crate::{
33 common::{
34 consts::{BINANCE, BINANCE_VENUE},
35 enums::BinanceProductType,
36 },
37 config::{BinanceDataClientConfig, BinanceExecClientConfig},
38 futures::{data::BinanceFuturesDataClient, execution::BinanceFuturesExecutionClient},
39 spot::{data::BinanceSpotDataClient, execution::BinanceSpotExecutionClient},
40};
41
42#[derive(Debug)]
44pub struct BinanceDataClientFactory;
45
46impl BinanceDataClientFactory {
47 #[must_use]
49 pub const fn new() -> Self {
50 Self
51 }
52}
53
54impl Default for BinanceDataClientFactory {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60impl DataClientFactory for BinanceDataClientFactory {
61 fn create(
62 &self,
63 name: &str,
64 config: &dyn ClientConfig,
65 _cache: Rc<RefCell<Cache>>,
66 _clock: Rc<RefCell<dyn Clock>>,
67 ) -> anyhow::Result<Box<dyn DataClient>> {
68 let binance_config = config
69 .as_any()
70 .downcast_ref::<BinanceDataClientConfig>()
71 .ok_or_else(|| {
72 anyhow::anyhow!(
73 "Invalid config type for BinanceDataClientFactory. Expected BinanceDataClientConfig, was {config:?}",
74 )
75 })?
76 .clone();
77
78 let client_id = ClientId::from(name);
79
80 let product_type = binance_config
81 .product_types
82 .first()
83 .copied()
84 .unwrap_or(BinanceProductType::Spot);
85
86 match product_type {
87 BinanceProductType::Spot => {
88 let client = BinanceSpotDataClient::new(client_id, binance_config)?;
89 Ok(Box::new(client))
90 }
91 BinanceProductType::UsdM | BinanceProductType::CoinM => {
92 let client =
93 BinanceFuturesDataClient::new(client_id, binance_config, product_type)?;
94 Ok(Box::new(client))
95 }
96 _ => {
97 anyhow::bail!("Unsupported product type for Binance data client: {product_type:?}")
98 }
99 }
100 }
101
102 fn name(&self) -> &'static str {
103 BINANCE
104 }
105
106 fn config_type(&self) -> &'static str {
107 stringify!(BinanceDataClientConfig)
108 }
109}
110
111#[derive(Debug)]
113pub struct BinanceExecutionClientFactory;
114
115impl BinanceExecutionClientFactory {
116 #[must_use]
118 pub const fn new() -> Self {
119 Self
120 }
121}
122
123impl Default for BinanceExecutionClientFactory {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl ExecutionClientFactory for BinanceExecutionClientFactory {
130 fn create(
131 &self,
132 name: &str,
133 config: &dyn ClientConfig,
134 cache: Rc<RefCell<Cache>>,
135 ) -> anyhow::Result<Box<dyn ExecutionClient>> {
136 let binance_config = config
137 .as_any()
138 .downcast_ref::<BinanceExecClientConfig>()
139 .ok_or_else(|| {
140 anyhow::anyhow!(
141 "Invalid config type for BinanceExecutionClientFactory. Expected BinanceExecClientConfig, was {config:?}",
142 )
143 })?
144 .clone();
145
146 let product_type = binance_config
147 .product_types
148 .first()
149 .copied()
150 .unwrap_or(BinanceProductType::Spot);
151
152 match product_type {
153 BinanceProductType::Spot => {
154 let account_type = AccountType::Cash;
156 let oms_type = OmsType::Hedging;
157
158 let core = ExecutionClientCore::new(
159 binance_config.trader_id,
160 ClientId::from(name),
161 *BINANCE_VENUE,
162 oms_type,
163 binance_config.account_id,
164 account_type,
165 None, cache,
167 );
168
169 let client = BinanceSpotExecutionClient::new(core, binance_config)?;
170 Ok(Box::new(client))
171 }
172 BinanceProductType::UsdM | BinanceProductType::CoinM => {
173 let account_type = AccountType::Margin;
175 let oms_type = OmsType::Netting;
176
177 let core = ExecutionClientCore::new(
178 binance_config.trader_id,
179 ClientId::from(name),
180 *BINANCE_VENUE,
181 oms_type,
182 binance_config.account_id,
183 account_type,
184 None, cache,
186 );
187
188 let client = BinanceFuturesExecutionClient::new(core, binance_config)?;
189 Ok(Box::new(client))
190 }
191 _ => {
192 anyhow::bail!(
193 "Unsupported product type for Binance execution client: {product_type:?}"
194 )
195 }
196 }
197 }
198
199 fn name(&self) -> &'static str {
200 BINANCE
201 }
202
203 fn config_type(&self) -> &'static str {
204 stringify!(BinanceExecClientConfig)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use nautilus_system::factories::DataClientFactory;
211 use rstest::rstest;
212
213 use super::*;
214
215 #[rstest]
216 fn test_binance_data_client_factory_creation() {
217 let factory = BinanceDataClientFactory::new();
218 assert_eq!(factory.name(), "BINANCE");
219 assert_eq!(factory.config_type(), "BinanceDataClientConfig");
220 }
221
222 #[rstest]
223 fn test_binance_data_client_factory_default() {
224 let factory = BinanceDataClientFactory;
225 assert_eq!(factory.name(), "BINANCE");
226 }
227}