Skip to main content

nautilus_bitmex/
factories.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Factory functions for creating BitMEX clients and components.
17
18use std::{any::Any, cell::RefCell, rc::Rc};
19
20use nautilus_common::{
21    cache::CacheView,
22    clients::{DataClient, ExecutionClient},
23    clock::Clock,
24    factories::{ClientConfig, DataClientFactory, ExecutionClientFactory},
25};
26use nautilus_live::ExecutionClientCore;
27use nautilus_model::{
28    enums::{AccountType, OmsType},
29    identifiers::{AccountId, ClientId, TraderId},
30};
31
32use crate::{
33    common::consts::{BITMEX, BITMEX_VENUE},
34    config::{BitmexDataClientConfig, BitmexExecutionClientConfig},
35    data::BitmexDataClient,
36    execution::BitmexExecutionClient,
37};
38
39impl ClientConfig for BitmexDataClientConfig {
40    fn as_any(&self) -> &dyn Any {
41        self
42    }
43}
44
45impl ClientConfig for BitmexExecutionClientConfig {
46    fn as_any(&self) -> &dyn Any {
47        self
48    }
49}
50
51/// Factory for creating BitMEX data clients.
52#[derive(Debug, Clone)]
53#[cfg_attr(
54    feature = "python",
55    pyo3::pyclass(module = "nautilus_trader.adapters.bitmex", from_py_object)
56)]
57#[cfg_attr(
58    feature = "python",
59    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.bitmex")
60)]
61pub struct BitmexDataClientFactory;
62
63impl BitmexDataClientFactory {
64    /// Creates a new [`BitmexDataClientFactory`] instance.
65    #[must_use]
66    pub const fn new() -> Self {
67        Self
68    }
69}
70
71impl Default for BitmexDataClientFactory {
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77impl DataClientFactory for BitmexDataClientFactory {
78    fn create(
79        &self,
80        name: &str,
81        config: &dyn ClientConfig,
82        _cache: CacheView,
83        _clock: Rc<RefCell<dyn Clock>>,
84    ) -> anyhow::Result<Box<dyn DataClient>> {
85        let bitmex_config = config
86            .as_any()
87            .downcast_ref::<BitmexDataClientConfig>()
88            .ok_or_else(|| {
89                anyhow::anyhow!(
90                    "Invalid config type for BitmexDataClientFactory. Expected BitmexDataClientConfig, was {config:?}",
91                )
92            })?
93            .clone();
94
95        let client_id = ClientId::from(name);
96        let client = BitmexDataClient::new(client_id, bitmex_config)?;
97        Ok(Box::new(client))
98    }
99
100    fn name(&self) -> &'static str {
101        BITMEX
102    }
103
104    fn config_type(&self) -> &'static str {
105        "BitmexDataClientConfig"
106    }
107}
108
109/// Factory for creating BitMEX execution clients.
110#[derive(Debug, Clone)]
111#[cfg_attr(
112    feature = "python",
113    pyo3::pyclass(module = "nautilus_trader.adapters.bitmex", from_py_object)
114)]
115#[cfg_attr(
116    feature = "python",
117    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.bitmex")
118)]
119pub struct BitmexExecutionClientFactory;
120
121impl BitmexExecutionClientFactory {
122    /// Creates a new [`BitmexExecutionClientFactory`] instance.
123    #[must_use]
124    pub const fn new() -> Self {
125        Self
126    }
127}
128
129impl Default for BitmexExecutionClientFactory {
130    fn default() -> Self {
131        Self::new()
132    }
133}
134
135impl ExecutionClientFactory for BitmexExecutionClientFactory {
136    fn create(
137        &self,
138        trader_id: TraderId,
139        name: &str,
140        config: &dyn ClientConfig,
141        cache: CacheView,
142        _clock: Rc<RefCell<dyn Clock>>,
143    ) -> anyhow::Result<Box<dyn ExecutionClient>> {
144        let mut bitmex_config = config
145            .as_any()
146            .downcast_ref::<BitmexExecutionClientConfig>()
147            .ok_or_else(|| {
148                anyhow::anyhow!(
149                    "Invalid config type for BitmexExecutionClientFactory. Expected BitmexExecutionClientConfig, was {config:?}",
150                )
151            })?
152            .clone();
153
154        let account_id = bitmex_config
155            .account_id
156            .unwrap_or_else(|| AccountId::from("BITMEX-001"));
157        bitmex_config.account_id = Some(account_id);
158
159        let core = ExecutionClientCore::new(
160            trader_id,
161            ClientId::from(name),
162            *BITMEX_VENUE,
163            OmsType::Netting,
164            account_id,
165            AccountType::Margin,
166            None, // base_currency
167            cache,
168        );
169
170        let client = BitmexExecutionClient::new(core, bitmex_config)?;
171        Ok(Box::new(client))
172    }
173
174    fn name(&self) -> &'static str {
175        BITMEX
176    }
177
178    fn config_type(&self) -> &'static str {
179        "BitmexExecutionClientConfig"
180    }
181}