deribit_base/model/
instrument.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 21/7/25
5******************************************************************************/
6
7use crate::model::currency::Currency;
8use serde::{Deserialize, Serialize};
9
10/// Instrument kind enumeration
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum InstrumentKind {
14    /// Future contract
15    Future,
16    /// Option contract
17    Option,
18    /// Spot trading
19    Spot,
20    /// Future combo
21    #[serde(rename = "future_combo")]
22    FutureCombo,
23    /// Option combo
24    #[serde(rename = "option_combo")]
25    OptionCombo,
26}
27
28/// Option type enumeration
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30#[serde(rename_all = "lowercase")]
31pub enum OptionType {
32    /// Call option
33    Call,
34    /// Put option
35    Put,
36}
37
38/// Instrument type enumeration
39#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
40#[serde(rename_all = "lowercase")]
41pub enum InstrumentType {
42    /// Linear instrument
43    Linear,
44    /// Reversed instrument
45    Reversed,
46}
47
48/// Instrument information
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct Instrument {
51    /// Instrument name (e.g., "BTC-PERPETUAL", "ETH-25JUL25-3000-C")
52    pub instrument_name: String,
53    /// Instrument kind
54    pub kind: InstrumentKind,
55    /// Base currency
56    pub currency: Currency,
57    /// Whether the instrument is active for trading
58    pub is_active: bool,
59    /// Expiration timestamp (None for perpetuals)
60    pub expiration_timestamp: Option<i64>,
61    /// Strike price (for options)
62    pub strike: Option<f64>,
63    /// Option type (call/put, for options only)
64    pub option_type: Option<OptionType>,
65    /// Minimum price movement
66    pub tick_size: f64,
67    /// Minimum trade amount
68    pub min_trade_amount: f64,
69    /// Contract size
70    pub contract_size: f64,
71    /// Settlement period
72    pub settlement_period: Option<String>,
73    /// Instrument type (linear/reversed)
74    pub instrument_type: Option<InstrumentType>,
75    /// Quote currency
76    pub quote_currency: Option<Currency>,
77    /// Settlement currency
78    pub settlement_currency: Option<Currency>,
79    /// Creation timestamp
80    pub creation_timestamp: Option<i64>,
81    /// Maximum leverage
82    pub max_leverage: Option<f64>,
83    /// Maker commission rate
84    pub maker_commission: Option<f64>,
85    /// Taker commission rate
86    pub taker_commission: Option<f64>,
87}
88
89impl Instrument {
90    /// Check if the instrument is a perpetual contract
91    pub fn is_perpetual(&self) -> bool {
92        self.expiration_timestamp.is_none() && self.kind == InstrumentKind::Future
93    }
94
95    /// Check if the instrument is an option
96    pub fn is_option(&self) -> bool {
97        self.kind == InstrumentKind::Option
98    }
99
100    /// Check if the instrument is a future
101    pub fn is_future(&self) -> bool {
102        matches!(
103            self.kind,
104            InstrumentKind::Future | InstrumentKind::FutureCombo
105        )
106    }
107
108    /// Check if the instrument is a spot
109    pub fn is_spot(&self) -> bool {
110        self.kind == InstrumentKind::Spot
111    }
112
113    /// Get the base currency as string
114    pub fn currency_str(&self) -> &'static str {
115        self.currency.as_str()
116    }
117}