deribit_base/model/
account.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 21/7/25
5******************************************************************************/
6
7use serde::{Deserialize, Serialize};
8
9use crate::{impl_json_debug_pretty, impl_json_display};
10/// Account summary information
11#[derive(Clone, Serialize, Deserialize)]
12pub struct AccountSummary {
13    /// Account currency (kept as Currencies enum for compatibility)
14    pub currency: String,
15    /// Total balance
16    pub balance: f64,
17    /// Account equity
18    pub equity: f64,
19    /// Available funds for trading
20    pub available_funds: f64,
21    /// Margin balance
22    pub margin_balance: f64,
23    /// Unrealized profit and loss
24    pub unrealized_pnl: f64,
25    /// Realized profit and loss
26    pub realized_pnl: f64,
27    /// Total profit and loss
28    pub total_pl: f64,
29    /// Session funding
30    pub session_funding: f64,
31    /// Session realized P&L
32    pub session_rpl: f64,
33    /// Session unrealized P&L
34    pub session_upl: f64,
35    /// Maintenance margin requirement
36    pub maintenance_margin: f64,
37    /// Initial margin requirement
38    pub initial_margin: f64,
39    /// Available withdrawal funds
40    pub available_withdrawal_funds: Option<f64>,
41    /// Cross collateral enabled
42    pub cross_collateral_enabled: Option<bool>,
43    /// Delta total
44    pub delta_total: Option<f64>,
45    /// Futures profit and loss
46    pub futures_pl: Option<f64>,
47    /// Futures session realized profit and loss
48    pub futures_session_rpl: Option<f64>,
49    /// Futures session unrealized profit and loss
50    pub futures_session_upl: Option<f64>,
51    /// Options delta
52    pub options_delta: Option<f64>,
53    /// Options gamma
54    pub options_gamma: Option<f64>,
55    /// Options profit and loss
56    pub options_pl: Option<f64>,
57    /// Options session realized profit and loss
58    pub options_session_rpl: Option<f64>,
59    /// Options session unrealized profit and loss
60    pub options_session_upl: Option<f64>,
61    /// Options theta
62    pub options_theta: Option<f64>,
63    /// Options vega
64    pub options_vega: Option<f64>,
65    /// Portfolio margin enabled
66    pub portfolio_margining_enabled: Option<bool>,
67    /// Projected delta total
68    pub projected_delta_total: Option<f64>,
69    /// Projected initial margin
70    pub projected_initial_margin: Option<f64>,
71    /// Projected maintenance margin
72    pub projected_maintenance_margin: Option<f64>,
73    /// System name
74    pub system_name: Option<String>,
75    /// Type of account
76    #[serde(rename = "type")]
77    pub account_type: String,
78    // Additional fields from deribit-http types.rs
79    /// Delta total map (currency -> delta)
80    pub delta_total_map: std::collections::HashMap<String, f64>,
81    /// Deposit address
82    pub deposit_address: String,
83    /// Fees structure
84    pub fees: Vec<std::collections::HashMap<String, f64>>,
85    /// Account limits
86    pub limits: std::collections::HashMap<String, f64>,
87}
88
89impl AccountSummary {
90    /// Calculate margin utilization as percentage
91    pub fn margin_utilization(&self) -> f64 {
92        if self.equity != 0.0 {
93            (self.initial_margin / self.equity) * 100.0
94        } else {
95            0.0
96        }
97    }
98
99    /// Calculate available margin
100    pub fn available_margin(&self) -> f64 {
101        self.equity - self.initial_margin
102    }
103
104    /// Check if account is at risk (high margin utilization)
105    pub fn is_at_risk(&self, threshold: f64) -> bool {
106        self.margin_utilization() > threshold
107    }
108
109    /// Calculate return on equity
110    pub fn return_on_equity(&self) -> f64 {
111        if self.equity != 0.0 {
112            (self.total_pl / self.equity) * 100.0
113        } else {
114            0.0
115        }
116    }
117}
118
119/// Subaccount information
120#[derive(Clone, Serialize, Deserialize)]
121pub struct Subaccount {
122    /// Subaccount email
123    pub email: String,
124    /// Subaccount ID
125    pub id: u64,
126    /// Whether login is enabled
127    pub login_enabled: bool,
128    /// Portfolio information (optional)
129    pub portfolio: Option<PortfolioInfo>,
130    /// Whether to receive notifications
131    pub receive_notifications: bool,
132    /// System name
133    pub system_name: String,
134    /// Time in force (optional)
135    pub tif: Option<String>,
136    /// Subaccount type
137    #[serde(rename = "type")]
138    pub subaccount_type: String,
139    /// Username
140    pub username: String,
141}
142
143/// Portfolio information
144#[derive(Clone, Serialize, Deserialize)]
145pub struct PortfolioInfo {
146    /// Available funds
147    pub available_funds: f64,
148    /// Available withdrawal funds
149    pub available_withdrawal_funds: f64,
150    /// Balance
151    pub balance: f64,
152    /// Currency
153    pub currency: String,
154    /// Delta total
155    pub delta_total: f64,
156    /// Equity
157    pub equity: f64,
158    /// Initial margin
159    pub initial_margin: f64,
160    /// Maintenance margin
161    pub maintenance_margin: f64,
162    /// Margin balance
163    pub margin_balance: f64,
164    /// Session realized P&L
165    pub session_rpl: f64,
166    /// Session unrealized P&L
167    pub session_upl: f64,
168    /// Total P&L
169    pub total_pl: f64,
170}
171
172/// Portfolio information
173#[derive(Clone, Serialize, Deserialize)]
174pub struct Portfolio {
175    /// Currency of the portfolio
176    pub currency: String,
177    /// Account summaries for different currencies
178    pub accounts: Vec<AccountSummary>,
179    /// Total portfolio value in USD
180    pub total_usd_value: Option<f64>,
181    /// Cross-currency margin enabled
182    pub cross_margin_enabled: bool,
183}
184
185impl Portfolio {
186    /// Create a new empty portfolio
187    pub fn new(currency: String) -> Self {
188        Self {
189            currency,
190            accounts: Vec::new(),
191            total_usd_value: None,
192            cross_margin_enabled: false,
193        }
194    }
195
196    /// Add an account summary to the portfolio
197    pub fn add_account(&mut self, account: AccountSummary) {
198        self.accounts.push(account);
199    }
200
201    /// Get account summary for a specific currency
202    pub fn get_account(&self, currency: &String) -> Option<&AccountSummary> {
203        self.accounts.iter().find(|acc| &acc.currency == currency)
204    }
205
206    /// Calculate total equity across all accounts
207    pub fn total_equity(&self) -> f64 {
208        self.accounts.iter().map(|acc| acc.equity).sum()
209    }
210
211    /// Calculate total unrealized PnL across all accounts
212    pub fn total_unrealized_pnl(&self) -> f64 {
213        self.accounts.iter().map(|acc| acc.unrealized_pnl).sum()
214    }
215
216    /// Calculate total realized PnL across all accounts
217    pub fn total_realized_pnl(&self) -> f64 {
218        self.accounts.iter().map(|acc| acc.realized_pnl).sum()
219    }
220}
221
222// Debug implementations using pretty JSON formatting
223impl_json_debug_pretty!(AccountSummary, Portfolio, Subaccount, PortfolioInfo);
224
225// Display implementations using compact JSON formatting
226impl_json_display!(AccountSummary, Portfolio, Subaccount, PortfolioInfo);