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    ) -> anyhow::Result<Box<dyn ExecutionClient>> {
143        let mut bitmex_config = config
144            .as_any()
145            .downcast_ref::<BitmexExecutionClientConfig>()
146            .ok_or_else(|| {
147                anyhow::anyhow!(
148                    "Invalid config type for BitmexExecutionClientFactory. Expected BitmexExecutionClientConfig, was {config:?}",
149                )
150            })?
151            .clone();
152
153        let account_id = bitmex_config
154            .account_id
155            .unwrap_or_else(|| AccountId::from("BITMEX-001"));
156        bitmex_config.account_id = Some(account_id);
157
158        let core = ExecutionClientCore::new(
159            trader_id,
160            ClientId::from(name),
161            *BITMEX_VENUE,
162            OmsType::Netting,
163            account_id,
164            AccountType::Margin,
165            None, // base_currency
166            cache,
167        );
168
169        let client = BitmexExecutionClient::new(core, bitmex_config)?;
170        Ok(Box::new(client))
171    }
172
173    fn name(&self) -> &'static str {
174        BITMEX
175    }
176
177    fn config_type(&self) -> &'static str {
178        "BitmexExecutionClientConfig"
179    }
180}