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);