1use nautilus_core::serialization::{deserialize_decimal, deserialize_optional_decimal};
19use rust_decimal::Decimal;
20use serde::{Deserialize, Serialize};
21use ustr::Ustr;
22
23pub use crate::common::{
24 enums::{DeribitCurrency, DeribitOptionType, DeribitProductType},
25 rpc::{DeribitJsonRpcError, DeribitJsonRpcRequest, DeribitJsonRpcResponse},
26};
27
28#[derive(Debug, Serialize, Deserialize)]
30#[serde(untagged)]
31pub enum DeribitResponsePayload<T> {
32 Success { result: T },
34 Error { error: DeribitJsonRpcError },
36}
37
38#[derive(Clone, Debug, Serialize, Deserialize)]
40pub struct DeribitInstrument {
41 pub base_currency: Ustr,
43 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
45 pub block_trade_commission: Option<Decimal>,
46 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
48 pub block_trade_min_trade_amount: Option<Decimal>,
49 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
51 pub block_trade_tick_size: Option<Decimal>,
52 #[serde(deserialize_with = "deserialize_decimal")]
54 pub contract_size: Decimal,
55 pub counter_currency: Option<Ustr>,
57 pub creation_timestamp: i64,
59 pub expiration_timestamp: Option<i64>,
61 pub future_type: Option<String>,
63 pub instrument_id: i64,
65 pub instrument_name: Ustr,
67 pub instrument_type: Option<String>,
69 pub is_active: bool,
71 pub kind: DeribitProductType,
73 #[serde(deserialize_with = "deserialize_decimal")]
75 pub maker_commission: Decimal,
76 pub max_leverage: Option<i64>,
78 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
80 pub max_liquidation_commission: Option<Decimal>,
81 #[serde(deserialize_with = "deserialize_decimal")]
83 pub min_trade_amount: Decimal,
84 pub option_type: Option<DeribitOptionType>,
86 pub price_index: Option<String>,
88 pub quote_currency: Ustr,
90 pub settlement_currency: Option<Ustr>,
92 pub settlement_period: Option<String>,
94 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
96 pub strike: Option<Decimal>,
97 #[serde(deserialize_with = "deserialize_decimal")]
99 pub taker_commission: Decimal,
100 #[serde(deserialize_with = "deserialize_decimal")]
102 pub tick_size: Decimal,
103 pub tick_size_steps: Option<Vec<DeribitTickSizeStep>>,
105}
106
107#[derive(Clone, Debug, Serialize, Deserialize)]
109pub struct DeribitTickSizeStep {
110 #[serde(deserialize_with = "deserialize_decimal")]
112 pub above_price: Decimal,
113 #[serde(deserialize_with = "deserialize_decimal")]
115 pub tick_size: Decimal,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct DeribitAccountSummariesResponse {
124 pub summaries: Vec<DeribitAccountSummary>,
126 #[serde(default)]
128 pub id: Option<i64>,
129 #[serde(default)]
131 pub email: Option<String>,
132 #[serde(default)]
134 pub system_name: Option<String>,
135 #[serde(default)]
137 pub username: Option<String>,
138 #[serde(rename = "type", default)]
140 pub account_type: Option<String>,
141 #[serde(default)]
143 pub creation_timestamp: Option<i64>,
144 #[serde(default)]
146 pub referrer_id: Option<String>,
147 #[serde(default)]
149 pub login_enabled: Option<bool>,
150 #[serde(default)]
152 pub security_keys_enabled: Option<bool>,
153 #[serde(default)]
155 pub mmp_enabled: Option<bool>,
156 #[serde(default)]
158 pub interuser_transfers_enabled: Option<bool>,
159 #[serde(default)]
161 pub self_trading_reject_mode: Option<String>,
162 #[serde(default)]
164 pub self_trading_extended_to_subaccounts: Option<bool>,
165 #[serde(default)]
167 pub block_rfq_self_match_prevention: Option<bool>,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct DeribitAccountSummary {
175 pub currency: Ustr,
177 #[serde(deserialize_with = "deserialize_decimal")]
179 pub equity: Decimal,
180 #[serde(deserialize_with = "deserialize_decimal")]
182 pub balance: Decimal,
183 #[serde(deserialize_with = "deserialize_decimal")]
185 pub available_funds: Decimal,
186 #[serde(deserialize_with = "deserialize_decimal")]
188 pub margin_balance: Decimal,
189 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
191 pub initial_margin: Option<Decimal>,
192 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
194 pub maintenance_margin: Option<Decimal>,
195 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
197 pub total_pl: Option<Decimal>,
198 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
200 pub session_upl: Option<Decimal>,
201 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
203 pub session_rpl: Option<Decimal>,
204 #[serde(default)]
206 pub portfolio_margining_enabled: Option<bool>,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct DeribitAccountSummaryExtended {
216 pub currency: Ustr,
218 #[serde(deserialize_with = "deserialize_decimal")]
220 pub equity: Decimal,
221 #[serde(deserialize_with = "deserialize_decimal")]
223 pub balance: Decimal,
224 #[serde(deserialize_with = "deserialize_decimal")]
226 pub available_funds: Decimal,
227 #[serde(deserialize_with = "deserialize_decimal")]
229 pub margin_balance: Decimal,
230 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
232 pub initial_margin: Option<Decimal>,
233 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
235 pub maintenance_margin: Option<Decimal>,
236 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
238 pub total_pl: Option<Decimal>,
239 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
241 pub session_upl: Option<Decimal>,
242 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
244 pub session_rpl: Option<Decimal>,
245 #[serde(default)]
247 pub portfolio_margining_enabled: Option<bool>,
248 #[serde(default)]
251 pub id: Option<i64>,
252 #[serde(default)]
254 pub email: Option<String>,
255 #[serde(default)]
257 pub username: Option<String>,
258 #[serde(default)]
260 pub system_name: Option<String>,
261 #[serde(rename = "type", default)]
263 pub account_type: Option<String>,
264 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
266 pub futures_session_upl: Option<Decimal>,
267 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
269 pub futures_session_rpl: Option<Decimal>,
270 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
272 pub options_session_upl: Option<Decimal>,
273 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
275 pub options_session_rpl: Option<Decimal>,
276 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
278 pub futures_pl: Option<Decimal>,
279 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
281 pub options_pl: Option<Decimal>,
282 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
284 pub options_delta: Option<Decimal>,
285 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
287 pub options_gamma: Option<Decimal>,
288 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
290 pub options_vega: Option<Decimal>,
291 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
293 pub options_theta: Option<Decimal>,
294 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
296 pub options_value: Option<Decimal>,
297 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
299 pub delta_total: Option<Decimal>,
300 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
302 pub projected_delta_total: Option<Decimal>,
303 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
305 pub projected_initial_margin: Option<Decimal>,
306 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
308 pub projected_maintenance_margin: Option<Decimal>,
309 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
311 pub estimated_liquidation_ratio: Option<Decimal>,
312 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
314 pub available_withdrawal_funds: Option<Decimal>,
315 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
317 pub spot_reserve: Option<Decimal>,
318 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
320 pub fee_balance: Option<Decimal>,
321 #[serde(default)]
323 pub margin_model: Option<String>,
324 #[serde(default)]
326 pub cross_collateral_enabled: Option<bool>,
327 #[serde(default)]
329 pub creation_timestamp: Option<i64>,
330 #[serde(default)]
332 pub login_enabled: Option<bool>,
333 #[serde(default)]
335 pub security_keys_enabled: Option<bool>,
336 #[serde(default)]
338 pub mmp_enabled: Option<bool>,
339 #[serde(default)]
341 pub interuser_transfers_enabled: Option<bool>,
342 #[serde(default)]
344 pub self_trading_reject_mode: Option<String>,
345 #[serde(default)]
347 pub self_trading_extended_to_subaccounts: Option<bool>,
348 #[serde(default)]
350 pub referrer_id: Option<String>,
351 #[serde(default)]
353 pub block_rfq_self_match_prevention: Option<bool>,
354}
355
356#[derive(Clone, Debug, Serialize, Deserialize)]
361pub struct DeribitPublicTrade {
362 #[serde(deserialize_with = "deserialize_decimal")]
365 pub amount: Decimal,
366 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
368 pub contracts: Option<Decimal>,
369 pub direction: String,
371 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
373 pub index_price: Option<Decimal>,
374 pub instrument_name: String,
376 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
378 pub iv: Option<Decimal>,
379 #[serde(default)]
381 pub liquidation: Option<String>,
382 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
384 pub mark_price: Option<Decimal>,
385 #[serde(deserialize_with = "deserialize_decimal")]
387 pub price: Decimal,
388 pub tick_direction: i32,
390 pub timestamp: i64,
392 pub trade_id: String,
394 pub trade_seq: i64,
396 #[serde(default)]
398 pub block_trade_id: Option<String>,
399 #[serde(default)]
401 pub block_trade_leg_count: Option<i32>,
402 #[serde(default)]
404 pub block_rfq_id: Option<i64>,
405 #[serde(default)]
407 pub combo_id: Option<String>,
408 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
410 pub combo_trade_id: Option<Decimal>,
411}
412
413#[derive(Clone, Debug, Serialize, Deserialize)]
417pub struct DeribitTradesResponse {
418 pub has_more: bool,
420 pub trades: Vec<DeribitPublicTrade>,
422}
423
424#[derive(Clone, Debug, Serialize, Deserialize)]
429pub struct DeribitTradingViewChartData {
430 pub close: Vec<f64>,
432 #[serde(default)]
434 pub cost: Vec<f64>,
435 pub high: Vec<f64>,
437 pub low: Vec<f64>,
439 pub open: Vec<f64>,
441 pub status: String,
443 pub ticks: Vec<i64>,
445 pub volume: Vec<f64>,
447}
448
449#[derive(Clone, Debug, Serialize, Deserialize)]
453pub struct DeribitOrderBook {
454 pub timestamp: i64,
456 pub instrument_name: String,
458 pub bids: Vec<[f64; 2]>,
460 pub asks: Vec<[f64; 2]>,
462 pub state: String,
464 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
466 pub best_bid_price: Option<Decimal>,
467 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
469 pub best_ask_price: Option<Decimal>,
470 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
472 pub best_bid_amount: Option<Decimal>,
473 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
475 pub best_ask_amount: Option<Decimal>,
476 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
478 pub mark_price: Option<Decimal>,
479 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
481 pub last_price: Option<Decimal>,
482 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
484 pub index_price: Option<Decimal>,
485 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
487 pub open_interest: Option<Decimal>,
488 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
490 pub max_price: Option<Decimal>,
491 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
493 pub min_price: Option<Decimal>,
494 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
496 pub current_funding: Option<Decimal>,
497 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
499 pub funding_8h: Option<Decimal>,
500 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
502 pub settlement_price: Option<Decimal>,
503 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
505 pub delivery_price: Option<Decimal>,
506 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
508 pub bid_iv: Option<Decimal>,
509 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
511 pub ask_iv: Option<Decimal>,
512 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
514 pub mark_iv: Option<Decimal>,
515 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
517 pub underlying_price: Option<Decimal>,
518 #[serde(default)]
520 pub underlying_index: Option<serde_json::Value>,
521 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
523 pub interest_rate: Option<Decimal>,
524}
525
526#[derive(Clone, Debug, Serialize, Deserialize)]
531pub struct DeribitBookSummary {
532 pub instrument_name: String,
534 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
536 pub underlying_price: Option<Decimal>,
537 #[serde(default)]
539 pub underlying_index: Option<String>,
540 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
542 pub mark_price: Option<Decimal>,
543 pub creation_timestamp: i64,
545}
546
547#[derive(Clone, Debug, Serialize, Deserialize)]
552pub struct DeribitTicker {
553 pub instrument_name: String,
555 #[serde(default, deserialize_with = "deserialize_optional_decimal")]
557 pub underlying_price: Option<Decimal>,
558 #[serde(default)]
560 pub underlying_index: Option<String>,
561}
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct DeribitPosition {
568 pub instrument_name: Ustr,
570 pub direction: String,
572 #[serde(
574 serialize_with = "nautilus_core::serialization::serialize_decimal",
575 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
576 )]
577 pub size: Decimal,
578 #[serde(
580 serialize_with = "nautilus_core::serialization::serialize_decimal",
581 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
582 )]
583 pub average_price: Decimal,
584 #[serde(
586 serialize_with = "nautilus_core::serialization::serialize_decimal",
587 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
588 )]
589 pub mark_price: Decimal,
590 #[serde(
592 default,
593 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
594 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
595 )]
596 pub index_price: Option<Decimal>,
597 #[serde(
599 serialize_with = "nautilus_core::serialization::serialize_decimal",
600 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
601 )]
602 pub maintenance_margin: Decimal,
603 #[serde(
605 serialize_with = "nautilus_core::serialization::serialize_decimal",
606 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
607 )]
608 pub initial_margin: Decimal,
609 #[serde(default)]
611 pub leverage: Option<i64>,
612 #[serde(
614 serialize_with = "nautilus_core::serialization::serialize_decimal",
615 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
616 )]
617 pub floating_profit_loss: Decimal,
618 #[serde(
620 serialize_with = "nautilus_core::serialization::serialize_decimal",
621 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
622 )]
623 pub realized_profit_loss: Decimal,
624 #[serde(
626 serialize_with = "nautilus_core::serialization::serialize_decimal",
627 deserialize_with = "nautilus_core::serialization::deserialize_decimal"
628 )]
629 pub total_profit_loss: Decimal,
630 pub kind: DeribitProductType,
632 #[serde(
634 default,
635 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
636 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
637 )]
638 pub size_currency: Option<Decimal>,
639 #[serde(
641 default,
642 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
643 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
644 )]
645 pub estimated_liquidation_price: Option<Decimal>,
646 #[serde(
648 default,
649 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
650 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
651 )]
652 pub delta: Option<Decimal>,
653 #[serde(
655 default,
656 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
657 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
658 )]
659 pub gamma: Option<Decimal>,
660 #[serde(
662 default,
663 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
664 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
665 )]
666 pub vega: Option<Decimal>,
667 #[serde(
669 default,
670 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
671 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
672 )]
673 pub theta: Option<Decimal>,
674 #[serde(
676 default,
677 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
678 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
679 )]
680 pub settlement_price: Option<Decimal>,
681 #[serde(
683 default,
684 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
685 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
686 )]
687 pub open_orders_margin: Option<Decimal>,
688 #[serde(
690 default,
691 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
692 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
693 )]
694 pub average_price_usd: Option<Decimal>,
695 #[serde(
697 default,
698 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
699 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
700 )]
701 pub realized_profit_loss_session: Option<Decimal>,
702 #[serde(
704 default,
705 serialize_with = "nautilus_core::serialization::serialize_optional_decimal",
706 deserialize_with = "nautilus_core::serialization::deserialize_optional_decimal"
707 )]
708 pub floating_profit_loss_usd: Option<Decimal>,
709}
710
711#[derive(Clone, Debug, Serialize, Deserialize)]
716pub struct DeribitUserTradesResponse {
717 pub has_more: bool,
719 pub trades: Vec<crate::websocket::messages::DeribitUserTradeMsg>,
721}
722
723#[cfg(test)]
724mod tests {
725 use rstest::rstest;
726 use rust_decimal_macros::dec;
727
728 use super::*;
729
730 #[rstest]
731 fn test_deserialize_public_trade_with_empty_mark_and_index_price() {
732 let json = r#"{
733 "amount": 1.0,
734 "direction": "sell",
735 "index_price": "",
736 "instrument_name": "ETH-PERPETUAL",
737 "mark_price": "",
738 "price": 2968.3,
739 "tick_direction": 0,
740 "timestamp": 1766332040636,
741 "trade_id": "ETH-123",
742 "trade_seq": 1
743 }"#;
744
745 let trade: DeribitPublicTrade = serde_json::from_str(json).unwrap();
746 assert_eq!(trade.index_price, None);
747 assert_eq!(trade.mark_price, None);
748 assert_eq!(trade.price, dec!(2968.3));
749 }
750
751 #[rstest]
752 fn test_deserialize_public_trade_with_missing_mark_and_index_price() {
753 let json = r#"{
754 "amount": 1.0,
755 "direction": "sell",
756 "instrument_name": "ETH-PERPETUAL",
757 "price": 2968.3,
758 "tick_direction": 0,
759 "timestamp": 1766332040636,
760 "trade_id": "ETH-123",
761 "trade_seq": 1
762 }"#;
763
764 let trade: DeribitPublicTrade = serde_json::from_str(json).unwrap();
765 assert_eq!(trade.index_price, None);
766 assert_eq!(trade.mark_price, None);
767 }
768
769 #[rstest]
770 fn test_deserialize_public_trade_with_present_mark_and_index_price() {
771 let json = r#"{
772 "amount": 1.0,
773 "direction": "sell",
774 "index_price": 2967.73,
775 "instrument_name": "ETH-PERPETUAL",
776 "mark_price": 2968.01,
777 "price": 2968.3,
778 "tick_direction": 0,
779 "timestamp": 1766332040636,
780 "trade_id": "ETH-123",
781 "trade_seq": 1
782 }"#;
783
784 let trade: DeribitPublicTrade = serde_json::from_str(json).unwrap();
785 assert_eq!(trade.index_price, Some(dec!(2967.73)));
786 assert_eq!(trade.mark_price, Some(dec!(2968.01)));
787 }
788}