Skip to main content

deribit_websocket/model/
account.rs

1//! Account model definitions for Deribit WebSocket API
2//!
3//! This module provides types for account queries including positions,
4//! account summaries, and order state.
5
6use serde::{Deserialize, Serialize};
7
8/// Direction of a position (buy/sell)
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum Direction {
12    /// Buy/long position
13    Buy,
14    /// Sell/short position
15    Sell,
16    /// Zero position (no direction)
17    Zero,
18}
19
20impl Direction {
21    /// Returns the direction as a string
22    #[must_use]
23    pub fn as_str(&self) -> &'static str {
24        match self {
25            Direction::Buy => "buy",
26            Direction::Sell => "sell",
27            Direction::Zero => "zero",
28        }
29    }
30}
31
32/// Position structure representing a user's position in an instrument
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct Position {
35    /// Average price of the position
36    pub average_price: f64,
37    /// Average price in USD
38    #[serde(default)]
39    pub average_price_usd: Option<f64>,
40    /// Delta (price sensitivity) of the position
41    #[serde(default)]
42    pub delta: Option<f64>,
43    /// Direction of the position (buy/sell)
44    pub direction: Direction,
45    /// Estimated liquidation price
46    #[serde(default)]
47    pub estimated_liquidation_price: Option<f64>,
48    /// Floating profit/loss
49    #[serde(default)]
50    pub floating_profit_loss: Option<f64>,
51    /// Floating profit/loss in USD
52    #[serde(default)]
53    pub floating_profit_loss_usd: Option<f64>,
54    /// Gamma (delta sensitivity) of the position
55    #[serde(default)]
56    pub gamma: Option<f64>,
57    /// Current index price
58    #[serde(default)]
59    pub index_price: Option<f64>,
60    /// Initial margin requirement
61    #[serde(default)]
62    pub initial_margin: Option<f64>,
63    /// Name of the instrument
64    pub instrument_name: String,
65    /// Interest value
66    #[serde(default)]
67    pub interest_value: Option<f64>,
68    /// Instrument kind (future, option, etc.)
69    #[serde(default)]
70    pub kind: Option<String>,
71    /// Leverage used for the position
72    #[serde(default)]
73    pub leverage: Option<i32>,
74    /// Maintenance margin requirement
75    #[serde(default)]
76    pub maintenance_margin: Option<f64>,
77    /// Current mark price
78    #[serde(default)]
79    pub mark_price: Option<f64>,
80    /// Margin used by open orders
81    #[serde(default)]
82    pub open_orders_margin: Option<f64>,
83    /// Realized funding payments
84    #[serde(default)]
85    pub realized_funding: Option<f64>,
86    /// Realized profit/loss
87    #[serde(default)]
88    pub realized_profit_loss: Option<f64>,
89    /// Settlement price
90    #[serde(default)]
91    pub settlement_price: Option<f64>,
92    /// Position size
93    pub size: f64,
94    /// Position size in currency units
95    #[serde(default)]
96    pub size_currency: Option<f64>,
97    /// Theta (time decay) of the position
98    #[serde(default)]
99    pub theta: Option<f64>,
100    /// Total profit/loss
101    #[serde(default)]
102    pub total_profit_loss: Option<f64>,
103    /// Vega (volatility sensitivity) of the position
104    #[serde(default)]
105    pub vega: Option<f64>,
106}
107
108/// Per-currency account summary
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct CurrencySummary {
111    /// Currency of the summary
112    pub currency: String,
113    /// The account's balance
114    pub balance: f64,
115    /// The account's current equity
116    pub equity: f64,
117    /// The account's available funds
118    pub available_funds: f64,
119    /// The account's margin balance
120    pub margin_balance: f64,
121    /// Total profit and loss
122    #[serde(default)]
123    pub total_pl: Option<f64>,
124    /// Session realized profit and loss
125    #[serde(default)]
126    pub session_rpl: Option<f64>,
127    /// Session unrealized profit and loss
128    #[serde(default)]
129    pub session_upl: Option<f64>,
130    /// The maintenance margin
131    pub maintenance_margin: f64,
132    /// The account's initial margin
133    pub initial_margin: f64,
134    /// The account's available to withdrawal funds
135    #[serde(default)]
136    pub available_withdrawal_funds: Option<f64>,
137    /// When true cross collateral is enabled for user
138    #[serde(default)]
139    pub cross_collateral_enabled: Option<bool>,
140    /// The sum of position deltas
141    #[serde(default)]
142    pub delta_total: Option<f64>,
143    /// Futures profit and Loss
144    #[serde(default)]
145    pub futures_pl: Option<f64>,
146    /// Futures session realized profit and Loss
147    #[serde(default)]
148    pub futures_session_rpl: Option<f64>,
149    /// Futures session unrealized profit and Loss
150    #[serde(default)]
151    pub futures_session_upl: Option<f64>,
152    /// Options summary delta
153    #[serde(default)]
154    pub options_delta: Option<f64>,
155    /// Options summary gamma
156    #[serde(default)]
157    pub options_gamma: Option<f64>,
158    /// Options profit and Loss
159    #[serde(default)]
160    pub options_pl: Option<f64>,
161    /// Options session realized profit and Loss
162    #[serde(default)]
163    pub options_session_rpl: Option<f64>,
164    /// Options session unrealized profit and Loss
165    #[serde(default)]
166    pub options_session_upl: Option<f64>,
167    /// Options summary theta
168    #[serde(default)]
169    pub options_theta: Option<f64>,
170    /// Options summary vega
171    #[serde(default)]
172    pub options_vega: Option<f64>,
173    /// true when portfolio margining is enabled for user
174    #[serde(default)]
175    pub portfolio_margining_enabled: Option<bool>,
176}
177
178/// Account summary response containing user account information
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct AccountSummary {
181    /// Account id
182    #[serde(default)]
183    pub id: Option<u64>,
184    /// User email
185    #[serde(default)]
186    pub email: Option<String>,
187    /// System generated user nickname
188    #[serde(default)]
189    pub system_name: Option<String>,
190    /// Account name (given by user)
191    #[serde(default)]
192    pub username: Option<String>,
193    /// Time at which the account was created (milliseconds since the Unix epoch)
194    #[serde(default)]
195    pub creation_timestamp: Option<u64>,
196    /// Account type
197    #[serde(rename = "type", default)]
198    pub account_type: Option<String>,
199    /// Whether MMP is enabled
200    #[serde(default)]
201    pub mmp_enabled: Option<bool>,
202    /// Aggregated list of per-currency account summaries
203    #[serde(default)]
204    pub summaries: Option<Vec<CurrencySummary>>,
205    /// Currency (for single-currency response)
206    #[serde(default)]
207    pub currency: Option<String>,
208    /// Balance (for single-currency response)
209    #[serde(default)]
210    pub balance: Option<f64>,
211    /// Equity (for single-currency response)
212    #[serde(default)]
213    pub equity: Option<f64>,
214    /// Available funds (for single-currency response)
215    #[serde(default)]
216    pub available_funds: Option<f64>,
217    /// Margin balance (for single-currency response)
218    #[serde(default)]
219    pub margin_balance: Option<f64>,
220    /// Initial margin (for single-currency response)
221    #[serde(default)]
222    pub initial_margin: Option<f64>,
223    /// Maintenance margin (for single-currency response)
224    #[serde(default)]
225    pub maintenance_margin: Option<f64>,
226    /// Delta total (for single-currency response)
227    #[serde(default)]
228    pub delta_total: Option<f64>,
229    /// Options value (for single-currency response)
230    #[serde(default)]
231    pub options_value: Option<f64>,
232    /// Futures profit and loss (for single-currency response)
233    #[serde(default)]
234    pub futures_pl: Option<f64>,
235    /// Options profit and loss (for single-currency response)
236    #[serde(default)]
237    pub options_pl: Option<f64>,
238    /// Total profit and loss (for single-currency response)
239    #[serde(default)]
240    pub total_pl: Option<f64>,
241}
242
243#[cfg(test)]
244mod tests {
245    use super::*;
246
247    #[test]
248    fn test_direction_as_str() {
249        assert_eq!(Direction::Buy.as_str(), "buy");
250        assert_eq!(Direction::Sell.as_str(), "sell");
251        assert_eq!(Direction::Zero.as_str(), "zero");
252    }
253
254    #[test]
255    fn test_direction_serialization() {
256        let dir = Direction::Buy;
257        let json = serde_json::to_string(&dir).expect("serialize");
258        assert_eq!(json, "\"buy\"");
259    }
260
261    #[test]
262    fn test_direction_deserialization() {
263        let dir: Direction = serde_json::from_str("\"sell\"").expect("deserialize");
264        assert_eq!(dir, Direction::Sell);
265    }
266
267    #[test]
268    fn test_position_deserialization() {
269        let json = r#"{
270            "average_price": 50000.0,
271            "direction": "buy",
272            "instrument_name": "BTC-PERPETUAL",
273            "size": 100.0,
274            "floating_profit_loss": 50.0,
275            "mark_price": 50050.0
276        }"#;
277
278        let position: Position = serde_json::from_str(json).expect("deserialize");
279        assert_eq!(position.instrument_name, "BTC-PERPETUAL");
280        assert_eq!(position.size, 100.0);
281        assert_eq!(position.direction, Direction::Buy);
282        assert_eq!(position.average_price, 50000.0);
283    }
284
285    #[test]
286    fn test_currency_summary_deserialization() {
287        let json = r#"{
288            "currency": "BTC",
289            "balance": 1.5,
290            "equity": 1.6,
291            "available_funds": 1.0,
292            "margin_balance": 1.5,
293            "maintenance_margin": 0.1,
294            "initial_margin": 0.2
295        }"#;
296
297        let summary: CurrencySummary = serde_json::from_str(json).expect("deserialize");
298        assert_eq!(summary.currency, "BTC");
299        assert_eq!(summary.balance, 1.5);
300        assert_eq!(summary.equity, 1.6);
301    }
302
303    #[test]
304    fn test_account_summary_deserialization() {
305        let json = r#"{
306            "currency": "BTC",
307            "balance": 1.5,
308            "equity": 1.6,
309            "available_funds": 1.0,
310            "margin_balance": 1.5,
311            "initial_margin": 0.2,
312            "maintenance_margin": 0.1,
313            "delta_total": 0.5
314        }"#;
315
316        let summary: AccountSummary = serde_json::from_str(json).expect("deserialize");
317        assert_eq!(summary.currency, Some("BTC".to_string()));
318        assert_eq!(summary.balance, Some(1.5));
319    }
320}