1use serde::Serialize;
7
8use crate::client::Client;
9use reqwest::StatusCode;
10
11use crate::Result;
12use crate::error::{BinanceApiError, Error};
13use crate::models::{
14 AccountCommission, AccountInfo, Allocation, AmendOrderResponse, CancelOrderResponse,
15 CancelReplaceErrorResponse, CancelReplaceResponse, OcoOrder, Order, OrderAmendment, OrderFull,
16 PreventedMatch, SorOrderTestResponse, UnfilledOrderCount, UserTrade,
17};
18use crate::types::{
19 CancelReplaceMode, CancelRestrictions, OrderRateLimitExceededMode, OrderResponseType,
20 OrderSide, OrderType, TimeInForce,
21};
22
23const API_V3_ACCOUNT: &str = "/api/v3/account";
25const API_V3_MY_TRADES: &str = "/api/v3/myTrades";
26const API_V3_ORDER: &str = "/api/v3/order";
27const API_V3_ORDER_TEST: &str = "/api/v3/order/test";
28const API_V3_OPEN_ORDERS: &str = "/api/v3/openOrders";
29const API_V3_ALL_ORDERS: &str = "/api/v3/allOrders";
30const API_V3_ORDER_OCO: &str = "/api/v3/order/oco";
31const API_V3_ORDER_LIST_OTO: &str = "/api/v3/orderList/oto";
32const API_V3_ORDER_LIST_OTOCO: &str = "/api/v3/orderList/otoco";
33const API_V3_ORDER_LIST_OPO: &str = "/api/v3/orderList/opo";
34const API_V3_ORDER_LIST_OPOCO: &str = "/api/v3/orderList/opoco";
35const API_V3_ORDER_LIST: &str = "/api/v3/orderList";
36const API_V3_ALL_ORDER_LIST: &str = "/api/v3/allOrderList";
37const API_V3_OPEN_ORDER_LIST: &str = "/api/v3/openOrderList";
38const API_V3_MY_PREVENTED_MATCHES: &str = "/api/v3/myPreventedMatches";
39const API_V3_MY_ALLOCATIONS: &str = "/api/v3/myAllocations";
40const API_V3_ACCOUNT_COMMISSION: &str = "/api/v3/account/commission";
41const API_V3_ORDER_CANCEL_REPLACE: &str = "/api/v3/order/cancelReplace";
42const API_V3_SOR_ORDER: &str = "/api/v3/sor/order";
43const API_V3_SOR_ORDER_TEST: &str = "/api/v3/sor/order/test";
44const API_V3_RATE_LIMIT_ORDER: &str = "/api/v3/rateLimit/order";
45const API_V3_ORDER_AMEND: &str = "/api/v3/order/amend/keepPriority";
46const API_V3_ORDER_AMENDMENTS: &str = "/api/v3/order/amendments";
47
48#[derive(Clone)]
53pub struct Account {
54 client: Client,
55}
56
57impl Account {
58 pub(crate) fn new(client: Client) -> Self {
60 Self { client }
61 }
62
63 pub async fn get_account(&self) -> Result<AccountInfo> {
80 self.client.get_signed(API_V3_ACCOUNT, &[]).await
81 }
82
83 pub async fn my_trades(
100 &self,
101 symbol: &str,
102 from_id: Option<u64>,
103 start_time: Option<u64>,
104 end_time: Option<u64>,
105 limit: Option<u32>,
106 ) -> Result<Vec<UserTrade>> {
107 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
108
109 if let Some(id) = from_id {
110 params.push(("fromId", id.to_string()));
111 }
112 if let Some(start) = start_time {
113 params.push(("startTime", start.to_string()));
114 }
115 if let Some(end) = end_time {
116 params.push(("endTime", end.to_string()));
117 }
118 if let Some(l) = limit {
119 params.push(("limit", l.to_string()));
120 }
121
122 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
123 self.client.get_signed(API_V3_MY_TRADES, ¶ms_ref).await
124 }
125
126 pub async fn my_prevented_matches(
136 &self,
137 symbol: &str,
138 prevented_match_id: Option<u64>,
139 order_id: Option<u64>,
140 from_prevented_match_id: Option<u64>,
141 limit: Option<u32>,
142 ) -> Result<Vec<PreventedMatch>> {
143 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
144
145 if let Some(id) = prevented_match_id {
146 params.push(("preventedMatchId", id.to_string()));
147 }
148 if let Some(id) = order_id {
149 params.push(("orderId", id.to_string()));
150 }
151 if let Some(id) = from_prevented_match_id {
152 params.push(("fromPreventedMatchId", id.to_string()));
153 }
154 if let Some(l) = limit {
155 params.push(("limit", l.to_string()));
156 }
157
158 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
159 self.client
160 .get_signed(API_V3_MY_PREVENTED_MATCHES, ¶ms_ref)
161 .await
162 }
163
164 pub async fn my_allocations(
175 &self,
176 symbol: &str,
177 start_time: Option<u64>,
178 end_time: Option<u64>,
179 from_allocation_id: Option<u64>,
180 limit: Option<u32>,
181 order_id: Option<u64>,
182 ) -> Result<Vec<Allocation>> {
183 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
184
185 if let Some(start) = start_time {
186 params.push(("startTime", start.to_string()));
187 }
188 if let Some(end) = end_time {
189 params.push(("endTime", end.to_string()));
190 }
191 if let Some(id) = from_allocation_id {
192 params.push(("fromAllocationId", id.to_string()));
193 }
194 if let Some(l) = limit {
195 params.push(("limit", l.to_string()));
196 }
197 if let Some(id) = order_id {
198 params.push(("orderId", id.to_string()));
199 }
200
201 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
202 self.client
203 .get_signed(API_V3_MY_ALLOCATIONS, ¶ms_ref)
204 .await
205 }
206
207 pub async fn commission_rates(&self, symbol: &str) -> Result<AccountCommission> {
213 let params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
214 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
215 self.client
216 .get_signed(API_V3_ACCOUNT_COMMISSION, ¶ms_ref)
217 .await
218 }
219
220 pub async fn unfilled_order_count(&self) -> Result<Vec<UnfilledOrderCount>> {
236 self.client.get_signed(API_V3_RATE_LIMIT_ORDER, &[]).await
237 }
238
239 pub async fn order_amendments(
260 &self,
261 symbol: &str,
262 order_id: u64,
263 from_execution_id: Option<u64>,
264 limit: Option<u32>,
265 ) -> Result<Vec<OrderAmendment>> {
266 let mut params: Vec<(&str, String)> = vec![
267 ("symbol", symbol.to_string()),
268 ("orderId", order_id.to_string()),
269 ];
270
271 if let Some(from_id) = from_execution_id {
272 params.push(("fromExecutionId", from_id.to_string()));
273 }
274 if let Some(l) = limit {
275 params.push(("limit", l.to_string()));
276 }
277
278 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
279 self.client
280 .get_signed(API_V3_ORDER_AMENDMENTS, ¶ms_ref)
281 .await
282 }
283
284 pub async fn create_order(&self, order: &NewOrder) -> Result<OrderFull> {
307 let params = order.to_params();
308 let params_ref: Vec<(&str, &str)> = params
309 .iter()
310 .map(|(k, v)| (k.as_str(), v.as_str()))
311 .collect();
312 self.client.post_signed(API_V3_ORDER, ¶ms_ref).await
313 }
314
315 pub async fn test_order(&self, order: &NewOrder) -> Result<()> {
330 let params = order.to_params();
331 let params_ref: Vec<(&str, &str)> = params
332 .iter()
333 .map(|(k, v)| (k.as_str(), v.as_str()))
334 .collect();
335 let _: serde_json::Value = self
336 .client
337 .post_signed(API_V3_ORDER_TEST, ¶ms_ref)
338 .await?;
339 Ok(())
340 }
341
342 pub async fn amend_order_keep_priority(
373 &self,
374 symbol: &str,
375 order_id: Option<u64>,
376 orig_client_order_id: Option<&str>,
377 new_qty: &str,
378 new_client_order_id: Option<&str>,
379 ) -> Result<AmendOrderResponse> {
380 let mut params: Vec<(&str, String)> = vec![
381 ("symbol", symbol.to_string()),
382 ("newQty", new_qty.to_string()),
383 ];
384
385 if let Some(id) = order_id {
386 params.push(("orderId", id.to_string()));
387 }
388 if let Some(cid) = orig_client_order_id {
389 params.push(("origClientOrderId", cid.to_string()));
390 }
391 if let Some(new_cid) = new_client_order_id {
392 params.push(("newClientOrderId", new_cid.to_string()));
393 }
394
395 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
396 self.client
397 .put_signed(API_V3_ORDER_AMEND, ¶ms_ref)
398 .await
399 }
400
401 pub async fn cancel_replace_order(
420 &self,
421 request: &CancelReplaceOrder,
422 ) -> Result<CancelReplaceResponse> {
423 let params = request.to_params();
424 let params_ref: Vec<(&str, &str)> = params
425 .iter()
426 .map(|(k, v)| (k.as_str(), v.as_str()))
427 .collect();
428 let response = self
429 .client
430 .post_signed_raw(API_V3_ORDER_CANCEL_REPLACE, ¶ms_ref)
431 .await?;
432
433 match response.status() {
434 StatusCode::OK => Ok(response.json().await?),
435 StatusCode::BAD_REQUEST | StatusCode::CONFLICT => {
436 let error: CancelReplaceErrorResponse = response.json().await?;
437 Err(Error::from_cancel_replace_error(error))
438 }
439 StatusCode::UNAUTHORIZED => Err(Error::Api {
440 code: 401,
441 message: "Unauthorized".to_string(),
442 }),
443 StatusCode::FORBIDDEN | StatusCode::TOO_MANY_REQUESTS => {
444 let error: BinanceApiError = response.json().await?;
445 Err(Error::from_binance_error(error))
446 }
447 StatusCode::INTERNAL_SERVER_ERROR => Err(Error::Api {
448 code: 500,
449 message: "Internal server error".to_string(),
450 }),
451 StatusCode::SERVICE_UNAVAILABLE => Err(Error::Api {
452 code: 503,
453 message: "Service unavailable".to_string(),
454 }),
455 status => Err(Error::Api {
456 code: status.as_u16() as i32,
457 message: format!("Unexpected status code: {}", status),
458 }),
459 }
460 }
461
462 pub async fn create_sor_order(&self, order: &NewOrder) -> Result<OrderFull> {
464 let params = order.to_params();
465 let params_ref: Vec<(&str, &str)> = params
466 .iter()
467 .map(|(k, v)| (k.as_str(), v.as_str()))
468 .collect();
469 self.client.post_signed(API_V3_SOR_ORDER, ¶ms_ref).await
470 }
471
472 pub async fn test_sor_order(
474 &self,
475 order: &NewOrder,
476 compute_commission_rates: bool,
477 ) -> Result<SorOrderTestResponse> {
478 let mut params = order.to_params();
479 if compute_commission_rates {
480 params.push((
481 "computeCommissionRates".to_string(),
482 compute_commission_rates.to_string(),
483 ));
484 }
485 let params_ref: Vec<(&str, &str)> = params
486 .iter()
487 .map(|(k, v)| (k.as_str(), v.as_str()))
488 .collect();
489 self.client
490 .post_signed(API_V3_SOR_ORDER_TEST, ¶ms_ref)
491 .await
492 }
493
494 pub async fn get_order(
510 &self,
511 symbol: &str,
512 order_id: Option<u64>,
513 client_order_id: Option<&str>,
514 ) -> Result<Order> {
515 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
516
517 if let Some(id) = order_id {
518 params.push(("orderId", id.to_string()));
519 }
520 if let Some(cid) = client_order_id {
521 params.push(("origClientOrderId", cid.to_string()));
522 }
523
524 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
525 self.client.get_signed(API_V3_ORDER, ¶ms_ref).await
526 }
527
528 pub async fn cancel_order(
544 &self,
545 symbol: &str,
546 order_id: Option<u64>,
547 client_order_id: Option<&str>,
548 ) -> Result<CancelOrderResponse> {
549 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
550
551 if let Some(id) = order_id {
552 params.push(("orderId", id.to_string()));
553 }
554 if let Some(cid) = client_order_id {
555 params.push(("origClientOrderId", cid.to_string()));
556 }
557
558 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
559 self.client.delete_signed(API_V3_ORDER, ¶ms_ref).await
560 }
561
562 pub async fn open_orders(&self, symbol: Option<&str>) -> Result<Vec<Order>> {
580 let params: Vec<(&str, String)> = match symbol {
581 Some(s) => vec![("symbol", s.to_string())],
582 None => vec![],
583 };
584
585 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
586 self.client
587 .get_signed(API_V3_OPEN_ORDERS, ¶ms_ref)
588 .await
589 }
590
591 pub async fn cancel_all_orders(&self, symbol: &str) -> Result<Vec<CancelOrderResponse>> {
605 let params = [("symbol", symbol)];
606 self.client.delete_signed(API_V3_OPEN_ORDERS, ¶ms).await
607 }
608
609 pub async fn all_orders(
626 &self,
627 symbol: &str,
628 order_id: Option<u64>,
629 start_time: Option<u64>,
630 end_time: Option<u64>,
631 limit: Option<u32>,
632 ) -> Result<Vec<Order>> {
633 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
634
635 if let Some(id) = order_id {
636 params.push(("orderId", id.to_string()));
637 }
638 if let Some(start) = start_time {
639 params.push(("startTime", start.to_string()));
640 }
641 if let Some(end) = end_time {
642 params.push(("endTime", end.to_string()));
643 }
644 if let Some(l) = limit {
645 params.push(("limit", l.to_string()));
646 }
647
648 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
649 self.client.get_signed(API_V3_ALL_ORDERS, ¶ms_ref).await
650 }
651
652 pub async fn create_oco(&self, order: &NewOcoOrder) -> Result<OcoOrder> {
668 let params = order.to_params();
669 let params_ref: Vec<(&str, &str)> = params
670 .iter()
671 .map(|(k, v)| (k.as_str(), v.as_str()))
672 .collect();
673 self.client.post_signed(API_V3_ORDER_OCO, ¶ms_ref).await
674 }
675
676 pub async fn create_oto(&self, order: &NewOtoOrder) -> Result<OcoOrder> {
678 let params = order.to_params();
679 let params_ref: Vec<(&str, &str)> = params
680 .iter()
681 .map(|(k, v)| (k.as_str(), v.as_str()))
682 .collect();
683 self.client
684 .post_signed(API_V3_ORDER_LIST_OTO, ¶ms_ref)
685 .await
686 }
687
688 pub async fn create_otoco(&self, order: &NewOtocoOrder) -> Result<OcoOrder> {
690 let params = order.to_params();
691 let params_ref: Vec<(&str, &str)> = params
692 .iter()
693 .map(|(k, v)| (k.as_str(), v.as_str()))
694 .collect();
695 self.client
696 .post_signed(API_V3_ORDER_LIST_OTOCO, ¶ms_ref)
697 .await
698 }
699
700 pub async fn create_opo(&self, order: &NewOpoOrder) -> Result<OcoOrder> {
702 let params = order.to_params();
703 let params_ref: Vec<(&str, &str)> = params
704 .iter()
705 .map(|(k, v)| (k.as_str(), v.as_str()))
706 .collect();
707 self.client
708 .post_signed(API_V3_ORDER_LIST_OPO, ¶ms_ref)
709 .await
710 }
711
712 pub async fn create_opoco(&self, order: &NewOpocoOrder) -> Result<OcoOrder> {
714 let params = order.to_params();
715 let params_ref: Vec<(&str, &str)> = params
716 .iter()
717 .map(|(k, v)| (k.as_str(), v.as_str()))
718 .collect();
719 self.client
720 .post_signed(API_V3_ORDER_LIST_OPOCO, ¶ms_ref)
721 .await
722 }
723
724 pub async fn get_order_list(
728 &self,
729 order_list_id: Option<u64>,
730 client_order_list_id: Option<&str>,
731 ) -> Result<OcoOrder> {
732 self.get_oco(order_list_id, client_order_list_id).await
733 }
734
735 pub async fn cancel_order_list(
739 &self,
740 symbol: &str,
741 order_list_id: Option<u64>,
742 client_order_list_id: Option<&str>,
743 ) -> Result<OcoOrder> {
744 self.cancel_oco(symbol, order_list_id, client_order_list_id)
745 .await
746 }
747
748 pub async fn all_order_lists(
752 &self,
753 from_id: Option<u64>,
754 start_time: Option<u64>,
755 end_time: Option<u64>,
756 limit: Option<u32>,
757 ) -> Result<Vec<OcoOrder>> {
758 self.all_oco(from_id, start_time, end_time, limit).await
759 }
760
761 pub async fn open_order_lists(&self) -> Result<Vec<OcoOrder>> {
765 self.open_oco().await
766 }
767
768 pub async fn get_oco(
780 &self,
781 order_list_id: Option<u64>,
782 client_order_list_id: Option<&str>,
783 ) -> Result<OcoOrder> {
784 let mut params: Vec<(&str, String)> = vec![];
785
786 if let Some(id) = order_list_id {
787 params.push(("orderListId", id.to_string()));
788 }
789 if let Some(cid) = client_order_list_id {
790 params.push(("origClientOrderId", cid.to_string()));
791 }
792
793 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
794 self.client.get_signed(API_V3_ORDER_LIST, ¶ms_ref).await
795 }
796
797 pub async fn cancel_oco(
810 &self,
811 symbol: &str,
812 order_list_id: Option<u64>,
813 client_order_list_id: Option<&str>,
814 ) -> Result<OcoOrder> {
815 let mut params: Vec<(&str, String)> = vec![("symbol", symbol.to_string())];
816
817 if let Some(id) = order_list_id {
818 params.push(("orderListId", id.to_string()));
819 }
820 if let Some(cid) = client_order_list_id {
821 params.push(("listClientOrderId", cid.to_string()));
822 }
823
824 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
825 self.client
826 .delete_signed(API_V3_ORDER_LIST, ¶ms_ref)
827 .await
828 }
829
830 pub async fn all_oco(
839 &self,
840 from_id: Option<u64>,
841 start_time: Option<u64>,
842 end_time: Option<u64>,
843 limit: Option<u32>,
844 ) -> Result<Vec<OcoOrder>> {
845 let mut params: Vec<(&str, String)> = vec![];
846
847 if let Some(id) = from_id {
848 params.push(("fromId", id.to_string()));
849 }
850 if let Some(start) = start_time {
851 params.push(("startTime", start.to_string()));
852 }
853 if let Some(end) = end_time {
854 params.push(("endTime", end.to_string()));
855 }
856 if let Some(l) = limit {
857 params.push(("limit", l.to_string()));
858 }
859
860 let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
861 self.client
862 .get_signed(API_V3_ALL_ORDER_LIST, ¶ms_ref)
863 .await
864 }
865
866 pub async fn open_oco(&self) -> Result<Vec<OcoOrder>> {
868 self.client.get_signed(API_V3_OPEN_ORDER_LIST, &[]).await
869 }
870
871 pub async fn limit_buy(&self, symbol: &str, quantity: &str, price: &str) -> Result<OrderFull> {
888 let order = OrderBuilder::new(symbol, OrderSide::Buy, OrderType::Limit)
889 .quantity(quantity)
890 .price(price)
891 .time_in_force(TimeInForce::GTC)
892 .build();
893 self.create_order(&order).await
894 }
895
896 pub async fn limit_sell(&self, symbol: &str, quantity: &str, price: &str) -> Result<OrderFull> {
911 let order = OrderBuilder::new(symbol, OrderSide::Sell, OrderType::Limit)
912 .quantity(quantity)
913 .price(price)
914 .time_in_force(TimeInForce::GTC)
915 .build();
916 self.create_order(&order).await
917 }
918
919 pub async fn market_buy(&self, symbol: &str, quantity: &str) -> Result<OrderFull> {
933 let order = OrderBuilder::new(symbol, OrderSide::Buy, OrderType::Market)
934 .quantity(quantity)
935 .build();
936 self.create_order(&order).await
937 }
938
939 pub async fn market_sell(&self, symbol: &str, quantity: &str) -> Result<OrderFull> {
953 let order = OrderBuilder::new(symbol, OrderSide::Sell, OrderType::Market)
954 .quantity(quantity)
955 .build();
956 self.create_order(&order).await
957 }
958
959 pub async fn market_buy_quote(&self, symbol: &str, quote_quantity: &str) -> Result<OrderFull> {
976 let order = OrderBuilder::new(symbol, OrderSide::Buy, OrderType::Market)
977 .quote_quantity(quote_quantity)
978 .build();
979 self.create_order(&order).await
980 }
981}
982
983#[derive(Debug, Clone)]
998pub struct OrderBuilder {
999 symbol: String,
1000 side: OrderSide,
1001 order_type: OrderType,
1002 quantity: Option<String>,
1003 quote_quantity: Option<String>,
1004 price: Option<String>,
1005 stop_price: Option<String>,
1006 time_in_force: Option<TimeInForce>,
1007 client_order_id: Option<String>,
1008 iceberg_qty: Option<String>,
1009 response_type: Option<OrderResponseType>,
1010}
1011
1012#[derive(Debug, Clone)]
1014pub struct CancelReplaceOrderBuilder {
1015 symbol: String,
1016 side: OrderSide,
1017 order_type: OrderType,
1018 cancel_replace_mode: CancelReplaceMode,
1019 time_in_force: Option<TimeInForce>,
1020 quantity: Option<String>,
1021 quote_quantity: Option<String>,
1022 price: Option<String>,
1023 cancel_new_client_order_id: Option<String>,
1024 cancel_orig_client_order_id: Option<String>,
1025 cancel_order_id: Option<u64>,
1026 new_client_order_id: Option<String>,
1027 strategy_id: Option<u64>,
1028 strategy_type: Option<i32>,
1029 stop_price: Option<String>,
1030 trailing_delta: Option<u64>,
1031 iceberg_qty: Option<String>,
1032 response_type: Option<OrderResponseType>,
1033 self_trade_prevention_mode: Option<String>,
1034 cancel_restrictions: Option<CancelRestrictions>,
1035 order_rate_limit_exceeded_mode: Option<OrderRateLimitExceededMode>,
1036 peg_price_type: Option<String>,
1037 peg_offset_value: Option<i32>,
1038 peg_offset_type: Option<String>,
1039}
1040
1041impl CancelReplaceOrderBuilder {
1042 pub fn new(
1044 symbol: &str,
1045 side: OrderSide,
1046 order_type: OrderType,
1047 cancel_replace_mode: CancelReplaceMode,
1048 ) -> Self {
1049 Self {
1050 symbol: symbol.to_string(),
1051 side,
1052 order_type,
1053 cancel_replace_mode,
1054 time_in_force: None,
1055 quantity: None,
1056 quote_quantity: None,
1057 price: None,
1058 cancel_new_client_order_id: None,
1059 cancel_orig_client_order_id: None,
1060 cancel_order_id: None,
1061 new_client_order_id: None,
1062 strategy_id: None,
1063 strategy_type: None,
1064 stop_price: None,
1065 trailing_delta: None,
1066 iceberg_qty: None,
1067 response_type: None,
1068 self_trade_prevention_mode: None,
1069 cancel_restrictions: None,
1070 order_rate_limit_exceeded_mode: None,
1071 peg_price_type: None,
1072 peg_offset_value: None,
1073 peg_offset_type: None,
1074 }
1075 }
1076
1077 pub fn quantity(mut self, quantity: &str) -> Self {
1079 self.quantity = Some(quantity.to_string());
1080 self
1081 }
1082
1083 pub fn quote_quantity(mut self, quantity: &str) -> Self {
1085 self.quote_quantity = Some(quantity.to_string());
1086 self
1087 }
1088
1089 pub fn price(mut self, price: &str) -> Self {
1091 self.price = Some(price.to_string());
1092 self
1093 }
1094
1095 pub fn stop_price(mut self, price: &str) -> Self {
1097 self.stop_price = Some(price.to_string());
1098 self
1099 }
1100
1101 pub fn time_in_force(mut self, tif: TimeInForce) -> Self {
1103 self.time_in_force = Some(tif);
1104 self
1105 }
1106
1107 pub fn cancel_new_client_order_id(mut self, id: &str) -> Self {
1109 self.cancel_new_client_order_id = Some(id.to_string());
1110 self
1111 }
1112
1113 pub fn cancel_orig_client_order_id(mut self, id: &str) -> Self {
1115 self.cancel_orig_client_order_id = Some(id.to_string());
1116 self
1117 }
1118
1119 pub fn cancel_order_id(mut self, id: u64) -> Self {
1121 self.cancel_order_id = Some(id);
1122 self
1123 }
1124
1125 pub fn new_client_order_id(mut self, id: &str) -> Self {
1127 self.new_client_order_id = Some(id.to_string());
1128 self
1129 }
1130
1131 pub fn strategy_id(mut self, id: u64) -> Self {
1133 self.strategy_id = Some(id);
1134 self
1135 }
1136
1137 pub fn strategy_type(mut self, strategy_type: i32) -> Self {
1139 self.strategy_type = Some(strategy_type);
1140 self
1141 }
1142
1143 pub fn trailing_delta(mut self, delta: u64) -> Self {
1145 self.trailing_delta = Some(delta);
1146 self
1147 }
1148
1149 pub fn iceberg_qty(mut self, qty: &str) -> Self {
1151 self.iceberg_qty = Some(qty.to_string());
1152 self
1153 }
1154
1155 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
1157 self.response_type = Some(resp_type);
1158 self
1159 }
1160
1161 pub fn self_trade_prevention_mode(mut self, mode: &str) -> Self {
1163 self.self_trade_prevention_mode = Some(mode.to_string());
1164 self
1165 }
1166
1167 pub fn cancel_restrictions(mut self, restrictions: CancelRestrictions) -> Self {
1169 self.cancel_restrictions = Some(restrictions);
1170 self
1171 }
1172
1173 pub fn order_rate_limit_exceeded_mode(mut self, mode: OrderRateLimitExceededMode) -> Self {
1175 self.order_rate_limit_exceeded_mode = Some(mode);
1176 self
1177 }
1178
1179 pub fn peg_price_type(mut self, peg_price_type: &str) -> Self {
1181 self.peg_price_type = Some(peg_price_type.to_string());
1182 self
1183 }
1184
1185 pub fn peg_offset_value(mut self, peg_offset_value: i32) -> Self {
1187 self.peg_offset_value = Some(peg_offset_value);
1188 self
1189 }
1190
1191 pub fn peg_offset_type(mut self, peg_offset_type: &str) -> Self {
1193 self.peg_offset_type = Some(peg_offset_type.to_string());
1194 self
1195 }
1196
1197 pub fn build(self) -> CancelReplaceOrder {
1199 CancelReplaceOrder {
1200 symbol: self.symbol,
1201 side: self.side,
1202 order_type: self.order_type,
1203 cancel_replace_mode: self.cancel_replace_mode,
1204 time_in_force: self.time_in_force,
1205 quantity: self.quantity,
1206 quote_quantity: self.quote_quantity,
1207 price: self.price,
1208 cancel_new_client_order_id: self.cancel_new_client_order_id,
1209 cancel_orig_client_order_id: self.cancel_orig_client_order_id,
1210 cancel_order_id: self.cancel_order_id,
1211 new_client_order_id: self.new_client_order_id,
1212 strategy_id: self.strategy_id,
1213 strategy_type: self.strategy_type,
1214 stop_price: self.stop_price,
1215 trailing_delta: self.trailing_delta,
1216 iceberg_qty: self.iceberg_qty,
1217 response_type: self.response_type,
1218 self_trade_prevention_mode: self.self_trade_prevention_mode,
1219 cancel_restrictions: self.cancel_restrictions,
1220 order_rate_limit_exceeded_mode: self.order_rate_limit_exceeded_mode,
1221 peg_price_type: self.peg_price_type,
1222 peg_offset_value: self.peg_offset_value,
1223 peg_offset_type: self.peg_offset_type,
1224 }
1225 }
1226}
1227
1228#[derive(Debug, Clone)]
1230pub struct CancelReplaceOrder {
1231 symbol: String,
1232 side: OrderSide,
1233 order_type: OrderType,
1234 cancel_replace_mode: CancelReplaceMode,
1235 time_in_force: Option<TimeInForce>,
1236 quantity: Option<String>,
1237 quote_quantity: Option<String>,
1238 price: Option<String>,
1239 cancel_new_client_order_id: Option<String>,
1240 cancel_orig_client_order_id: Option<String>,
1241 cancel_order_id: Option<u64>,
1242 new_client_order_id: Option<String>,
1243 strategy_id: Option<u64>,
1244 strategy_type: Option<i32>,
1245 stop_price: Option<String>,
1246 trailing_delta: Option<u64>,
1247 iceberg_qty: Option<String>,
1248 response_type: Option<OrderResponseType>,
1249 self_trade_prevention_mode: Option<String>,
1250 cancel_restrictions: Option<CancelRestrictions>,
1251 order_rate_limit_exceeded_mode: Option<OrderRateLimitExceededMode>,
1252 peg_price_type: Option<String>,
1253 peg_offset_value: Option<i32>,
1254 peg_offset_type: Option<String>,
1255}
1256
1257impl CancelReplaceOrder {
1258 fn to_params(&self) -> Vec<(String, String)> {
1259 let mut params = vec![
1260 ("symbol".to_string(), self.symbol.clone()),
1261 (
1262 "side".to_string(),
1263 format!("{:?}", self.side).to_uppercase(),
1264 ),
1265 (
1266 "type".to_string(),
1267 format!("{:?}", self.order_type).to_uppercase(),
1268 ),
1269 (
1270 "cancelReplaceMode".to_string(),
1271 self.cancel_replace_mode.to_string(),
1272 ),
1273 ];
1274
1275 if let Some(ref tif) = self.time_in_force {
1276 params.push(("timeInForce".to_string(), format!("{:?}", tif)));
1277 }
1278 if let Some(ref qty) = self.quantity {
1279 params.push(("quantity".to_string(), qty.clone()));
1280 }
1281 if let Some(ref qty) = self.quote_quantity {
1282 params.push(("quoteOrderQty".to_string(), qty.clone()));
1283 }
1284 if let Some(ref price) = self.price {
1285 params.push(("price".to_string(), price.clone()));
1286 }
1287 if let Some(ref id) = self.cancel_new_client_order_id {
1288 params.push(("cancelNewClientOrderId".to_string(), id.clone()));
1289 }
1290 if let Some(ref id) = self.cancel_orig_client_order_id {
1291 params.push(("cancelOrigClientOrderId".to_string(), id.clone()));
1292 }
1293 if let Some(id) = self.cancel_order_id {
1294 params.push(("cancelOrderId".to_string(), id.to_string()));
1295 }
1296 if let Some(ref id) = self.new_client_order_id {
1297 params.push(("newClientOrderId".to_string(), id.clone()));
1298 }
1299 if let Some(id) = self.strategy_id {
1300 params.push(("strategyId".to_string(), id.to_string()));
1301 }
1302 if let Some(id) = self.strategy_type {
1303 params.push(("strategyType".to_string(), id.to_string()));
1304 }
1305 if let Some(ref stop) = self.stop_price {
1306 params.push(("stopPrice".to_string(), stop.clone()));
1307 }
1308 if let Some(delta) = self.trailing_delta {
1309 params.push(("trailingDelta".to_string(), delta.to_string()));
1310 }
1311 if let Some(ref ice) = self.iceberg_qty {
1312 params.push(("icebergQty".to_string(), ice.clone()));
1313 }
1314 if let Some(ref resp) = self.response_type {
1315 params.push((
1316 "newOrderRespType".to_string(),
1317 format!("{:?}", resp).to_uppercase(),
1318 ));
1319 }
1320 if let Some(ref mode) = self.self_trade_prevention_mode {
1321 params.push(("selfTradePreventionMode".to_string(), mode.clone()));
1322 }
1323 if let Some(restrictions) = self.cancel_restrictions {
1324 params.push(("cancelRestrictions".to_string(), restrictions.to_string()));
1325 }
1326 if let Some(mode) = self.order_rate_limit_exceeded_mode {
1327 params.push(("orderRateLimitExceededMode".to_string(), mode.to_string()));
1328 }
1329 if let Some(ref peg) = self.peg_price_type {
1330 params.push(("pegPriceType".to_string(), peg.clone()));
1331 }
1332 if let Some(value) = self.peg_offset_value {
1333 params.push(("pegOffsetValue".to_string(), value.to_string()));
1334 }
1335 if let Some(ref peg) = self.peg_offset_type {
1336 params.push(("pegOffsetType".to_string(), peg.clone()));
1337 }
1338
1339 params
1340 }
1341}
1342
1343impl OrderBuilder {
1344 pub fn new(symbol: &str, side: OrderSide, order_type: OrderType) -> Self {
1346 Self {
1347 symbol: symbol.to_string(),
1348 side,
1349 order_type,
1350 quantity: None,
1351 quote_quantity: None,
1352 price: None,
1353 stop_price: None,
1354 time_in_force: None,
1355 client_order_id: None,
1356 iceberg_qty: None,
1357 response_type: None,
1358 }
1359 }
1360
1361 pub fn quantity(mut self, quantity: &str) -> Self {
1363 self.quantity = Some(quantity.to_string());
1364 self
1365 }
1366
1367 pub fn quote_quantity(mut self, quantity: &str) -> Self {
1369 self.quote_quantity = Some(quantity.to_string());
1370 self
1371 }
1372
1373 pub fn price(mut self, price: &str) -> Self {
1375 self.price = Some(price.to_string());
1376 self
1377 }
1378
1379 pub fn stop_price(mut self, price: &str) -> Self {
1381 self.stop_price = Some(price.to_string());
1382 self
1383 }
1384
1385 pub fn time_in_force(mut self, tif: TimeInForce) -> Self {
1387 self.time_in_force = Some(tif);
1388 self
1389 }
1390
1391 pub fn client_order_id(mut self, id: &str) -> Self {
1393 self.client_order_id = Some(id.to_string());
1394 self
1395 }
1396
1397 pub fn iceberg_qty(mut self, qty: &str) -> Self {
1399 self.iceberg_qty = Some(qty.to_string());
1400 self
1401 }
1402
1403 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
1405 self.response_type = Some(resp_type);
1406 self
1407 }
1408
1409 pub fn build(self) -> NewOrder {
1411 NewOrder {
1412 symbol: self.symbol,
1413 side: self.side,
1414 order_type: self.order_type,
1415 quantity: self.quantity,
1416 quote_quantity: self.quote_quantity,
1417 price: self.price,
1418 stop_price: self.stop_price,
1419 time_in_force: self.time_in_force,
1420 client_order_id: self.client_order_id,
1421 iceberg_qty: self.iceberg_qty,
1422 response_type: self.response_type,
1423 }
1424 }
1425}
1426
1427#[derive(Debug, Clone, Serialize)]
1429#[serde(rename_all = "camelCase")]
1430pub struct NewOrder {
1431 symbol: String,
1432 side: OrderSide,
1433 #[serde(rename = "type")]
1434 order_type: OrderType,
1435 #[serde(skip_serializing_if = "Option::is_none")]
1436 quantity: Option<String>,
1437 #[serde(skip_serializing_if = "Option::is_none", rename = "quoteOrderQty")]
1438 quote_quantity: Option<String>,
1439 #[serde(skip_serializing_if = "Option::is_none")]
1440 price: Option<String>,
1441 #[serde(skip_serializing_if = "Option::is_none")]
1442 stop_price: Option<String>,
1443 #[serde(skip_serializing_if = "Option::is_none")]
1444 time_in_force: Option<TimeInForce>,
1445 #[serde(skip_serializing_if = "Option::is_none", rename = "newClientOrderId")]
1446 client_order_id: Option<String>,
1447 #[serde(skip_serializing_if = "Option::is_none")]
1448 iceberg_qty: Option<String>,
1449 #[serde(skip_serializing_if = "Option::is_none", rename = "newOrderRespType")]
1450 response_type: Option<OrderResponseType>,
1451}
1452
1453impl NewOrder {
1454 fn to_params(&self) -> Vec<(String, String)> {
1455 let mut params = vec![
1456 ("symbol".to_string(), self.symbol.clone()),
1457 (
1458 "side".to_string(),
1459 format!("{:?}", self.side).to_uppercase(),
1460 ),
1461 (
1462 "type".to_string(),
1463 format!("{:?}", self.order_type).to_uppercase(),
1464 ),
1465 ];
1466
1467 if let Some(ref qty) = self.quantity {
1468 params.push(("quantity".to_string(), qty.clone()));
1469 }
1470 if let Some(ref qty) = self.quote_quantity {
1471 params.push(("quoteOrderQty".to_string(), qty.clone()));
1472 }
1473 if let Some(ref price) = self.price {
1474 params.push(("price".to_string(), price.clone()));
1475 }
1476 if let Some(ref stop) = self.stop_price {
1477 params.push(("stopPrice".to_string(), stop.clone()));
1478 }
1479 if let Some(ref tif) = self.time_in_force {
1480 params.push(("timeInForce".to_string(), format!("{:?}", tif)));
1481 }
1482 if let Some(ref cid) = self.client_order_id {
1483 params.push(("newClientOrderId".to_string(), cid.clone()));
1484 }
1485 if let Some(ref ice) = self.iceberg_qty {
1486 params.push(("icebergQty".to_string(), ice.clone()));
1487 }
1488 if let Some(ref resp) = self.response_type {
1489 params.push((
1490 "newOrderRespType".to_string(),
1491 format!("{:?}", resp).to_uppercase(),
1492 ));
1493 }
1494
1495 params
1496 }
1497}
1498
1499#[derive(Debug, Clone)]
1501pub struct OcoOrderBuilder {
1502 symbol: String,
1503 side: OrderSide,
1504 quantity: String,
1505 price: String,
1506 stop_price: String,
1507 stop_limit_price: Option<String>,
1508 stop_limit_time_in_force: Option<TimeInForce>,
1509 list_client_order_id: Option<String>,
1510 limit_client_order_id: Option<String>,
1511 stop_client_order_id: Option<String>,
1512}
1513
1514impl OcoOrderBuilder {
1515 pub fn new(
1525 symbol: &str,
1526 side: OrderSide,
1527 quantity: &str,
1528 price: &str,
1529 stop_price: &str,
1530 ) -> Self {
1531 Self {
1532 symbol: symbol.to_string(),
1533 side,
1534 quantity: quantity.to_string(),
1535 price: price.to_string(),
1536 stop_price: stop_price.to_string(),
1537 stop_limit_price: None,
1538 stop_limit_time_in_force: None,
1539 list_client_order_id: None,
1540 limit_client_order_id: None,
1541 stop_client_order_id: None,
1542 }
1543 }
1544
1545 pub fn stop_limit_price(mut self, price: &str) -> Self {
1547 self.stop_limit_price = Some(price.to_string());
1548 self
1549 }
1550
1551 pub fn stop_limit_time_in_force(mut self, tif: TimeInForce) -> Self {
1553 self.stop_limit_time_in_force = Some(tif);
1554 self
1555 }
1556
1557 pub fn list_client_order_id(mut self, id: &str) -> Self {
1559 self.list_client_order_id = Some(id.to_string());
1560 self
1561 }
1562
1563 pub fn limit_client_order_id(mut self, id: &str) -> Self {
1565 self.limit_client_order_id = Some(id.to_string());
1566 self
1567 }
1568
1569 pub fn stop_client_order_id(mut self, id: &str) -> Self {
1571 self.stop_client_order_id = Some(id.to_string());
1572 self
1573 }
1574
1575 pub fn build(self) -> NewOcoOrder {
1577 NewOcoOrder {
1578 symbol: self.symbol,
1579 side: self.side,
1580 quantity: self.quantity,
1581 price: self.price,
1582 stop_price: self.stop_price,
1583 stop_limit_price: self.stop_limit_price,
1584 stop_limit_time_in_force: self.stop_limit_time_in_force,
1585 list_client_order_id: self.list_client_order_id,
1586 limit_client_order_id: self.limit_client_order_id,
1587 stop_client_order_id: self.stop_client_order_id,
1588 }
1589 }
1590}
1591
1592#[derive(Debug, Clone)]
1594pub struct NewOcoOrder {
1595 symbol: String,
1596 side: OrderSide,
1597 quantity: String,
1598 price: String,
1599 stop_price: String,
1600 stop_limit_price: Option<String>,
1601 stop_limit_time_in_force: Option<TimeInForce>,
1602 list_client_order_id: Option<String>,
1603 limit_client_order_id: Option<String>,
1604 stop_client_order_id: Option<String>,
1605}
1606
1607impl NewOcoOrder {
1608 fn to_params(&self) -> Vec<(String, String)> {
1609 let mut params = vec![
1610 ("symbol".to_string(), self.symbol.clone()),
1611 (
1612 "side".to_string(),
1613 format!("{:?}", self.side).to_uppercase(),
1614 ),
1615 ("quantity".to_string(), self.quantity.clone()),
1616 ("price".to_string(), self.price.clone()),
1617 ("stopPrice".to_string(), self.stop_price.clone()),
1618 ];
1619
1620 if let Some(ref slp) = self.stop_limit_price {
1621 params.push(("stopLimitPrice".to_string(), slp.clone()));
1622 }
1623 if let Some(ref tif) = self.stop_limit_time_in_force {
1624 params.push(("stopLimitTimeInForce".to_string(), format!("{:?}", tif)));
1625 }
1626 if let Some(ref id) = self.list_client_order_id {
1627 params.push(("listClientOrderId".to_string(), id.clone()));
1628 }
1629 if let Some(ref id) = self.limit_client_order_id {
1630 params.push(("limitClientOrderId".to_string(), id.clone()));
1631 }
1632 if let Some(ref id) = self.stop_client_order_id {
1633 params.push(("stopClientOrderId".to_string(), id.clone()));
1634 }
1635
1636 params
1637 }
1638}
1639
1640#[derive(Debug, Clone)]
1642pub struct OtoOrderBuilder {
1643 symbol: String,
1644 working_type: OrderType,
1645 working_side: OrderSide,
1646 working_price: String,
1647 working_quantity: String,
1648 pending_type: OrderType,
1649 pending_side: OrderSide,
1650 pending_quantity: String,
1651 list_client_order_id: Option<String>,
1652 response_type: Option<OrderResponseType>,
1653 self_trade_prevention_mode: Option<String>,
1654 working_client_order_id: Option<String>,
1655 working_iceberg_qty: Option<String>,
1656 working_time_in_force: Option<TimeInForce>,
1657 working_strategy_id: Option<u64>,
1658 working_strategy_type: Option<i32>,
1659 working_peg_price_type: Option<String>,
1660 working_peg_offset_type: Option<String>,
1661 working_peg_offset_value: Option<i32>,
1662 pending_client_order_id: Option<String>,
1663 pending_price: Option<String>,
1664 pending_stop_price: Option<String>,
1665 pending_trailing_delta: Option<u64>,
1666 pending_iceberg_qty: Option<String>,
1667 pending_time_in_force: Option<TimeInForce>,
1668 pending_strategy_id: Option<u64>,
1669 pending_strategy_type: Option<i32>,
1670 pending_peg_price_type: Option<String>,
1671 pending_peg_offset_type: Option<String>,
1672 pending_peg_offset_value: Option<i32>,
1673}
1674
1675impl OtoOrderBuilder {
1676 #[allow(clippy::too_many_arguments)]
1678 pub fn new(
1679 symbol: &str,
1680 working_type: OrderType,
1681 working_side: OrderSide,
1682 working_price: &str,
1683 working_quantity: &str,
1684 pending_type: OrderType,
1685 pending_side: OrderSide,
1686 pending_quantity: &str,
1687 ) -> Self {
1688 Self {
1689 symbol: symbol.to_string(),
1690 working_type,
1691 working_side,
1692 working_price: working_price.to_string(),
1693 working_quantity: working_quantity.to_string(),
1694 pending_type,
1695 pending_side,
1696 pending_quantity: pending_quantity.to_string(),
1697 list_client_order_id: None,
1698 response_type: None,
1699 self_trade_prevention_mode: None,
1700 working_client_order_id: None,
1701 working_iceberg_qty: None,
1702 working_time_in_force: None,
1703 working_strategy_id: None,
1704 working_strategy_type: None,
1705 working_peg_price_type: None,
1706 working_peg_offset_type: None,
1707 working_peg_offset_value: None,
1708 pending_client_order_id: None,
1709 pending_price: None,
1710 pending_stop_price: None,
1711 pending_trailing_delta: None,
1712 pending_iceberg_qty: None,
1713 pending_time_in_force: None,
1714 pending_strategy_id: None,
1715 pending_strategy_type: None,
1716 pending_peg_price_type: None,
1717 pending_peg_offset_type: None,
1718 pending_peg_offset_value: None,
1719 }
1720 }
1721
1722 pub fn list_client_order_id(mut self, id: &str) -> Self {
1723 self.list_client_order_id = Some(id.to_string());
1724 self
1725 }
1726
1727 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
1728 self.response_type = Some(resp_type);
1729 self
1730 }
1731
1732 pub fn self_trade_prevention_mode(mut self, mode: &str) -> Self {
1733 self.self_trade_prevention_mode = Some(mode.to_string());
1734 self
1735 }
1736
1737 pub fn working_client_order_id(mut self, id: &str) -> Self {
1738 self.working_client_order_id = Some(id.to_string());
1739 self
1740 }
1741
1742 pub fn working_iceberg_qty(mut self, qty: &str) -> Self {
1743 self.working_iceberg_qty = Some(qty.to_string());
1744 self
1745 }
1746
1747 pub fn working_time_in_force(mut self, tif: TimeInForce) -> Self {
1748 self.working_time_in_force = Some(tif);
1749 self
1750 }
1751
1752 pub fn working_strategy_id(mut self, id: u64) -> Self {
1753 self.working_strategy_id = Some(id);
1754 self
1755 }
1756
1757 pub fn working_strategy_type(mut self, strategy_type: i32) -> Self {
1758 self.working_strategy_type = Some(strategy_type);
1759 self
1760 }
1761
1762 pub fn working_peg_price_type(mut self, peg_price_type: &str) -> Self {
1763 self.working_peg_price_type = Some(peg_price_type.to_string());
1764 self
1765 }
1766
1767 pub fn working_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
1768 self.working_peg_offset_type = Some(peg_offset_type.to_string());
1769 self
1770 }
1771
1772 pub fn working_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
1773 self.working_peg_offset_value = Some(peg_offset_value);
1774 self
1775 }
1776
1777 pub fn pending_client_order_id(mut self, id: &str) -> Self {
1778 self.pending_client_order_id = Some(id.to_string());
1779 self
1780 }
1781
1782 pub fn pending_price(mut self, price: &str) -> Self {
1783 self.pending_price = Some(price.to_string());
1784 self
1785 }
1786
1787 pub fn pending_stop_price(mut self, price: &str) -> Self {
1788 self.pending_stop_price = Some(price.to_string());
1789 self
1790 }
1791
1792 pub fn pending_trailing_delta(mut self, delta: u64) -> Self {
1793 self.pending_trailing_delta = Some(delta);
1794 self
1795 }
1796
1797 pub fn pending_iceberg_qty(mut self, qty: &str) -> Self {
1798 self.pending_iceberg_qty = Some(qty.to_string());
1799 self
1800 }
1801
1802 pub fn pending_time_in_force(mut self, tif: TimeInForce) -> Self {
1803 self.pending_time_in_force = Some(tif);
1804 self
1805 }
1806
1807 pub fn pending_strategy_id(mut self, id: u64) -> Self {
1808 self.pending_strategy_id = Some(id);
1809 self
1810 }
1811
1812 pub fn pending_strategy_type(mut self, strategy_type: i32) -> Self {
1813 self.pending_strategy_type = Some(strategy_type);
1814 self
1815 }
1816
1817 pub fn pending_peg_price_type(mut self, peg_price_type: &str) -> Self {
1818 self.pending_peg_price_type = Some(peg_price_type.to_string());
1819 self
1820 }
1821
1822 pub fn pending_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
1823 self.pending_peg_offset_type = Some(peg_offset_type.to_string());
1824 self
1825 }
1826
1827 pub fn pending_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
1828 self.pending_peg_offset_value = Some(peg_offset_value);
1829 self
1830 }
1831
1832 pub fn build(self) -> NewOtoOrder {
1833 NewOtoOrder {
1834 symbol: self.symbol,
1835 working_type: self.working_type,
1836 working_side: self.working_side,
1837 working_price: self.working_price,
1838 working_quantity: self.working_quantity,
1839 pending_type: self.pending_type,
1840 pending_side: self.pending_side,
1841 pending_quantity: Some(self.pending_quantity),
1842 list_client_order_id: self.list_client_order_id,
1843 response_type: self.response_type,
1844 self_trade_prevention_mode: self.self_trade_prevention_mode,
1845 working_client_order_id: self.working_client_order_id,
1846 working_iceberg_qty: self.working_iceberg_qty,
1847 working_time_in_force: self.working_time_in_force,
1848 working_strategy_id: self.working_strategy_id,
1849 working_strategy_type: self.working_strategy_type,
1850 working_peg_price_type: self.working_peg_price_type,
1851 working_peg_offset_type: self.working_peg_offset_type,
1852 working_peg_offset_value: self.working_peg_offset_value,
1853 pending_client_order_id: self.pending_client_order_id,
1854 pending_price: self.pending_price,
1855 pending_stop_price: self.pending_stop_price,
1856 pending_trailing_delta: self.pending_trailing_delta,
1857 pending_iceberg_qty: self.pending_iceberg_qty,
1858 pending_time_in_force: self.pending_time_in_force,
1859 pending_strategy_id: self.pending_strategy_id,
1860 pending_strategy_type: self.pending_strategy_type,
1861 pending_peg_price_type: self.pending_peg_price_type,
1862 pending_peg_offset_type: self.pending_peg_offset_type,
1863 pending_peg_offset_value: self.pending_peg_offset_value,
1864 }
1865 }
1866}
1867
1868#[derive(Debug, Clone)]
1870pub struct NewOtoOrder {
1871 symbol: String,
1872 working_type: OrderType,
1873 working_side: OrderSide,
1874 working_price: String,
1875 working_quantity: String,
1876 pending_type: OrderType,
1877 pending_side: OrderSide,
1878 pending_quantity: Option<String>,
1879 list_client_order_id: Option<String>,
1880 response_type: Option<OrderResponseType>,
1881 self_trade_prevention_mode: Option<String>,
1882 working_client_order_id: Option<String>,
1883 working_iceberg_qty: Option<String>,
1884 working_time_in_force: Option<TimeInForce>,
1885 working_strategy_id: Option<u64>,
1886 working_strategy_type: Option<i32>,
1887 working_peg_price_type: Option<String>,
1888 working_peg_offset_type: Option<String>,
1889 working_peg_offset_value: Option<i32>,
1890 pending_client_order_id: Option<String>,
1891 pending_price: Option<String>,
1892 pending_stop_price: Option<String>,
1893 pending_trailing_delta: Option<u64>,
1894 pending_iceberg_qty: Option<String>,
1895 pending_time_in_force: Option<TimeInForce>,
1896 pending_strategy_id: Option<u64>,
1897 pending_strategy_type: Option<i32>,
1898 pending_peg_price_type: Option<String>,
1899 pending_peg_offset_type: Option<String>,
1900 pending_peg_offset_value: Option<i32>,
1901}
1902
1903impl NewOtoOrder {
1904 fn to_params(&self) -> Vec<(String, String)> {
1905 let mut params = vec![
1906 ("symbol".to_string(), self.symbol.clone()),
1907 (
1908 "workingType".to_string(),
1909 format!("{:?}", self.working_type).to_uppercase(),
1910 ),
1911 (
1912 "workingSide".to_string(),
1913 format!("{:?}", self.working_side).to_uppercase(),
1914 ),
1915 ("workingPrice".to_string(), self.working_price.clone()),
1916 ("workingQuantity".to_string(), self.working_quantity.clone()),
1917 (
1918 "pendingType".to_string(),
1919 format!("{:?}", self.pending_type).to_uppercase(),
1920 ),
1921 (
1922 "pendingSide".to_string(),
1923 format!("{:?}", self.pending_side).to_uppercase(),
1924 ),
1925 ];
1926
1927 if let Some(ref qty) = self.pending_quantity {
1928 params.push(("pendingQuantity".to_string(), qty.clone()));
1929 }
1930 if let Some(ref id) = self.list_client_order_id {
1931 params.push(("listClientOrderId".to_string(), id.clone()));
1932 }
1933 if let Some(ref resp) = self.response_type {
1934 params.push((
1935 "newOrderRespType".to_string(),
1936 format!("{:?}", resp).to_uppercase(),
1937 ));
1938 }
1939 if let Some(ref mode) = self.self_trade_prevention_mode {
1940 params.push(("selfTradePreventionMode".to_string(), mode.clone()));
1941 }
1942 if let Some(ref id) = self.working_client_order_id {
1943 params.push(("workingClientOrderId".to_string(), id.clone()));
1944 }
1945 if let Some(ref qty) = self.working_iceberg_qty {
1946 params.push(("workingIcebergQty".to_string(), qty.clone()));
1947 }
1948 if let Some(ref tif) = self.working_time_in_force {
1949 params.push(("workingTimeInForce".to_string(), format!("{:?}", tif)));
1950 }
1951 if let Some(id) = self.working_strategy_id {
1952 params.push(("workingStrategyId".to_string(), id.to_string()));
1953 }
1954 if let Some(id) = self.working_strategy_type {
1955 params.push(("workingStrategyType".to_string(), id.to_string()));
1956 }
1957 if let Some(ref peg) = self.working_peg_price_type {
1958 params.push(("workingPegPriceType".to_string(), peg.clone()));
1959 }
1960 if let Some(ref peg) = self.working_peg_offset_type {
1961 params.push(("workingPegOffsetType".to_string(), peg.clone()));
1962 }
1963 if let Some(value) = self.working_peg_offset_value {
1964 params.push(("workingPegOffsetValue".to_string(), value.to_string()));
1965 }
1966 if let Some(ref id) = self.pending_client_order_id {
1967 params.push(("pendingClientOrderId".to_string(), id.clone()));
1968 }
1969 if let Some(ref price) = self.pending_price {
1970 params.push(("pendingPrice".to_string(), price.clone()));
1971 }
1972 if let Some(ref price) = self.pending_stop_price {
1973 params.push(("pendingStopPrice".to_string(), price.clone()));
1974 }
1975 if let Some(delta) = self.pending_trailing_delta {
1976 params.push(("pendingTrailingDelta".to_string(), delta.to_string()));
1977 }
1978 if let Some(ref qty) = self.pending_iceberg_qty {
1979 params.push(("pendingIcebergQty".to_string(), qty.clone()));
1980 }
1981 if let Some(ref tif) = self.pending_time_in_force {
1982 params.push(("pendingTimeInForce".to_string(), format!("{:?}", tif)));
1983 }
1984 if let Some(id) = self.pending_strategy_id {
1985 params.push(("pendingStrategyId".to_string(), id.to_string()));
1986 }
1987 if let Some(id) = self.pending_strategy_type {
1988 params.push(("pendingStrategyType".to_string(), id.to_string()));
1989 }
1990 if let Some(ref peg) = self.pending_peg_price_type {
1991 params.push(("pendingPegPriceType".to_string(), peg.clone()));
1992 }
1993 if let Some(ref peg) = self.pending_peg_offset_type {
1994 params.push(("pendingPegOffsetType".to_string(), peg.clone()));
1995 }
1996 if let Some(value) = self.pending_peg_offset_value {
1997 params.push(("pendingPegOffsetValue".to_string(), value.to_string()));
1998 }
1999
2000 params
2001 }
2002}
2003
2004#[derive(Debug, Clone)]
2006pub struct OpoOrderBuilder {
2007 inner: NewOtoOrder,
2008}
2009
2010impl OpoOrderBuilder {
2011 pub fn new(
2013 symbol: &str,
2014 working_type: OrderType,
2015 working_side: OrderSide,
2016 working_price: &str,
2017 working_quantity: &str,
2018 pending_type: OrderType,
2019 pending_side: OrderSide,
2020 ) -> Self {
2021 Self {
2022 inner: NewOtoOrder {
2023 symbol: symbol.to_string(),
2024 working_type,
2025 working_side,
2026 working_price: working_price.to_string(),
2027 working_quantity: working_quantity.to_string(),
2028 pending_type,
2029 pending_side,
2030 pending_quantity: None,
2031 list_client_order_id: None,
2032 response_type: None,
2033 self_trade_prevention_mode: None,
2034 working_client_order_id: None,
2035 working_iceberg_qty: None,
2036 working_time_in_force: None,
2037 working_strategy_id: None,
2038 working_strategy_type: None,
2039 working_peg_price_type: None,
2040 working_peg_offset_type: None,
2041 working_peg_offset_value: None,
2042 pending_client_order_id: None,
2043 pending_price: None,
2044 pending_stop_price: None,
2045 pending_trailing_delta: None,
2046 pending_iceberg_qty: None,
2047 pending_time_in_force: None,
2048 pending_strategy_id: None,
2049 pending_strategy_type: None,
2050 pending_peg_price_type: None,
2051 pending_peg_offset_type: None,
2052 pending_peg_offset_value: None,
2053 },
2054 }
2055 }
2056
2057 pub fn list_client_order_id(mut self, id: &str) -> Self {
2058 self.inner.list_client_order_id = Some(id.to_string());
2059 self
2060 }
2061
2062 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
2063 self.inner.response_type = Some(resp_type);
2064 self
2065 }
2066
2067 pub fn self_trade_prevention_mode(mut self, mode: &str) -> Self {
2068 self.inner.self_trade_prevention_mode = Some(mode.to_string());
2069 self
2070 }
2071
2072 pub fn working_client_order_id(mut self, id: &str) -> Self {
2073 self.inner.working_client_order_id = Some(id.to_string());
2074 self
2075 }
2076
2077 pub fn working_iceberg_qty(mut self, qty: &str) -> Self {
2078 self.inner.working_iceberg_qty = Some(qty.to_string());
2079 self
2080 }
2081
2082 pub fn working_time_in_force(mut self, tif: TimeInForce) -> Self {
2083 self.inner.working_time_in_force = Some(tif);
2084 self
2085 }
2086
2087 pub fn working_strategy_id(mut self, id: u64) -> Self {
2088 self.inner.working_strategy_id = Some(id);
2089 self
2090 }
2091
2092 pub fn working_strategy_type(mut self, strategy_type: i32) -> Self {
2093 self.inner.working_strategy_type = Some(strategy_type);
2094 self
2095 }
2096
2097 pub fn working_peg_price_type(mut self, peg_price_type: &str) -> Self {
2098 self.inner.working_peg_price_type = Some(peg_price_type.to_string());
2099 self
2100 }
2101
2102 pub fn working_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2103 self.inner.working_peg_offset_type = Some(peg_offset_type.to_string());
2104 self
2105 }
2106
2107 pub fn working_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2108 self.inner.working_peg_offset_value = Some(peg_offset_value);
2109 self
2110 }
2111
2112 pub fn pending_client_order_id(mut self, id: &str) -> Self {
2113 self.inner.pending_client_order_id = Some(id.to_string());
2114 self
2115 }
2116
2117 pub fn pending_quantity(mut self, qty: &str) -> Self {
2118 self.inner.pending_quantity = Some(qty.to_string());
2119 self
2120 }
2121
2122 pub fn pending_price(mut self, price: &str) -> Self {
2123 self.inner.pending_price = Some(price.to_string());
2124 self
2125 }
2126
2127 pub fn pending_stop_price(mut self, price: &str) -> Self {
2128 self.inner.pending_stop_price = Some(price.to_string());
2129 self
2130 }
2131
2132 pub fn pending_trailing_delta(mut self, delta: u64) -> Self {
2133 self.inner.pending_trailing_delta = Some(delta);
2134 self
2135 }
2136
2137 pub fn pending_iceberg_qty(mut self, qty: &str) -> Self {
2138 self.inner.pending_iceberg_qty = Some(qty.to_string());
2139 self
2140 }
2141
2142 pub fn pending_time_in_force(mut self, tif: TimeInForce) -> Self {
2143 self.inner.pending_time_in_force = Some(tif);
2144 self
2145 }
2146
2147 pub fn pending_strategy_id(mut self, id: u64) -> Self {
2148 self.inner.pending_strategy_id = Some(id);
2149 self
2150 }
2151
2152 pub fn pending_strategy_type(mut self, strategy_type: i32) -> Self {
2153 self.inner.pending_strategy_type = Some(strategy_type);
2154 self
2155 }
2156
2157 pub fn pending_peg_price_type(mut self, peg_price_type: &str) -> Self {
2158 self.inner.pending_peg_price_type = Some(peg_price_type.to_string());
2159 self
2160 }
2161
2162 pub fn pending_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2163 self.inner.pending_peg_offset_type = Some(peg_offset_type.to_string());
2164 self
2165 }
2166
2167 pub fn pending_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2168 self.inner.pending_peg_offset_value = Some(peg_offset_value);
2169 self
2170 }
2171
2172 pub fn build(self) -> NewOpoOrder {
2173 NewOpoOrder { inner: self.inner }
2174 }
2175}
2176
2177#[derive(Debug, Clone)]
2179pub struct NewOpoOrder {
2180 inner: NewOtoOrder,
2181}
2182
2183impl NewOpoOrder {
2184 fn to_params(&self) -> Vec<(String, String)> {
2185 self.inner.to_params()
2186 }
2187}
2188
2189#[derive(Debug, Clone)]
2191pub struct OtocoOrderBuilder {
2192 symbol: String,
2193 working_type: OrderType,
2194 working_side: OrderSide,
2195 working_price: String,
2196 working_quantity: String,
2197 pending_side: OrderSide,
2198 pending_quantity: String,
2199 pending_above_type: OrderType,
2200 list_client_order_id: Option<String>,
2201 response_type: Option<OrderResponseType>,
2202 self_trade_prevention_mode: Option<String>,
2203 working_client_order_id: Option<String>,
2204 working_iceberg_qty: Option<String>,
2205 working_time_in_force: Option<TimeInForce>,
2206 working_strategy_id: Option<u64>,
2207 working_strategy_type: Option<i32>,
2208 working_peg_price_type: Option<String>,
2209 working_peg_offset_type: Option<String>,
2210 working_peg_offset_value: Option<i32>,
2211 pending_above_client_order_id: Option<String>,
2212 pending_above_price: Option<String>,
2213 pending_above_stop_price: Option<String>,
2214 pending_above_trailing_delta: Option<u64>,
2215 pending_above_iceberg_qty: Option<String>,
2216 pending_above_time_in_force: Option<TimeInForce>,
2217 pending_above_strategy_id: Option<u64>,
2218 pending_above_strategy_type: Option<i32>,
2219 pending_above_peg_price_type: Option<String>,
2220 pending_above_peg_offset_type: Option<String>,
2221 pending_above_peg_offset_value: Option<i32>,
2222 pending_below_type: Option<OrderType>,
2223 pending_below_client_order_id: Option<String>,
2224 pending_below_price: Option<String>,
2225 pending_below_stop_price: Option<String>,
2226 pending_below_trailing_delta: Option<u64>,
2227 pending_below_iceberg_qty: Option<String>,
2228 pending_below_time_in_force: Option<TimeInForce>,
2229 pending_below_strategy_id: Option<u64>,
2230 pending_below_strategy_type: Option<i32>,
2231 pending_below_peg_price_type: Option<String>,
2232 pending_below_peg_offset_type: Option<String>,
2233 pending_below_peg_offset_value: Option<i32>,
2234}
2235
2236impl OtocoOrderBuilder {
2237 #[allow(clippy::too_many_arguments)]
2239 pub fn new(
2240 symbol: &str,
2241 working_type: OrderType,
2242 working_side: OrderSide,
2243 working_price: &str,
2244 working_quantity: &str,
2245 pending_side: OrderSide,
2246 pending_quantity: &str,
2247 pending_above_type: OrderType,
2248 ) -> Self {
2249 Self {
2250 symbol: symbol.to_string(),
2251 working_type,
2252 working_side,
2253 working_price: working_price.to_string(),
2254 working_quantity: working_quantity.to_string(),
2255 pending_side,
2256 pending_quantity: pending_quantity.to_string(),
2257 pending_above_type,
2258 list_client_order_id: None,
2259 response_type: None,
2260 self_trade_prevention_mode: None,
2261 working_client_order_id: None,
2262 working_iceberg_qty: None,
2263 working_time_in_force: None,
2264 working_strategy_id: None,
2265 working_strategy_type: None,
2266 working_peg_price_type: None,
2267 working_peg_offset_type: None,
2268 working_peg_offset_value: None,
2269 pending_above_client_order_id: None,
2270 pending_above_price: None,
2271 pending_above_stop_price: None,
2272 pending_above_trailing_delta: None,
2273 pending_above_iceberg_qty: None,
2274 pending_above_time_in_force: None,
2275 pending_above_strategy_id: None,
2276 pending_above_strategy_type: None,
2277 pending_above_peg_price_type: None,
2278 pending_above_peg_offset_type: None,
2279 pending_above_peg_offset_value: None,
2280 pending_below_type: None,
2281 pending_below_client_order_id: None,
2282 pending_below_price: None,
2283 pending_below_stop_price: None,
2284 pending_below_trailing_delta: None,
2285 pending_below_iceberg_qty: None,
2286 pending_below_time_in_force: None,
2287 pending_below_strategy_id: None,
2288 pending_below_strategy_type: None,
2289 pending_below_peg_price_type: None,
2290 pending_below_peg_offset_type: None,
2291 pending_below_peg_offset_value: None,
2292 }
2293 }
2294
2295 pub fn list_client_order_id(mut self, id: &str) -> Self {
2296 self.list_client_order_id = Some(id.to_string());
2297 self
2298 }
2299
2300 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
2301 self.response_type = Some(resp_type);
2302 self
2303 }
2304
2305 pub fn self_trade_prevention_mode(mut self, mode: &str) -> Self {
2306 self.self_trade_prevention_mode = Some(mode.to_string());
2307 self
2308 }
2309
2310 pub fn working_client_order_id(mut self, id: &str) -> Self {
2311 self.working_client_order_id = Some(id.to_string());
2312 self
2313 }
2314
2315 pub fn working_iceberg_qty(mut self, qty: &str) -> Self {
2316 self.working_iceberg_qty = Some(qty.to_string());
2317 self
2318 }
2319
2320 pub fn working_time_in_force(mut self, tif: TimeInForce) -> Self {
2321 self.working_time_in_force = Some(tif);
2322 self
2323 }
2324
2325 pub fn working_strategy_id(mut self, id: u64) -> Self {
2326 self.working_strategy_id = Some(id);
2327 self
2328 }
2329
2330 pub fn working_strategy_type(mut self, strategy_type: i32) -> Self {
2331 self.working_strategy_type = Some(strategy_type);
2332 self
2333 }
2334
2335 pub fn working_peg_price_type(mut self, peg_price_type: &str) -> Self {
2336 self.working_peg_price_type = Some(peg_price_type.to_string());
2337 self
2338 }
2339
2340 pub fn working_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2341 self.working_peg_offset_type = Some(peg_offset_type.to_string());
2342 self
2343 }
2344
2345 pub fn working_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2346 self.working_peg_offset_value = Some(peg_offset_value);
2347 self
2348 }
2349
2350 pub fn pending_above_client_order_id(mut self, id: &str) -> Self {
2351 self.pending_above_client_order_id = Some(id.to_string());
2352 self
2353 }
2354
2355 pub fn pending_above_price(mut self, price: &str) -> Self {
2356 self.pending_above_price = Some(price.to_string());
2357 self
2358 }
2359
2360 pub fn pending_above_stop_price(mut self, price: &str) -> Self {
2361 self.pending_above_stop_price = Some(price.to_string());
2362 self
2363 }
2364
2365 pub fn pending_above_trailing_delta(mut self, delta: u64) -> Self {
2366 self.pending_above_trailing_delta = Some(delta);
2367 self
2368 }
2369
2370 pub fn pending_above_iceberg_qty(mut self, qty: &str) -> Self {
2371 self.pending_above_iceberg_qty = Some(qty.to_string());
2372 self
2373 }
2374
2375 pub fn pending_above_time_in_force(mut self, tif: TimeInForce) -> Self {
2376 self.pending_above_time_in_force = Some(tif);
2377 self
2378 }
2379
2380 pub fn pending_above_strategy_id(mut self, id: u64) -> Self {
2381 self.pending_above_strategy_id = Some(id);
2382 self
2383 }
2384
2385 pub fn pending_above_strategy_type(mut self, strategy_type: i32) -> Self {
2386 self.pending_above_strategy_type = Some(strategy_type);
2387 self
2388 }
2389
2390 pub fn pending_above_peg_price_type(mut self, peg_price_type: &str) -> Self {
2391 self.pending_above_peg_price_type = Some(peg_price_type.to_string());
2392 self
2393 }
2394
2395 pub fn pending_above_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2396 self.pending_above_peg_offset_type = Some(peg_offset_type.to_string());
2397 self
2398 }
2399
2400 pub fn pending_above_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2401 self.pending_above_peg_offset_value = Some(peg_offset_value);
2402 self
2403 }
2404
2405 pub fn pending_below_type(mut self, order_type: OrderType) -> Self {
2406 self.pending_below_type = Some(order_type);
2407 self
2408 }
2409
2410 pub fn pending_below_client_order_id(mut self, id: &str) -> Self {
2411 self.pending_below_client_order_id = Some(id.to_string());
2412 self
2413 }
2414
2415 pub fn pending_below_price(mut self, price: &str) -> Self {
2416 self.pending_below_price = Some(price.to_string());
2417 self
2418 }
2419
2420 pub fn pending_below_stop_price(mut self, price: &str) -> Self {
2421 self.pending_below_stop_price = Some(price.to_string());
2422 self
2423 }
2424
2425 pub fn pending_below_trailing_delta(mut self, delta: u64) -> Self {
2426 self.pending_below_trailing_delta = Some(delta);
2427 self
2428 }
2429
2430 pub fn pending_below_iceberg_qty(mut self, qty: &str) -> Self {
2431 self.pending_below_iceberg_qty = Some(qty.to_string());
2432 self
2433 }
2434
2435 pub fn pending_below_time_in_force(mut self, tif: TimeInForce) -> Self {
2436 self.pending_below_time_in_force = Some(tif);
2437 self
2438 }
2439
2440 pub fn pending_below_strategy_id(mut self, id: u64) -> Self {
2441 self.pending_below_strategy_id = Some(id);
2442 self
2443 }
2444
2445 pub fn pending_below_strategy_type(mut self, strategy_type: i32) -> Self {
2446 self.pending_below_strategy_type = Some(strategy_type);
2447 self
2448 }
2449
2450 pub fn pending_below_peg_price_type(mut self, peg_price_type: &str) -> Self {
2451 self.pending_below_peg_price_type = Some(peg_price_type.to_string());
2452 self
2453 }
2454
2455 pub fn pending_below_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2456 self.pending_below_peg_offset_type = Some(peg_offset_type.to_string());
2457 self
2458 }
2459
2460 pub fn pending_below_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2461 self.pending_below_peg_offset_value = Some(peg_offset_value);
2462 self
2463 }
2464
2465 pub fn build(self) -> NewOtocoOrder {
2466 NewOtocoOrder {
2467 symbol: self.symbol,
2468 working_type: self.working_type,
2469 working_side: self.working_side,
2470 working_price: self.working_price,
2471 working_quantity: self.working_quantity,
2472 pending_side: self.pending_side,
2473 pending_quantity: Some(self.pending_quantity),
2474 pending_above_type: self.pending_above_type,
2475 list_client_order_id: self.list_client_order_id,
2476 response_type: self.response_type,
2477 self_trade_prevention_mode: self.self_trade_prevention_mode,
2478 working_client_order_id: self.working_client_order_id,
2479 working_iceberg_qty: self.working_iceberg_qty,
2480 working_time_in_force: self.working_time_in_force,
2481 working_strategy_id: self.working_strategy_id,
2482 working_strategy_type: self.working_strategy_type,
2483 working_peg_price_type: self.working_peg_price_type,
2484 working_peg_offset_type: self.working_peg_offset_type,
2485 working_peg_offset_value: self.working_peg_offset_value,
2486 pending_above_client_order_id: self.pending_above_client_order_id,
2487 pending_above_price: self.pending_above_price,
2488 pending_above_stop_price: self.pending_above_stop_price,
2489 pending_above_trailing_delta: self.pending_above_trailing_delta,
2490 pending_above_iceberg_qty: self.pending_above_iceberg_qty,
2491 pending_above_time_in_force: self.pending_above_time_in_force,
2492 pending_above_strategy_id: self.pending_above_strategy_id,
2493 pending_above_strategy_type: self.pending_above_strategy_type,
2494 pending_above_peg_price_type: self.pending_above_peg_price_type,
2495 pending_above_peg_offset_type: self.pending_above_peg_offset_type,
2496 pending_above_peg_offset_value: self.pending_above_peg_offset_value,
2497 pending_below_type: self.pending_below_type,
2498 pending_below_client_order_id: self.pending_below_client_order_id,
2499 pending_below_price: self.pending_below_price,
2500 pending_below_stop_price: self.pending_below_stop_price,
2501 pending_below_trailing_delta: self.pending_below_trailing_delta,
2502 pending_below_iceberg_qty: self.pending_below_iceberg_qty,
2503 pending_below_time_in_force: self.pending_below_time_in_force,
2504 pending_below_strategy_id: self.pending_below_strategy_id,
2505 pending_below_strategy_type: self.pending_below_strategy_type,
2506 pending_below_peg_price_type: self.pending_below_peg_price_type,
2507 pending_below_peg_offset_type: self.pending_below_peg_offset_type,
2508 pending_below_peg_offset_value: self.pending_below_peg_offset_value,
2509 }
2510 }
2511}
2512
2513#[derive(Debug, Clone)]
2515pub struct NewOtocoOrder {
2516 symbol: String,
2517 working_type: OrderType,
2518 working_side: OrderSide,
2519 working_price: String,
2520 working_quantity: String,
2521 pending_side: OrderSide,
2522 pending_quantity: Option<String>,
2523 pending_above_type: OrderType,
2524 list_client_order_id: Option<String>,
2525 response_type: Option<OrderResponseType>,
2526 self_trade_prevention_mode: Option<String>,
2527 working_client_order_id: Option<String>,
2528 working_iceberg_qty: Option<String>,
2529 working_time_in_force: Option<TimeInForce>,
2530 working_strategy_id: Option<u64>,
2531 working_strategy_type: Option<i32>,
2532 working_peg_price_type: Option<String>,
2533 working_peg_offset_type: Option<String>,
2534 working_peg_offset_value: Option<i32>,
2535 pending_above_client_order_id: Option<String>,
2536 pending_above_price: Option<String>,
2537 pending_above_stop_price: Option<String>,
2538 pending_above_trailing_delta: Option<u64>,
2539 pending_above_iceberg_qty: Option<String>,
2540 pending_above_time_in_force: Option<TimeInForce>,
2541 pending_above_strategy_id: Option<u64>,
2542 pending_above_strategy_type: Option<i32>,
2543 pending_above_peg_price_type: Option<String>,
2544 pending_above_peg_offset_type: Option<String>,
2545 pending_above_peg_offset_value: Option<i32>,
2546 pending_below_type: Option<OrderType>,
2547 pending_below_client_order_id: Option<String>,
2548 pending_below_price: Option<String>,
2549 pending_below_stop_price: Option<String>,
2550 pending_below_trailing_delta: Option<u64>,
2551 pending_below_iceberg_qty: Option<String>,
2552 pending_below_time_in_force: Option<TimeInForce>,
2553 pending_below_strategy_id: Option<u64>,
2554 pending_below_strategy_type: Option<i32>,
2555 pending_below_peg_price_type: Option<String>,
2556 pending_below_peg_offset_type: Option<String>,
2557 pending_below_peg_offset_value: Option<i32>,
2558}
2559
2560impl NewOtocoOrder {
2561 fn to_params(&self) -> Vec<(String, String)> {
2562 let mut params = vec![
2563 ("symbol".to_string(), self.symbol.clone()),
2564 (
2565 "workingType".to_string(),
2566 format!("{:?}", self.working_type).to_uppercase(),
2567 ),
2568 (
2569 "workingSide".to_string(),
2570 format!("{:?}", self.working_side).to_uppercase(),
2571 ),
2572 ("workingPrice".to_string(), self.working_price.clone()),
2573 ("workingQuantity".to_string(), self.working_quantity.clone()),
2574 (
2575 "pendingSide".to_string(),
2576 format!("{:?}", self.pending_side).to_uppercase(),
2577 ),
2578 (
2579 "pendingAboveType".to_string(),
2580 format!("{:?}", self.pending_above_type).to_uppercase(),
2581 ),
2582 ];
2583
2584 if let Some(ref qty) = self.pending_quantity {
2585 params.push(("pendingQuantity".to_string(), qty.clone()));
2586 }
2587 if let Some(ref id) = self.list_client_order_id {
2588 params.push(("listClientOrderId".to_string(), id.clone()));
2589 }
2590 if let Some(ref resp) = self.response_type {
2591 params.push((
2592 "newOrderRespType".to_string(),
2593 format!("{:?}", resp).to_uppercase(),
2594 ));
2595 }
2596 if let Some(ref mode) = self.self_trade_prevention_mode {
2597 params.push(("selfTradePreventionMode".to_string(), mode.clone()));
2598 }
2599 if let Some(ref id) = self.working_client_order_id {
2600 params.push(("workingClientOrderId".to_string(), id.clone()));
2601 }
2602 if let Some(ref qty) = self.working_iceberg_qty {
2603 params.push(("workingIcebergQty".to_string(), qty.clone()));
2604 }
2605 if let Some(ref tif) = self.working_time_in_force {
2606 params.push(("workingTimeInForce".to_string(), format!("{:?}", tif)));
2607 }
2608 if let Some(id) = self.working_strategy_id {
2609 params.push(("workingStrategyId".to_string(), id.to_string()));
2610 }
2611 if let Some(id) = self.working_strategy_type {
2612 params.push(("workingStrategyType".to_string(), id.to_string()));
2613 }
2614 if let Some(ref peg) = self.working_peg_price_type {
2615 params.push(("workingPegPriceType".to_string(), peg.clone()));
2616 }
2617 if let Some(ref peg) = self.working_peg_offset_type {
2618 params.push(("workingPegOffsetType".to_string(), peg.clone()));
2619 }
2620 if let Some(value) = self.working_peg_offset_value {
2621 params.push(("workingPegOffsetValue".to_string(), value.to_string()));
2622 }
2623 if let Some(ref id) = self.pending_above_client_order_id {
2624 params.push(("pendingAboveClientOrderId".to_string(), id.clone()));
2625 }
2626 if let Some(ref price) = self.pending_above_price {
2627 params.push(("pendingAbovePrice".to_string(), price.clone()));
2628 }
2629 if let Some(ref price) = self.pending_above_stop_price {
2630 params.push(("pendingAboveStopPrice".to_string(), price.clone()));
2631 }
2632 if let Some(delta) = self.pending_above_trailing_delta {
2633 params.push(("pendingAboveTrailingDelta".to_string(), delta.to_string()));
2634 }
2635 if let Some(ref qty) = self.pending_above_iceberg_qty {
2636 params.push(("pendingAboveIcebergQty".to_string(), qty.clone()));
2637 }
2638 if let Some(ref tif) = self.pending_above_time_in_force {
2639 params.push(("pendingAboveTimeInForce".to_string(), format!("{:?}", tif)));
2640 }
2641 if let Some(id) = self.pending_above_strategy_id {
2642 params.push(("pendingAboveStrategyId".to_string(), id.to_string()));
2643 }
2644 if let Some(id) = self.pending_above_strategy_type {
2645 params.push(("pendingAboveStrategyType".to_string(), id.to_string()));
2646 }
2647 if let Some(ref peg) = self.pending_above_peg_price_type {
2648 params.push(("pendingAbovePegPriceType".to_string(), peg.clone()));
2649 }
2650 if let Some(ref peg) = self.pending_above_peg_offset_type {
2651 params.push(("pendingAbovePegOffsetType".to_string(), peg.clone()));
2652 }
2653 if let Some(value) = self.pending_above_peg_offset_value {
2654 params.push(("pendingAbovePegOffsetValue".to_string(), value.to_string()));
2655 }
2656 if let Some(order_type) = self.pending_below_type {
2657 params.push((
2658 "pendingBelowType".to_string(),
2659 format!("{:?}", order_type).to_uppercase(),
2660 ));
2661 }
2662 if let Some(ref id) = self.pending_below_client_order_id {
2663 params.push(("pendingBelowClientOrderId".to_string(), id.clone()));
2664 }
2665 if let Some(ref price) = self.pending_below_price {
2666 params.push(("pendingBelowPrice".to_string(), price.clone()));
2667 }
2668 if let Some(ref price) = self.pending_below_stop_price {
2669 params.push(("pendingBelowStopPrice".to_string(), price.clone()));
2670 }
2671 if let Some(delta) = self.pending_below_trailing_delta {
2672 params.push(("pendingBelowTrailingDelta".to_string(), delta.to_string()));
2673 }
2674 if let Some(ref qty) = self.pending_below_iceberg_qty {
2675 params.push(("pendingBelowIcebergQty".to_string(), qty.clone()));
2676 }
2677 if let Some(ref tif) = self.pending_below_time_in_force {
2678 params.push(("pendingBelowTimeInForce".to_string(), format!("{:?}", tif)));
2679 }
2680 if let Some(id) = self.pending_below_strategy_id {
2681 params.push(("pendingBelowStrategyId".to_string(), id.to_string()));
2682 }
2683 if let Some(id) = self.pending_below_strategy_type {
2684 params.push(("pendingBelowStrategyType".to_string(), id.to_string()));
2685 }
2686 if let Some(ref peg) = self.pending_below_peg_price_type {
2687 params.push(("pendingBelowPegPriceType".to_string(), peg.clone()));
2688 }
2689 if let Some(ref peg) = self.pending_below_peg_offset_type {
2690 params.push(("pendingBelowPegOffsetType".to_string(), peg.clone()));
2691 }
2692 if let Some(value) = self.pending_below_peg_offset_value {
2693 params.push(("pendingBelowPegOffsetValue".to_string(), value.to_string()));
2694 }
2695
2696 params
2697 }
2698}
2699
2700#[derive(Debug, Clone)]
2702pub struct OpocoOrderBuilder {
2703 inner: NewOtocoOrder,
2704}
2705
2706impl OpocoOrderBuilder {
2707 pub fn new(
2709 symbol: &str,
2710 working_type: OrderType,
2711 working_side: OrderSide,
2712 working_price: &str,
2713 working_quantity: &str,
2714 pending_side: OrderSide,
2715 pending_above_type: OrderType,
2716 ) -> Self {
2717 Self {
2718 inner: NewOtocoOrder {
2719 symbol: symbol.to_string(),
2720 working_type,
2721 working_side,
2722 working_price: working_price.to_string(),
2723 working_quantity: working_quantity.to_string(),
2724 pending_side,
2725 pending_quantity: None,
2726 pending_above_type,
2727 list_client_order_id: None,
2728 response_type: None,
2729 self_trade_prevention_mode: None,
2730 working_client_order_id: None,
2731 working_iceberg_qty: None,
2732 working_time_in_force: None,
2733 working_strategy_id: None,
2734 working_strategy_type: None,
2735 working_peg_price_type: None,
2736 working_peg_offset_type: None,
2737 working_peg_offset_value: None,
2738 pending_above_client_order_id: None,
2739 pending_above_price: None,
2740 pending_above_stop_price: None,
2741 pending_above_trailing_delta: None,
2742 pending_above_iceberg_qty: None,
2743 pending_above_time_in_force: None,
2744 pending_above_strategy_id: None,
2745 pending_above_strategy_type: None,
2746 pending_above_peg_price_type: None,
2747 pending_above_peg_offset_type: None,
2748 pending_above_peg_offset_value: None,
2749 pending_below_type: None,
2750 pending_below_client_order_id: None,
2751 pending_below_price: None,
2752 pending_below_stop_price: None,
2753 pending_below_trailing_delta: None,
2754 pending_below_iceberg_qty: None,
2755 pending_below_time_in_force: None,
2756 pending_below_strategy_id: None,
2757 pending_below_strategy_type: None,
2758 pending_below_peg_price_type: None,
2759 pending_below_peg_offset_type: None,
2760 pending_below_peg_offset_value: None,
2761 },
2762 }
2763 }
2764
2765 pub fn list_client_order_id(mut self, id: &str) -> Self {
2766 self.inner.list_client_order_id = Some(id.to_string());
2767 self
2768 }
2769
2770 pub fn response_type(mut self, resp_type: OrderResponseType) -> Self {
2771 self.inner.response_type = Some(resp_type);
2772 self
2773 }
2774
2775 pub fn self_trade_prevention_mode(mut self, mode: &str) -> Self {
2776 self.inner.self_trade_prevention_mode = Some(mode.to_string());
2777 self
2778 }
2779
2780 pub fn working_client_order_id(mut self, id: &str) -> Self {
2781 self.inner.working_client_order_id = Some(id.to_string());
2782 self
2783 }
2784
2785 pub fn working_iceberg_qty(mut self, qty: &str) -> Self {
2786 self.inner.working_iceberg_qty = Some(qty.to_string());
2787 self
2788 }
2789
2790 pub fn working_time_in_force(mut self, tif: TimeInForce) -> Self {
2791 self.inner.working_time_in_force = Some(tif);
2792 self
2793 }
2794
2795 pub fn working_strategy_id(mut self, id: u64) -> Self {
2796 self.inner.working_strategy_id = Some(id);
2797 self
2798 }
2799
2800 pub fn working_strategy_type(mut self, strategy_type: i32) -> Self {
2801 self.inner.working_strategy_type = Some(strategy_type);
2802 self
2803 }
2804
2805 pub fn working_peg_price_type(mut self, peg_price_type: &str) -> Self {
2806 self.inner.working_peg_price_type = Some(peg_price_type.to_string());
2807 self
2808 }
2809
2810 pub fn working_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2811 self.inner.working_peg_offset_type = Some(peg_offset_type.to_string());
2812 self
2813 }
2814
2815 pub fn working_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2816 self.inner.working_peg_offset_value = Some(peg_offset_value);
2817 self
2818 }
2819
2820 pub fn pending_quantity(mut self, qty: &str) -> Self {
2821 self.inner.pending_quantity = Some(qty.to_string());
2822 self
2823 }
2824
2825 pub fn pending_above_client_order_id(mut self, id: &str) -> Self {
2826 self.inner.pending_above_client_order_id = Some(id.to_string());
2827 self
2828 }
2829
2830 pub fn pending_above_price(mut self, price: &str) -> Self {
2831 self.inner.pending_above_price = Some(price.to_string());
2832 self
2833 }
2834
2835 pub fn pending_above_stop_price(mut self, price: &str) -> Self {
2836 self.inner.pending_above_stop_price = Some(price.to_string());
2837 self
2838 }
2839
2840 pub fn pending_above_trailing_delta(mut self, delta: u64) -> Self {
2841 self.inner.pending_above_trailing_delta = Some(delta);
2842 self
2843 }
2844
2845 pub fn pending_above_iceberg_qty(mut self, qty: &str) -> Self {
2846 self.inner.pending_above_iceberg_qty = Some(qty.to_string());
2847 self
2848 }
2849
2850 pub fn pending_above_time_in_force(mut self, tif: TimeInForce) -> Self {
2851 self.inner.pending_above_time_in_force = Some(tif);
2852 self
2853 }
2854
2855 pub fn pending_above_strategy_id(mut self, id: u64) -> Self {
2856 self.inner.pending_above_strategy_id = Some(id);
2857 self
2858 }
2859
2860 pub fn pending_above_strategy_type(mut self, strategy_type: i32) -> Self {
2861 self.inner.pending_above_strategy_type = Some(strategy_type);
2862 self
2863 }
2864
2865 pub fn pending_above_peg_price_type(mut self, peg_price_type: &str) -> Self {
2866 self.inner.pending_above_peg_price_type = Some(peg_price_type.to_string());
2867 self
2868 }
2869
2870 pub fn pending_above_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2871 self.inner.pending_above_peg_offset_type = Some(peg_offset_type.to_string());
2872 self
2873 }
2874
2875 pub fn pending_above_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2876 self.inner.pending_above_peg_offset_value = Some(peg_offset_value);
2877 self
2878 }
2879
2880 pub fn pending_below_type(mut self, order_type: OrderType) -> Self {
2881 self.inner.pending_below_type = Some(order_type);
2882 self
2883 }
2884
2885 pub fn pending_below_client_order_id(mut self, id: &str) -> Self {
2886 self.inner.pending_below_client_order_id = Some(id.to_string());
2887 self
2888 }
2889
2890 pub fn pending_below_price(mut self, price: &str) -> Self {
2891 self.inner.pending_below_price = Some(price.to_string());
2892 self
2893 }
2894
2895 pub fn pending_below_stop_price(mut self, price: &str) -> Self {
2896 self.inner.pending_below_stop_price = Some(price.to_string());
2897 self
2898 }
2899
2900 pub fn pending_below_trailing_delta(mut self, delta: u64) -> Self {
2901 self.inner.pending_below_trailing_delta = Some(delta);
2902 self
2903 }
2904
2905 pub fn pending_below_iceberg_qty(mut self, qty: &str) -> Self {
2906 self.inner.pending_below_iceberg_qty = Some(qty.to_string());
2907 self
2908 }
2909
2910 pub fn pending_below_time_in_force(mut self, tif: TimeInForce) -> Self {
2911 self.inner.pending_below_time_in_force = Some(tif);
2912 self
2913 }
2914
2915 pub fn pending_below_strategy_id(mut self, id: u64) -> Self {
2916 self.inner.pending_below_strategy_id = Some(id);
2917 self
2918 }
2919
2920 pub fn pending_below_strategy_type(mut self, strategy_type: i32) -> Self {
2921 self.inner.pending_below_strategy_type = Some(strategy_type);
2922 self
2923 }
2924
2925 pub fn pending_below_peg_price_type(mut self, peg_price_type: &str) -> Self {
2926 self.inner.pending_below_peg_price_type = Some(peg_price_type.to_string());
2927 self
2928 }
2929
2930 pub fn pending_below_peg_offset_type(mut self, peg_offset_type: &str) -> Self {
2931 self.inner.pending_below_peg_offset_type = Some(peg_offset_type.to_string());
2932 self
2933 }
2934
2935 pub fn pending_below_peg_offset_value(mut self, peg_offset_value: i32) -> Self {
2936 self.inner.pending_below_peg_offset_value = Some(peg_offset_value);
2937 self
2938 }
2939
2940 pub fn build(self) -> NewOpocoOrder {
2941 NewOpocoOrder { inner: self.inner }
2942 }
2943}
2944
2945#[derive(Debug, Clone)]
2947pub struct NewOpocoOrder {
2948 inner: NewOtocoOrder,
2949}
2950
2951impl NewOpocoOrder {
2952 fn to_params(&self) -> Vec<(String, String)> {
2953 self.inner.to_params()
2954 }
2955}
2956
2957#[cfg(test)]
2958mod tests {
2959 use super::*;
2960
2961 #[test]
2962 fn test_order_builder_limit() {
2963 let order = OrderBuilder::new("BTCUSDT", OrderSide::Buy, OrderType::Limit)
2964 .quantity("0.001")
2965 .price("50000.00")
2966 .time_in_force(TimeInForce::GTC)
2967 .build();
2968
2969 assert_eq!(order.symbol, "BTCUSDT");
2970 assert_eq!(order.side, OrderSide::Buy);
2971 assert_eq!(order.order_type, OrderType::Limit);
2972 assert_eq!(order.quantity, Some("0.001".to_string()));
2973 assert_eq!(order.price, Some("50000.00".to_string()));
2974 assert_eq!(order.time_in_force, Some(TimeInForce::GTC));
2975 }
2976
2977 #[test]
2978 fn test_order_builder_market() {
2979 let order = OrderBuilder::new("BTCUSDT", OrderSide::Sell, OrderType::Market)
2980 .quantity("1.0")
2981 .build();
2982
2983 assert_eq!(order.symbol, "BTCUSDT");
2984 assert_eq!(order.side, OrderSide::Sell);
2985 assert_eq!(order.order_type, OrderType::Market);
2986 assert_eq!(order.quantity, Some("1.0".to_string()));
2987 assert!(order.price.is_none());
2988 }
2989
2990 #[test]
2991 fn test_order_to_params() {
2992 let order = OrderBuilder::new("BTCUSDT", OrderSide::Buy, OrderType::Limit)
2993 .quantity("0.001")
2994 .price("50000.00")
2995 .time_in_force(TimeInForce::GTC)
2996 .build();
2997
2998 let params = order.to_params();
2999
3000 assert!(params.iter().any(|(k, v)| k == "symbol" && v == "BTCUSDT"));
3001 assert!(params.iter().any(|(k, v)| k == "side" && v == "BUY"));
3002 assert!(params.iter().any(|(k, v)| k == "type" && v == "LIMIT"));
3003 assert!(params.iter().any(|(k, v)| k == "quantity" && v == "0.001"));
3004 assert!(params.iter().any(|(k, v)| k == "price" && v == "50000.00"));
3005 }
3006
3007 #[test]
3008 fn test_oco_order_builder() {
3009 let order = OcoOrderBuilder::new("BTCUSDT", OrderSide::Sell, "1.0", "55000.00", "48000.00")
3010 .stop_limit_price("47900.00")
3011 .stop_limit_time_in_force(TimeInForce::GTC)
3012 .build();
3013
3014 assert_eq!(order.symbol, "BTCUSDT");
3015 assert_eq!(order.side, OrderSide::Sell);
3016 assert_eq!(order.quantity, "1.0");
3017 assert_eq!(order.price, "55000.00");
3018 assert_eq!(order.stop_price, "48000.00");
3019 assert_eq!(order.stop_limit_price, Some("47900.00".to_string()));
3020 }
3021}