nautilus_deribit/
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 Deribit clients and components.
17
18use std::{any::Any, cell::RefCell, rc::Rc};
19
20use nautilus_common::{cache::Cache, clock::Clock};
21use nautilus_data::client::DataClient;
22use nautilus_execution::client::{ExecutionClient, base::ExecutionClientCore};
23use nautilus_model::{
24    enums::{AccountType, OmsType},
25    identifiers::ClientId,
26};
27use nautilus_system::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
28
29use crate::{
30    common::consts::DERIBIT_VENUE,
31    config::{DeribitDataClientConfig, DeribitExecClientConfig},
32    data::DeribitDataClient,
33    execution::DeribitExecutionClient,
34};
35
36impl ClientConfig for DeribitDataClientConfig {
37    fn as_any(&self) -> &dyn Any {
38        self
39    }
40}
41
42/// Factory for creating Deribit data clients.
43#[derive(Debug)]
44pub struct DeribitDataClientFactory;
45
46impl DeribitDataClientFactory {
47    /// Creates a new [`DeribitDataClientFactory`] instance.
48    #[must_use]
49    pub const fn new() -> Self {
50        Self
51    }
52}
53
54impl Default for DeribitDataClientFactory {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60impl DataClientFactory for DeribitDataClientFactory {
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 deribit_config = config
69            .as_any()
70            .downcast_ref::<DeribitDataClientConfig>()
71            .ok_or_else(|| {
72                anyhow::anyhow!(
73                    "Invalid config type for DeribitDataClientFactory. Expected DeribitDataClientConfig, was {config:?}",
74                )
75            })?
76            .clone();
77
78        let client_id = ClientId::from(name);
79        let client = DeribitDataClient::new(client_id, deribit_config)?;
80        Ok(Box::new(client))
81    }
82
83    fn name(&self) -> &'static str {
84        "DERIBIT"
85    }
86
87    fn config_type(&self) -> &'static str {
88        "DeribitDataClientConfig"
89    }
90}
91
92// ------------------------------------------------------------------------------------------------
93
94impl ClientConfig for DeribitExecClientConfig {
95    fn as_any(&self) -> &dyn Any {
96        self
97    }
98}
99
100/// Factory for creating Deribit execution clients.
101#[derive(Debug)]
102pub struct DeribitExecutionClientFactory;
103
104impl DeribitExecutionClientFactory {
105    /// Creates a new [`DeribitExecutionClientFactory`] instance.
106    #[must_use]
107    pub const fn new() -> Self {
108        Self
109    }
110}
111
112impl Default for DeribitExecutionClientFactory {
113    fn default() -> Self {
114        Self::new()
115    }
116}
117
118impl ExecutionClientFactory for DeribitExecutionClientFactory {
119    fn create(
120        &self,
121        name: &str,
122        config: &dyn ClientConfig,
123        cache: Rc<RefCell<Cache>>,
124        clock: Rc<RefCell<dyn Clock>>,
125    ) -> anyhow::Result<Box<dyn ExecutionClient>> {
126        let deribit_config = config
127            .as_any()
128            .downcast_ref::<DeribitExecClientConfig>()
129            .ok_or_else(|| {
130                anyhow::anyhow!(
131                    "Invalid config type for DeribitExecutionClientFactory. Expected DeribitExecClientConfig, was {config:?}",
132                )
133            })?
134            .clone();
135
136        // Deribit uses netting (derivatives only, no hedging)
137        let oms_type = OmsType::Netting;
138        let account_type = AccountType::Margin;
139
140        let client_id = ClientId::from(name);
141        let core = ExecutionClientCore::new(
142            deribit_config.trader_id,
143            client_id,
144            *DERIBIT_VENUE,
145            oms_type,
146            deribit_config.account_id,
147            account_type,
148            None, // base_currency
149            clock,
150            cache,
151        );
152
153        let client = DeribitExecutionClient::new(core, deribit_config)?;
154        Ok(Box::new(client))
155    }
156
157    fn name(&self) -> &'static str {
158        "DERIBIT"
159    }
160
161    fn config_type(&self) -> &'static str {
162        "DeribitExecClientConfig"
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use std::{cell::RefCell, rc::Rc};
169
170    use nautilus_common::{
171        cache::Cache, clock::TestClock, live::runner::set_data_event_sender, messages::DataEvent,
172    };
173    use nautilus_system::factories::{ClientConfig, DataClientFactory};
174    use rstest::rstest;
175
176    use super::*;
177    use crate::http::models::DeribitInstrumentKind;
178
179    fn setup_test_env() {
180        // Initialize data event sender for tests
181        let (sender, _receiver) = tokio::sync::mpsc::unbounded_channel::<DataEvent>();
182        set_data_event_sender(sender);
183    }
184
185    #[rstest]
186    fn test_deribit_data_client_factory_creation() {
187        let factory = DeribitDataClientFactory::new();
188        assert_eq!(factory.name(), "DERIBIT");
189        assert_eq!(factory.config_type(), "DeribitDataClientConfig");
190    }
191
192    #[rstest]
193    fn test_deribit_data_client_factory_default() {
194        let factory = DeribitDataClientFactory::new();
195        assert_eq!(factory.name(), "DERIBIT");
196    }
197
198    #[rstest]
199    fn test_deribit_data_client_config_implements_client_config() {
200        let config = DeribitDataClientConfig {
201            instrument_kinds: vec![DeribitInstrumentKind::Future],
202            ..Default::default()
203        };
204
205        let boxed_config: Box<dyn ClientConfig> = Box::new(config);
206        let downcasted = boxed_config
207            .as_any()
208            .downcast_ref::<DeribitDataClientConfig>();
209
210        assert!(downcasted.is_some());
211    }
212
213    #[rstest]
214    fn test_deribit_data_client_factory_creates_client() {
215        setup_test_env();
216
217        let factory = DeribitDataClientFactory::new();
218        let config = DeribitDataClientConfig {
219            instrument_kinds: vec![DeribitInstrumentKind::Future],
220            use_testnet: true,
221            ..Default::default()
222        };
223
224        let cache = Rc::new(RefCell::new(Cache::default()));
225        let clock = Rc::new(RefCell::new(TestClock::new()));
226
227        let result = factory.create("DERIBIT-TEST", &config, cache, clock);
228        assert!(result.is_ok());
229
230        let client = result.unwrap();
231        assert_eq!(client.client_id(), ClientId::from("DERIBIT-TEST"));
232    }
233}