1use std::fmt::Display;
19
20use nautilus_model::enums::BookAction;
21use serde::{Deserialize, Serialize};
22use strum::{AsRefStr, Display, EnumIter, EnumString};
23
24#[derive(
29 Clone,
30 Copy,
31 Debug,
32 Default,
33 PartialEq,
34 Eq,
35 Hash,
36 AsRefStr,
37 EnumIter,
38 EnumString,
39 Serialize,
40 Deserialize,
41)]
42#[serde(rename_all = "snake_case")]
43#[cfg_attr(
44 feature = "python",
45 pyo3::pyclass(
46 eq,
47 eq_int,
48 module = "nautilus_trader.core.nautilus_pyo3.deribit",
49 from_py_object,
50 rename_all = "SCREAMING_SNAKE_CASE",
51 )
52)]
53pub enum DeribitUpdateInterval {
54 #[strum(serialize = "raw", serialize = "Raw")]
57 Raw,
58 #[default]
60 #[strum(serialize = "100ms", serialize = "Ms100")]
61 Ms100,
62 #[strum(serialize = "agg2", serialize = "Agg2")]
64 Agg2,
65}
66
67impl DeribitUpdateInterval {
68 #[must_use]
70 pub const fn as_str(&self) -> &'static str {
71 match self {
72 Self::Raw => "raw",
73 Self::Ms100 => "100ms",
74 Self::Agg2 => "agg2",
75 }
76 }
77
78 #[must_use]
80 pub const fn requires_auth(&self) -> bool {
81 matches!(self, Self::Raw)
82 }
83}
84
85impl Display for DeribitUpdateInterval {
86 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87 write!(f, "{}", self.as_str())
88 }
89}
90
91#[derive(
95 Clone,
96 Copy,
97 Debug,
98 Display,
99 PartialEq,
100 Eq,
101 Hash,
102 AsRefStr,
103 EnumIter,
104 EnumString,
105 Serialize,
106 Deserialize,
107)]
108#[cfg_attr(
109 feature = "python",
110 pyo3::pyclass(
111 eq,
112 eq_int,
113 module = "nautilus_trader.core.nautilus_pyo3.deribit",
114 from_py_object
115 )
116)]
117pub enum DeribitWsChannel {
118 Trades,
121 Book,
123 Ticker,
125 Quote,
127 PriceIndex,
129 PriceRanking,
131 VolatilityIndex,
133 EstimatedExpirationPrice,
135 Perpetual,
137 MarkPriceOptions,
139 PlatformState,
141 Announcements,
143 ChartTrades,
145 InstrumentState,
148
149 UserOrders,
152 UserTrades,
154 UserPortfolio,
156 UserChanges,
158 UserAccessLog,
160}
161
162impl DeribitWsChannel {
163 #[must_use]
180 pub fn format_channel(
181 &self,
182 instrument_or_currency: &str,
183 interval: Option<DeribitUpdateInterval>,
184 ) -> String {
185 let interval_str = interval.unwrap_or_default().as_str();
186 match self {
187 Self::Trades => format!("trades.{instrument_or_currency}.{interval_str}"),
188 Self::Book => format!("book.{instrument_or_currency}.{interval_str}"),
189 Self::Ticker => format!("ticker.{instrument_or_currency}.{interval_str}"),
190 Self::Quote => format!("quote.{instrument_or_currency}"),
191 Self::PriceIndex => format!("deribit_price_index.{instrument_or_currency}"),
192 Self::PriceRanking => format!("deribit_price_ranking.{instrument_or_currency}"),
193 Self::VolatilityIndex => format!("deribit_volatility_index.{instrument_or_currency}"),
194 Self::EstimatedExpirationPrice => {
195 format!("estimated_expiration_price.{instrument_or_currency}")
196 }
197 Self::Perpetual => format!("perpetual.{instrument_or_currency}.{interval_str}"),
198 Self::MarkPriceOptions => format!("markprice.options.{instrument_or_currency}"),
199 Self::PlatformState => "platform_state".to_string(),
200 Self::Announcements => "announcements".to_string(),
201 Self::ChartTrades => format!("chart.trades.{instrument_or_currency}.{interval_str}"),
202 Self::UserOrders => format!("user.orders.{instrument_or_currency}.{interval_str}"),
203 Self::UserTrades => format!("user.trades.{instrument_or_currency}.{interval_str}"),
204 Self::UserPortfolio => format!("user.portfolio.{instrument_or_currency}"),
205 Self::UserChanges => format!("user.changes.{instrument_or_currency}.{interval_str}"),
206 Self::UserAccessLog => "user.access_log".to_string(),
207 Self::InstrumentState => {
208 panic!(
210 "InstrumentState channel requires kind and currency parameters, use format_instrument_state_channel() instead"
211 )
212 }
213 }
214 }
215
216 #[must_use]
225 pub fn format_instrument_state_channel(kind: &str, currency: &str) -> String {
226 format!("instrument.state.{kind}.{currency}")
227 }
228
229 #[must_use]
233 pub fn from_channel_string(channel: &str) -> Option<Self> {
234 if channel.starts_with("trades.") {
235 Some(Self::Trades)
236 } else if channel.starts_with("book.") {
237 Some(Self::Book)
238 } else if channel.starts_with("ticker.") {
239 Some(Self::Ticker)
240 } else if channel.starts_with("quote.") {
241 Some(Self::Quote)
242 } else if channel.starts_with("deribit_price_index.") {
243 Some(Self::PriceIndex)
244 } else if channel.starts_with("deribit_price_ranking.") {
245 Some(Self::PriceRanking)
246 } else if channel.starts_with("deribit_volatility_index.") {
247 Some(Self::VolatilityIndex)
248 } else if channel.starts_with("estimated_expiration_price.") {
249 Some(Self::EstimatedExpirationPrice)
250 } else if channel.starts_with("perpetual.") {
251 Some(Self::Perpetual)
252 } else if channel.starts_with("markprice.options.") {
253 Some(Self::MarkPriceOptions)
254 } else if channel == "platform_state" {
255 Some(Self::PlatformState)
256 } else if channel == "announcements" {
257 Some(Self::Announcements)
258 } else if channel.starts_with("chart.trades.") {
259 Some(Self::ChartTrades)
260 } else if channel.starts_with("user.orders.") {
261 Some(Self::UserOrders)
262 } else if channel.starts_with("user.trades.") {
263 Some(Self::UserTrades)
264 } else if channel.starts_with("user.portfolio.") {
265 Some(Self::UserPortfolio)
266 } else if channel.starts_with("user.changes.") {
267 Some(Self::UserChanges)
268 } else if channel == "user.access_log" {
269 Some(Self::UserAccessLog)
270 } else if channel.starts_with("instrument.state.") {
271 Some(Self::InstrumentState)
272 } else {
273 None
274 }
275 }
276
277 #[must_use]
279 pub const fn is_private(&self) -> bool {
280 matches!(
281 self,
282 Self::UserOrders
283 | Self::UserTrades
284 | Self::UserPortfolio
285 | Self::UserChanges
286 | Self::UserAccessLog
287 )
288 }
289}
290
291#[derive(
293 Clone,
294 Debug,
295 Display,
296 PartialEq,
297 Eq,
298 Hash,
299 AsRefStr,
300 EnumIter,
301 EnumString,
302 Serialize,
303 Deserialize,
304)]
305pub enum DeribitWsMethod {
306 #[serde(rename = "public/subscribe")]
309 #[strum(serialize = "public/subscribe")]
310 PublicSubscribe,
311 #[serde(rename = "public/unsubscribe")]
313 #[strum(serialize = "public/unsubscribe")]
314 PublicUnsubscribe,
315 #[serde(rename = "public/auth")]
317 #[strum(serialize = "public/auth")]
318 PublicAuth,
319 #[serde(rename = "public/set_heartbeat")]
321 #[strum(serialize = "public/set_heartbeat")]
322 SetHeartbeat,
323 #[serde(rename = "public/disable_heartbeat")]
325 #[strum(serialize = "public/disable_heartbeat")]
326 DisableHeartbeat,
327 #[serde(rename = "public/test")]
329 #[strum(serialize = "public/test")]
330 Test,
331 #[serde(rename = "public/hello")]
333 #[strum(serialize = "public/hello")]
334 Hello,
335 #[serde(rename = "public/get_time")]
337 #[strum(serialize = "public/get_time")]
338 GetTime,
339
340 #[serde(rename = "private/subscribe")]
343 #[strum(serialize = "private/subscribe")]
344 PrivateSubscribe,
345 #[serde(rename = "private/unsubscribe")]
347 #[strum(serialize = "private/unsubscribe")]
348 PrivateUnsubscribe,
349 #[serde(rename = "private/logout")]
351 #[strum(serialize = "private/logout")]
352 Logout,
353}
354
355impl DeribitWsMethod {
356 #[must_use]
358 pub fn as_method_str(&self) -> &'static str {
359 match self {
360 Self::PublicSubscribe => "public/subscribe",
361 Self::PublicUnsubscribe => "public/unsubscribe",
362 Self::PublicAuth => "public/auth",
363 Self::SetHeartbeat => "public/set_heartbeat",
364 Self::DisableHeartbeat => "public/disable_heartbeat",
365 Self::Test => "public/test",
366 Self::Hello => "public/hello",
367 Self::GetTime => "public/get_time",
368 Self::PrivateSubscribe => "private/subscribe",
369 Self::PrivateUnsubscribe => "private/unsubscribe",
370 Self::Logout => "private/logout",
371 }
372 }
373}
374
375#[derive(
377 Clone, Debug, Display, PartialEq, Eq, Hash, AsRefStr, EnumString, Serialize, Deserialize,
378)]
379#[serde(rename_all = "snake_case")]
380#[strum(serialize_all = "snake_case")]
381pub enum DeribitBookAction {
382 #[serde(rename = "new")]
384 New,
385 #[serde(rename = "change")]
387 Change,
388 #[serde(rename = "delete")]
390 Delete,
391}
392
393impl From<DeribitBookAction> for BookAction {
394 fn from(action: DeribitBookAction) -> Self {
395 match action {
396 DeribitBookAction::New => Self::Add,
397 DeribitBookAction::Change => Self::Update,
398 DeribitBookAction::Delete => Self::Delete,
399 }
400 }
401}
402
403#[derive(
405 Clone, Debug, Display, PartialEq, Eq, Hash, AsRefStr, EnumString, Serialize, Deserialize,
406)]
407#[serde(rename_all = "snake_case")]
408pub enum DeribitBookMsgType {
409 #[serde(rename = "snapshot")]
411 Snapshot,
412 #[serde(rename = "change")]
414 Change,
415}
416
417#[derive(
419 Clone, Debug, Display, PartialEq, Eq, Hash, AsRefStr, EnumString, Serialize, Deserialize,
420)]
421#[serde(rename_all = "snake_case")]
422pub enum DeribitHeartbeatType {
423 #[serde(rename = "heartbeat")]
425 Heartbeat,
426 #[serde(rename = "test_request")]
428 TestRequest,
429}