kiteconnect_async_wasm/models/orders/
order_data.rs

1use crate::models::common::{Exchange, OrderType, Product, TransactionType, Validity};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4
5/// Order data structure as returned by KiteConnect API
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Order {
8    /// Account ID
9    pub account_id: String,
10
11    /// Order ID assigned by the system
12    #[serde(rename = "order_id")]
13    pub order_id: String,
14
15    /// Exchange order ID
16    #[serde(rename = "exchange_order_id")]
17    pub exchange_order_id: Option<String>,
18
19    /// Parent order ID for bracket/cover orders
20    #[serde(rename = "parent_order_id")]
21    pub parent_order_id: Option<String>,
22
23    /// Order status
24    pub status: OrderStatus,
25
26    /// Status message from exchange
27    #[serde(rename = "status_message")]
28    pub status_message: Option<String>,
29
30    /// Status message from OMS
31    #[serde(rename = "status_message_raw")]
32    pub status_message_raw: Option<String>,
33
34    /// Order timestamp
35    #[serde(rename = "order_timestamp")]
36    pub order_timestamp: DateTime<Utc>,
37
38    /// Exchange timestamp
39    #[serde(rename = "exchange_timestamp")]
40    pub exchange_timestamp: Option<DateTime<Utc>>,
41
42    /// Exchange update timestamp
43    #[serde(rename = "exchange_update_timestamp")]
44    pub exchange_update_timestamp: Option<DateTime<Utc>>,
45
46    /// Trading symbol
47    #[serde(rename = "tradingsymbol")]
48    pub trading_symbol: String,
49
50    /// Exchange
51    pub exchange: Exchange,
52
53    /// Instrument token
54    #[serde(rename = "instrument_token")]
55    pub instrument_token: u32,
56
57    /// Order type
58    #[serde(rename = "order_type")]
59    pub order_type: OrderType,
60
61    /// Transaction type (BUY/SELL)
62    #[serde(rename = "transaction_type")]
63    pub transaction_type: TransactionType,
64
65    /// Validity
66    pub validity: Validity,
67
68    /// Product type
69    pub product: Product,
70
71    /// Quantity
72    pub quantity: u32,
73
74    /// Disclosed quantity
75    #[serde(rename = "disclosed_quantity")]
76    pub disclosed_quantity: u32,
77
78    /// Price
79    pub price: f64,
80
81    /// Trigger price for SL orders
82    #[serde(rename = "trigger_price")]
83    pub trigger_price: f64,
84
85    /// Average price at which the order was executed
86    #[serde(rename = "average_price")]
87    pub average_price: f64,
88
89    /// Filled quantity
90    #[serde(rename = "filled_quantity")]
91    pub filled_quantity: u32,
92
93    /// Pending quantity
94    #[serde(rename = "pending_quantity")]
95    pub pending_quantity: u32,
96
97    /// Cancelled quantity
98    #[serde(rename = "cancelled_quantity")]
99    pub cancelled_quantity: u32,
100
101    /// Market protection percentage
102    #[serde(rename = "market_protection")]
103    pub market_protection: f64,
104
105    /// Meta information
106    pub meta: Option<OrderMeta>,
107
108    /// Tag for the order
109    pub tag: Option<String>,
110
111    /// GUID for idempotency
112    pub guid: String,
113}
114
115/// Order status enumeration
116#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
117#[serde(rename_all = "UPPERCASE")]
118pub enum OrderStatus {
119    /// Order is in the system but not yet sent to exchange
120    Open,
121    /// Order sent to exchange and confirmed
122    Complete,
123    /// Order is cancelled
124    Cancelled,
125    /// Order is rejected by system or exchange
126    Rejected,
127    /// Order placed successfully
128    Put,
129    /// Order validation passed
130    Validated,
131    /// Order modification validation passed
132    #[serde(rename = "MODIFY VALIDATION PENDING")]
133    ModifyValidationPending,
134    /// Modification pending
135    #[serde(rename = "MODIFY PENDING")]
136    ModifyPending,
137    /// Order trigger is pending
138    #[serde(rename = "TRIGGER PENDING")]
139    TriggerPending,
140    /// Order cancellation is pending
141    #[serde(rename = "CANCEL PENDING")]
142    CancelPending,
143    /// AMO (After Market Order) placed
144    #[serde(rename = "AMO REQ RECEIVED")]
145    AmoReqReceived,
146}
147
148/// Order meta information
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct OrderMeta {
151    /// Demat consent
152    pub demat_consent: Option<String>,
153
154    /// ICEBERG leg count
155    pub iceberg_legs: Option<u32>,
156
157    /// ICEBERG quantity
158    pub iceberg_quantity: Option<u32>,
159}
160
161/// Order modification data
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct OrderModification {
164    /// Order ID to modify
165    #[serde(rename = "order_id")]
166    pub order_id: String,
167
168    /// New quantity
169    pub quantity: Option<u32>,
170
171    /// New price
172    pub price: Option<f64>,
173
174    /// New trigger price
175    #[serde(rename = "trigger_price")]
176    pub trigger_price: Option<f64>,
177
178    /// New order type
179    #[serde(rename = "order_type")]
180    pub order_type: Option<OrderType>,
181
182    /// New validity
183    pub validity: Option<Validity>,
184
185    /// New disclosed quantity
186    #[serde(rename = "disclosed_quantity")]
187    pub disclosed_quantity: Option<u32>,
188}
189
190/// Order cancellation response
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct OrderCancellation {
193    /// Order ID that was cancelled
194    #[serde(rename = "order_id")]
195    pub order_id: String,
196}
197
198/// Bracket order response
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct BracketOrderResponse {
201    /// Parent order details
202    pub order_id: String,
203
204    /// Child order details (if any)
205    pub child_order_ids: Vec<String>,
206}
207
208/// Cover order response
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct CoverOrderResponse {
211    /// Order ID
212    pub order_id: String,
213}
214
215impl Order {
216    /// Check if order is open (pending)
217    pub fn is_open(&self) -> bool {
218        matches!(
219            self.status,
220            OrderStatus::Open | OrderStatus::Put | OrderStatus::Validated
221        )
222    }
223
224    /// Check if order is completed
225    pub fn is_complete(&self) -> bool {
226        self.status == OrderStatus::Complete
227    }
228
229    /// Check if order is cancelled
230    pub fn is_cancelled(&self) -> bool {
231        self.status == OrderStatus::Cancelled
232    }
233
234    /// Check if order is rejected
235    pub fn is_rejected(&self) -> bool {
236        self.status == OrderStatus::Rejected
237    }
238
239    /// Get remaining quantity
240    pub fn remaining_quantity(&self) -> u32 {
241        self.quantity.saturating_sub(self.filled_quantity)
242    }
243
244    /// Check if order is partially filled
245    pub fn is_partially_filled(&self) -> bool {
246        self.filled_quantity > 0 && self.filled_quantity < self.quantity
247    }
248
249    /// Get fill percentage
250    pub fn fill_percentage(&self) -> f64 {
251        if self.quantity == 0 {
252            0.0
253        } else {
254            (self.filled_quantity as f64 / self.quantity as f64) * 100.0
255        }
256    }
257}
258
259impl OrderStatus {
260    /// Check if the status indicates the order is still active
261    pub fn is_active(&self) -> bool {
262        matches!(
263            self,
264            OrderStatus::Open
265                | OrderStatus::Put
266                | OrderStatus::Validated
267                | OrderStatus::ModifyValidationPending
268                | OrderStatus::ModifyPending
269                | OrderStatus::TriggerPending
270                | OrderStatus::CancelPending
271                | OrderStatus::AmoReqReceived
272        )
273    }
274
275    /// Check if the status indicates the order is final (no more updates expected)
276    pub fn is_final(&self) -> bool {
277        matches!(
278            self,
279            OrderStatus::Complete | OrderStatus::Cancelled | OrderStatus::Rejected
280        )
281    }
282}