kiteconnect_async_wasm/models/orders/
order_history.rs1use super::OrderStatus;
2use crate::models::common::{Exchange, OrderType, Product, TransactionType, Validity};
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Trade {
9 #[serde(rename = "trade_id")]
11 pub trade_id: String,
12
13 #[serde(rename = "order_id")]
15 pub order_id: String,
16
17 #[serde(rename = "exchange_order_id")]
19 pub exchange_order_id: String,
20
21 #[serde(rename = "tradingsymbol")]
23 pub trading_symbol: String,
24
25 pub exchange: Exchange,
27
28 #[serde(rename = "instrument_token")]
30 pub instrument_token: u32,
31
32 pub product: Product,
34
35 #[serde(rename = "average_price")]
37 pub average_price: f64,
38
39 pub quantity: u32,
41
42 #[serde(rename = "fill_timestamp")]
44 pub fill_timestamp: DateTime<Utc>,
45
46 #[serde(rename = "exchange_timestamp")]
48 pub exchange_timestamp: DateTime<Utc>,
49
50 #[serde(rename = "transaction_type")]
52 pub transaction_type: TransactionType,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct OrderHistoryEntry {
58 pub account_id: String,
60
61 #[serde(rename = "order_id")]
63 pub order_id: String,
64
65 #[serde(rename = "exchange_order_id")]
67 pub exchange_order_id: Option<String>,
68
69 #[serde(rename = "parent_order_id")]
71 pub parent_order_id: Option<String>,
72
73 pub status: OrderStatus,
75
76 #[serde(rename = "status_message")]
78 pub status_message: Option<String>,
79
80 #[serde(rename = "status_message_raw")]
82 pub status_message_raw: Option<String>,
83
84 #[serde(rename = "order_timestamp")]
86 pub order_timestamp: DateTime<Utc>,
87
88 #[serde(rename = "exchange_timestamp")]
90 pub exchange_timestamp: Option<DateTime<Utc>>,
91
92 #[serde(rename = "exchange_update_timestamp")]
94 pub exchange_update_timestamp: Option<DateTime<Utc>>,
95
96 #[serde(rename = "tradingsymbol")]
98 pub trading_symbol: String,
99
100 pub exchange: Exchange,
102
103 #[serde(rename = "instrument_token")]
105 pub instrument_token: u32,
106
107 #[serde(rename = "order_type")]
109 pub order_type: OrderType,
110
111 #[serde(rename = "transaction_type")]
113 pub transaction_type: TransactionType,
114
115 pub validity: Validity,
117
118 pub product: Product,
120
121 pub quantity: u32,
123
124 #[serde(rename = "disclosed_quantity")]
126 pub disclosed_quantity: u32,
127
128 pub price: f64,
130
131 #[serde(rename = "trigger_price")]
133 pub trigger_price: f64,
134
135 #[serde(rename = "average_price")]
137 pub average_price: f64,
138
139 #[serde(rename = "filled_quantity")]
141 pub filled_quantity: u32,
142
143 #[serde(rename = "pending_quantity")]
145 pub pending_quantity: u32,
146
147 #[serde(rename = "cancelled_quantity")]
149 pub cancelled_quantity: u32,
150
151 #[serde(rename = "market_protection")]
153 pub market_protection: f64,
154
155 pub tag: Option<String>,
157
158 pub guid: String,
160
161 pub variety: Option<String>,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct OrderHistory {
168 pub entries: Vec<OrderHistoryEntry>,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct TradeHistory {
175 pub trades: Vec<Trade>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct OrderBook {
182 pub orders: Vec<super::Order>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct TradeBook {
189 pub trades: Vec<Trade>,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct OrderResponse {
196 #[serde(rename = "order_id")]
198 pub order_id: String,
199}
200
201impl Trade {
202 pub fn total_value(&self) -> f64 {
204 self.average_price * self.quantity as f64
205 }
206
207 pub fn is_buy(&self) -> bool {
209 self.transaction_type == TransactionType::BUY
210 }
211
212 pub fn is_sell(&self) -> bool {
214 self.transaction_type == TransactionType::SELL
215 }
216}
217
218impl OrderHistory {
219 pub fn latest_status(&self) -> Option<&OrderStatus> {
221 self.entries
222 .iter()
223 .max_by_key(|entry| &entry.order_timestamp)
224 .map(|entry| &entry.status)
225 }
226
227 pub fn status_transitions(&self) -> Vec<(&OrderStatus, &DateTime<Utc>)> {
229 let mut entries: Vec<_> = self
230 .entries
231 .iter()
232 .map(|entry| (&entry.status, &entry.order_timestamp))
233 .collect();
234
235 entries.sort_by_key(|(_, timestamp)| *timestamp);
236 entries
237 }
238
239 pub fn was_rejected(&self) -> bool {
241 self.entries
242 .iter()
243 .any(|entry| entry.status == OrderStatus::Rejected)
244 }
245
246 pub fn was_cancelled(&self) -> bool {
248 self.entries
249 .iter()
250 .any(|entry| entry.status == OrderStatus::Cancelled)
251 }
252
253 pub fn total_filled_quantity(&self) -> u32 {
255 self.entries
256 .iter()
257 .map(|entry| entry.filled_quantity)
258 .max()
259 .unwrap_or(0)
260 }
261}
262
263impl TradeHistory {
264 pub fn total_value(&self) -> f64 {
266 self.trades.iter().map(|trade| trade.total_value()).sum()
267 }
268
269 pub fn total_quantity(&self) -> u32 {
271 self.trades.iter().map(|trade| trade.quantity).sum()
272 }
273
274 pub fn average_price(&self) -> f64 {
276 let total_value = self.total_value();
277 let total_quantity = self.total_quantity();
278
279 if total_quantity > 0 {
280 total_value / total_quantity as f64
281 } else {
282 0.0
283 }
284 }
285
286 pub fn trades_by_type(&self, transaction_type: TransactionType) -> Vec<&Trade> {
288 self.trades
289 .iter()
290 .filter(|trade| trade.transaction_type == transaction_type)
291 .collect()
292 }
293
294 pub fn buy_trades(&self) -> Vec<&Trade> {
296 self.trades_by_type(TransactionType::BUY)
297 }
298
299 pub fn sell_trades(&self) -> Vec<&Trade> {
301 self.trades_by_type(TransactionType::SELL)
302 }
303}
304
305impl OrderBook {
306 pub fn orders_by_status(&self, status: OrderStatus) -> Vec<&super::Order> {
308 self.orders
309 .iter()
310 .filter(|order| order.status == status)
311 .collect()
312 }
313
314 pub fn open_orders(&self) -> Vec<&super::Order> {
316 self.orders.iter().filter(|order| order.is_open()).collect()
317 }
318
319 pub fn completed_orders(&self) -> Vec<&super::Order> {
321 self.orders
322 .iter()
323 .filter(|order| order.is_complete())
324 .collect()
325 }
326
327 pub fn cancelled_orders(&self) -> Vec<&super::Order> {
329 self.orders
330 .iter()
331 .filter(|order| order.is_cancelled())
332 .collect()
333 }
334
335 pub fn rejected_orders(&self) -> Vec<&super::Order> {
337 self.orders
338 .iter()
339 .filter(|order| order.is_rejected())
340 .collect()
341 }
342
343 pub fn find_order(&self, order_id: &str) -> Option<&super::Order> {
345 self.orders.iter().find(|order| order.order_id == order_id)
346 }
347
348 pub fn orders_by_symbol(&self, symbol: &str) -> Vec<&super::Order> {
350 self.orders
351 .iter()
352 .filter(|order| order.trading_symbol == symbol)
353 .collect()
354 }
355}
356
357impl TradeBook {
358 pub fn total_value(&self) -> f64 {
360 self.trades.iter().map(|trade| trade.total_value()).sum()
361 }
362
363 pub fn total_quantity(&self) -> u32 {
365 self.trades.iter().map(|trade| trade.quantity).sum()
366 }
367
368 pub fn trades_by_symbol(&self, symbol: &str) -> Vec<&Trade> {
370 self.trades
371 .iter()
372 .filter(|trade| trade.trading_symbol == symbol)
373 .collect()
374 }
375
376 pub fn trades_by_type(&self, transaction_type: TransactionType) -> Vec<&Trade> {
378 self.trades
379 .iter()
380 .filter(|trade| trade.transaction_type == transaction_type)
381 .collect()
382 }
383
384 pub fn group_by_symbol(&self) -> std::collections::HashMap<String, Vec<&Trade>> {
386 let mut grouped = std::collections::HashMap::new();
387
388 for trade in &self.trades {
389 grouped
390 .entry(trade.trading_symbol.clone())
391 .or_insert_with(Vec::new)
392 .push(trade);
393 }
394
395 grouped
396 }
397}