1use serde::Serialize;
2
3#[derive(Debug, Clone, Default, Serialize)]
5pub struct AttachedAlgoOrderRequest {
6 #[serde(rename = "attachAlgoClOrdId", skip_serializing_if = "Option::is_none")]
7 attach_algo_cl_ord_id: Option<String>,
8 #[serde(rename = "tpTriggerPx", skip_serializing_if = "Option::is_none")]
9 tp_trigger_px: Option<String>,
10 #[serde(rename = "tpTriggerRatio", skip_serializing_if = "Option::is_none")]
11 tp_trigger_ratio: Option<String>,
12 #[serde(rename = "tpTriggerPxType", skip_serializing_if = "Option::is_none")]
13 tp_trigger_px_type: Option<String>,
14 #[serde(rename = "tpOrdPx", skip_serializing_if = "Option::is_none")]
15 tp_ord_px: Option<String>,
16 #[serde(rename = "slTriggerPx", skip_serializing_if = "Option::is_none")]
17 sl_trigger_px: Option<String>,
18 #[serde(rename = "slTriggerRatio", skip_serializing_if = "Option::is_none")]
19 sl_trigger_ratio: Option<String>,
20 #[serde(rename = "slTriggerPxType", skip_serializing_if = "Option::is_none")]
21 sl_trigger_px_type: Option<String>,
22 #[serde(rename = "slOrdPx", skip_serializing_if = "Option::is_none")]
23 sl_ord_px: Option<String>,
24}
25
26impl AttachedAlgoOrderRequest {
27 pub fn new() -> Self {
29 Self::default()
30 }
31
32 pub fn client_algo_order_id(mut self, value: impl Into<String>) -> Self {
34 self.attach_algo_cl_ord_id = Some(value.into());
35 self
36 }
37
38 pub fn take_profit(
40 mut self,
41 trigger_px: impl Into<String>,
42 order_px: impl Into<String>,
43 ) -> Self {
44 self.tp_trigger_px = Some(trigger_px.into());
45 self.tp_ord_px = Some(order_px.into());
46 self
47 }
48
49 pub fn take_profit_ratio(
51 mut self,
52 trigger_ratio: impl Into<String>,
53 order_px: impl Into<String>,
54 ) -> Self {
55 self.tp_trigger_ratio = Some(trigger_ratio.into());
56 self.tp_ord_px = Some(order_px.into());
57 self
58 }
59
60 pub fn take_profit_price_type(mut self, value: impl Into<String>) -> Self {
62 self.tp_trigger_px_type = Some(value.into());
63 self
64 }
65
66 pub fn stop_loss(mut self, trigger_px: impl Into<String>, order_px: impl Into<String>) -> Self {
68 self.sl_trigger_px = Some(trigger_px.into());
69 self.sl_ord_px = Some(order_px.into());
70 self
71 }
72
73 pub fn stop_loss_ratio(
75 mut self,
76 trigger_ratio: impl Into<String>,
77 order_px: impl Into<String>,
78 ) -> Self {
79 self.sl_trigger_ratio = Some(trigger_ratio.into());
80 self.sl_ord_px = Some(order_px.into());
81 self
82 }
83
84 pub fn stop_loss_price_type(mut self, value: impl Into<String>) -> Self {
86 self.sl_trigger_px_type = Some(value.into());
87 self
88 }
89}
90
91#[derive(Debug, Clone, Serialize)]
93pub struct SmartIcebergTriggerRequest {
94 #[serde(rename = "triggerAction")]
95 trigger_action: String,
96 #[serde(rename = "triggerStrategy")]
97 trigger_strategy: String,
98 #[serde(rename = "triggerPx", skip_serializing_if = "Option::is_none")]
99 trigger_px: Option<String>,
100 #[serde(rename = "triggerCond", skip_serializing_if = "Option::is_none")]
101 trigger_cond: Option<String>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 timeframe: Option<String>,
104 #[serde(skip_serializing_if = "Option::is_none")]
105 thold: Option<String>,
106 #[serde(rename = "timePeriod", skip_serializing_if = "Option::is_none")]
107 time_period: Option<String>,
108}
109
110impl SmartIcebergTriggerRequest {
111 pub fn new(trigger_strategy: impl Into<String>) -> Self {
113 Self {
114 trigger_action: "start".to_owned(),
115 trigger_strategy: trigger_strategy.into(),
116 trigger_px: None,
117 trigger_cond: None,
118 timeframe: None,
119 thold: None,
120 time_period: None,
121 }
122 }
123
124 pub fn price(mut self, trigger_px: impl Into<String>) -> Self {
126 self.trigger_px = Some(trigger_px.into());
127 self
128 }
129
130 pub fn condition(mut self, value: impl Into<String>) -> Self {
132 self.trigger_cond = Some(value.into());
133 self
134 }
135
136 pub fn timeframe(mut self, value: impl Into<String>) -> Self {
138 self.timeframe = Some(value.into());
139 self
140 }
141
142 pub fn threshold(mut self, value: impl Into<String>) -> Self {
144 self.thold = Some(value.into());
145 self
146 }
147
148 pub fn time_period(mut self, value: impl Into<String>) -> Self {
150 self.time_period = Some(value.into());
151 self
152 }
153}
154
155#[derive(Debug, Clone, Serialize)]
157pub struct AlgoOrderRequest {
158 #[serde(rename = "instId")]
159 inst_id: String,
160 #[serde(rename = "tdMode")]
161 td_mode: String,
162 side: String,
163 #[serde(rename = "ordType")]
164 ord_type: String,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 sz: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 ccy: Option<String>,
169 #[serde(rename = "posSide", skip_serializing_if = "Option::is_none")]
170 pos_side: Option<String>,
171 #[serde(rename = "reduceOnly", skip_serializing_if = "Option::is_none")]
172 reduce_only: Option<bool>,
173 #[serde(rename = "algoClOrdId", skip_serializing_if = "Option::is_none")]
174 algo_cl_ord_id: Option<String>,
175 #[serde(rename = "tgtCcy", skip_serializing_if = "Option::is_none")]
176 tgt_ccy: Option<String>,
177 #[serde(rename = "closeFraction", skip_serializing_if = "Option::is_none")]
178 close_fraction: Option<String>,
179 #[serde(rename = "tradeQuoteCcy", skip_serializing_if = "Option::is_none")]
180 trade_quote_ccy: Option<String>,
181 #[serde(rename = "triggerPx", skip_serializing_if = "Option::is_none")]
182 trigger_px: Option<String>,
183 #[serde(rename = "orderPx", skip_serializing_if = "Option::is_none")]
184 order_px: Option<String>,
185 #[serde(rename = "advanceOrdType", skip_serializing_if = "Option::is_none")]
186 advance_ord_type: Option<String>,
187 #[serde(rename = "triggerPxType", skip_serializing_if = "Option::is_none")]
188 trigger_px_type: Option<String>,
189 #[serde(rename = "tpTriggerPx", skip_serializing_if = "Option::is_none")]
190 tp_trigger_px: Option<String>,
191 #[serde(rename = "tpTriggerPxType", skip_serializing_if = "Option::is_none")]
192 tp_trigger_px_type: Option<String>,
193 #[serde(rename = "tpOrdPx", skip_serializing_if = "Option::is_none")]
194 tp_ord_px: Option<String>,
195 #[serde(rename = "tpOrdKind", skip_serializing_if = "Option::is_none")]
196 tp_ord_kind: Option<String>,
197 #[serde(rename = "slTriggerPx", skip_serializing_if = "Option::is_none")]
198 sl_trigger_px: Option<String>,
199 #[serde(rename = "slTriggerPxType", skip_serializing_if = "Option::is_none")]
200 sl_trigger_px_type: Option<String>,
201 #[serde(rename = "slOrdPx", skip_serializing_if = "Option::is_none")]
202 sl_ord_px: Option<String>,
203 #[serde(rename = "cxlOnClosePos", skip_serializing_if = "Option::is_none")]
204 cxl_on_close_pos: Option<bool>,
205 #[serde(rename = "attachAlgoOrds", skip_serializing_if = "Option::is_none")]
206 attach_algo_ords: Option<Vec<AttachedAlgoOrderRequest>>,
207 #[serde(rename = "callbackRatio", skip_serializing_if = "Option::is_none")]
208 callback_ratio: Option<String>,
209 #[serde(rename = "callbackSpread", skip_serializing_if = "Option::is_none")]
210 callback_spread: Option<String>,
211 #[serde(rename = "activePx", skip_serializing_if = "Option::is_none")]
212 active_px: Option<String>,
213 #[serde(rename = "chaseType", skip_serializing_if = "Option::is_none")]
214 chase_type: Option<String>,
215 #[serde(rename = "chaseVal", skip_serializing_if = "Option::is_none")]
216 chase_val: Option<String>,
217 #[serde(rename = "maxChaseType", skip_serializing_if = "Option::is_none")]
218 max_chase_type: Option<String>,
219 #[serde(rename = "maxChaseVal", skip_serializing_if = "Option::is_none")]
220 max_chase_val: Option<String>,
221 #[serde(rename = "pxVar", skip_serializing_if = "Option::is_none")]
222 px_var: Option<String>,
223 #[serde(rename = "pxSpread", skip_serializing_if = "Option::is_none")]
224 px_spread: Option<String>,
225 #[serde(rename = "szLimit", skip_serializing_if = "Option::is_none")]
226 sz_limit: Option<String>,
227 #[serde(rename = "pxLimit", skip_serializing_if = "Option::is_none")]
228 px_limit: Option<String>,
229 #[serde(rename = "timeInterval", skip_serializing_if = "Option::is_none")]
230 time_interval: Option<String>,
231 #[serde(rename = "lmtOrderNumber", skip_serializing_if = "Option::is_none")]
232 lmt_order_number: Option<String>,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 aggressiveness: Option<String>,
235 #[serde(rename = "triggerParams", skip_serializing_if = "Option::is_none")]
236 trigger_params: Option<Vec<SmartIcebergTriggerRequest>>,
237 #[serde(skip_serializing_if = "Option::is_none")]
238 tag: Option<String>,
239}
240
241impl AlgoOrderRequest {
242 pub fn new(
244 inst_id: impl Into<String>,
245 td_mode: impl Into<String>,
246 side: impl Into<String>,
247 ord_type: impl Into<String>,
248 sz: impl Into<String>,
249 ) -> Self {
250 Self {
251 inst_id: inst_id.into(),
252 td_mode: td_mode.into(),
253 side: side.into(),
254 ord_type: ord_type.into(),
255 sz: Some(sz.into()),
256 ccy: None,
257 pos_side: None,
258 reduce_only: None,
259 algo_cl_ord_id: None,
260 tgt_ccy: None,
261 close_fraction: None,
262 trade_quote_ccy: None,
263 trigger_px: None,
264 order_px: None,
265 advance_ord_type: None,
266 trigger_px_type: None,
267 tp_trigger_px: None,
268 tp_trigger_px_type: None,
269 tp_ord_px: None,
270 tp_ord_kind: None,
271 sl_trigger_px: None,
272 sl_trigger_px_type: None,
273 sl_ord_px: None,
274 cxl_on_close_pos: None,
275 attach_algo_ords: None,
276 callback_ratio: None,
277 callback_spread: None,
278 active_px: None,
279 chase_type: None,
280 chase_val: None,
281 max_chase_type: None,
282 max_chase_val: None,
283 px_var: None,
284 px_spread: None,
285 sz_limit: None,
286 px_limit: None,
287 time_interval: None,
288 lmt_order_number: None,
289 aggressiveness: None,
290 trigger_params: None,
291 tag: None,
292 }
293 }
294
295 pub fn full_close(mut self) -> Self {
297 self.sz = None;
298 self.close_fraction = Some("1".to_owned());
299 self
300 }
301
302 pub fn currency(mut self, value: impl Into<String>) -> Self {
304 self.ccy = Some(value.into());
305 self
306 }
307
308 pub fn position_side(mut self, value: impl Into<String>) -> Self {
310 self.pos_side = Some(value.into());
311 self
312 }
313
314 pub fn reduce_only(mut self, value: bool) -> Self {
316 self.reduce_only = Some(value);
317 self
318 }
319
320 pub fn client_algo_order_id(mut self, value: impl Into<String>) -> Self {
322 self.algo_cl_ord_id = Some(value.into());
323 self
324 }
325
326 pub fn target_currency(mut self, value: impl Into<String>) -> Self {
328 self.tgt_ccy = Some(value.into());
329 self
330 }
331
332 pub fn trade_quote_currency(mut self, value: impl Into<String>) -> Self {
334 self.trade_quote_ccy = Some(value.into());
335 self
336 }
337
338 pub fn trigger(mut self, px: impl Into<String>, order_px: impl Into<String>) -> Self {
340 self.trigger_px = Some(px.into());
341 self.order_px = Some(order_px.into());
342 self
343 }
344
345 pub fn advance_order_type(mut self, value: impl Into<String>) -> Self {
347 self.advance_ord_type = Some(value.into());
348 self
349 }
350
351 pub fn trigger_price_type(mut self, value: impl Into<String>) -> Self {
353 self.trigger_px_type = Some(value.into());
354 self
355 }
356
357 pub fn take_profit(
359 mut self,
360 trigger_px: impl Into<String>,
361 order_px: impl Into<String>,
362 ) -> Self {
363 self.tp_trigger_px = Some(trigger_px.into());
364 self.tp_ord_px = Some(order_px.into());
365 self
366 }
367
368 pub fn limit_take_profit(mut self, order_px: impl Into<String>) -> Self {
370 self.tp_ord_kind = Some("limit".to_owned());
371 self.tp_ord_px = Some(order_px.into());
372 self
373 }
374
375 pub fn take_profit_price_type(mut self, value: impl Into<String>) -> Self {
377 self.tp_trigger_px_type = Some(value.into());
378 self
379 }
380
381 pub fn stop_loss(mut self, trigger_px: impl Into<String>, order_px: impl Into<String>) -> Self {
383 self.sl_trigger_px = Some(trigger_px.into());
384 self.sl_ord_px = Some(order_px.into());
385 self
386 }
387
388 pub fn stop_loss_price_type(mut self, value: impl Into<String>) -> Self {
390 self.sl_trigger_px_type = Some(value.into());
391 self
392 }
393
394 pub fn cancel_on_close_position(mut self, value: bool) -> Self {
396 self.cxl_on_close_pos = Some(value);
397 self
398 }
399
400 pub fn attached_algo_orders(mut self, values: Vec<AttachedAlgoOrderRequest>) -> Self {
402 self.attach_algo_ords = Some(values);
403 self
404 }
405
406 pub fn callback_ratio(mut self, value: impl Into<String>) -> Self {
408 self.callback_ratio = Some(value.into());
409 self
410 }
411
412 pub fn callback_spread(mut self, value: impl Into<String>) -> Self {
414 self.callback_spread = Some(value.into());
415 self
416 }
417
418 pub fn active_price(mut self, value: impl Into<String>) -> Self {
420 self.active_px = Some(value.into());
421 self
422 }
423
424 pub fn chase(mut self, chase_type: impl Into<String>, chase_val: impl Into<String>) -> Self {
426 self.chase_type = Some(chase_type.into());
427 self.chase_val = Some(chase_val.into());
428 self
429 }
430
431 pub fn maximum_chase(
433 mut self,
434 chase_type: impl Into<String>,
435 chase_val: impl Into<String>,
436 ) -> Self {
437 self.max_chase_type = Some(chase_type.into());
438 self.max_chase_val = Some(chase_val.into());
439 self
440 }
441
442 pub fn twap_by_variance(
444 mut self,
445 px_var: impl Into<String>,
446 sz_limit: impl Into<String>,
447 px_limit: impl Into<String>,
448 time_interval: impl Into<String>,
449 ) -> Self {
450 self.px_var = Some(px_var.into());
451 self.px_spread = None;
452 self.sz_limit = Some(sz_limit.into());
453 self.px_limit = Some(px_limit.into());
454 self.time_interval = Some(time_interval.into());
455 self
456 }
457
458 pub fn twap_by_spread(
460 mut self,
461 px_spread: impl Into<String>,
462 sz_limit: impl Into<String>,
463 px_limit: impl Into<String>,
464 time_interval: impl Into<String>,
465 ) -> Self {
466 self.px_var = None;
467 self.px_spread = Some(px_spread.into());
468 self.sz_limit = Some(sz_limit.into());
469 self.px_limit = Some(px_limit.into());
470 self.time_interval = Some(time_interval.into());
471 self
472 }
473
474 pub fn smart_iceberg(
476 mut self,
477 sz_limit: impl Into<String>,
478 lmt_order_number: impl Into<String>,
479 aggressiveness: impl Into<String>,
480 ) -> Self {
481 self.sz_limit = Some(sz_limit.into());
482 self.lmt_order_number = Some(lmt_order_number.into());
483 self.aggressiveness = Some(aggressiveness.into());
484 self
485 }
486
487 pub fn price_limit(mut self, value: impl Into<String>) -> Self {
489 self.px_limit = Some(value.into());
490 self
491 }
492
493 pub fn smart_iceberg_triggers(mut self, values: Vec<SmartIcebergTriggerRequest>) -> Self {
495 self.trigger_params = Some(values);
496 self
497 }
498
499 pub fn tag(mut self, value: impl Into<String>) -> Self {
501 self.tag = Some(value.into());
502 self
503 }
504}
505
506#[derive(Debug, Clone, Serialize)]
508pub struct CancelAlgoOrderRequest {
509 #[serde(rename = "algoId", skip_serializing_if = "Option::is_none")]
510 algo_id: Option<String>,
511 #[serde(rename = "algoClOrdId", skip_serializing_if = "Option::is_none")]
512 algo_cl_ord_id: Option<String>,
513 #[serde(rename = "instId")]
514 inst_id: String,
515}
516
517impl CancelAlgoOrderRequest {
518 pub fn new(algo_id: impl Into<String>, inst_id: impl Into<String>) -> Self {
520 Self {
521 algo_id: Some(algo_id.into()),
522 algo_cl_ord_id: None,
523 inst_id: inst_id.into(),
524 }
525 }
526
527 pub fn by_client_algo_order_id(
529 algo_cl_ord_id: impl Into<String>,
530 inst_id: impl Into<String>,
531 ) -> Self {
532 Self {
533 algo_id: None,
534 algo_cl_ord_id: Some(algo_cl_ord_id.into()),
535 inst_id: inst_id.into(),
536 }
537 }
538}
539
540#[derive(Debug, Clone, Serialize)]
542pub struct AmendAlgoOrderRequest {
543 #[serde(rename = "instId")]
544 inst_id: String,
545 #[serde(rename = "algoId", skip_serializing_if = "Option::is_none")]
546 algo_id: Option<String>,
547 #[serde(rename = "algoClOrdId", skip_serializing_if = "Option::is_none")]
548 algo_cl_ord_id: Option<String>,
549 #[serde(rename = "reqId", skip_serializing_if = "Option::is_none")]
550 req_id: Option<String>,
551 #[serde(rename = "newSz", skip_serializing_if = "Option::is_none")]
552 new_sz: Option<String>,
553 #[serde(rename = "newTpTriggerPx", skip_serializing_if = "Option::is_none")]
554 new_tp_trigger_px: Option<String>,
555 #[serde(rename = "newTpOrdPx", skip_serializing_if = "Option::is_none")]
556 new_tp_ord_px: Option<String>,
557 #[serde(rename = "newTpTriggerPxType", skip_serializing_if = "Option::is_none")]
558 new_tp_trigger_px_type: Option<String>,
559 #[serde(rename = "newSlTriggerPx", skip_serializing_if = "Option::is_none")]
560 new_sl_trigger_px: Option<String>,
561 #[serde(rename = "newSlOrdPx", skip_serializing_if = "Option::is_none")]
562 new_sl_ord_px: Option<String>,
563 #[serde(rename = "newSlTriggerPxType", skip_serializing_if = "Option::is_none")]
564 new_sl_trigger_px_type: Option<String>,
565 #[serde(rename = "cxlOnFail", skip_serializing_if = "Option::is_none")]
566 cancel_on_fail: Option<bool>,
567}
568
569impl AmendAlgoOrderRequest {
570 pub fn new(inst_id: impl Into<String>) -> Self {
572 Self {
573 inst_id: inst_id.into(),
574 algo_id: None,
575 algo_cl_ord_id: None,
576 req_id: None,
577 new_sz: None,
578 new_tp_trigger_px: None,
579 new_tp_ord_px: None,
580 new_tp_trigger_px_type: None,
581 new_sl_trigger_px: None,
582 new_sl_ord_px: None,
583 new_sl_trigger_px_type: None,
584 cancel_on_fail: None,
585 }
586 }
587
588 pub fn algo_id(mut self, value: impl Into<String>) -> Self {
590 self.algo_id = Some(value.into());
591 self
592 }
593
594 pub fn client_algo_order_id(mut self, value: impl Into<String>) -> Self {
596 self.algo_cl_ord_id = Some(value.into());
597 self
598 }
599
600 pub fn request_id(mut self, value: impl Into<String>) -> Self {
602 self.req_id = Some(value.into());
603 self
604 }
605
606 pub fn new_size(mut self, value: impl Into<String>) -> Self {
608 self.new_sz = Some(value.into());
609 self
610 }
611
612 pub fn take_profit(
614 mut self,
615 trigger_px: impl Into<String>,
616 order_px: impl Into<String>,
617 ) -> Self {
618 self.new_tp_trigger_px = Some(trigger_px.into());
619 self.new_tp_ord_px = Some(order_px.into());
620 self
621 }
622
623 pub fn take_profit_price_type(mut self, value: impl Into<String>) -> Self {
625 self.new_tp_trigger_px_type = Some(value.into());
626 self
627 }
628
629 pub fn delete_take_profit(mut self) -> Self {
631 self.new_tp_trigger_px = Some("0".to_owned());
632 self.new_tp_ord_px = None;
633 self.new_tp_trigger_px_type = None;
634 self
635 }
636
637 pub fn stop_loss(mut self, trigger_px: impl Into<String>, order_px: impl Into<String>) -> Self {
639 self.new_sl_trigger_px = Some(trigger_px.into());
640 self.new_sl_ord_px = Some(order_px.into());
641 self
642 }
643
644 pub fn stop_loss_price_type(mut self, value: impl Into<String>) -> Self {
646 self.new_sl_trigger_px_type = Some(value.into());
647 self
648 }
649
650 pub fn delete_stop_loss(mut self) -> Self {
652 self.new_sl_trigger_px = Some("0".to_owned());
653 self.new_sl_ord_px = None;
654 self.new_sl_trigger_px_type = None;
655 self
656 }
657
658 pub fn cancel_on_fail(mut self, value: bool) -> Self {
660 self.cancel_on_fail = Some(value);
661 self
662 }
663}
664
665#[derive(Debug, Clone, Serialize)]
667pub struct AlgoOrderListRequest {
668 #[serde(rename = "ordType")]
669 ord_type: String,
670 #[serde(rename = "algoId", skip_serializing_if = "Option::is_none")]
671 algo_id: Option<String>,
672 #[serde(rename = "instType", skip_serializing_if = "Option::is_none")]
673 inst_type: Option<String>,
674 #[serde(rename = "instId", skip_serializing_if = "Option::is_none")]
675 inst_id: Option<String>,
676 #[serde(skip_serializing_if = "Option::is_none")]
677 after: Option<String>,
678 #[serde(skip_serializing_if = "Option::is_none")]
679 before: Option<String>,
680 #[serde(skip_serializing_if = "Option::is_none")]
681 limit: Option<u32>,
682}
683
684impl AlgoOrderListRequest {
685 pub fn new(ord_type: impl Into<String>) -> Self {
687 Self {
688 ord_type: ord_type.into(),
689 algo_id: None,
690 inst_type: None,
691 inst_id: None,
692 after: None,
693 before: None,
694 limit: None,
695 }
696 }
697
698 pub fn algo_id(mut self, value: impl Into<String>) -> Self {
700 self.algo_id = Some(value.into());
701 self
702 }
703
704 pub fn inst_type(mut self, value: impl Into<String>) -> Self {
706 self.inst_type = Some(value.into());
707 self
708 }
709
710 pub fn inst_id(mut self, value: impl Into<String>) -> Self {
712 self.inst_id = Some(value.into());
713 self
714 }
715
716 pub fn after(mut self, value: impl Into<String>) -> Self {
718 self.after = Some(value.into());
719 self
720 }
721
722 pub fn before(mut self, value: impl Into<String>) -> Self {
724 self.before = Some(value.into());
725 self
726 }
727
728 pub fn limit(mut self, value: u32) -> Self {
730 self.limit = Some(value);
731 self
732 }
733}
734
735#[derive(Debug, Clone, Serialize)]
737pub struct AlgoOrderHistoryRequest {
738 #[serde(flatten)]
739 common: AlgoOrderListRequest,
740 #[serde(skip_serializing_if = "Option::is_none")]
741 state: Option<String>,
742}
743
744impl AlgoOrderHistoryRequest {
745 pub fn new(ord_type: impl Into<String>) -> Self {
747 Self {
748 common: AlgoOrderListRequest::new(ord_type),
749 state: None,
750 }
751 }
752
753 pub fn state(mut self, value: impl Into<String>) -> Self {
755 self.state = Some(value.into());
756 self
757 }
758
759 pub fn algo_id(mut self, value: impl Into<String>) -> Self {
761 self.common = self.common.algo_id(value);
762 self
763 }
764
765 pub fn inst_type(mut self, value: impl Into<String>) -> Self {
767 self.common = self.common.inst_type(value);
768 self
769 }
770
771 pub fn inst_id(mut self, value: impl Into<String>) -> Self {
773 self.common = self.common.inst_id(value);
774 self
775 }
776
777 pub fn after(mut self, value: impl Into<String>) -> Self {
779 self.common = self.common.after(value);
780 self
781 }
782
783 pub fn before(mut self, value: impl Into<String>) -> Self {
785 self.common = self.common.before(value);
786 self
787 }
788
789 pub fn limit(mut self, value: u32) -> Self {
791 self.common = self.common.limit(value);
792 self
793 }
794}
795
796#[derive(Debug, Clone, Default, Serialize)]
798pub struct AlgoOrderDetailsRequest {
799 #[serde(rename = "algoId", skip_serializing_if = "Option::is_none")]
800 algo_id: Option<String>,
801 #[serde(rename = "algoClOrdId", skip_serializing_if = "Option::is_none")]
802 algo_cl_ord_id: Option<String>,
803}
804
805impl AlgoOrderDetailsRequest {
806 pub fn by_algo_id(value: impl Into<String>) -> Self {
808 Self {
809 algo_id: Some(value.into()),
810 algo_cl_ord_id: None,
811 }
812 }
813
814 pub fn by_client_algo_order_id(value: impl Into<String>) -> Self {
816 Self {
817 algo_id: None,
818 algo_cl_ord_id: Some(value.into()),
819 }
820 }
821}
822
823#[cfg(test)]
824mod tests {
825 use super::*;
826
827 #[test]
828 fn twap_official_example_validates_and_serializes() {
829 let request = AlgoOrderRequest::new("BTC-USDT-SWAP", "cross", "buy", "twap", "10")
830 .position_side("net")
831 .twap_by_spread("10", "10", "100", "10");
832
833 assert_eq!(
834 serde_json::to_value(&request).unwrap(),
835 serde_json::json!({
836 "instId": "BTC-USDT-SWAP",
837 "tdMode": "cross",
838 "side": "buy",
839 "ordType": "twap",
840 "sz": "10",
841 "posSide": "net",
842 "pxSpread": "10",
843 "szLimit": "10",
844 "pxLimit": "100",
845 "timeInterval": "10"
846 })
847 );
848 }
849
850 #[test]
851 fn smart_iceberg_official_example_validates_and_serializes() {
852 let trigger = SmartIcebergTriggerRequest::new("price")
853 .price("90000")
854 .condition("cross_down");
855 let request = AlgoOrderRequest::new("BTC-USDT", "cash", "buy", "smart_iceberg", "100")
856 .smart_iceberg("10", "5", "conservative")
857 .price_limit("95000")
858 .smart_iceberg_triggers(vec![trigger]);
859
860 assert_eq!(
861 serde_json::to_value(&request).unwrap(),
862 serde_json::json!({
863 "instId": "BTC-USDT",
864 "tdMode": "cash",
865 "side": "buy",
866 "ordType": "smart_iceberg",
867 "sz": "100",
868 "szLimit": "10",
869 "pxLimit": "95000",
870 "lmtOrderNumber": "5",
871 "aggressiveness": "conservative",
872 "triggerParams": [{
873 "triggerAction": "start",
874 "triggerStrategy": "price",
875 "triggerPx": "90000",
876 "triggerCond": "cross_down"
877 }]
878 })
879 );
880 }
881
882 #[test]
883 fn amend_allows_both_identifiers_and_documented_delete_sentinel() {
884 let request = AmendAlgoOrderRequest::new("BTC-USDT")
885 .algo_id("1")
886 .client_algo_order_id("client1")
887 .delete_take_profit();
888 assert_eq!(
889 serde_json::to_value(&request).unwrap(),
890 serde_json::json!({
891 "instId": "BTC-USDT",
892 "algoId": "1",
893 "algoClOrdId": "client1",
894 "newTpTriggerPx": "0"
895 })
896 );
897 }
898}