deribit_http/model/
trade.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 15/9/25
5******************************************************************************/
6use crate::model::instrument::InstrumentKind;
7use crate::model::order::OrderSide;
8use pretty_simple_display::{DebugPretty, DisplaySimple};
9use serde::{Deserialize, Serialize};
10use serde_with::skip_serializing_none;
11
12/// Trade execution
13#[skip_serializing_none]
14#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
15pub struct TradeExecution {
16    /// Trade amount
17    pub amount: f64,
18    /// Trade direction (buy/sell)
19    pub direction: String,
20    /// Trading fee paid
21    pub fee: f64,
22    /// Currency of the trading fee
23    pub fee_currency: String,
24    /// Index price at execution time
25    pub index_price: f64,
26    /// Name of the traded instrument
27    pub instrument_name: String,
28    /// Implied volatility (for options)
29    pub iv: Option<f64>,
30    /// User-defined label for the trade
31    pub label: String,
32    /// Liquidity type (maker/taker)
33    pub liquidity: String,
34    /// Mark price at execution time
35    pub mark_price: f64,
36    /// Matching engine identifier
37    pub matching_id: Option<String>,
38    /// Order ID that generated this trade
39    pub order_id: String,
40    /// Type of the order that generated this trade
41    pub order_type: String,
42    /// Original order type before modifications
43    pub original_order_type: Option<String>,
44    /// Execution price
45    pub price: f64,
46    /// Whether this was a self trade
47    pub self_trade: bool,
48    /// Current state of the trade
49    pub state: String,
50    /// Price tick direction (1=up, -1=down, 0=no change)
51    pub tick_direction: i32,
52    /// Execution timestamp
53    pub timestamp: u64,
54    /// Unique trade identifier
55    pub trade_id: String,
56    /// Trade sequence number
57    pub trade_seq: u64,
58    /// Underlying asset price (for derivatives)
59    pub underlying_price: Option<f64>,
60}
61
62/// User trade information
63#[skip_serializing_none]
64#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
65pub struct UserTrade {
66    /// Trade amount in base currency units
67    pub amount: f64,
68    /// Whether the order was placed via API
69    pub api: Option<bool>,
70    /// Number of contracts traded
71    pub contracts: Option<f64>,
72    /// Trade direction (buy/sell)
73    pub direction: String,
74    /// Trading fee paid
75    pub fee: f64,
76    /// Currency of the trading fee
77    pub fee_currency: String,
78    /// Index price at execution time
79    pub index_price: f64,
80    /// Name of the traded instrument
81    pub instrument_name: String,
82    /// Implied volatility (for options)
83    pub iv: Option<f64>,
84    /// User-defined label for the trade
85    pub label: Option<String>,
86    /// Liquidity type (M=maker, T=taker)
87    pub liquidity: String,
88    /// Mark price at execution time
89    pub mark_price: f64,
90    /// Matching engine identifier
91    pub matching_id: Option<String>,
92    /// Whether Market Maker Protection was active
93    pub mmp: Option<bool>,
94    /// Order ID that generated this trade
95    pub order_id: String,
96    /// Type of the order that generated this trade
97    pub order_type: String,
98    /// Original order type before modifications
99    pub original_order_type: Option<String>,
100    /// Whether this was a post-only order
101    pub post_only: Option<bool>,
102    /// Execution price
103    pub price: f64,
104    /// Profit or loss from this trade
105    pub profit_loss: Option<f64>,
106    /// Whether this was a reduce-only order
107    pub reduce_only: Option<bool>,
108    /// Whether this trade was risk reducing
109    pub risk_reducing: Option<bool>,
110    /// Whether this was a self trade
111    pub self_trade: bool,
112    /// Current state of the trade
113    pub state: String,
114    /// Price tick direction (1=up, -1=down, 0=no change)
115    pub tick_direction: i32,
116    /// Execution timestamp (milliseconds since UNIX epoch)
117    pub timestamp: u64,
118    /// Unique trade identifier
119    pub trade_id: String,
120    /// Trade sequence number
121    pub trade_seq: u64,
122    /// Underlying asset price (for derivatives)
123    pub underlying_price: Option<f64>,
124    /// User ID who executed the trade
125    pub user_id: Option<u64>,
126}
127
128/// Last trade
129#[skip_serializing_none]
130#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
131pub struct LastTrade {
132    /// Trade amount
133    pub amount: f64,
134    /// Trade direction (buy/sell)
135    pub direction: String,
136    /// Index price at execution time
137    pub index_price: f64,
138    /// Name of the traded instrument
139    pub instrument_name: String,
140    /// Implied volatility (for options)
141    pub iv: Option<f64>,
142    /// Liquidity information
143    pub liquid: Option<String>,
144    /// Execution price
145    pub price: f64,
146    /// Price tick direction (1=up, -1=down, 0=no change)
147    pub tick_direction: i32,
148    /// Execution timestamp
149    pub timestamp: u64,
150    /// Unique trade identifier
151    pub trade_id: String,
152    /// Trade sequence number
153    pub trade_seq: u64,
154}
155
156/// Liquidity type enumeration
157#[derive(DebugPretty, DisplaySimple, Clone, PartialEq, Eq, Serialize, Deserialize)]
158pub enum Liquidity {
159    /// Maker (provided liquidity)
160    #[serde(rename = "M")]
161    Maker,
162    /// Taker (consumed liquidity)
163    #[serde(rename = "T")]
164    Taker,
165    /// Mixed (both maker and taker in same trade)
166    #[serde(rename = "MT")]
167    Mixed,
168}
169
170/// Trade execution information
171#[skip_serializing_none]
172#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
173pub struct Trade {
174    /// Unique trade identifier
175    pub trade_id: String,
176    /// Instrument name
177    pub instrument_name: String,
178    /// Order ID that generated this trade
179    pub order_id: String,
180    /// Trade direction (buy/sell)
181    pub direction: OrderSide,
182    /// Trade amount
183    pub amount: f64,
184    /// Execution price
185    pub price: f64,
186    /// Trade timestamp
187    pub timestamp: i64,
188    /// Fee amount
189    pub fee: f64,
190    /// Fee currency
191    pub fee_currency: String,
192    /// Liquidity type (maker/taker)
193    pub liquidity: Liquidity,
194    /// Mark price at time of trade
195    pub mark_price: f64,
196    /// Index price at time of trade
197    pub index_price: f64,
198    /// Instrument kind
199    pub instrument_kind: Option<InstrumentKind>,
200    /// Trade sequence number
201    pub trade_seq: Option<u64>,
202    /// User role in the trade
203    pub user_role: Option<String>,
204    /// Whether this is a block trade
205    pub block_trade: Option<bool>,
206    /// Underlying price (for options)
207    pub underlying_price: Option<f64>,
208    /// Implied volatility (for options)
209    pub iv: Option<f64>,
210    /// Label associated with the order
211    pub label: Option<String>,
212    /// Profit and loss from this trade
213    pub profit_loss: Option<f64>,
214    /// Tick direction
215    pub tick_direction: Option<i32>,
216    /// Whether this trade was self-traded
217    pub self_trade: Option<bool>,
218}
219
220impl Trade {
221    /// Calculate the notional value of the trade
222    pub fn notional_value(&self) -> f64 {
223        self.amount * self.price
224    }
225
226    /// Check if this was a maker trade
227    pub fn is_maker(&self) -> bool {
228        matches!(self.liquidity, Liquidity::Maker | Liquidity::Mixed)
229    }
230
231    /// Check if this was a taker trade
232    pub fn is_taker(&self) -> bool {
233        matches!(self.liquidity, Liquidity::Taker | Liquidity::Mixed)
234    }
235
236    /// Check if this is a buy trade
237    pub fn is_buy(&self) -> bool {
238        self.direction == OrderSide::Buy
239    }
240
241    /// Check if this is a sell trade
242    pub fn is_sell(&self) -> bool {
243        self.direction == OrderSide::Sell
244    }
245
246    /// Get fee as percentage of notional
247    pub fn fee_percentage(&self) -> f64 {
248        if self.notional_value() != 0.0 {
249            (self.fee / self.notional_value()) * 100.0
250        } else {
251            0.0
252        }
253    }
254}
255
256/// Trade statistics
257#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
258pub struct TradeStats {
259    /// Total number of trades
260    pub count: u64,
261    /// Total volume
262    pub volume: f64,
263    /// Total fees paid
264    pub total_fees: f64,
265    /// Average price
266    pub avg_price: f64,
267    /// Profit and loss
268    pub pnl: f64,
269    /// Number of winning trades
270    pub winning_trades: u64,
271    /// Number of losing trades
272    pub losing_trades: u64,
273}
274
275impl TradeStats {
276    /// Create empty trade statistics
277    pub fn new() -> Self {
278        Self {
279            count: 0,
280            volume: 0.0,
281            total_fees: 0.0,
282            avg_price: 0.0,
283            pnl: 0.0,
284            winning_trades: 0,
285            losing_trades: 0,
286        }
287    }
288
289    /// Calculate win rate as percentage
290    pub fn win_rate(&self) -> f64 {
291        if self.count > 0 {
292            (self.winning_trades as f64 / self.count as f64) * 100.0
293        } else {
294            0.0
295        }
296    }
297}
298
299impl Default for TradeStats {
300    fn default() -> Self {
301        Self::new()
302    }
303}
304
305/// Trade allocation structure for Block RFQ pre-allocation
306#[skip_serializing_none]
307#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
308pub struct TradeAllocation {
309    /// Amount allocated to this user
310    pub amount: f64,
311
312    /// Optional client allocation info for brokers
313    pub client_info: Option<ClientInfo>,
314
315    /// Fee for the allocated part of the trade
316    pub fee: f64,
317
318    /// User ID to which part of the trade is allocated. For brokers the User ID is obstructed.
319    pub user_id: u64,
320}
321
322/// Client information structure for broker allocations
323#[skip_serializing_none]
324#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
325pub struct ClientInfo {
326    /// ID of a client; available to broker. Represents a group of users under a common name.
327    pub client_id: u64,
328
329    /// ID assigned to a single user in a client; available to broker.
330    pub client_link_id: u64,
331
332    /// Name of the linked user within the client; available to broker.
333    pub name: String,
334}