deribit_base/model/
trade.rs1use crate::model::{currency::Currency, instrument::InstrumentKind, order::OrderSide};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub enum Liquidity {
13 #[serde(rename = "M")]
15 Maker,
16 #[serde(rename = "T")]
18 Taker,
19 #[serde(rename = "MT")]
21 Mixed,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct Trade {
27 pub trade_id: String,
29 pub instrument_name: String,
31 pub order_id: String,
33 pub direction: OrderSide,
35 pub amount: f64,
37 pub price: f64,
39 pub timestamp: i64,
41 pub fee: f64,
43 pub fee_currency: Currency,
45 pub liquidity: Liquidity,
47 pub mark_price: f64,
49 pub index_price: f64,
51 pub instrument_kind: Option<InstrumentKind>,
53 pub trade_seq: Option<u64>,
55 pub user_role: Option<String>,
57 pub block_trade: Option<bool>,
59 pub underlying_price: Option<f64>,
61 pub iv: Option<f64>,
63 pub label: Option<String>,
65 pub profit_loss: Option<f64>,
67 pub tick_direction: Option<i32>,
69 pub self_trade: Option<bool>,
71}
72
73impl Trade {
74 pub fn notional_value(&self) -> f64 {
76 self.amount * self.price
77 }
78
79 pub fn is_maker(&self) -> bool {
81 matches!(self.liquidity, Liquidity::Maker | Liquidity::Mixed)
82 }
83
84 pub fn is_taker(&self) -> bool {
86 matches!(self.liquidity, Liquidity::Taker | Liquidity::Mixed)
87 }
88
89 pub fn is_buy(&self) -> bool {
91 self.direction == OrderSide::Buy
92 }
93
94 pub fn is_sell(&self) -> bool {
96 self.direction == OrderSide::Sell
97 }
98
99 pub fn fee_percentage(&self) -> f64 {
101 if self.notional_value() != 0.0 {
102 (self.fee / self.notional_value()) * 100.0
103 } else {
104 0.0
105 }
106 }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct TradeStats {
112 pub count: u64,
114 pub volume: f64,
116 pub total_fees: f64,
118 pub avg_price: f64,
120 pub pnl: f64,
122 pub winning_trades: u64,
124 pub losing_trades: u64,
126}
127
128impl TradeStats {
129 pub fn new() -> Self {
131 Self {
132 count: 0,
133 volume: 0.0,
134 total_fees: 0.0,
135 avg_price: 0.0,
136 pnl: 0.0,
137 winning_trades: 0,
138 losing_trades: 0,
139 }
140 }
141
142 pub fn win_rate(&self) -> f64 {
144 if self.count > 0 {
145 (self.winning_trades as f64 / self.count as f64) * 100.0
146 } else {
147 0.0
148 }
149 }
150}
151
152impl Default for TradeStats {
153 fn default() -> Self {
154 Self::new()
155 }
156}