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 ) -> anyhow::Result<Box<dyn ExecutionClient>> {
143 let deribit_config = config
144 .as_any()
145 .downcast_ref::<DeribitExecutionClientConfig>()
146 .ok_or_else(|| {
147 anyhow::anyhow!(
148 "Invalid config type for DeribitExecutionClientFactory. Expected DeribitExecutionClientConfig, was {config:?}",
149 )
150 })?
151 .clone();
152
153 let oms_type = OmsType::Netting;
155 let account_type = AccountType::Margin;
156
157 let client_id = ClientId::from(name);
158 let core = ExecutionClientCore::new(
159 trader_id,
160 client_id,
161 *DERIBIT_VENUE,
162 oms_type,
163 deribit_config.account_id,
164 account_type,
165 None, cache,
167 );
168
169 let client = DeribitExecutionClient::new(core, deribit_config)?;
170 Ok(Box::new(client))
171 }
172
173 fn name(&self) -> &'static str {
174 DERIBIT
175 }
176
177 fn config_type(&self) -> &'static str {
178 "DeribitExecutionClientConfig"
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use std::{cell::RefCell, rc::Rc};
185
186 use nautilus_common::{
187 cache::Cache,
188 clock::TestClock,
189 factories::{ClientConfig, DataClientFactory},
190 live::runner::set_data_event_sender,
191 messages::DataEvent,
192 };
193 use rstest::rstest;
194
195 use super::*;
196 use crate::http::models::DeribitProductType;
197
198 fn setup_test_env() {
199 let (sender, _receiver) = tokio::sync::mpsc::unbounded_channel::<DataEvent>();
201 set_data_event_sender(sender);
202 }
203
204 #[rstest]
205 fn test_deribit_data_client_factory_creation() {
206 let factory = DeribitDataClientFactory::new();
207 assert_eq!(factory.name(), DERIBIT);
208 assert_eq!(factory.config_type(), "DeribitDataClientConfig");
209 }
210
211 #[rstest]
212 fn test_deribit_data_client_factory_default() {
213 let factory = DeribitDataClientFactory::new();
214 assert_eq!(factory.name(), DERIBIT);
215 }
216
217 #[rstest]
218 fn test_deribit_data_client_config_implements_client_config() {
219 let config = DeribitDataClientConfig {
220 product_types: vec![DeribitProductType::Future],
221 ..Default::default()
222 };
223
224 let boxed_config: Box<dyn ClientConfig> = Box::new(config);
225 let downcasted = boxed_config
226 .as_any()
227 .downcast_ref::<DeribitDataClientConfig>();
228
229 assert!(downcasted.is_some());
230 }
231
232 #[rstest]
233 fn test_deribit_data_client_factory_creates_client() {
234 setup_test_env();
235
236 let factory = DeribitDataClientFactory::new();
237 let config = DeribitDataClientConfig {
238 product_types: vec![DeribitProductType::Future],
239 environment: crate::common::enums::DeribitEnvironment::Testnet,
240 ..Default::default()
241 };
242
243 let cache = Rc::new(RefCell::new(Cache::default()));
244 let clock = Rc::new(RefCell::new(TestClock::new()));
245
246 let result = factory.create("DERIBIT-TEST", &config, cache.into(), clock);
247 assert!(result.is_ok());
248
249 let client = result.unwrap();
250 assert_eq!(client.client_id(), ClientId::from("DERIBIT-TEST"));
251 }
252}