deribit_base/model/
trade.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::{instrument::InstrumentKind, order::OrderSide};
8use serde::{Deserialize, Serialize};
9
10use crate::{impl_json_debug_pretty, impl_json_display};
11/// Liquidity type enumeration
12#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub enum Liquidity {
14    /// Maker (provided liquidity)
15    #[serde(rename = "M")]
16    Maker,
17    /// Taker (consumed liquidity)
18    #[serde(rename = "T")]
19    Taker,
20    /// Mixed (both maker and taker in same trade)
21    #[serde(rename = "MT")]
22    Mixed,
23}
24
25/// Trade execution information
26#[derive(Clone, Serialize, Deserialize)]
27pub struct Trade {
28    /// Unique trade identifier
29    pub trade_id: String,
30    /// Instrument name
31    pub instrument_name: String,
32    /// Order ID that generated this trade
33    pub order_id: String,
34    /// Trade direction (buy/sell)
35    pub direction: OrderSide,
36    /// Trade amount
37    pub amount: f64,
38    /// Execution price
39    pub price: f64,
40    /// Trade timestamp
41    pub timestamp: i64,
42    /// Fee amount
43    pub fee: f64,
44    /// Fee currency
45    pub fee_currency: String,
46    /// Liquidity type (maker/taker)
47    pub liquidity: Liquidity,
48    /// Mark price at time of trade
49    pub mark_price: f64,
50    /// Index price at time of trade
51    pub index_price: f64,
52    /// Instrument kind
53    pub instrument_kind: Option<InstrumentKind>,
54    /// Trade sequence number
55    pub trade_seq: Option<u64>,
56    /// User role in the trade
57    pub user_role: Option<String>,
58    /// Whether this is a block trade
59    pub block_trade: Option<bool>,
60    /// Underlying price (for options)
61    pub underlying_price: Option<f64>,
62    /// Implied volatility (for options)
63    pub iv: Option<f64>,
64    /// Label associated with the order
65    pub label: Option<String>,
66    /// Profit and loss from this trade
67    pub profit_loss: Option<f64>,
68    /// Tick direction
69    pub tick_direction: Option<i32>,
70    /// Whether this trade was self-traded
71    pub self_trade: Option<bool>,
72}
73
74impl Trade {
75    /// Calculate the notional value of the trade
76    pub fn notional_value(&self) -> f64 {
77        self.amount * self.price
78    }
79
80    /// Check if this was a maker trade
81    pub fn is_maker(&self) -> bool {
82        matches!(self.liquidity, Liquidity::Maker | Liquidity::Mixed)
83    }
84
85    /// Check if this was a taker trade
86    pub fn is_taker(&self) -> bool {
87        matches!(self.liquidity, Liquidity::Taker | Liquidity::Mixed)
88    }
89
90    /// Check if this is a buy trade
91    pub fn is_buy(&self) -> bool {
92        self.direction == OrderSide::Buy
93    }
94
95    /// Check if this is a sell trade
96    pub fn is_sell(&self) -> bool {
97        self.direction == OrderSide::Sell
98    }
99
100    /// Get fee as percentage of notional
101    pub fn fee_percentage(&self) -> f64 {
102        if self.notional_value() != 0.0 {
103            (self.fee / self.notional_value()) * 100.0
104        } else {
105            0.0
106        }
107    }
108}
109
110/// Trade statistics
111#[derive(Clone, Serialize, Deserialize)]
112pub struct TradeStats {
113    /// Total number of trades
114    pub count: u64,
115    /// Total volume
116    pub volume: f64,
117    /// Total fees paid
118    pub total_fees: f64,
119    /// Average price
120    pub avg_price: f64,
121    /// Profit and loss
122    pub pnl: f64,
123    /// Number of winning trades
124    pub winning_trades: u64,
125    /// Number of losing trades
126    pub losing_trades: u64,
127}
128
129impl TradeStats {
130    /// Create empty trade statistics
131    pub fn new() -> Self {
132        Self {
133            count: 0,
134            volume: 0.0,
135            total_fees: 0.0,
136            avg_price: 0.0,
137            pnl: 0.0,
138            winning_trades: 0,
139            losing_trades: 0,
140        }
141    }
142
143    /// Calculate win rate as percentage
144    pub fn win_rate(&self) -> f64 {
145        if self.count > 0 {
146            (self.winning_trades as f64 / self.count as f64) * 100.0
147        } else {
148            0.0
149        }
150    }
151}
152
153impl Default for TradeStats {
154    fn default() -> Self {
155        Self::new()
156    }
157}
158
159/// Trade execution
160#[derive(Clone, Serialize, Deserialize)]
161pub struct TradeExecution {
162    /// Trade amount
163    pub amount: f64,
164    /// Trade direction (buy/sell)
165    pub direction: String,
166    /// Trading fee paid
167    pub fee: f64,
168    /// Currency of the trading fee
169    pub fee_currency: String,
170    /// Index price at execution time
171    pub index_price: f64,
172    /// Name of the traded instrument
173    pub instrument_name: String,
174    /// Implied volatility (for options)
175    pub iv: Option<f64>,
176    /// User-defined label for the trade
177    pub label: String,
178    /// Liquidity type (maker/taker)
179    pub liquidity: String,
180    /// Mark price at execution time
181    pub mark_price: f64,
182    /// Matching engine identifier
183    pub matching_id: Option<String>,
184    /// Order ID that generated this trade
185    pub order_id: String,
186    /// Type of the order that generated this trade
187    pub order_type: String,
188    /// Original order type before modifications
189    pub original_order_type: Option<String>,
190    /// Execution price
191    pub price: f64,
192    /// Whether this was a self trade
193    pub self_trade: bool,
194    /// Current state of the trade
195    pub state: String,
196    /// Price tick direction (1=up, -1=down, 0=no change)
197    pub tick_direction: i32,
198    /// Execution timestamp
199    pub timestamp: u64,
200    /// Unique trade identifier
201    pub trade_id: String,
202    /// Trade sequence number
203    pub trade_seq: u64,
204    /// Underlying asset price (for derivatives)
205    pub underlying_price: Option<f64>,
206}
207
208/// User trade information
209#[derive(Clone, Serialize, Deserialize)]
210pub struct UserTrade {
211    /// Trade amount
212    pub amount: f64,
213    /// Trade direction (buy/sell)
214    pub direction: String,
215    /// Trading fee paid
216    pub fee: f64,
217    /// Currency of the trading fee
218    pub fee_currency: String,
219    /// Index price at execution time
220    pub index_price: f64,
221    /// Name of the traded instrument
222    pub instrument_name: String,
223    /// Implied volatility (for options)
224    pub iv: Option<f64>,
225    /// User-defined label for the trade
226    pub label: String,
227    /// Liquidity type (maker/taker)
228    pub liquidity: String,
229    /// Mark price at execution time
230    pub mark_price: f64,
231    /// Matching engine identifier
232    pub matching_id: Option<String>,
233    /// Order ID that generated this trade
234    pub order_id: String,
235    /// Type of the order that generated this trade
236    pub order_type: String,
237    /// Original order type before modifications
238    pub original_order_type: Option<String>,
239    /// Execution price
240    pub price: f64,
241    /// Whether this was a self trade
242    pub self_trade: bool,
243    /// Current state of the trade
244    pub state: String,
245    /// Price tick direction (1=up, -1=down, 0=no change)
246    pub tick_direction: i32,
247    /// Execution timestamp
248    pub timestamp: u64,
249    /// Unique trade identifier
250    pub trade_id: String,
251    /// Trade sequence number
252    pub trade_seq: u64,
253    /// Underlying asset price (for derivatives)
254    pub underlying_price: Option<f64>,
255}
256
257/// Last trade
258#[derive(Clone, Serialize, Deserialize)]
259pub struct LastTrade {
260    /// Trade amount
261    pub amount: f64,
262    /// Trade direction (buy/sell)
263    pub direction: String,
264    /// Index price at execution time
265    pub index_price: f64,
266    /// Name of the traded instrument
267    pub instrument_name: String,
268    /// Implied volatility (for options)
269    pub iv: Option<f64>,
270    /// Liquidity information
271    pub liquid: Option<String>,
272    /// Execution price
273    pub price: f64,
274    /// Price tick direction (1=up, -1=down, 0=no change)
275    pub tick_direction: i32,
276    /// Execution timestamp
277    pub timestamp: u64,
278    /// Unique trade identifier
279    pub trade_id: String,
280    /// Trade sequence number
281    pub trade_seq: u64,
282}
283
284// Debug implementations using pretty JSON formatting
285impl_json_debug_pretty!(
286    LastTrade,
287    Liquidity,
288    Trade,
289    TradeStats,
290    TradeExecution,
291    UserTrade
292);
293
294// Display implementations using compact JSON formatting
295impl_json_display!(
296    LastTrade,
297    Liquidity,
298    Trade,
299    TradeStats,
300    TradeExecution,
301    UserTrade
302);