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}