nautilus_deribit/
factories.rs1use 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::{ClientId, TraderId},
30};
31
32use crate::{
33 common::consts::{DERIBIT, DERIBIT_VENUE},
34 config::{DeribitDataClientConfig, DeribitExecutionClientConfig},
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#[derive(Debug, Clone)]
47#[cfg_attr(
48 feature = "python",
49 pyo3::pyclass(module = "nautilus_trader.adapters.deribit", from_py_object)
50)]
51#[cfg_attr(
52 feature = "python",
53 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.deribit")
54)]
55pub struct DeribitDataClientFactory;
56
57impl DeribitDataClientFactory {
58 #[must_use]
60 pub const fn new() -> Self {
61 Self
62 }
63}
64
65impl Default for DeribitDataClientFactory {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl DataClientFactory for DeribitDataClientFactory {
72 fn create(
73 &self,
74 name: &str,
75 config: &dyn ClientConfig,
76 _cache: CacheView,
77 _clock: Rc<RefCell<dyn Clock>>,
78 ) -> anyhow::Result<Box<dyn DataClient>> {
79 let deribit_config = config
80 .as_any()
81 .downcast_ref::<DeribitDataClientConfig>()
82 .ok_or_else(|| {
83 anyhow::anyhow!(
84 "Invalid config type for DeribitDataClientFactory. Expected DeribitDataClientConfig, was {config:?}",
85 )
86 })?
87 .clone();
88
89 let client_id = ClientId::from(name);
90 let client = DeribitDataClient::new(client_id, deribit_config)?;
91 Ok(Box::new(client))
92 }
93
94 fn name(&self) -> &'static str {
95 DERIBIT
96 }
97
98 fn config_type(&self) -> &'static str {
99 "DeribitDataClientConfig"
100 }
101}
102
103impl ClientConfig for DeribitExecutionClientConfig {
104 fn as_any(&self) -> &dyn Any {
105 self
106 }
107}
108
109#[derive(Debug, Clone)]
111#[cfg_attr(
112 feature = "python",
113 pyo3::pyclass(module = "nautilus_trader.adapters.deribit", from_py_object)
114)]
115#[cfg_attr(
116 feature = "python",
117 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.deribit")
118)]
119pub struct DeribitExecutionClientFactory;
120
121impl DeribitExecutionClientFactory {
122 #[must_use]
124 pub const fn new() -> Self {
125 Self
126 }
127}
128
129impl Default for DeribitExecutionClientFactory {
130 fn default() -> Self {
131 Self::new()
132 }
133}
134
135impl ExecutionClientFactory for DeribitExecutionClientFactory {
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 deribit_config = config
145 .as_any()
146 .downcast_ref::<DeribitExecutionClientConfig>()
147 .ok_or_else(|| {
148 anyhow::anyhow!(
149 "Invalid config type for DeribitExecutionClientFactory. Expected DeribitExecutionClientConfig, was {config:?}",
150 )
151 })?
152 .clone();
153
154 let oms_type = OmsType::Netting;
156 let account_type = AccountType::Margin;
157
158 let client_id = ClientId::from(name);
159 let core = ExecutionClientCore::new(
160 trader_id,
161 client_id,
162 *DERIBIT_VENUE,
163 oms_type,
164 deribit_config.account_id,
165 account_type,
166 None, cache,
168 );
169
170 let client = DeribitExecutionClient::new(core, deribit_config)?;
171 Ok(Box::new(client))
172 }
173
174 fn name(&self) -> &'static str {
175 DERIBIT
176 }
177
178 fn config_type(&self) -> &'static str {
179 "DeribitExecutionClientConfig"
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use std::{cell::RefCell, rc::Rc};
186
187 use nautilus_common::{
188 cache::Cache,
189 clock::VirtualClock,
190 factories::{ClientConfig, DataClientFactory},
191 live::runner::set_data_event_sender,
192 messages::DataEvent,
193 };
194 use rstest::rstest;
195
196 use super::*;
197 use crate::http::models::DeribitProductType;
198
199 fn setup_test_env() {
200 let (sender, _receiver) = tokio::sync::mpsc::unbounded_channel::<DataEvent>();
202 set_data_event_sender(sender);
203 }
204
205 #[rstest]
206 fn test_deribit_data_client_factory_creation() {
207 let factory = DeribitDataClientFactory::new();
208 assert_eq!(factory.name(), DERIBIT);
209 assert_eq!(factory.config_type(), "DeribitDataClientConfig");
210 }
211
212 #[rstest]
213 fn test_deribit_data_client_factory_default() {
214 let factory = DeribitDataClientFactory::new();
215 assert_eq!(factory.name(), DERIBIT);
216 }
217
218 #[rstest]
219 fn test_deribit_data_client_config_implements_client_config() {
220 let config = DeribitDataClientConfig {
221 product_types: vec![DeribitProductType::Future],
222 ..Default::default()
223 };
224
225 let boxed_config: Box<dyn ClientConfig> = Box::new(config);
226 let downcasted = boxed_config
227 .as_any()
228 .downcast_ref::<DeribitDataClientConfig>();
229
230 assert!(downcasted.is_some());
231 }
232
233 #[rstest]
234 fn test_deribit_data_client_factory_creates_client() {
235 setup_test_env();
236
237 let factory = DeribitDataClientFactory::new();
238 let config = DeribitDataClientConfig {
239 product_types: vec![DeribitProductType::Future],
240 environment: crate::common::enums::DeribitEnvironment::Testnet,
241 ..Default::default()
242 };
243
244 let cache = Rc::new(RefCell::new(Cache::default()));
245 let clock = Rc::new(RefCell::new(VirtualClock::new()));
246
247 let result = factory.create("DERIBIT-TEST", &config, cache.into(), clock);
248 assert!(result.is_ok());
249
250 let client = result.unwrap();
251 assert_eq!(client.client_id(), ClientId::from("DERIBIT-TEST"));
252 }
253}