kiteconnect_async_wasm/models/orders/
order_params.rs1use crate::models::common::{Exchange, OrderType, Product, TransactionType, Validity};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct OrderParams {
7 #[serde(rename = "tradingsymbol")]
9 pub trading_symbol: String,
10
11 pub exchange: Exchange,
13
14 #[serde(rename = "transaction_type")]
16 pub transaction_type: TransactionType,
17
18 #[serde(rename = "order_type")]
20 pub order_type: OrderType,
21
22 pub quantity: u32,
24
25 pub product: Product,
27
28 #[serde(skip_serializing_if = "Option::is_none")]
30 pub price: Option<f64>,
31
32 #[serde(rename = "trigger_price", skip_serializing_if = "Option::is_none")]
34 pub trigger_price: Option<f64>,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub validity: Option<Validity>,
39
40 #[serde(rename = "disclosed_quantity", skip_serializing_if = "Option::is_none")]
42 pub disclosed_quantity: Option<u32>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub tag: Option<String>,
47
48 #[serde(rename = "squareoff", skip_serializing_if = "Option::is_none")]
50 pub squareoff: Option<f64>,
51
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub stoploss: Option<f64>,
55
56 #[serde(rename = "trailing_stoploss", skip_serializing_if = "Option::is_none")]
58 pub trailing_stoploss: Option<f64>,
59
60 #[serde(rename = "market_protection", skip_serializing_if = "Option::is_none")]
62 pub market_protection: Option<f64>,
63
64 #[serde(rename = "iceberg_legs", skip_serializing_if = "Option::is_none")]
66 pub iceberg_legs: Option<u32>,
67
68 #[serde(rename = "iceberg_quantity", skip_serializing_if = "Option::is_none")]
70 pub iceberg_quantity: Option<u32>,
71
72 #[serde(rename = "auction_number", skip_serializing_if = "Option::is_none")]
74 pub auction_number: Option<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct BracketOrderParams {
80 #[serde(flatten)]
82 pub order_params: OrderParams,
83
84 pub squareoff: f64,
86
87 pub stoploss: f64,
89
90 #[serde(rename = "trailing_stoploss", skip_serializing_if = "Option::is_none")]
92 pub trailing_stoploss: Option<f64>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct CoverOrderParams {
98 #[serde(flatten)]
100 pub order_params: OrderParams,
101
102 #[serde(rename = "trigger_price")]
104 pub trigger_price: f64,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct OrderModifyParams {
110 #[serde(skip_serializing)]
112 pub order_id: String,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub quantity: Option<u32>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub price: Option<f64>,
121
122 #[serde(rename = "trigger_price", skip_serializing_if = "Option::is_none")]
124 pub trigger_price: Option<f64>,
125
126 #[serde(rename = "order_type", skip_serializing_if = "Option::is_none")]
128 pub order_type: Option<OrderType>,
129
130 #[serde(skip_serializing_if = "Option::is_none")]
132 pub validity: Option<Validity>,
133
134 #[serde(rename = "disclosed_quantity", skip_serializing_if = "Option::is_none")]
136 pub disclosed_quantity: Option<u32>,
137
138 #[serde(rename = "parent_order_id", skip_serializing_if = "Option::is_none")]
140 pub parent_order_id: Option<String>,
141}
142
143#[derive(Debug, Clone)]
145pub struct OrderBuilder {
146 params: OrderParams,
147}
148
149impl OrderBuilder {
150 pub fn new() -> Self {
152 Self {
153 params: OrderParams {
154 trading_symbol: String::new(),
155 exchange: Exchange::NSE,
156 transaction_type: TransactionType::BUY,
157 order_type: OrderType::LIMIT,
158 quantity: 0,
159 product: Product::CNC,
160 price: None,
161 trigger_price: None,
162 validity: Some(Validity::DAY),
163 disclosed_quantity: None,
164 tag: None,
165 squareoff: None,
166 stoploss: None,
167 trailing_stoploss: None,
168 market_protection: None,
169 iceberg_legs: None,
170 iceberg_quantity: None,
171 auction_number: None,
172 },
173 }
174 }
175
176 pub fn trading_symbol<S: Into<String>>(mut self, symbol: S) -> Self {
178 self.params.trading_symbol = symbol.into();
179 self
180 }
181
182 pub fn exchange(mut self, exchange: Exchange) -> Self {
184 self.params.exchange = exchange;
185 self
186 }
187
188 pub fn transaction_type(mut self, transaction_type: TransactionType) -> Self {
190 self.params.transaction_type = transaction_type;
191 self
192 }
193
194 pub fn order_type(mut self, order_type: OrderType) -> Self {
196 self.params.order_type = order_type;
197 self
198 }
199
200 pub fn quantity(mut self, quantity: u32) -> Self {
202 self.params.quantity = quantity;
203 self
204 }
205
206 pub fn product(mut self, product: Product) -> Self {
208 self.params.product = product;
209 self
210 }
211
212 pub fn price(mut self, price: f64) -> Self {
214 self.params.price = Some(price);
215 self
216 }
217
218 pub fn trigger_price(mut self, trigger_price: f64) -> Self {
220 self.params.trigger_price = Some(trigger_price);
221 self
222 }
223
224 pub fn validity(mut self, validity: Validity) -> Self {
226 self.params.validity = Some(validity);
227 self
228 }
229
230 pub fn disclosed_quantity(mut self, disclosed_quantity: u32) -> Self {
232 self.params.disclosed_quantity = Some(disclosed_quantity);
233 self
234 }
235
236 pub fn tag<S: Into<String>>(mut self, tag: S) -> Self {
238 self.params.tag = Some(tag.into());
239 self
240 }
241
242 pub fn market_protection(mut self, market_protection: f64) -> Self {
244 self.params.market_protection = Some(market_protection);
245 self
246 }
247
248 pub fn iceberg(mut self, legs: u32, quantity: u32) -> Self {
250 self.params.iceberg_legs = Some(legs);
251 self.params.iceberg_quantity = Some(quantity);
252 self
253 }
254
255 pub fn build(self) -> Result<OrderParams, String> {
257 if self.params.trading_symbol.is_empty() {
259 return Err("Trading symbol is required".to_string());
260 }
261
262 if self.params.quantity == 0 {
263 return Err("Quantity must be greater than 0".to_string());
264 }
265
266 if self.params.order_type == OrderType::LIMIT && self.params.price.is_none() {
268 return Err("Price is required for LIMIT orders".to_string());
269 }
270
271 if matches!(self.params.order_type, OrderType::SL | OrderType::SLM)
273 && self.params.trigger_price.is_none()
274 {
275 return Err("Trigger price is required for SL/SL-M orders".to_string());
276 }
277
278 Ok(self.params)
279 }
280}
281
282impl Default for OrderBuilder {
283 fn default() -> Self {
284 Self::new()
285 }
286}
287
288pub struct BracketOrderBuilder {
290 params: OrderParams,
291 squareoff: Option<f64>,
292 stoploss: Option<f64>,
293 trailing_stoploss: Option<f64>,
294}
295
296impl BracketOrderBuilder {
297 pub fn new() -> Self {
299 Self {
300 params: OrderParams {
301 trading_symbol: String::new(),
302 exchange: Exchange::NSE,
303 transaction_type: TransactionType::BUY,
304 order_type: OrderType::LIMIT,
305 quantity: 0,
306 product: Product::MIS,
307 price: None,
308 trigger_price: None,
309 validity: Some(Validity::DAY),
310 disclosed_quantity: None,
311 tag: None,
312 squareoff: None,
313 stoploss: None,
314 trailing_stoploss: None,
315 market_protection: None,
316 iceberg_legs: None,
317 iceberg_quantity: None,
318 auction_number: None,
319 },
320 squareoff: None,
321 stoploss: None,
322 trailing_stoploss: None,
323 }
324 }
325
326 pub fn trading_symbol<S: Into<String>>(mut self, symbol: S) -> Self {
328 self.params.trading_symbol = symbol.into();
329 self
330 }
331
332 pub fn exchange(mut self, exchange: Exchange) -> Self {
334 self.params.exchange = exchange;
335 self
336 }
337
338 pub fn transaction_type(mut self, transaction_type: TransactionType) -> Self {
340 self.params.transaction_type = transaction_type;
341 self
342 }
343
344 pub fn quantity(mut self, quantity: u32) -> Self {
346 self.params.quantity = quantity;
347 self
348 }
349
350 pub fn price(mut self, price: f64) -> Self {
352 self.params.price = Some(price);
353 self
354 }
355
356 pub fn squareoff(mut self, squareoff: f64) -> Self {
358 self.squareoff = Some(squareoff);
359 self
360 }
361
362 pub fn stoploss(mut self, stoploss: f64) -> Self {
364 self.stoploss = Some(stoploss);
365 self
366 }
367
368 pub fn trailing_stoploss(mut self, trailing_stoploss: f64) -> Self {
370 self.trailing_stoploss = Some(trailing_stoploss);
371 self
372 }
373
374 pub fn build(self) -> Result<BracketOrderParams, String> {
376 if self.params.trading_symbol.is_empty() {
378 return Err("Trading symbol is required".to_string());
379 }
380
381 if self.params.quantity == 0 {
382 return Err("Quantity must be greater than 0".to_string());
383 }
384
385 if self.params.price.is_none() {
386 return Err("Price is required for bracket orders".to_string());
387 }
388
389 let squareoff = self
390 .squareoff
391 .ok_or("Square off value is required for bracket orders")?;
392 let stoploss = self
393 .stoploss
394 .ok_or("Stoploss value is required for bracket orders")?;
395
396 let mut order_params = self.params;
397 order_params.squareoff = Some(squareoff);
398 order_params.stoploss = Some(stoploss);
399 order_params.trailing_stoploss = self.trailing_stoploss;
400
401 Ok(BracketOrderParams {
402 order_params,
403 squareoff,
404 stoploss,
405 trailing_stoploss: self.trailing_stoploss,
406 })
407 }
408}
409
410impl Default for BracketOrderBuilder {
411 fn default() -> Self {
412 Self::new()
413 }
414}