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