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