Skip to main content

binance_sdk/spot/websocket_api/apis/
trade_api.rs

1/*
2 * Binance Spot WebSocket API
3 *
4 * OpenAPI Specifications for the Binance Spot WebSocket API
5 *
6 * API documents:
7 * - [Github web-socket-api documentation file](https://github.com/binance/binance-spot-api-docs/blob/master/web-socket-api.md)
8 * - [General API information for web-socket-api on website](https://developers.binance.com/docs/binance-spot-api-docs/web-socket-api/general-api-information)
9 *
10 *
11 * The version of the OpenAPI document: 1.0.0
12 *
13 *
14 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
15 * https://openapi-generator.tech
16 * Do not edit the class manually.
17 */
18
19#![allow(unused_imports)]
20use anyhow::Context;
21use async_trait::async_trait;
22use derive_builder::Builder;
23use rust_decimal::prelude::*;
24use serde::{Deserialize, Serialize};
25use serde_json::Value;
26use std::{collections::BTreeMap, sync::Arc};
27
28use crate::common::{
29    errors::WebsocketError,
30    models::{ParamBuildError, WebsocketApiResponse},
31    utils::remove_empty_value,
32    websocket::{WebsocketApi, WebsocketMessageSendOptions},
33};
34use crate::spot::websocket_api::models;
35
36#[async_trait]
37pub trait TradeApi: Send + Sync {
38    async fn open_orders_cancel_all(
39        &self,
40        params: OpenOrdersCancelAllParams,
41    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::OpenOrdersCancelAllResponseResultInner>>>;
42    async fn order_amend_keep_priority(
43        &self,
44        params: OrderAmendKeepPriorityParams,
45    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderAmendKeepPriorityResponseResult>>>;
46    async fn order_cancel(
47        &self,
48        params: OrderCancelParams,
49    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelResponseResult>>>;
50    async fn order_cancel_replace(
51        &self,
52        params: OrderCancelReplaceParams,
53    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelReplaceResponseResult>>>;
54    async fn order_list_cancel(
55        &self,
56        params: OrderListCancelParams,
57    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListCancelResponseResult>>>;
58    async fn order_list_place(
59        &self,
60        params: OrderListPlaceParams,
61    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceResponseResult>>>;
62    async fn order_list_place_oco(
63        &self,
64        params: OrderListPlaceOcoParams,
65    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOcoResponseResult>>>;
66    async fn order_list_place_opo(
67        &self,
68        params: OrderListPlaceOpoParams,
69    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpoResponseResult>>>;
70    async fn order_list_place_opoco(
71        &self,
72        params: OrderListPlaceOpocoParams,
73    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpocoResponseResult>>>;
74    async fn order_list_place_oto(
75        &self,
76        params: OrderListPlaceOtoParams,
77    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtoResponseResult>>>;
78    async fn order_list_place_otoco(
79        &self,
80        params: OrderListPlaceOtocoParams,
81    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtocoResponseResult>>>;
82    async fn order_place(
83        &self,
84        params: OrderPlaceParams,
85    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderPlaceResponseResult>>>;
86    async fn order_test(
87        &self,
88        params: OrderTestParams,
89    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderTestResponseResult>>>;
90    async fn sor_order_place(
91        &self,
92        params: SorOrderPlaceParams,
93    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::SorOrderPlaceResponseResultInner>>>;
94    async fn sor_order_test(
95        &self,
96        params: SorOrderTestParams,
97    ) -> anyhow::Result<WebsocketApiResponse<Box<models::SorOrderTestResponseResult>>>;
98}
99
100#[derive(Clone)]
101pub struct TradeApiClient {
102    websocket_api_base: Arc<WebsocketApi>,
103}
104
105impl TradeApiClient {
106    pub fn new(websocket_api_base: Arc<WebsocketApi>) -> Self {
107        Self { websocket_api_base }
108    }
109}
110
111#[allow(non_camel_case_types)]
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub enum OrderCancelCancelRestrictionsEnum {
114    #[serde(rename = "ONLY_NEW")]
115    OnlyNew,
116    #[serde(rename = "NEW")]
117    New,
118    #[serde(rename = "ONLY_PARTIALLY_FILLED")]
119    OnlyPartiallyFilled,
120    #[serde(rename = "PARTIALLY_FILLED")]
121    PartiallyFilled,
122}
123
124impl OrderCancelCancelRestrictionsEnum {
125    #[must_use]
126    pub fn as_str(&self) -> &'static str {
127        match self {
128            Self::OnlyNew => "ONLY_NEW",
129            Self::New => "NEW",
130            Self::OnlyPartiallyFilled => "ONLY_PARTIALLY_FILLED",
131            Self::PartiallyFilled => "PARTIALLY_FILLED",
132        }
133    }
134}
135
136impl std::str::FromStr for OrderCancelCancelRestrictionsEnum {
137    type Err = Box<dyn std::error::Error + Send + Sync>;
138
139    fn from_str(s: &str) -> Result<Self, Self::Err> {
140        match s {
141            "ONLY_NEW" => Ok(Self::OnlyNew),
142            "NEW" => Ok(Self::New),
143            "ONLY_PARTIALLY_FILLED" => Ok(Self::OnlyPartiallyFilled),
144            "PARTIALLY_FILLED" => Ok(Self::PartiallyFilled),
145            other => Err(format!("invalid OrderCancelCancelRestrictionsEnum: {}", other).into()),
146        }
147    }
148}
149
150#[allow(non_camel_case_types)]
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub enum OrderCancelReplaceCancelReplaceModeEnum {
153    #[serde(rename = "STOP_ON_FAILURE")]
154    StopOnFailure,
155    #[serde(rename = "ALLOW_FAILURE")]
156    AllowFailure,
157}
158
159impl OrderCancelReplaceCancelReplaceModeEnum {
160    #[must_use]
161    pub fn as_str(&self) -> &'static str {
162        match self {
163            Self::StopOnFailure => "STOP_ON_FAILURE",
164            Self::AllowFailure => "ALLOW_FAILURE",
165        }
166    }
167}
168
169impl std::str::FromStr for OrderCancelReplaceCancelReplaceModeEnum {
170    type Err = Box<dyn std::error::Error + Send + Sync>;
171
172    fn from_str(s: &str) -> Result<Self, Self::Err> {
173        match s {
174            "STOP_ON_FAILURE" => Ok(Self::StopOnFailure),
175            "ALLOW_FAILURE" => Ok(Self::AllowFailure),
176            other => {
177                Err(format!("invalid OrderCancelReplaceCancelReplaceModeEnum: {}", other).into())
178            }
179        }
180    }
181}
182
183#[allow(non_camel_case_types)]
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub enum OrderCancelReplaceSideEnum {
186    #[serde(rename = "BUY")]
187    Buy,
188    #[serde(rename = "SELL")]
189    Sell,
190}
191
192impl OrderCancelReplaceSideEnum {
193    #[must_use]
194    pub fn as_str(&self) -> &'static str {
195        match self {
196            Self::Buy => "BUY",
197            Self::Sell => "SELL",
198        }
199    }
200}
201
202impl std::str::FromStr for OrderCancelReplaceSideEnum {
203    type Err = Box<dyn std::error::Error + Send + Sync>;
204
205    fn from_str(s: &str) -> Result<Self, Self::Err> {
206        match s {
207            "BUY" => Ok(Self::Buy),
208            "SELL" => Ok(Self::Sell),
209            other => Err(format!("invalid OrderCancelReplaceSideEnum: {}", other).into()),
210        }
211    }
212}
213
214#[allow(non_camel_case_types)]
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub enum OrderCancelReplaceTypeEnum {
217    #[serde(rename = "MARKET")]
218    Market,
219    #[serde(rename = "LIMIT")]
220    Limit,
221    #[serde(rename = "STOP_LOSS")]
222    StopLoss,
223    #[serde(rename = "STOP_LOSS_LIMIT")]
224    StopLossLimit,
225    #[serde(rename = "TAKE_PROFIT")]
226    TakeProfit,
227    #[serde(rename = "TAKE_PROFIT_LIMIT")]
228    TakeProfitLimit,
229    #[serde(rename = "LIMIT_MAKER")]
230    LimitMaker,
231    #[serde(rename = "NON_REPRESENTABLE")]
232    NonRepresentable,
233}
234
235impl OrderCancelReplaceTypeEnum {
236    #[must_use]
237    pub fn as_str(&self) -> &'static str {
238        match self {
239            Self::Market => "MARKET",
240            Self::Limit => "LIMIT",
241            Self::StopLoss => "STOP_LOSS",
242            Self::StopLossLimit => "STOP_LOSS_LIMIT",
243            Self::TakeProfit => "TAKE_PROFIT",
244            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
245            Self::LimitMaker => "LIMIT_MAKER",
246            Self::NonRepresentable => "NON_REPRESENTABLE",
247        }
248    }
249}
250
251impl std::str::FromStr for OrderCancelReplaceTypeEnum {
252    type Err = Box<dyn std::error::Error + Send + Sync>;
253
254    fn from_str(s: &str) -> Result<Self, Self::Err> {
255        match s {
256            "MARKET" => Ok(Self::Market),
257            "LIMIT" => Ok(Self::Limit),
258            "STOP_LOSS" => Ok(Self::StopLoss),
259            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
260            "TAKE_PROFIT" => Ok(Self::TakeProfit),
261            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
262            "LIMIT_MAKER" => Ok(Self::LimitMaker),
263            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
264            other => Err(format!("invalid OrderCancelReplaceTypeEnum: {}", other).into()),
265        }
266    }
267}
268
269#[allow(non_camel_case_types)]
270#[derive(Debug, Clone, Serialize, Deserialize)]
271pub enum OrderCancelReplaceTimeInForceEnum {
272    #[serde(rename = "GTC")]
273    Gtc,
274    #[serde(rename = "IOC")]
275    Ioc,
276    #[serde(rename = "FOK")]
277    Fok,
278    #[serde(rename = "NON_REPRESENTABLE")]
279    NonRepresentable,
280}
281
282impl OrderCancelReplaceTimeInForceEnum {
283    #[must_use]
284    pub fn as_str(&self) -> &'static str {
285        match self {
286            Self::Gtc => "GTC",
287            Self::Ioc => "IOC",
288            Self::Fok => "FOK",
289            Self::NonRepresentable => "NON_REPRESENTABLE",
290        }
291    }
292}
293
294impl std::str::FromStr for OrderCancelReplaceTimeInForceEnum {
295    type Err = Box<dyn std::error::Error + Send + Sync>;
296
297    fn from_str(s: &str) -> Result<Self, Self::Err> {
298        match s {
299            "GTC" => Ok(Self::Gtc),
300            "IOC" => Ok(Self::Ioc),
301            "FOK" => Ok(Self::Fok),
302            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
303            other => Err(format!("invalid OrderCancelReplaceTimeInForceEnum: {}", other).into()),
304        }
305    }
306}
307
308#[allow(non_camel_case_types)]
309#[derive(Debug, Clone, Serialize, Deserialize)]
310pub enum OrderCancelReplaceNewOrderRespTypeEnum {
311    #[serde(rename = "ACK")]
312    Ack,
313    #[serde(rename = "RESULT")]
314    Result,
315    #[serde(rename = "FULL")]
316    Full,
317    #[serde(rename = "MARKET")]
318    Market,
319    #[serde(rename = "LIMIT")]
320    Limit,
321}
322
323impl OrderCancelReplaceNewOrderRespTypeEnum {
324    #[must_use]
325    pub fn as_str(&self) -> &'static str {
326        match self {
327            Self::Ack => "ACK",
328            Self::Result => "RESULT",
329            Self::Full => "FULL",
330            Self::Market => "MARKET",
331            Self::Limit => "LIMIT",
332        }
333    }
334}
335
336impl std::str::FromStr for OrderCancelReplaceNewOrderRespTypeEnum {
337    type Err = Box<dyn std::error::Error + Send + Sync>;
338
339    fn from_str(s: &str) -> Result<Self, Self::Err> {
340        match s {
341            "ACK" => Ok(Self::Ack),
342            "RESULT" => Ok(Self::Result),
343            "FULL" => Ok(Self::Full),
344            "MARKET" => Ok(Self::Market),
345            "LIMIT" => Ok(Self::Limit),
346            other => {
347                Err(format!("invalid OrderCancelReplaceNewOrderRespTypeEnum: {}", other).into())
348            }
349        }
350    }
351}
352
353#[allow(non_camel_case_types)]
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub enum OrderCancelReplaceSelfTradePreventionModeEnum {
356    #[serde(rename = "NONE")]
357    None,
358    #[serde(rename = "EXPIRE_TAKER")]
359    ExpireTaker,
360    #[serde(rename = "EXPIRE_MAKER")]
361    ExpireMaker,
362    #[serde(rename = "EXPIRE_BOTH")]
363    ExpireBoth,
364    #[serde(rename = "DECREMENT")]
365    Decrement,
366    #[serde(rename = "TRANSFER")]
367    Transfer,
368    #[serde(rename = "NON_REPRESENTABLE")]
369    NonRepresentable,
370}
371
372impl OrderCancelReplaceSelfTradePreventionModeEnum {
373    #[must_use]
374    pub fn as_str(&self) -> &'static str {
375        match self {
376            Self::None => "NONE",
377            Self::ExpireTaker => "EXPIRE_TAKER",
378            Self::ExpireMaker => "EXPIRE_MAKER",
379            Self::ExpireBoth => "EXPIRE_BOTH",
380            Self::Decrement => "DECREMENT",
381            Self::Transfer => "TRANSFER",
382            Self::NonRepresentable => "NON_REPRESENTABLE",
383        }
384    }
385}
386
387impl std::str::FromStr for OrderCancelReplaceSelfTradePreventionModeEnum {
388    type Err = Box<dyn std::error::Error + Send + Sync>;
389
390    fn from_str(s: &str) -> Result<Self, Self::Err> {
391        match s {
392            "NONE" => Ok(Self::None),
393            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
394            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
395            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
396            "DECREMENT" => Ok(Self::Decrement),
397            "TRANSFER" => Ok(Self::Transfer),
398            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
399            other => Err(format!(
400                "invalid OrderCancelReplaceSelfTradePreventionModeEnum: {}",
401                other
402            )
403            .into()),
404        }
405    }
406}
407
408#[allow(non_camel_case_types)]
409#[derive(Debug, Clone, Serialize, Deserialize)]
410pub enum OrderCancelReplaceCancelRestrictionsEnum {
411    #[serde(rename = "ONLY_NEW")]
412    OnlyNew,
413    #[serde(rename = "NEW")]
414    New,
415    #[serde(rename = "ONLY_PARTIALLY_FILLED")]
416    OnlyPartiallyFilled,
417    #[serde(rename = "PARTIALLY_FILLED")]
418    PartiallyFilled,
419}
420
421impl OrderCancelReplaceCancelRestrictionsEnum {
422    #[must_use]
423    pub fn as_str(&self) -> &'static str {
424        match self {
425            Self::OnlyNew => "ONLY_NEW",
426            Self::New => "NEW",
427            Self::OnlyPartiallyFilled => "ONLY_PARTIALLY_FILLED",
428            Self::PartiallyFilled => "PARTIALLY_FILLED",
429        }
430    }
431}
432
433impl std::str::FromStr for OrderCancelReplaceCancelRestrictionsEnum {
434    type Err = Box<dyn std::error::Error + Send + Sync>;
435
436    fn from_str(s: &str) -> Result<Self, Self::Err> {
437        match s {
438            "ONLY_NEW" => Ok(Self::OnlyNew),
439            "NEW" => Ok(Self::New),
440            "ONLY_PARTIALLY_FILLED" => Ok(Self::OnlyPartiallyFilled),
441            "PARTIALLY_FILLED" => Ok(Self::PartiallyFilled),
442            other => Err(format!(
443                "invalid OrderCancelReplaceCancelRestrictionsEnum: {}",
444                other
445            )
446            .into()),
447        }
448    }
449}
450
451#[allow(non_camel_case_types)]
452#[derive(Debug, Clone, Serialize, Deserialize)]
453pub enum OrderCancelReplaceOrderRateLimitExceededModeEnum {
454    #[serde(rename = "DO_NOTHING")]
455    DoNothing,
456    #[serde(rename = "CANCEL_ONLY")]
457    CancelOnly,
458}
459
460impl OrderCancelReplaceOrderRateLimitExceededModeEnum {
461    #[must_use]
462    pub fn as_str(&self) -> &'static str {
463        match self {
464            Self::DoNothing => "DO_NOTHING",
465            Self::CancelOnly => "CANCEL_ONLY",
466        }
467    }
468}
469
470impl std::str::FromStr for OrderCancelReplaceOrderRateLimitExceededModeEnum {
471    type Err = Box<dyn std::error::Error + Send + Sync>;
472
473    fn from_str(s: &str) -> Result<Self, Self::Err> {
474        match s {
475            "DO_NOTHING" => Ok(Self::DoNothing),
476            "CANCEL_ONLY" => Ok(Self::CancelOnly),
477            other => Err(format!(
478                "invalid OrderCancelReplaceOrderRateLimitExceededModeEnum: {}",
479                other
480            )
481            .into()),
482        }
483    }
484}
485
486#[allow(non_camel_case_types)]
487#[derive(Debug, Clone, Serialize, Deserialize)]
488pub enum OrderCancelReplacePegPriceTypeEnum {
489    #[serde(rename = "PRIMARY_PEG")]
490    PrimaryPeg,
491    #[serde(rename = "MARKET_PEG")]
492    MarketPeg,
493    #[serde(rename = "NON_REPRESENTABLE")]
494    NonRepresentable,
495}
496
497impl OrderCancelReplacePegPriceTypeEnum {
498    #[must_use]
499    pub fn as_str(&self) -> &'static str {
500        match self {
501            Self::PrimaryPeg => "PRIMARY_PEG",
502            Self::MarketPeg => "MARKET_PEG",
503            Self::NonRepresentable => "NON_REPRESENTABLE",
504        }
505    }
506}
507
508impl std::str::FromStr for OrderCancelReplacePegPriceTypeEnum {
509    type Err = Box<dyn std::error::Error + Send + Sync>;
510
511    fn from_str(s: &str) -> Result<Self, Self::Err> {
512        match s {
513            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
514            "MARKET_PEG" => Ok(Self::MarketPeg),
515            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
516            other => Err(format!("invalid OrderCancelReplacePegPriceTypeEnum: {}", other).into()),
517        }
518    }
519}
520
521#[allow(non_camel_case_types)]
522#[derive(Debug, Clone, Serialize, Deserialize)]
523pub enum OrderCancelReplacePegOffsetTypeEnum {
524    #[serde(rename = "PRICE_LEVEL")]
525    PriceLevel,
526    #[serde(rename = "NON_REPRESENTABLE")]
527    NonRepresentable,
528}
529
530impl OrderCancelReplacePegOffsetTypeEnum {
531    #[must_use]
532    pub fn as_str(&self) -> &'static str {
533        match self {
534            Self::PriceLevel => "PRICE_LEVEL",
535            Self::NonRepresentable => "NON_REPRESENTABLE",
536        }
537    }
538}
539
540impl std::str::FromStr for OrderCancelReplacePegOffsetTypeEnum {
541    type Err = Box<dyn std::error::Error + Send + Sync>;
542
543    fn from_str(s: &str) -> Result<Self, Self::Err> {
544        match s {
545            "PRICE_LEVEL" => Ok(Self::PriceLevel),
546            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
547            other => Err(format!("invalid OrderCancelReplacePegOffsetTypeEnum: {}", other).into()),
548        }
549    }
550}
551
552#[allow(non_camel_case_types)]
553#[derive(Debug, Clone, Serialize, Deserialize)]
554pub enum OrderListPlaceSideEnum {
555    #[serde(rename = "BUY")]
556    Buy,
557    #[serde(rename = "SELL")]
558    Sell,
559}
560
561impl OrderListPlaceSideEnum {
562    #[must_use]
563    pub fn as_str(&self) -> &'static str {
564        match self {
565            Self::Buy => "BUY",
566            Self::Sell => "SELL",
567        }
568    }
569}
570
571impl std::str::FromStr for OrderListPlaceSideEnum {
572    type Err = Box<dyn std::error::Error + Send + Sync>;
573
574    fn from_str(s: &str) -> Result<Self, Self::Err> {
575        match s {
576            "BUY" => Ok(Self::Buy),
577            "SELL" => Ok(Self::Sell),
578            other => Err(format!("invalid OrderListPlaceSideEnum: {}", other).into()),
579        }
580    }
581}
582
583#[allow(non_camel_case_types)]
584#[derive(Debug, Clone, Serialize, Deserialize)]
585pub enum OrderListPlaceStopLimitTimeInForceEnum {
586    #[serde(rename = "GTC")]
587    Gtc,
588    #[serde(rename = "IOC")]
589    Ioc,
590    #[serde(rename = "FOK")]
591    Fok,
592}
593
594impl OrderListPlaceStopLimitTimeInForceEnum {
595    #[must_use]
596    pub fn as_str(&self) -> &'static str {
597        match self {
598            Self::Gtc => "GTC",
599            Self::Ioc => "IOC",
600            Self::Fok => "FOK",
601        }
602    }
603}
604
605impl std::str::FromStr for OrderListPlaceStopLimitTimeInForceEnum {
606    type Err = Box<dyn std::error::Error + Send + Sync>;
607
608    fn from_str(s: &str) -> Result<Self, Self::Err> {
609        match s {
610            "GTC" => Ok(Self::Gtc),
611            "IOC" => Ok(Self::Ioc),
612            "FOK" => Ok(Self::Fok),
613            other => {
614                Err(format!("invalid OrderListPlaceStopLimitTimeInForceEnum: {}", other).into())
615            }
616        }
617    }
618}
619
620#[allow(non_camel_case_types)]
621#[derive(Debug, Clone, Serialize, Deserialize)]
622pub enum OrderListPlaceNewOrderRespTypeEnum {
623    #[serde(rename = "ACK")]
624    Ack,
625    #[serde(rename = "RESULT")]
626    Result,
627    #[serde(rename = "FULL")]
628    Full,
629    #[serde(rename = "MARKET")]
630    Market,
631    #[serde(rename = "LIMIT")]
632    Limit,
633}
634
635impl OrderListPlaceNewOrderRespTypeEnum {
636    #[must_use]
637    pub fn as_str(&self) -> &'static str {
638        match self {
639            Self::Ack => "ACK",
640            Self::Result => "RESULT",
641            Self::Full => "FULL",
642            Self::Market => "MARKET",
643            Self::Limit => "LIMIT",
644        }
645    }
646}
647
648impl std::str::FromStr for OrderListPlaceNewOrderRespTypeEnum {
649    type Err = Box<dyn std::error::Error + Send + Sync>;
650
651    fn from_str(s: &str) -> Result<Self, Self::Err> {
652        match s {
653            "ACK" => Ok(Self::Ack),
654            "RESULT" => Ok(Self::Result),
655            "FULL" => Ok(Self::Full),
656            "MARKET" => Ok(Self::Market),
657            "LIMIT" => Ok(Self::Limit),
658            other => Err(format!("invalid OrderListPlaceNewOrderRespTypeEnum: {}", other).into()),
659        }
660    }
661}
662
663#[allow(non_camel_case_types)]
664#[derive(Debug, Clone, Serialize, Deserialize)]
665pub enum OrderListPlaceSelfTradePreventionModeEnum {
666    #[serde(rename = "NONE")]
667    None,
668    #[serde(rename = "EXPIRE_TAKER")]
669    ExpireTaker,
670    #[serde(rename = "EXPIRE_MAKER")]
671    ExpireMaker,
672    #[serde(rename = "EXPIRE_BOTH")]
673    ExpireBoth,
674    #[serde(rename = "DECREMENT")]
675    Decrement,
676    #[serde(rename = "TRANSFER")]
677    Transfer,
678    #[serde(rename = "NON_REPRESENTABLE")]
679    NonRepresentable,
680}
681
682impl OrderListPlaceSelfTradePreventionModeEnum {
683    #[must_use]
684    pub fn as_str(&self) -> &'static str {
685        match self {
686            Self::None => "NONE",
687            Self::ExpireTaker => "EXPIRE_TAKER",
688            Self::ExpireMaker => "EXPIRE_MAKER",
689            Self::ExpireBoth => "EXPIRE_BOTH",
690            Self::Decrement => "DECREMENT",
691            Self::Transfer => "TRANSFER",
692            Self::NonRepresentable => "NON_REPRESENTABLE",
693        }
694    }
695}
696
697impl std::str::FromStr for OrderListPlaceSelfTradePreventionModeEnum {
698    type Err = Box<dyn std::error::Error + Send + Sync>;
699
700    fn from_str(s: &str) -> Result<Self, Self::Err> {
701        match s {
702            "NONE" => Ok(Self::None),
703            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
704            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
705            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
706            "DECREMENT" => Ok(Self::Decrement),
707            "TRANSFER" => Ok(Self::Transfer),
708            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
709            other => Err(format!(
710                "invalid OrderListPlaceSelfTradePreventionModeEnum: {}",
711                other
712            )
713            .into()),
714        }
715    }
716}
717
718#[allow(non_camel_case_types)]
719#[derive(Debug, Clone, Serialize, Deserialize)]
720pub enum OrderListPlaceOcoSideEnum {
721    #[serde(rename = "BUY")]
722    Buy,
723    #[serde(rename = "SELL")]
724    Sell,
725}
726
727impl OrderListPlaceOcoSideEnum {
728    #[must_use]
729    pub fn as_str(&self) -> &'static str {
730        match self {
731            Self::Buy => "BUY",
732            Self::Sell => "SELL",
733        }
734    }
735}
736
737impl std::str::FromStr for OrderListPlaceOcoSideEnum {
738    type Err = Box<dyn std::error::Error + Send + Sync>;
739
740    fn from_str(s: &str) -> Result<Self, Self::Err> {
741        match s {
742            "BUY" => Ok(Self::Buy),
743            "SELL" => Ok(Self::Sell),
744            other => Err(format!("invalid OrderListPlaceOcoSideEnum: {}", other).into()),
745        }
746    }
747}
748
749#[allow(non_camel_case_types)]
750#[derive(Debug, Clone, Serialize, Deserialize)]
751pub enum OrderListPlaceOcoAboveTypeEnum {
752    #[serde(rename = "STOP_LOSS_LIMIT")]
753    StopLossLimit,
754    #[serde(rename = "STOP_LOSS")]
755    StopLoss,
756    #[serde(rename = "LIMIT_MAKER")]
757    LimitMaker,
758    #[serde(rename = "TAKE_PROFIT")]
759    TakeProfit,
760    #[serde(rename = "TAKE_PROFIT_LIMIT")]
761    TakeProfitLimit,
762}
763
764impl OrderListPlaceOcoAboveTypeEnum {
765    #[must_use]
766    pub fn as_str(&self) -> &'static str {
767        match self {
768            Self::StopLossLimit => "STOP_LOSS_LIMIT",
769            Self::StopLoss => "STOP_LOSS",
770            Self::LimitMaker => "LIMIT_MAKER",
771            Self::TakeProfit => "TAKE_PROFIT",
772            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
773        }
774    }
775}
776
777impl std::str::FromStr for OrderListPlaceOcoAboveTypeEnum {
778    type Err = Box<dyn std::error::Error + Send + Sync>;
779
780    fn from_str(s: &str) -> Result<Self, Self::Err> {
781        match s {
782            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
783            "STOP_LOSS" => Ok(Self::StopLoss),
784            "LIMIT_MAKER" => Ok(Self::LimitMaker),
785            "TAKE_PROFIT" => Ok(Self::TakeProfit),
786            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
787            other => Err(format!("invalid OrderListPlaceOcoAboveTypeEnum: {}", other).into()),
788        }
789    }
790}
791
792#[allow(non_camel_case_types)]
793#[derive(Debug, Clone, Serialize, Deserialize)]
794pub enum OrderListPlaceOcoBelowTypeEnum {
795    #[serde(rename = "STOP_LOSS")]
796    StopLoss,
797    #[serde(rename = "STOP_LOSS_LIMIT")]
798    StopLossLimit,
799    #[serde(rename = "TAKE_PROFIT")]
800    TakeProfit,
801    #[serde(rename = "TAKE_PROFIT_LIMIT")]
802    TakeProfitLimit,
803}
804
805impl OrderListPlaceOcoBelowTypeEnum {
806    #[must_use]
807    pub fn as_str(&self) -> &'static str {
808        match self {
809            Self::StopLoss => "STOP_LOSS",
810            Self::StopLossLimit => "STOP_LOSS_LIMIT",
811            Self::TakeProfit => "TAKE_PROFIT",
812            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
813        }
814    }
815}
816
817impl std::str::FromStr for OrderListPlaceOcoBelowTypeEnum {
818    type Err = Box<dyn std::error::Error + Send + Sync>;
819
820    fn from_str(s: &str) -> Result<Self, Self::Err> {
821        match s {
822            "STOP_LOSS" => Ok(Self::StopLoss),
823            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
824            "TAKE_PROFIT" => Ok(Self::TakeProfit),
825            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
826            other => Err(format!("invalid OrderListPlaceOcoBelowTypeEnum: {}", other).into()),
827        }
828    }
829}
830
831#[allow(non_camel_case_types)]
832#[derive(Debug, Clone, Serialize, Deserialize)]
833pub enum OrderListPlaceOcoAboveTimeInForceEnum {
834    #[serde(rename = "GTC")]
835    Gtc,
836    #[serde(rename = "IOC")]
837    Ioc,
838    #[serde(rename = "FOK")]
839    Fok,
840}
841
842impl OrderListPlaceOcoAboveTimeInForceEnum {
843    #[must_use]
844    pub fn as_str(&self) -> &'static str {
845        match self {
846            Self::Gtc => "GTC",
847            Self::Ioc => "IOC",
848            Self::Fok => "FOK",
849        }
850    }
851}
852
853impl std::str::FromStr for OrderListPlaceOcoAboveTimeInForceEnum {
854    type Err = Box<dyn std::error::Error + Send + Sync>;
855
856    fn from_str(s: &str) -> Result<Self, Self::Err> {
857        match s {
858            "GTC" => Ok(Self::Gtc),
859            "IOC" => Ok(Self::Ioc),
860            "FOK" => Ok(Self::Fok),
861            other => {
862                Err(format!("invalid OrderListPlaceOcoAboveTimeInForceEnum: {}", other).into())
863            }
864        }
865    }
866}
867
868#[allow(non_camel_case_types)]
869#[derive(Debug, Clone, Serialize, Deserialize)]
870pub enum OrderListPlaceOcoAbovePegPriceTypeEnum {
871    #[serde(rename = "PRIMARY_PEG")]
872    PrimaryPeg,
873    #[serde(rename = "MARKET_PEG")]
874    MarketPeg,
875}
876
877impl OrderListPlaceOcoAbovePegPriceTypeEnum {
878    #[must_use]
879    pub fn as_str(&self) -> &'static str {
880        match self {
881            Self::PrimaryPeg => "PRIMARY_PEG",
882            Self::MarketPeg => "MARKET_PEG",
883        }
884    }
885}
886
887impl std::str::FromStr for OrderListPlaceOcoAbovePegPriceTypeEnum {
888    type Err = Box<dyn std::error::Error + Send + Sync>;
889
890    fn from_str(s: &str) -> Result<Self, Self::Err> {
891        match s {
892            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
893            "MARKET_PEG" => Ok(Self::MarketPeg),
894            other => {
895                Err(format!("invalid OrderListPlaceOcoAbovePegPriceTypeEnum: {}", other).into())
896            }
897        }
898    }
899}
900
901#[allow(non_camel_case_types)]
902#[derive(Debug, Clone, Serialize, Deserialize)]
903pub enum OrderListPlaceOcoAbovePegOffsetTypeEnum {
904    #[serde(rename = "PRICE_LEVEL")]
905    PriceLevel,
906}
907
908impl OrderListPlaceOcoAbovePegOffsetTypeEnum {
909    #[must_use]
910    pub fn as_str(&self) -> &'static str {
911        match self {
912            Self::PriceLevel => "PRICE_LEVEL",
913        }
914    }
915}
916
917impl std::str::FromStr for OrderListPlaceOcoAbovePegOffsetTypeEnum {
918    type Err = Box<dyn std::error::Error + Send + Sync>;
919
920    fn from_str(s: &str) -> Result<Self, Self::Err> {
921        match s {
922            "PRICE_LEVEL" => Ok(Self::PriceLevel),
923            other => {
924                Err(format!("invalid OrderListPlaceOcoAbovePegOffsetTypeEnum: {}", other).into())
925            }
926        }
927    }
928}
929
930#[allow(non_camel_case_types)]
931#[derive(Debug, Clone, Serialize, Deserialize)]
932pub enum OrderListPlaceOcoBelowTimeInForceEnum {
933    #[serde(rename = "GTC")]
934    Gtc,
935    #[serde(rename = "IOC")]
936    Ioc,
937    #[serde(rename = "FOK")]
938    Fok,
939}
940
941impl OrderListPlaceOcoBelowTimeInForceEnum {
942    #[must_use]
943    pub fn as_str(&self) -> &'static str {
944        match self {
945            Self::Gtc => "GTC",
946            Self::Ioc => "IOC",
947            Self::Fok => "FOK",
948        }
949    }
950}
951
952impl std::str::FromStr for OrderListPlaceOcoBelowTimeInForceEnum {
953    type Err = Box<dyn std::error::Error + Send + Sync>;
954
955    fn from_str(s: &str) -> Result<Self, Self::Err> {
956        match s {
957            "GTC" => Ok(Self::Gtc),
958            "IOC" => Ok(Self::Ioc),
959            "FOK" => Ok(Self::Fok),
960            other => {
961                Err(format!("invalid OrderListPlaceOcoBelowTimeInForceEnum: {}", other).into())
962            }
963        }
964    }
965}
966
967#[allow(non_camel_case_types)]
968#[derive(Debug, Clone, Serialize, Deserialize)]
969pub enum OrderListPlaceOcoBelowPegPriceTypeEnum {
970    #[serde(rename = "PRIMARY_PEG")]
971    PrimaryPeg,
972    #[serde(rename = "MARKET_PEG")]
973    MarketPeg,
974}
975
976impl OrderListPlaceOcoBelowPegPriceTypeEnum {
977    #[must_use]
978    pub fn as_str(&self) -> &'static str {
979        match self {
980            Self::PrimaryPeg => "PRIMARY_PEG",
981            Self::MarketPeg => "MARKET_PEG",
982        }
983    }
984}
985
986impl std::str::FromStr for OrderListPlaceOcoBelowPegPriceTypeEnum {
987    type Err = Box<dyn std::error::Error + Send + Sync>;
988
989    fn from_str(s: &str) -> Result<Self, Self::Err> {
990        match s {
991            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
992            "MARKET_PEG" => Ok(Self::MarketPeg),
993            other => {
994                Err(format!("invalid OrderListPlaceOcoBelowPegPriceTypeEnum: {}", other).into())
995            }
996        }
997    }
998}
999
1000#[allow(non_camel_case_types)]
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub enum OrderListPlaceOcoBelowPegOffsetTypeEnum {
1003    #[serde(rename = "PRICE_LEVEL")]
1004    PriceLevel,
1005}
1006
1007impl OrderListPlaceOcoBelowPegOffsetTypeEnum {
1008    #[must_use]
1009    pub fn as_str(&self) -> &'static str {
1010        match self {
1011            Self::PriceLevel => "PRICE_LEVEL",
1012        }
1013    }
1014}
1015
1016impl std::str::FromStr for OrderListPlaceOcoBelowPegOffsetTypeEnum {
1017    type Err = Box<dyn std::error::Error + Send + Sync>;
1018
1019    fn from_str(s: &str) -> Result<Self, Self::Err> {
1020        match s {
1021            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1022            other => {
1023                Err(format!("invalid OrderListPlaceOcoBelowPegOffsetTypeEnum: {}", other).into())
1024            }
1025        }
1026    }
1027}
1028
1029#[allow(non_camel_case_types)]
1030#[derive(Debug, Clone, Serialize, Deserialize)]
1031pub enum OrderListPlaceOcoNewOrderRespTypeEnum {
1032    #[serde(rename = "ACK")]
1033    Ack,
1034    #[serde(rename = "RESULT")]
1035    Result,
1036    #[serde(rename = "FULL")]
1037    Full,
1038    #[serde(rename = "MARKET")]
1039    Market,
1040    #[serde(rename = "LIMIT")]
1041    Limit,
1042}
1043
1044impl OrderListPlaceOcoNewOrderRespTypeEnum {
1045    #[must_use]
1046    pub fn as_str(&self) -> &'static str {
1047        match self {
1048            Self::Ack => "ACK",
1049            Self::Result => "RESULT",
1050            Self::Full => "FULL",
1051            Self::Market => "MARKET",
1052            Self::Limit => "LIMIT",
1053        }
1054    }
1055}
1056
1057impl std::str::FromStr for OrderListPlaceOcoNewOrderRespTypeEnum {
1058    type Err = Box<dyn std::error::Error + Send + Sync>;
1059
1060    fn from_str(s: &str) -> Result<Self, Self::Err> {
1061        match s {
1062            "ACK" => Ok(Self::Ack),
1063            "RESULT" => Ok(Self::Result),
1064            "FULL" => Ok(Self::Full),
1065            "MARKET" => Ok(Self::Market),
1066            "LIMIT" => Ok(Self::Limit),
1067            other => {
1068                Err(format!("invalid OrderListPlaceOcoNewOrderRespTypeEnum: {}", other).into())
1069            }
1070        }
1071    }
1072}
1073
1074#[allow(non_camel_case_types)]
1075#[derive(Debug, Clone, Serialize, Deserialize)]
1076pub enum OrderListPlaceOcoSelfTradePreventionModeEnum {
1077    #[serde(rename = "NONE")]
1078    None,
1079    #[serde(rename = "EXPIRE_TAKER")]
1080    ExpireTaker,
1081    #[serde(rename = "EXPIRE_MAKER")]
1082    ExpireMaker,
1083    #[serde(rename = "EXPIRE_BOTH")]
1084    ExpireBoth,
1085    #[serde(rename = "DECREMENT")]
1086    Decrement,
1087    #[serde(rename = "TRANSFER")]
1088    Transfer,
1089    #[serde(rename = "NON_REPRESENTABLE")]
1090    NonRepresentable,
1091}
1092
1093impl OrderListPlaceOcoSelfTradePreventionModeEnum {
1094    #[must_use]
1095    pub fn as_str(&self) -> &'static str {
1096        match self {
1097            Self::None => "NONE",
1098            Self::ExpireTaker => "EXPIRE_TAKER",
1099            Self::ExpireMaker => "EXPIRE_MAKER",
1100            Self::ExpireBoth => "EXPIRE_BOTH",
1101            Self::Decrement => "DECREMENT",
1102            Self::Transfer => "TRANSFER",
1103            Self::NonRepresentable => "NON_REPRESENTABLE",
1104        }
1105    }
1106}
1107
1108impl std::str::FromStr for OrderListPlaceOcoSelfTradePreventionModeEnum {
1109    type Err = Box<dyn std::error::Error + Send + Sync>;
1110
1111    fn from_str(s: &str) -> Result<Self, Self::Err> {
1112        match s {
1113            "NONE" => Ok(Self::None),
1114            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1115            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1116            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1117            "DECREMENT" => Ok(Self::Decrement),
1118            "TRANSFER" => Ok(Self::Transfer),
1119            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
1120            other => Err(format!(
1121                "invalid OrderListPlaceOcoSelfTradePreventionModeEnum: {}",
1122                other
1123            )
1124            .into()),
1125        }
1126    }
1127}
1128
1129#[allow(non_camel_case_types)]
1130#[derive(Debug, Clone, Serialize, Deserialize)]
1131pub enum OrderListPlaceOpoWorkingTypeEnum {
1132    #[serde(rename = "LIMIT")]
1133    Limit,
1134    #[serde(rename = "LIMIT_MAKER")]
1135    LimitMaker,
1136}
1137
1138impl OrderListPlaceOpoWorkingTypeEnum {
1139    #[must_use]
1140    pub fn as_str(&self) -> &'static str {
1141        match self {
1142            Self::Limit => "LIMIT",
1143            Self::LimitMaker => "LIMIT_MAKER",
1144        }
1145    }
1146}
1147
1148impl std::str::FromStr for OrderListPlaceOpoWorkingTypeEnum {
1149    type Err = Box<dyn std::error::Error + Send + Sync>;
1150
1151    fn from_str(s: &str) -> Result<Self, Self::Err> {
1152        match s {
1153            "LIMIT" => Ok(Self::Limit),
1154            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1155            other => Err(format!("invalid OrderListPlaceOpoWorkingTypeEnum: {}", other).into()),
1156        }
1157    }
1158}
1159
1160#[allow(non_camel_case_types)]
1161#[derive(Debug, Clone, Serialize, Deserialize)]
1162pub enum OrderListPlaceOpoWorkingSideEnum {
1163    #[serde(rename = "BUY")]
1164    Buy,
1165    #[serde(rename = "SELL")]
1166    Sell,
1167}
1168
1169impl OrderListPlaceOpoWorkingSideEnum {
1170    #[must_use]
1171    pub fn as_str(&self) -> &'static str {
1172        match self {
1173            Self::Buy => "BUY",
1174            Self::Sell => "SELL",
1175        }
1176    }
1177}
1178
1179impl std::str::FromStr for OrderListPlaceOpoWorkingSideEnum {
1180    type Err = Box<dyn std::error::Error + Send + Sync>;
1181
1182    fn from_str(s: &str) -> Result<Self, Self::Err> {
1183        match s {
1184            "BUY" => Ok(Self::Buy),
1185            "SELL" => Ok(Self::Sell),
1186            other => Err(format!("invalid OrderListPlaceOpoWorkingSideEnum: {}", other).into()),
1187        }
1188    }
1189}
1190
1191#[allow(non_camel_case_types)]
1192#[derive(Debug, Clone, Serialize, Deserialize)]
1193pub enum OrderListPlaceOpoPendingTypeEnum {
1194    #[serde(rename = "LIMIT")]
1195    Limit,
1196    #[serde(rename = "MARKET")]
1197    Market,
1198    #[serde(rename = "STOP_LOSS")]
1199    StopLoss,
1200    #[serde(rename = "STOP_LOSS_LIMIT")]
1201    StopLossLimit,
1202    #[serde(rename = "TAKE_PROFIT")]
1203    TakeProfit,
1204    #[serde(rename = "TAKE_PROFIT_LIMIT")]
1205    TakeProfitLimit,
1206    #[serde(rename = "LIMIT_MAKER")]
1207    LimitMaker,
1208}
1209
1210impl OrderListPlaceOpoPendingTypeEnum {
1211    #[must_use]
1212    pub fn as_str(&self) -> &'static str {
1213        match self {
1214            Self::Limit => "LIMIT",
1215            Self::Market => "MARKET",
1216            Self::StopLoss => "STOP_LOSS",
1217            Self::StopLossLimit => "STOP_LOSS_LIMIT",
1218            Self::TakeProfit => "TAKE_PROFIT",
1219            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
1220            Self::LimitMaker => "LIMIT_MAKER",
1221        }
1222    }
1223}
1224
1225impl std::str::FromStr for OrderListPlaceOpoPendingTypeEnum {
1226    type Err = Box<dyn std::error::Error + Send + Sync>;
1227
1228    fn from_str(s: &str) -> Result<Self, Self::Err> {
1229        match s {
1230            "LIMIT" => Ok(Self::Limit),
1231            "MARKET" => Ok(Self::Market),
1232            "STOP_LOSS" => Ok(Self::StopLoss),
1233            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
1234            "TAKE_PROFIT" => Ok(Self::TakeProfit),
1235            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
1236            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1237            other => Err(format!("invalid OrderListPlaceOpoPendingTypeEnum: {}", other).into()),
1238        }
1239    }
1240}
1241
1242#[allow(non_camel_case_types)]
1243#[derive(Debug, Clone, Serialize, Deserialize)]
1244pub enum OrderListPlaceOpoPendingSideEnum {
1245    #[serde(rename = "BUY")]
1246    Buy,
1247    #[serde(rename = "SELL")]
1248    Sell,
1249}
1250
1251impl OrderListPlaceOpoPendingSideEnum {
1252    #[must_use]
1253    pub fn as_str(&self) -> &'static str {
1254        match self {
1255            Self::Buy => "BUY",
1256            Self::Sell => "SELL",
1257        }
1258    }
1259}
1260
1261impl std::str::FromStr for OrderListPlaceOpoPendingSideEnum {
1262    type Err = Box<dyn std::error::Error + Send + Sync>;
1263
1264    fn from_str(s: &str) -> Result<Self, Self::Err> {
1265        match s {
1266            "BUY" => Ok(Self::Buy),
1267            "SELL" => Ok(Self::Sell),
1268            other => Err(format!("invalid OrderListPlaceOpoPendingSideEnum: {}", other).into()),
1269        }
1270    }
1271}
1272
1273#[allow(non_camel_case_types)]
1274#[derive(Debug, Clone, Serialize, Deserialize)]
1275pub enum OrderListPlaceOpoNewOrderRespTypeEnum {
1276    #[serde(rename = "ACK")]
1277    Ack,
1278    #[serde(rename = "RESULT")]
1279    Result,
1280    #[serde(rename = "FULL")]
1281    Full,
1282    #[serde(rename = "MARKET")]
1283    Market,
1284    #[serde(rename = "LIMIT")]
1285    Limit,
1286}
1287
1288impl OrderListPlaceOpoNewOrderRespTypeEnum {
1289    #[must_use]
1290    pub fn as_str(&self) -> &'static str {
1291        match self {
1292            Self::Ack => "ACK",
1293            Self::Result => "RESULT",
1294            Self::Full => "FULL",
1295            Self::Market => "MARKET",
1296            Self::Limit => "LIMIT",
1297        }
1298    }
1299}
1300
1301impl std::str::FromStr for OrderListPlaceOpoNewOrderRespTypeEnum {
1302    type Err = Box<dyn std::error::Error + Send + Sync>;
1303
1304    fn from_str(s: &str) -> Result<Self, Self::Err> {
1305        match s {
1306            "ACK" => Ok(Self::Ack),
1307            "RESULT" => Ok(Self::Result),
1308            "FULL" => Ok(Self::Full),
1309            "MARKET" => Ok(Self::Market),
1310            "LIMIT" => Ok(Self::Limit),
1311            other => {
1312                Err(format!("invalid OrderListPlaceOpoNewOrderRespTypeEnum: {}", other).into())
1313            }
1314        }
1315    }
1316}
1317
1318#[allow(non_camel_case_types)]
1319#[derive(Debug, Clone, Serialize, Deserialize)]
1320pub enum OrderListPlaceOpoSelfTradePreventionModeEnum {
1321    #[serde(rename = "NONE")]
1322    None,
1323    #[serde(rename = "EXPIRE_TAKER")]
1324    ExpireTaker,
1325    #[serde(rename = "EXPIRE_MAKER")]
1326    ExpireMaker,
1327    #[serde(rename = "EXPIRE_BOTH")]
1328    ExpireBoth,
1329    #[serde(rename = "DECREMENT")]
1330    Decrement,
1331    #[serde(rename = "TRANSFER")]
1332    Transfer,
1333    #[serde(rename = "NON_REPRESENTABLE")]
1334    NonRepresentable,
1335}
1336
1337impl OrderListPlaceOpoSelfTradePreventionModeEnum {
1338    #[must_use]
1339    pub fn as_str(&self) -> &'static str {
1340        match self {
1341            Self::None => "NONE",
1342            Self::ExpireTaker => "EXPIRE_TAKER",
1343            Self::ExpireMaker => "EXPIRE_MAKER",
1344            Self::ExpireBoth => "EXPIRE_BOTH",
1345            Self::Decrement => "DECREMENT",
1346            Self::Transfer => "TRANSFER",
1347            Self::NonRepresentable => "NON_REPRESENTABLE",
1348        }
1349    }
1350}
1351
1352impl std::str::FromStr for OrderListPlaceOpoSelfTradePreventionModeEnum {
1353    type Err = Box<dyn std::error::Error + Send + Sync>;
1354
1355    fn from_str(s: &str) -> Result<Self, Self::Err> {
1356        match s {
1357            "NONE" => Ok(Self::None),
1358            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1359            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1360            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1361            "DECREMENT" => Ok(Self::Decrement),
1362            "TRANSFER" => Ok(Self::Transfer),
1363            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
1364            other => Err(format!(
1365                "invalid OrderListPlaceOpoSelfTradePreventionModeEnum: {}",
1366                other
1367            )
1368            .into()),
1369        }
1370    }
1371}
1372
1373#[allow(non_camel_case_types)]
1374#[derive(Debug, Clone, Serialize, Deserialize)]
1375pub enum OrderListPlaceOpoWorkingTimeInForceEnum {
1376    #[serde(rename = "GTC")]
1377    Gtc,
1378    #[serde(rename = "IOC")]
1379    Ioc,
1380    #[serde(rename = "FOK")]
1381    Fok,
1382}
1383
1384impl OrderListPlaceOpoWorkingTimeInForceEnum {
1385    #[must_use]
1386    pub fn as_str(&self) -> &'static str {
1387        match self {
1388            Self::Gtc => "GTC",
1389            Self::Ioc => "IOC",
1390            Self::Fok => "FOK",
1391        }
1392    }
1393}
1394
1395impl std::str::FromStr for OrderListPlaceOpoWorkingTimeInForceEnum {
1396    type Err = Box<dyn std::error::Error + Send + Sync>;
1397
1398    fn from_str(s: &str) -> Result<Self, Self::Err> {
1399        match s {
1400            "GTC" => Ok(Self::Gtc),
1401            "IOC" => Ok(Self::Ioc),
1402            "FOK" => Ok(Self::Fok),
1403            other => {
1404                Err(format!("invalid OrderListPlaceOpoWorkingTimeInForceEnum: {}", other).into())
1405            }
1406        }
1407    }
1408}
1409
1410#[allow(non_camel_case_types)]
1411#[derive(Debug, Clone, Serialize, Deserialize)]
1412pub enum OrderListPlaceOpoWorkingPegPriceTypeEnum {
1413    #[serde(rename = "PRIMARY_PEG")]
1414    PrimaryPeg,
1415    #[serde(rename = "MARKET_PEG")]
1416    MarketPeg,
1417}
1418
1419impl OrderListPlaceOpoWorkingPegPriceTypeEnum {
1420    #[must_use]
1421    pub fn as_str(&self) -> &'static str {
1422        match self {
1423            Self::PrimaryPeg => "PRIMARY_PEG",
1424            Self::MarketPeg => "MARKET_PEG",
1425        }
1426    }
1427}
1428
1429impl std::str::FromStr for OrderListPlaceOpoWorkingPegPriceTypeEnum {
1430    type Err = Box<dyn std::error::Error + Send + Sync>;
1431
1432    fn from_str(s: &str) -> Result<Self, Self::Err> {
1433        match s {
1434            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1435            "MARKET_PEG" => Ok(Self::MarketPeg),
1436            other => Err(format!(
1437                "invalid OrderListPlaceOpoWorkingPegPriceTypeEnum: {}",
1438                other
1439            )
1440            .into()),
1441        }
1442    }
1443}
1444
1445#[allow(non_camel_case_types)]
1446#[derive(Debug, Clone, Serialize, Deserialize)]
1447pub enum OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1448    #[serde(rename = "PRICE_LEVEL")]
1449    PriceLevel,
1450}
1451
1452impl OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1453    #[must_use]
1454    pub fn as_str(&self) -> &'static str {
1455        match self {
1456            Self::PriceLevel => "PRICE_LEVEL",
1457        }
1458    }
1459}
1460
1461impl std::str::FromStr for OrderListPlaceOpoWorkingPegOffsetTypeEnum {
1462    type Err = Box<dyn std::error::Error + Send + Sync>;
1463
1464    fn from_str(s: &str) -> Result<Self, Self::Err> {
1465        match s {
1466            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1467            other => Err(format!(
1468                "invalid OrderListPlaceOpoWorkingPegOffsetTypeEnum: {}",
1469                other
1470            )
1471            .into()),
1472        }
1473    }
1474}
1475
1476#[allow(non_camel_case_types)]
1477#[derive(Debug, Clone, Serialize, Deserialize)]
1478pub enum OrderListPlaceOpoPendingTimeInForceEnum {
1479    #[serde(rename = "GTC")]
1480    Gtc,
1481    #[serde(rename = "IOC")]
1482    Ioc,
1483    #[serde(rename = "FOK")]
1484    Fok,
1485}
1486
1487impl OrderListPlaceOpoPendingTimeInForceEnum {
1488    #[must_use]
1489    pub fn as_str(&self) -> &'static str {
1490        match self {
1491            Self::Gtc => "GTC",
1492            Self::Ioc => "IOC",
1493            Self::Fok => "FOK",
1494        }
1495    }
1496}
1497
1498impl std::str::FromStr for OrderListPlaceOpoPendingTimeInForceEnum {
1499    type Err = Box<dyn std::error::Error + Send + Sync>;
1500
1501    fn from_str(s: &str) -> Result<Self, Self::Err> {
1502        match s {
1503            "GTC" => Ok(Self::Gtc),
1504            "IOC" => Ok(Self::Ioc),
1505            "FOK" => Ok(Self::Fok),
1506            other => {
1507                Err(format!("invalid OrderListPlaceOpoPendingTimeInForceEnum: {}", other).into())
1508            }
1509        }
1510    }
1511}
1512
1513#[allow(non_camel_case_types)]
1514#[derive(Debug, Clone, Serialize, Deserialize)]
1515pub enum OrderListPlaceOpoPendingPegPriceTypeEnum {
1516    #[serde(rename = "PRIMARY_PEG")]
1517    PrimaryPeg,
1518    #[serde(rename = "MARKET_PEG")]
1519    MarketPeg,
1520}
1521
1522impl OrderListPlaceOpoPendingPegPriceTypeEnum {
1523    #[must_use]
1524    pub fn as_str(&self) -> &'static str {
1525        match self {
1526            Self::PrimaryPeg => "PRIMARY_PEG",
1527            Self::MarketPeg => "MARKET_PEG",
1528        }
1529    }
1530}
1531
1532impl std::str::FromStr for OrderListPlaceOpoPendingPegPriceTypeEnum {
1533    type Err = Box<dyn std::error::Error + Send + Sync>;
1534
1535    fn from_str(s: &str) -> Result<Self, Self::Err> {
1536        match s {
1537            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1538            "MARKET_PEG" => Ok(Self::MarketPeg),
1539            other => Err(format!(
1540                "invalid OrderListPlaceOpoPendingPegPriceTypeEnum: {}",
1541                other
1542            )
1543            .into()),
1544        }
1545    }
1546}
1547
1548#[allow(non_camel_case_types)]
1549#[derive(Debug, Clone, Serialize, Deserialize)]
1550pub enum OrderListPlaceOpoPendingPegOffsetTypeEnum {
1551    #[serde(rename = "PRICE_LEVEL")]
1552    PriceLevel,
1553}
1554
1555impl OrderListPlaceOpoPendingPegOffsetTypeEnum {
1556    #[must_use]
1557    pub fn as_str(&self) -> &'static str {
1558        match self {
1559            Self::PriceLevel => "PRICE_LEVEL",
1560        }
1561    }
1562}
1563
1564impl std::str::FromStr for OrderListPlaceOpoPendingPegOffsetTypeEnum {
1565    type Err = Box<dyn std::error::Error + Send + Sync>;
1566
1567    fn from_str(s: &str) -> Result<Self, Self::Err> {
1568        match s {
1569            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1570            other => Err(format!(
1571                "invalid OrderListPlaceOpoPendingPegOffsetTypeEnum: {}",
1572                other
1573            )
1574            .into()),
1575        }
1576    }
1577}
1578
1579#[allow(non_camel_case_types)]
1580#[derive(Debug, Clone, Serialize, Deserialize)]
1581pub enum OrderListPlaceOpocoWorkingTypeEnum {
1582    #[serde(rename = "LIMIT")]
1583    Limit,
1584    #[serde(rename = "LIMIT_MAKER")]
1585    LimitMaker,
1586}
1587
1588impl OrderListPlaceOpocoWorkingTypeEnum {
1589    #[must_use]
1590    pub fn as_str(&self) -> &'static str {
1591        match self {
1592            Self::Limit => "LIMIT",
1593            Self::LimitMaker => "LIMIT_MAKER",
1594        }
1595    }
1596}
1597
1598impl std::str::FromStr for OrderListPlaceOpocoWorkingTypeEnum {
1599    type Err = Box<dyn std::error::Error + Send + Sync>;
1600
1601    fn from_str(s: &str) -> Result<Self, Self::Err> {
1602        match s {
1603            "LIMIT" => Ok(Self::Limit),
1604            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1605            other => Err(format!("invalid OrderListPlaceOpocoWorkingTypeEnum: {}", other).into()),
1606        }
1607    }
1608}
1609
1610#[allow(non_camel_case_types)]
1611#[derive(Debug, Clone, Serialize, Deserialize)]
1612pub enum OrderListPlaceOpocoWorkingSideEnum {
1613    #[serde(rename = "BUY")]
1614    Buy,
1615    #[serde(rename = "SELL")]
1616    Sell,
1617}
1618
1619impl OrderListPlaceOpocoWorkingSideEnum {
1620    #[must_use]
1621    pub fn as_str(&self) -> &'static str {
1622        match self {
1623            Self::Buy => "BUY",
1624            Self::Sell => "SELL",
1625        }
1626    }
1627}
1628
1629impl std::str::FromStr for OrderListPlaceOpocoWorkingSideEnum {
1630    type Err = Box<dyn std::error::Error + Send + Sync>;
1631
1632    fn from_str(s: &str) -> Result<Self, Self::Err> {
1633        match s {
1634            "BUY" => Ok(Self::Buy),
1635            "SELL" => Ok(Self::Sell),
1636            other => Err(format!("invalid OrderListPlaceOpocoWorkingSideEnum: {}", other).into()),
1637        }
1638    }
1639}
1640
1641#[allow(non_camel_case_types)]
1642#[derive(Debug, Clone, Serialize, Deserialize)]
1643pub enum OrderListPlaceOpocoPendingSideEnum {
1644    #[serde(rename = "BUY")]
1645    Buy,
1646    #[serde(rename = "SELL")]
1647    Sell,
1648}
1649
1650impl OrderListPlaceOpocoPendingSideEnum {
1651    #[must_use]
1652    pub fn as_str(&self) -> &'static str {
1653        match self {
1654            Self::Buy => "BUY",
1655            Self::Sell => "SELL",
1656        }
1657    }
1658}
1659
1660impl std::str::FromStr for OrderListPlaceOpocoPendingSideEnum {
1661    type Err = Box<dyn std::error::Error + Send + Sync>;
1662
1663    fn from_str(s: &str) -> Result<Self, Self::Err> {
1664        match s {
1665            "BUY" => Ok(Self::Buy),
1666            "SELL" => Ok(Self::Sell),
1667            other => Err(format!("invalid OrderListPlaceOpocoPendingSideEnum: {}", other).into()),
1668        }
1669    }
1670}
1671
1672#[allow(non_camel_case_types)]
1673#[derive(Debug, Clone, Serialize, Deserialize)]
1674pub enum OrderListPlaceOpocoPendingAboveTypeEnum {
1675    #[serde(rename = "STOP_LOSS_LIMIT")]
1676    StopLossLimit,
1677    #[serde(rename = "STOP_LOSS")]
1678    StopLoss,
1679    #[serde(rename = "LIMIT_MAKER")]
1680    LimitMaker,
1681    #[serde(rename = "TAKE_PROFIT")]
1682    TakeProfit,
1683    #[serde(rename = "TAKE_PROFIT_LIMIT")]
1684    TakeProfitLimit,
1685}
1686
1687impl OrderListPlaceOpocoPendingAboveTypeEnum {
1688    #[must_use]
1689    pub fn as_str(&self) -> &'static str {
1690        match self {
1691            Self::StopLossLimit => "STOP_LOSS_LIMIT",
1692            Self::StopLoss => "STOP_LOSS",
1693            Self::LimitMaker => "LIMIT_MAKER",
1694            Self::TakeProfit => "TAKE_PROFIT",
1695            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
1696        }
1697    }
1698}
1699
1700impl std::str::FromStr for OrderListPlaceOpocoPendingAboveTypeEnum {
1701    type Err = Box<dyn std::error::Error + Send + Sync>;
1702
1703    fn from_str(s: &str) -> Result<Self, Self::Err> {
1704        match s {
1705            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
1706            "STOP_LOSS" => Ok(Self::StopLoss),
1707            "LIMIT_MAKER" => Ok(Self::LimitMaker),
1708            "TAKE_PROFIT" => Ok(Self::TakeProfit),
1709            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
1710            other => {
1711                Err(format!("invalid OrderListPlaceOpocoPendingAboveTypeEnum: {}", other).into())
1712            }
1713        }
1714    }
1715}
1716
1717#[allow(non_camel_case_types)]
1718#[derive(Debug, Clone, Serialize, Deserialize)]
1719pub enum OrderListPlaceOpocoNewOrderRespTypeEnum {
1720    #[serde(rename = "ACK")]
1721    Ack,
1722    #[serde(rename = "RESULT")]
1723    Result,
1724    #[serde(rename = "FULL")]
1725    Full,
1726    #[serde(rename = "MARKET")]
1727    Market,
1728    #[serde(rename = "LIMIT")]
1729    Limit,
1730}
1731
1732impl OrderListPlaceOpocoNewOrderRespTypeEnum {
1733    #[must_use]
1734    pub fn as_str(&self) -> &'static str {
1735        match self {
1736            Self::Ack => "ACK",
1737            Self::Result => "RESULT",
1738            Self::Full => "FULL",
1739            Self::Market => "MARKET",
1740            Self::Limit => "LIMIT",
1741        }
1742    }
1743}
1744
1745impl std::str::FromStr for OrderListPlaceOpocoNewOrderRespTypeEnum {
1746    type Err = Box<dyn std::error::Error + Send + Sync>;
1747
1748    fn from_str(s: &str) -> Result<Self, Self::Err> {
1749        match s {
1750            "ACK" => Ok(Self::Ack),
1751            "RESULT" => Ok(Self::Result),
1752            "FULL" => Ok(Self::Full),
1753            "MARKET" => Ok(Self::Market),
1754            "LIMIT" => Ok(Self::Limit),
1755            other => {
1756                Err(format!("invalid OrderListPlaceOpocoNewOrderRespTypeEnum: {}", other).into())
1757            }
1758        }
1759    }
1760}
1761
1762#[allow(non_camel_case_types)]
1763#[derive(Debug, Clone, Serialize, Deserialize)]
1764pub enum OrderListPlaceOpocoSelfTradePreventionModeEnum {
1765    #[serde(rename = "NONE")]
1766    None,
1767    #[serde(rename = "EXPIRE_TAKER")]
1768    ExpireTaker,
1769    #[serde(rename = "EXPIRE_MAKER")]
1770    ExpireMaker,
1771    #[serde(rename = "EXPIRE_BOTH")]
1772    ExpireBoth,
1773    #[serde(rename = "DECREMENT")]
1774    Decrement,
1775    #[serde(rename = "TRANSFER")]
1776    Transfer,
1777    #[serde(rename = "NON_REPRESENTABLE")]
1778    NonRepresentable,
1779}
1780
1781impl OrderListPlaceOpocoSelfTradePreventionModeEnum {
1782    #[must_use]
1783    pub fn as_str(&self) -> &'static str {
1784        match self {
1785            Self::None => "NONE",
1786            Self::ExpireTaker => "EXPIRE_TAKER",
1787            Self::ExpireMaker => "EXPIRE_MAKER",
1788            Self::ExpireBoth => "EXPIRE_BOTH",
1789            Self::Decrement => "DECREMENT",
1790            Self::Transfer => "TRANSFER",
1791            Self::NonRepresentable => "NON_REPRESENTABLE",
1792        }
1793    }
1794}
1795
1796impl std::str::FromStr for OrderListPlaceOpocoSelfTradePreventionModeEnum {
1797    type Err = Box<dyn std::error::Error + Send + Sync>;
1798
1799    fn from_str(s: &str) -> Result<Self, Self::Err> {
1800        match s {
1801            "NONE" => Ok(Self::None),
1802            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
1803            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
1804            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
1805            "DECREMENT" => Ok(Self::Decrement),
1806            "TRANSFER" => Ok(Self::Transfer),
1807            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
1808            other => Err(format!(
1809                "invalid OrderListPlaceOpocoSelfTradePreventionModeEnum: {}",
1810                other
1811            )
1812            .into()),
1813        }
1814    }
1815}
1816
1817#[allow(non_camel_case_types)]
1818#[derive(Debug, Clone, Serialize, Deserialize)]
1819pub enum OrderListPlaceOpocoWorkingTimeInForceEnum {
1820    #[serde(rename = "GTC")]
1821    Gtc,
1822    #[serde(rename = "IOC")]
1823    Ioc,
1824    #[serde(rename = "FOK")]
1825    Fok,
1826}
1827
1828impl OrderListPlaceOpocoWorkingTimeInForceEnum {
1829    #[must_use]
1830    pub fn as_str(&self) -> &'static str {
1831        match self {
1832            Self::Gtc => "GTC",
1833            Self::Ioc => "IOC",
1834            Self::Fok => "FOK",
1835        }
1836    }
1837}
1838
1839impl std::str::FromStr for OrderListPlaceOpocoWorkingTimeInForceEnum {
1840    type Err = Box<dyn std::error::Error + Send + Sync>;
1841
1842    fn from_str(s: &str) -> Result<Self, Self::Err> {
1843        match s {
1844            "GTC" => Ok(Self::Gtc),
1845            "IOC" => Ok(Self::Ioc),
1846            "FOK" => Ok(Self::Fok),
1847            other => Err(format!(
1848                "invalid OrderListPlaceOpocoWorkingTimeInForceEnum: {}",
1849                other
1850            )
1851            .into()),
1852        }
1853    }
1854}
1855
1856#[allow(non_camel_case_types)]
1857#[derive(Debug, Clone, Serialize, Deserialize)]
1858pub enum OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1859    #[serde(rename = "PRIMARY_PEG")]
1860    PrimaryPeg,
1861    #[serde(rename = "MARKET_PEG")]
1862    MarketPeg,
1863}
1864
1865impl OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1866    #[must_use]
1867    pub fn as_str(&self) -> &'static str {
1868        match self {
1869            Self::PrimaryPeg => "PRIMARY_PEG",
1870            Self::MarketPeg => "MARKET_PEG",
1871        }
1872    }
1873}
1874
1875impl std::str::FromStr for OrderListPlaceOpocoWorkingPegPriceTypeEnum {
1876    type Err = Box<dyn std::error::Error + Send + Sync>;
1877
1878    fn from_str(s: &str) -> Result<Self, Self::Err> {
1879        match s {
1880            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1881            "MARKET_PEG" => Ok(Self::MarketPeg),
1882            other => Err(format!(
1883                "invalid OrderListPlaceOpocoWorkingPegPriceTypeEnum: {}",
1884                other
1885            )
1886            .into()),
1887        }
1888    }
1889}
1890
1891#[allow(non_camel_case_types)]
1892#[derive(Debug, Clone, Serialize, Deserialize)]
1893pub enum OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1894    #[serde(rename = "PRICE_LEVEL")]
1895    PriceLevel,
1896}
1897
1898impl OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1899    #[must_use]
1900    pub fn as_str(&self) -> &'static str {
1901        match self {
1902            Self::PriceLevel => "PRICE_LEVEL",
1903        }
1904    }
1905}
1906
1907impl std::str::FromStr for OrderListPlaceOpocoWorkingPegOffsetTypeEnum {
1908    type Err = Box<dyn std::error::Error + Send + Sync>;
1909
1910    fn from_str(s: &str) -> Result<Self, Self::Err> {
1911        match s {
1912            "PRICE_LEVEL" => Ok(Self::PriceLevel),
1913            other => Err(format!(
1914                "invalid OrderListPlaceOpocoWorkingPegOffsetTypeEnum: {}",
1915                other
1916            )
1917            .into()),
1918        }
1919    }
1920}
1921
1922#[allow(non_camel_case_types)]
1923#[derive(Debug, Clone, Serialize, Deserialize)]
1924pub enum OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1925    #[serde(rename = "GTC")]
1926    Gtc,
1927    #[serde(rename = "IOC")]
1928    Ioc,
1929    #[serde(rename = "FOK")]
1930    Fok,
1931}
1932
1933impl OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1934    #[must_use]
1935    pub fn as_str(&self) -> &'static str {
1936        match self {
1937            Self::Gtc => "GTC",
1938            Self::Ioc => "IOC",
1939            Self::Fok => "FOK",
1940        }
1941    }
1942}
1943
1944impl std::str::FromStr for OrderListPlaceOpocoPendingAboveTimeInForceEnum {
1945    type Err = Box<dyn std::error::Error + Send + Sync>;
1946
1947    fn from_str(s: &str) -> Result<Self, Self::Err> {
1948        match s {
1949            "GTC" => Ok(Self::Gtc),
1950            "IOC" => Ok(Self::Ioc),
1951            "FOK" => Ok(Self::Fok),
1952            other => Err(format!(
1953                "invalid OrderListPlaceOpocoPendingAboveTimeInForceEnum: {}",
1954                other
1955            )
1956            .into()),
1957        }
1958    }
1959}
1960
1961#[allow(non_camel_case_types)]
1962#[derive(Debug, Clone, Serialize, Deserialize)]
1963pub enum OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1964    #[serde(rename = "PRIMARY_PEG")]
1965    PrimaryPeg,
1966    #[serde(rename = "MARKET_PEG")]
1967    MarketPeg,
1968}
1969
1970impl OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1971    #[must_use]
1972    pub fn as_str(&self) -> &'static str {
1973        match self {
1974            Self::PrimaryPeg => "PRIMARY_PEG",
1975            Self::MarketPeg => "MARKET_PEG",
1976        }
1977    }
1978}
1979
1980impl std::str::FromStr for OrderListPlaceOpocoPendingAbovePegPriceTypeEnum {
1981    type Err = Box<dyn std::error::Error + Send + Sync>;
1982
1983    fn from_str(s: &str) -> Result<Self, Self::Err> {
1984        match s {
1985            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
1986            "MARKET_PEG" => Ok(Self::MarketPeg),
1987            other => Err(format!(
1988                "invalid OrderListPlaceOpocoPendingAbovePegPriceTypeEnum: {}",
1989                other
1990            )
1991            .into()),
1992        }
1993    }
1994}
1995
1996#[allow(non_camel_case_types)]
1997#[derive(Debug, Clone, Serialize, Deserialize)]
1998pub enum OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
1999    #[serde(rename = "PRICE_LEVEL")]
2000    PriceLevel,
2001}
2002
2003impl OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
2004    #[must_use]
2005    pub fn as_str(&self) -> &'static str {
2006        match self {
2007            Self::PriceLevel => "PRICE_LEVEL",
2008        }
2009    }
2010}
2011
2012impl std::str::FromStr for OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum {
2013    type Err = Box<dyn std::error::Error + Send + Sync>;
2014
2015    fn from_str(s: &str) -> Result<Self, Self::Err> {
2016        match s {
2017            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2018            other => Err(format!(
2019                "invalid OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum: {}",
2020                other
2021            )
2022            .into()),
2023        }
2024    }
2025}
2026
2027#[allow(non_camel_case_types)]
2028#[derive(Debug, Clone, Serialize, Deserialize)]
2029pub enum OrderListPlaceOpocoPendingBelowTypeEnum {
2030    #[serde(rename = "STOP_LOSS")]
2031    StopLoss,
2032    #[serde(rename = "STOP_LOSS_LIMIT")]
2033    StopLossLimit,
2034    #[serde(rename = "TAKE_PROFIT")]
2035    TakeProfit,
2036    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2037    TakeProfitLimit,
2038}
2039
2040impl OrderListPlaceOpocoPendingBelowTypeEnum {
2041    #[must_use]
2042    pub fn as_str(&self) -> &'static str {
2043        match self {
2044            Self::StopLoss => "STOP_LOSS",
2045            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2046            Self::TakeProfit => "TAKE_PROFIT",
2047            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2048        }
2049    }
2050}
2051
2052impl std::str::FromStr for OrderListPlaceOpocoPendingBelowTypeEnum {
2053    type Err = Box<dyn std::error::Error + Send + Sync>;
2054
2055    fn from_str(s: &str) -> Result<Self, Self::Err> {
2056        match s {
2057            "STOP_LOSS" => Ok(Self::StopLoss),
2058            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2059            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2060            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2061            other => {
2062                Err(format!("invalid OrderListPlaceOpocoPendingBelowTypeEnum: {}", other).into())
2063            }
2064        }
2065    }
2066}
2067
2068#[allow(non_camel_case_types)]
2069#[derive(Debug, Clone, Serialize, Deserialize)]
2070pub enum OrderListPlaceOpocoPendingBelowTimeInForceEnum {
2071    #[serde(rename = "GTC")]
2072    Gtc,
2073    #[serde(rename = "IOC")]
2074    Ioc,
2075    #[serde(rename = "FOK")]
2076    Fok,
2077}
2078
2079impl OrderListPlaceOpocoPendingBelowTimeInForceEnum {
2080    #[must_use]
2081    pub fn as_str(&self) -> &'static str {
2082        match self {
2083            Self::Gtc => "GTC",
2084            Self::Ioc => "IOC",
2085            Self::Fok => "FOK",
2086        }
2087    }
2088}
2089
2090impl std::str::FromStr for OrderListPlaceOpocoPendingBelowTimeInForceEnum {
2091    type Err = Box<dyn std::error::Error + Send + Sync>;
2092
2093    fn from_str(s: &str) -> Result<Self, Self::Err> {
2094        match s {
2095            "GTC" => Ok(Self::Gtc),
2096            "IOC" => Ok(Self::Ioc),
2097            "FOK" => Ok(Self::Fok),
2098            other => Err(format!(
2099                "invalid OrderListPlaceOpocoPendingBelowTimeInForceEnum: {}",
2100                other
2101            )
2102            .into()),
2103        }
2104    }
2105}
2106
2107#[allow(non_camel_case_types)]
2108#[derive(Debug, Clone, Serialize, Deserialize)]
2109pub enum OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2110    #[serde(rename = "PRIMARY_PEG")]
2111    PrimaryPeg,
2112    #[serde(rename = "MARKET_PEG")]
2113    MarketPeg,
2114}
2115
2116impl OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2117    #[must_use]
2118    pub fn as_str(&self) -> &'static str {
2119        match self {
2120            Self::PrimaryPeg => "PRIMARY_PEG",
2121            Self::MarketPeg => "MARKET_PEG",
2122        }
2123    }
2124}
2125
2126impl std::str::FromStr for OrderListPlaceOpocoPendingBelowPegPriceTypeEnum {
2127    type Err = Box<dyn std::error::Error + Send + Sync>;
2128
2129    fn from_str(s: &str) -> Result<Self, Self::Err> {
2130        match s {
2131            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2132            "MARKET_PEG" => Ok(Self::MarketPeg),
2133            other => Err(format!(
2134                "invalid OrderListPlaceOpocoPendingBelowPegPriceTypeEnum: {}",
2135                other
2136            )
2137            .into()),
2138        }
2139    }
2140}
2141
2142#[allow(non_camel_case_types)]
2143#[derive(Debug, Clone, Serialize, Deserialize)]
2144pub enum OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2145    #[serde(rename = "PRICE_LEVEL")]
2146    PriceLevel,
2147}
2148
2149impl OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2150    #[must_use]
2151    pub fn as_str(&self) -> &'static str {
2152        match self {
2153            Self::PriceLevel => "PRICE_LEVEL",
2154        }
2155    }
2156}
2157
2158impl std::str::FromStr for OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum {
2159    type Err = Box<dyn std::error::Error + Send + Sync>;
2160
2161    fn from_str(s: &str) -> Result<Self, Self::Err> {
2162        match s {
2163            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2164            other => Err(format!(
2165                "invalid OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum: {}",
2166                other
2167            )
2168            .into()),
2169        }
2170    }
2171}
2172
2173#[allow(non_camel_case_types)]
2174#[derive(Debug, Clone, Serialize, Deserialize)]
2175pub enum OrderListPlaceOtoWorkingTypeEnum {
2176    #[serde(rename = "LIMIT")]
2177    Limit,
2178    #[serde(rename = "LIMIT_MAKER")]
2179    LimitMaker,
2180}
2181
2182impl OrderListPlaceOtoWorkingTypeEnum {
2183    #[must_use]
2184    pub fn as_str(&self) -> &'static str {
2185        match self {
2186            Self::Limit => "LIMIT",
2187            Self::LimitMaker => "LIMIT_MAKER",
2188        }
2189    }
2190}
2191
2192impl std::str::FromStr for OrderListPlaceOtoWorkingTypeEnum {
2193    type Err = Box<dyn std::error::Error + Send + Sync>;
2194
2195    fn from_str(s: &str) -> Result<Self, Self::Err> {
2196        match s {
2197            "LIMIT" => Ok(Self::Limit),
2198            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2199            other => Err(format!("invalid OrderListPlaceOtoWorkingTypeEnum: {}", other).into()),
2200        }
2201    }
2202}
2203
2204#[allow(non_camel_case_types)]
2205#[derive(Debug, Clone, Serialize, Deserialize)]
2206pub enum OrderListPlaceOtoWorkingSideEnum {
2207    #[serde(rename = "BUY")]
2208    Buy,
2209    #[serde(rename = "SELL")]
2210    Sell,
2211}
2212
2213impl OrderListPlaceOtoWorkingSideEnum {
2214    #[must_use]
2215    pub fn as_str(&self) -> &'static str {
2216        match self {
2217            Self::Buy => "BUY",
2218            Self::Sell => "SELL",
2219        }
2220    }
2221}
2222
2223impl std::str::FromStr for OrderListPlaceOtoWorkingSideEnum {
2224    type Err = Box<dyn std::error::Error + Send + Sync>;
2225
2226    fn from_str(s: &str) -> Result<Self, Self::Err> {
2227        match s {
2228            "BUY" => Ok(Self::Buy),
2229            "SELL" => Ok(Self::Sell),
2230            other => Err(format!("invalid OrderListPlaceOtoWorkingSideEnum: {}", other).into()),
2231        }
2232    }
2233}
2234
2235#[allow(non_camel_case_types)]
2236#[derive(Debug, Clone, Serialize, Deserialize)]
2237pub enum OrderListPlaceOtoPendingTypeEnum {
2238    #[serde(rename = "LIMIT")]
2239    Limit,
2240    #[serde(rename = "MARKET")]
2241    Market,
2242    #[serde(rename = "STOP_LOSS")]
2243    StopLoss,
2244    #[serde(rename = "STOP_LOSS_LIMIT")]
2245    StopLossLimit,
2246    #[serde(rename = "TAKE_PROFIT")]
2247    TakeProfit,
2248    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2249    TakeProfitLimit,
2250    #[serde(rename = "LIMIT_MAKER")]
2251    LimitMaker,
2252}
2253
2254impl OrderListPlaceOtoPendingTypeEnum {
2255    #[must_use]
2256    pub fn as_str(&self) -> &'static str {
2257        match self {
2258            Self::Limit => "LIMIT",
2259            Self::Market => "MARKET",
2260            Self::StopLoss => "STOP_LOSS",
2261            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2262            Self::TakeProfit => "TAKE_PROFIT",
2263            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2264            Self::LimitMaker => "LIMIT_MAKER",
2265        }
2266    }
2267}
2268
2269impl std::str::FromStr for OrderListPlaceOtoPendingTypeEnum {
2270    type Err = Box<dyn std::error::Error + Send + Sync>;
2271
2272    fn from_str(s: &str) -> Result<Self, Self::Err> {
2273        match s {
2274            "LIMIT" => Ok(Self::Limit),
2275            "MARKET" => Ok(Self::Market),
2276            "STOP_LOSS" => Ok(Self::StopLoss),
2277            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2278            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2279            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2280            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2281            other => Err(format!("invalid OrderListPlaceOtoPendingTypeEnum: {}", other).into()),
2282        }
2283    }
2284}
2285
2286#[allow(non_camel_case_types)]
2287#[derive(Debug, Clone, Serialize, Deserialize)]
2288pub enum OrderListPlaceOtoPendingSideEnum {
2289    #[serde(rename = "BUY")]
2290    Buy,
2291    #[serde(rename = "SELL")]
2292    Sell,
2293}
2294
2295impl OrderListPlaceOtoPendingSideEnum {
2296    #[must_use]
2297    pub fn as_str(&self) -> &'static str {
2298        match self {
2299            Self::Buy => "BUY",
2300            Self::Sell => "SELL",
2301        }
2302    }
2303}
2304
2305impl std::str::FromStr for OrderListPlaceOtoPendingSideEnum {
2306    type Err = Box<dyn std::error::Error + Send + Sync>;
2307
2308    fn from_str(s: &str) -> Result<Self, Self::Err> {
2309        match s {
2310            "BUY" => Ok(Self::Buy),
2311            "SELL" => Ok(Self::Sell),
2312            other => Err(format!("invalid OrderListPlaceOtoPendingSideEnum: {}", other).into()),
2313        }
2314    }
2315}
2316
2317#[allow(non_camel_case_types)]
2318#[derive(Debug, Clone, Serialize, Deserialize)]
2319pub enum OrderListPlaceOtoNewOrderRespTypeEnum {
2320    #[serde(rename = "ACK")]
2321    Ack,
2322    #[serde(rename = "RESULT")]
2323    Result,
2324    #[serde(rename = "FULL")]
2325    Full,
2326    #[serde(rename = "MARKET")]
2327    Market,
2328    #[serde(rename = "LIMIT")]
2329    Limit,
2330}
2331
2332impl OrderListPlaceOtoNewOrderRespTypeEnum {
2333    #[must_use]
2334    pub fn as_str(&self) -> &'static str {
2335        match self {
2336            Self::Ack => "ACK",
2337            Self::Result => "RESULT",
2338            Self::Full => "FULL",
2339            Self::Market => "MARKET",
2340            Self::Limit => "LIMIT",
2341        }
2342    }
2343}
2344
2345impl std::str::FromStr for OrderListPlaceOtoNewOrderRespTypeEnum {
2346    type Err = Box<dyn std::error::Error + Send + Sync>;
2347
2348    fn from_str(s: &str) -> Result<Self, Self::Err> {
2349        match s {
2350            "ACK" => Ok(Self::Ack),
2351            "RESULT" => Ok(Self::Result),
2352            "FULL" => Ok(Self::Full),
2353            "MARKET" => Ok(Self::Market),
2354            "LIMIT" => Ok(Self::Limit),
2355            other => {
2356                Err(format!("invalid OrderListPlaceOtoNewOrderRespTypeEnum: {}", other).into())
2357            }
2358        }
2359    }
2360}
2361
2362#[allow(non_camel_case_types)]
2363#[derive(Debug, Clone, Serialize, Deserialize)]
2364pub enum OrderListPlaceOtoSelfTradePreventionModeEnum {
2365    #[serde(rename = "NONE")]
2366    None,
2367    #[serde(rename = "EXPIRE_TAKER")]
2368    ExpireTaker,
2369    #[serde(rename = "EXPIRE_MAKER")]
2370    ExpireMaker,
2371    #[serde(rename = "EXPIRE_BOTH")]
2372    ExpireBoth,
2373    #[serde(rename = "DECREMENT")]
2374    Decrement,
2375    #[serde(rename = "TRANSFER")]
2376    Transfer,
2377    #[serde(rename = "NON_REPRESENTABLE")]
2378    NonRepresentable,
2379}
2380
2381impl OrderListPlaceOtoSelfTradePreventionModeEnum {
2382    #[must_use]
2383    pub fn as_str(&self) -> &'static str {
2384        match self {
2385            Self::None => "NONE",
2386            Self::ExpireTaker => "EXPIRE_TAKER",
2387            Self::ExpireMaker => "EXPIRE_MAKER",
2388            Self::ExpireBoth => "EXPIRE_BOTH",
2389            Self::Decrement => "DECREMENT",
2390            Self::Transfer => "TRANSFER",
2391            Self::NonRepresentable => "NON_REPRESENTABLE",
2392        }
2393    }
2394}
2395
2396impl std::str::FromStr for OrderListPlaceOtoSelfTradePreventionModeEnum {
2397    type Err = Box<dyn std::error::Error + Send + Sync>;
2398
2399    fn from_str(s: &str) -> Result<Self, Self::Err> {
2400        match s {
2401            "NONE" => Ok(Self::None),
2402            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
2403            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
2404            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
2405            "DECREMENT" => Ok(Self::Decrement),
2406            "TRANSFER" => Ok(Self::Transfer),
2407            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
2408            other => Err(format!(
2409                "invalid OrderListPlaceOtoSelfTradePreventionModeEnum: {}",
2410                other
2411            )
2412            .into()),
2413        }
2414    }
2415}
2416
2417#[allow(non_camel_case_types)]
2418#[derive(Debug, Clone, Serialize, Deserialize)]
2419pub enum OrderListPlaceOtoWorkingTimeInForceEnum {
2420    #[serde(rename = "GTC")]
2421    Gtc,
2422    #[serde(rename = "IOC")]
2423    Ioc,
2424    #[serde(rename = "FOK")]
2425    Fok,
2426}
2427
2428impl OrderListPlaceOtoWorkingTimeInForceEnum {
2429    #[must_use]
2430    pub fn as_str(&self) -> &'static str {
2431        match self {
2432            Self::Gtc => "GTC",
2433            Self::Ioc => "IOC",
2434            Self::Fok => "FOK",
2435        }
2436    }
2437}
2438
2439impl std::str::FromStr for OrderListPlaceOtoWorkingTimeInForceEnum {
2440    type Err = Box<dyn std::error::Error + Send + Sync>;
2441
2442    fn from_str(s: &str) -> Result<Self, Self::Err> {
2443        match s {
2444            "GTC" => Ok(Self::Gtc),
2445            "IOC" => Ok(Self::Ioc),
2446            "FOK" => Ok(Self::Fok),
2447            other => {
2448                Err(format!("invalid OrderListPlaceOtoWorkingTimeInForceEnum: {}", other).into())
2449            }
2450        }
2451    }
2452}
2453
2454#[allow(non_camel_case_types)]
2455#[derive(Debug, Clone, Serialize, Deserialize)]
2456pub enum OrderListPlaceOtoWorkingPegPriceTypeEnum {
2457    #[serde(rename = "PRIMARY_PEG")]
2458    PrimaryPeg,
2459    #[serde(rename = "MARKET_PEG")]
2460    MarketPeg,
2461}
2462
2463impl OrderListPlaceOtoWorkingPegPriceTypeEnum {
2464    #[must_use]
2465    pub fn as_str(&self) -> &'static str {
2466        match self {
2467            Self::PrimaryPeg => "PRIMARY_PEG",
2468            Self::MarketPeg => "MARKET_PEG",
2469        }
2470    }
2471}
2472
2473impl std::str::FromStr for OrderListPlaceOtoWorkingPegPriceTypeEnum {
2474    type Err = Box<dyn std::error::Error + Send + Sync>;
2475
2476    fn from_str(s: &str) -> Result<Self, Self::Err> {
2477        match s {
2478            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2479            "MARKET_PEG" => Ok(Self::MarketPeg),
2480            other => Err(format!(
2481                "invalid OrderListPlaceOtoWorkingPegPriceTypeEnum: {}",
2482                other
2483            )
2484            .into()),
2485        }
2486    }
2487}
2488
2489#[allow(non_camel_case_types)]
2490#[derive(Debug, Clone, Serialize, Deserialize)]
2491pub enum OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2492    #[serde(rename = "PRICE_LEVEL")]
2493    PriceLevel,
2494}
2495
2496impl OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2497    #[must_use]
2498    pub fn as_str(&self) -> &'static str {
2499        match self {
2500            Self::PriceLevel => "PRICE_LEVEL",
2501        }
2502    }
2503}
2504
2505impl std::str::FromStr for OrderListPlaceOtoWorkingPegOffsetTypeEnum {
2506    type Err = Box<dyn std::error::Error + Send + Sync>;
2507
2508    fn from_str(s: &str) -> Result<Self, Self::Err> {
2509        match s {
2510            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2511            other => Err(format!(
2512                "invalid OrderListPlaceOtoWorkingPegOffsetTypeEnum: {}",
2513                other
2514            )
2515            .into()),
2516        }
2517    }
2518}
2519
2520#[allow(non_camel_case_types)]
2521#[derive(Debug, Clone, Serialize, Deserialize)]
2522pub enum OrderListPlaceOtoPendingTimeInForceEnum {
2523    #[serde(rename = "GTC")]
2524    Gtc,
2525    #[serde(rename = "IOC")]
2526    Ioc,
2527    #[serde(rename = "FOK")]
2528    Fok,
2529}
2530
2531impl OrderListPlaceOtoPendingTimeInForceEnum {
2532    #[must_use]
2533    pub fn as_str(&self) -> &'static str {
2534        match self {
2535            Self::Gtc => "GTC",
2536            Self::Ioc => "IOC",
2537            Self::Fok => "FOK",
2538        }
2539    }
2540}
2541
2542impl std::str::FromStr for OrderListPlaceOtoPendingTimeInForceEnum {
2543    type Err = Box<dyn std::error::Error + Send + Sync>;
2544
2545    fn from_str(s: &str) -> Result<Self, Self::Err> {
2546        match s {
2547            "GTC" => Ok(Self::Gtc),
2548            "IOC" => Ok(Self::Ioc),
2549            "FOK" => Ok(Self::Fok),
2550            other => {
2551                Err(format!("invalid OrderListPlaceOtoPendingTimeInForceEnum: {}", other).into())
2552            }
2553        }
2554    }
2555}
2556
2557#[allow(non_camel_case_types)]
2558#[derive(Debug, Clone, Serialize, Deserialize)]
2559pub enum OrderListPlaceOtoPendingPegOffsetTypeEnum {
2560    #[serde(rename = "PRICE_LEVEL")]
2561    PriceLevel,
2562}
2563
2564impl OrderListPlaceOtoPendingPegOffsetTypeEnum {
2565    #[must_use]
2566    pub fn as_str(&self) -> &'static str {
2567        match self {
2568            Self::PriceLevel => "PRICE_LEVEL",
2569        }
2570    }
2571}
2572
2573impl std::str::FromStr for OrderListPlaceOtoPendingPegOffsetTypeEnum {
2574    type Err = Box<dyn std::error::Error + Send + Sync>;
2575
2576    fn from_str(s: &str) -> Result<Self, Self::Err> {
2577        match s {
2578            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2579            other => Err(format!(
2580                "invalid OrderListPlaceOtoPendingPegOffsetTypeEnum: {}",
2581                other
2582            )
2583            .into()),
2584        }
2585    }
2586}
2587
2588#[allow(non_camel_case_types)]
2589#[derive(Debug, Clone, Serialize, Deserialize)]
2590pub enum OrderListPlaceOtoPendingPegPriceTypeEnum {
2591    #[serde(rename = "PRIMARY_PEG")]
2592    PrimaryPeg,
2593    #[serde(rename = "MARKET_PEG")]
2594    MarketPeg,
2595}
2596
2597impl OrderListPlaceOtoPendingPegPriceTypeEnum {
2598    #[must_use]
2599    pub fn as_str(&self) -> &'static str {
2600        match self {
2601            Self::PrimaryPeg => "PRIMARY_PEG",
2602            Self::MarketPeg => "MARKET_PEG",
2603        }
2604    }
2605}
2606
2607impl std::str::FromStr for OrderListPlaceOtoPendingPegPriceTypeEnum {
2608    type Err = Box<dyn std::error::Error + Send + Sync>;
2609
2610    fn from_str(s: &str) -> Result<Self, Self::Err> {
2611        match s {
2612            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2613            "MARKET_PEG" => Ok(Self::MarketPeg),
2614            other => Err(format!(
2615                "invalid OrderListPlaceOtoPendingPegPriceTypeEnum: {}",
2616                other
2617            )
2618            .into()),
2619        }
2620    }
2621}
2622
2623#[allow(non_camel_case_types)]
2624#[derive(Debug, Clone, Serialize, Deserialize)]
2625pub enum OrderListPlaceOtocoWorkingTypeEnum {
2626    #[serde(rename = "LIMIT")]
2627    Limit,
2628    #[serde(rename = "LIMIT_MAKER")]
2629    LimitMaker,
2630}
2631
2632impl OrderListPlaceOtocoWorkingTypeEnum {
2633    #[must_use]
2634    pub fn as_str(&self) -> &'static str {
2635        match self {
2636            Self::Limit => "LIMIT",
2637            Self::LimitMaker => "LIMIT_MAKER",
2638        }
2639    }
2640}
2641
2642impl std::str::FromStr for OrderListPlaceOtocoWorkingTypeEnum {
2643    type Err = Box<dyn std::error::Error + Send + Sync>;
2644
2645    fn from_str(s: &str) -> Result<Self, Self::Err> {
2646        match s {
2647            "LIMIT" => Ok(Self::Limit),
2648            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2649            other => Err(format!("invalid OrderListPlaceOtocoWorkingTypeEnum: {}", other).into()),
2650        }
2651    }
2652}
2653
2654#[allow(non_camel_case_types)]
2655#[derive(Debug, Clone, Serialize, Deserialize)]
2656pub enum OrderListPlaceOtocoWorkingSideEnum {
2657    #[serde(rename = "BUY")]
2658    Buy,
2659    #[serde(rename = "SELL")]
2660    Sell,
2661}
2662
2663impl OrderListPlaceOtocoWorkingSideEnum {
2664    #[must_use]
2665    pub fn as_str(&self) -> &'static str {
2666        match self {
2667            Self::Buy => "BUY",
2668            Self::Sell => "SELL",
2669        }
2670    }
2671}
2672
2673impl std::str::FromStr for OrderListPlaceOtocoWorkingSideEnum {
2674    type Err = Box<dyn std::error::Error + Send + Sync>;
2675
2676    fn from_str(s: &str) -> Result<Self, Self::Err> {
2677        match s {
2678            "BUY" => Ok(Self::Buy),
2679            "SELL" => Ok(Self::Sell),
2680            other => Err(format!("invalid OrderListPlaceOtocoWorkingSideEnum: {}", other).into()),
2681        }
2682    }
2683}
2684
2685#[allow(non_camel_case_types)]
2686#[derive(Debug, Clone, Serialize, Deserialize)]
2687pub enum OrderListPlaceOtocoPendingSideEnum {
2688    #[serde(rename = "BUY")]
2689    Buy,
2690    #[serde(rename = "SELL")]
2691    Sell,
2692}
2693
2694impl OrderListPlaceOtocoPendingSideEnum {
2695    #[must_use]
2696    pub fn as_str(&self) -> &'static str {
2697        match self {
2698            Self::Buy => "BUY",
2699            Self::Sell => "SELL",
2700        }
2701    }
2702}
2703
2704impl std::str::FromStr for OrderListPlaceOtocoPendingSideEnum {
2705    type Err = Box<dyn std::error::Error + Send + Sync>;
2706
2707    fn from_str(s: &str) -> Result<Self, Self::Err> {
2708        match s {
2709            "BUY" => Ok(Self::Buy),
2710            "SELL" => Ok(Self::Sell),
2711            other => Err(format!("invalid OrderListPlaceOtocoPendingSideEnum: {}", other).into()),
2712        }
2713    }
2714}
2715
2716#[allow(non_camel_case_types)]
2717#[derive(Debug, Clone, Serialize, Deserialize)]
2718pub enum OrderListPlaceOtocoPendingAboveTypeEnum {
2719    #[serde(rename = "STOP_LOSS_LIMIT")]
2720    StopLossLimit,
2721    #[serde(rename = "STOP_LOSS")]
2722    StopLoss,
2723    #[serde(rename = "LIMIT_MAKER")]
2724    LimitMaker,
2725    #[serde(rename = "TAKE_PROFIT")]
2726    TakeProfit,
2727    #[serde(rename = "TAKE_PROFIT_LIMIT")]
2728    TakeProfitLimit,
2729}
2730
2731impl OrderListPlaceOtocoPendingAboveTypeEnum {
2732    #[must_use]
2733    pub fn as_str(&self) -> &'static str {
2734        match self {
2735            Self::StopLossLimit => "STOP_LOSS_LIMIT",
2736            Self::StopLoss => "STOP_LOSS",
2737            Self::LimitMaker => "LIMIT_MAKER",
2738            Self::TakeProfit => "TAKE_PROFIT",
2739            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
2740        }
2741    }
2742}
2743
2744impl std::str::FromStr for OrderListPlaceOtocoPendingAboveTypeEnum {
2745    type Err = Box<dyn std::error::Error + Send + Sync>;
2746
2747    fn from_str(s: &str) -> Result<Self, Self::Err> {
2748        match s {
2749            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
2750            "STOP_LOSS" => Ok(Self::StopLoss),
2751            "LIMIT_MAKER" => Ok(Self::LimitMaker),
2752            "TAKE_PROFIT" => Ok(Self::TakeProfit),
2753            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
2754            other => {
2755                Err(format!("invalid OrderListPlaceOtocoPendingAboveTypeEnum: {}", other).into())
2756            }
2757        }
2758    }
2759}
2760
2761#[allow(non_camel_case_types)]
2762#[derive(Debug, Clone, Serialize, Deserialize)]
2763pub enum OrderListPlaceOtocoNewOrderRespTypeEnum {
2764    #[serde(rename = "ACK")]
2765    Ack,
2766    #[serde(rename = "RESULT")]
2767    Result,
2768    #[serde(rename = "FULL")]
2769    Full,
2770    #[serde(rename = "MARKET")]
2771    Market,
2772    #[serde(rename = "LIMIT")]
2773    Limit,
2774}
2775
2776impl OrderListPlaceOtocoNewOrderRespTypeEnum {
2777    #[must_use]
2778    pub fn as_str(&self) -> &'static str {
2779        match self {
2780            Self::Ack => "ACK",
2781            Self::Result => "RESULT",
2782            Self::Full => "FULL",
2783            Self::Market => "MARKET",
2784            Self::Limit => "LIMIT",
2785        }
2786    }
2787}
2788
2789impl std::str::FromStr for OrderListPlaceOtocoNewOrderRespTypeEnum {
2790    type Err = Box<dyn std::error::Error + Send + Sync>;
2791
2792    fn from_str(s: &str) -> Result<Self, Self::Err> {
2793        match s {
2794            "ACK" => Ok(Self::Ack),
2795            "RESULT" => Ok(Self::Result),
2796            "FULL" => Ok(Self::Full),
2797            "MARKET" => Ok(Self::Market),
2798            "LIMIT" => Ok(Self::Limit),
2799            other => {
2800                Err(format!("invalid OrderListPlaceOtocoNewOrderRespTypeEnum: {}", other).into())
2801            }
2802        }
2803    }
2804}
2805
2806#[allow(non_camel_case_types)]
2807#[derive(Debug, Clone, Serialize, Deserialize)]
2808pub enum OrderListPlaceOtocoSelfTradePreventionModeEnum {
2809    #[serde(rename = "NONE")]
2810    None,
2811    #[serde(rename = "EXPIRE_TAKER")]
2812    ExpireTaker,
2813    #[serde(rename = "EXPIRE_MAKER")]
2814    ExpireMaker,
2815    #[serde(rename = "EXPIRE_BOTH")]
2816    ExpireBoth,
2817    #[serde(rename = "DECREMENT")]
2818    Decrement,
2819    #[serde(rename = "TRANSFER")]
2820    Transfer,
2821    #[serde(rename = "NON_REPRESENTABLE")]
2822    NonRepresentable,
2823}
2824
2825impl OrderListPlaceOtocoSelfTradePreventionModeEnum {
2826    #[must_use]
2827    pub fn as_str(&self) -> &'static str {
2828        match self {
2829            Self::None => "NONE",
2830            Self::ExpireTaker => "EXPIRE_TAKER",
2831            Self::ExpireMaker => "EXPIRE_MAKER",
2832            Self::ExpireBoth => "EXPIRE_BOTH",
2833            Self::Decrement => "DECREMENT",
2834            Self::Transfer => "TRANSFER",
2835            Self::NonRepresentable => "NON_REPRESENTABLE",
2836        }
2837    }
2838}
2839
2840impl std::str::FromStr for OrderListPlaceOtocoSelfTradePreventionModeEnum {
2841    type Err = Box<dyn std::error::Error + Send + Sync>;
2842
2843    fn from_str(s: &str) -> Result<Self, Self::Err> {
2844        match s {
2845            "NONE" => Ok(Self::None),
2846            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
2847            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
2848            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
2849            "DECREMENT" => Ok(Self::Decrement),
2850            "TRANSFER" => Ok(Self::Transfer),
2851            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
2852            other => Err(format!(
2853                "invalid OrderListPlaceOtocoSelfTradePreventionModeEnum: {}",
2854                other
2855            )
2856            .into()),
2857        }
2858    }
2859}
2860
2861#[allow(non_camel_case_types)]
2862#[derive(Debug, Clone, Serialize, Deserialize)]
2863pub enum OrderListPlaceOtocoWorkingTimeInForceEnum {
2864    #[serde(rename = "GTC")]
2865    Gtc,
2866    #[serde(rename = "IOC")]
2867    Ioc,
2868    #[serde(rename = "FOK")]
2869    Fok,
2870}
2871
2872impl OrderListPlaceOtocoWorkingTimeInForceEnum {
2873    #[must_use]
2874    pub fn as_str(&self) -> &'static str {
2875        match self {
2876            Self::Gtc => "GTC",
2877            Self::Ioc => "IOC",
2878            Self::Fok => "FOK",
2879        }
2880    }
2881}
2882
2883impl std::str::FromStr for OrderListPlaceOtocoWorkingTimeInForceEnum {
2884    type Err = Box<dyn std::error::Error + Send + Sync>;
2885
2886    fn from_str(s: &str) -> Result<Self, Self::Err> {
2887        match s {
2888            "GTC" => Ok(Self::Gtc),
2889            "IOC" => Ok(Self::Ioc),
2890            "FOK" => Ok(Self::Fok),
2891            other => Err(format!(
2892                "invalid OrderListPlaceOtocoWorkingTimeInForceEnum: {}",
2893                other
2894            )
2895            .into()),
2896        }
2897    }
2898}
2899
2900#[allow(non_camel_case_types)]
2901#[derive(Debug, Clone, Serialize, Deserialize)]
2902pub enum OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2903    #[serde(rename = "PRIMARY_PEG")]
2904    PrimaryPeg,
2905    #[serde(rename = "MARKET_PEG")]
2906    MarketPeg,
2907}
2908
2909impl OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2910    #[must_use]
2911    pub fn as_str(&self) -> &'static str {
2912        match self {
2913            Self::PrimaryPeg => "PRIMARY_PEG",
2914            Self::MarketPeg => "MARKET_PEG",
2915        }
2916    }
2917}
2918
2919impl std::str::FromStr for OrderListPlaceOtocoWorkingPegPriceTypeEnum {
2920    type Err = Box<dyn std::error::Error + Send + Sync>;
2921
2922    fn from_str(s: &str) -> Result<Self, Self::Err> {
2923        match s {
2924            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
2925            "MARKET_PEG" => Ok(Self::MarketPeg),
2926            other => Err(format!(
2927                "invalid OrderListPlaceOtocoWorkingPegPriceTypeEnum: {}",
2928                other
2929            )
2930            .into()),
2931        }
2932    }
2933}
2934
2935#[allow(non_camel_case_types)]
2936#[derive(Debug, Clone, Serialize, Deserialize)]
2937pub enum OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2938    #[serde(rename = "PRICE_LEVEL")]
2939    PriceLevel,
2940}
2941
2942impl OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2943    #[must_use]
2944    pub fn as_str(&self) -> &'static str {
2945        match self {
2946            Self::PriceLevel => "PRICE_LEVEL",
2947        }
2948    }
2949}
2950
2951impl std::str::FromStr for OrderListPlaceOtocoWorkingPegOffsetTypeEnum {
2952    type Err = Box<dyn std::error::Error + Send + Sync>;
2953
2954    fn from_str(s: &str) -> Result<Self, Self::Err> {
2955        match s {
2956            "PRICE_LEVEL" => Ok(Self::PriceLevel),
2957            other => Err(format!(
2958                "invalid OrderListPlaceOtocoWorkingPegOffsetTypeEnum: {}",
2959                other
2960            )
2961            .into()),
2962        }
2963    }
2964}
2965
2966#[allow(non_camel_case_types)]
2967#[derive(Debug, Clone, Serialize, Deserialize)]
2968pub enum OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2969    #[serde(rename = "GTC")]
2970    Gtc,
2971    #[serde(rename = "IOC")]
2972    Ioc,
2973    #[serde(rename = "FOK")]
2974    Fok,
2975}
2976
2977impl OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2978    #[must_use]
2979    pub fn as_str(&self) -> &'static str {
2980        match self {
2981            Self::Gtc => "GTC",
2982            Self::Ioc => "IOC",
2983            Self::Fok => "FOK",
2984        }
2985    }
2986}
2987
2988impl std::str::FromStr for OrderListPlaceOtocoPendingAboveTimeInForceEnum {
2989    type Err = Box<dyn std::error::Error + Send + Sync>;
2990
2991    fn from_str(s: &str) -> Result<Self, Self::Err> {
2992        match s {
2993            "GTC" => Ok(Self::Gtc),
2994            "IOC" => Ok(Self::Ioc),
2995            "FOK" => Ok(Self::Fok),
2996            other => Err(format!(
2997                "invalid OrderListPlaceOtocoPendingAboveTimeInForceEnum: {}",
2998                other
2999            )
3000            .into()),
3001        }
3002    }
3003}
3004
3005#[allow(non_camel_case_types)]
3006#[derive(Debug, Clone, Serialize, Deserialize)]
3007pub enum OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
3008    #[serde(rename = "PRIMARY_PEG")]
3009    PrimaryPeg,
3010    #[serde(rename = "MARKET_PEG")]
3011    MarketPeg,
3012}
3013
3014impl OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
3015    #[must_use]
3016    pub fn as_str(&self) -> &'static str {
3017        match self {
3018            Self::PrimaryPeg => "PRIMARY_PEG",
3019            Self::MarketPeg => "MARKET_PEG",
3020        }
3021    }
3022}
3023
3024impl std::str::FromStr for OrderListPlaceOtocoPendingAbovePegPriceTypeEnum {
3025    type Err = Box<dyn std::error::Error + Send + Sync>;
3026
3027    fn from_str(s: &str) -> Result<Self, Self::Err> {
3028        match s {
3029            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3030            "MARKET_PEG" => Ok(Self::MarketPeg),
3031            other => Err(format!(
3032                "invalid OrderListPlaceOtocoPendingAbovePegPriceTypeEnum: {}",
3033                other
3034            )
3035            .into()),
3036        }
3037    }
3038}
3039
3040#[allow(non_camel_case_types)]
3041#[derive(Debug, Clone, Serialize, Deserialize)]
3042pub enum OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
3043    #[serde(rename = "PRICE_LEVEL")]
3044    PriceLevel,
3045}
3046
3047impl OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
3048    #[must_use]
3049    pub fn as_str(&self) -> &'static str {
3050        match self {
3051            Self::PriceLevel => "PRICE_LEVEL",
3052        }
3053    }
3054}
3055
3056impl std::str::FromStr for OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum {
3057    type Err = Box<dyn std::error::Error + Send + Sync>;
3058
3059    fn from_str(s: &str) -> Result<Self, Self::Err> {
3060        match s {
3061            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3062            other => Err(format!(
3063                "invalid OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum: {}",
3064                other
3065            )
3066            .into()),
3067        }
3068    }
3069}
3070
3071#[allow(non_camel_case_types)]
3072#[derive(Debug, Clone, Serialize, Deserialize)]
3073pub enum OrderListPlaceOtocoPendingBelowTypeEnum {
3074    #[serde(rename = "STOP_LOSS")]
3075    StopLoss,
3076    #[serde(rename = "STOP_LOSS_LIMIT")]
3077    StopLossLimit,
3078    #[serde(rename = "TAKE_PROFIT")]
3079    TakeProfit,
3080    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3081    TakeProfitLimit,
3082}
3083
3084impl OrderListPlaceOtocoPendingBelowTypeEnum {
3085    #[must_use]
3086    pub fn as_str(&self) -> &'static str {
3087        match self {
3088            Self::StopLoss => "STOP_LOSS",
3089            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3090            Self::TakeProfit => "TAKE_PROFIT",
3091            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3092        }
3093    }
3094}
3095
3096impl std::str::FromStr for OrderListPlaceOtocoPendingBelowTypeEnum {
3097    type Err = Box<dyn std::error::Error + Send + Sync>;
3098
3099    fn from_str(s: &str) -> Result<Self, Self::Err> {
3100        match s {
3101            "STOP_LOSS" => Ok(Self::StopLoss),
3102            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3103            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3104            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3105            other => {
3106                Err(format!("invalid OrderListPlaceOtocoPendingBelowTypeEnum: {}", other).into())
3107            }
3108        }
3109    }
3110}
3111
3112#[allow(non_camel_case_types)]
3113#[derive(Debug, Clone, Serialize, Deserialize)]
3114pub enum OrderListPlaceOtocoPendingBelowTimeInForceEnum {
3115    #[serde(rename = "GTC")]
3116    Gtc,
3117    #[serde(rename = "IOC")]
3118    Ioc,
3119    #[serde(rename = "FOK")]
3120    Fok,
3121}
3122
3123impl OrderListPlaceOtocoPendingBelowTimeInForceEnum {
3124    #[must_use]
3125    pub fn as_str(&self) -> &'static str {
3126        match self {
3127            Self::Gtc => "GTC",
3128            Self::Ioc => "IOC",
3129            Self::Fok => "FOK",
3130        }
3131    }
3132}
3133
3134impl std::str::FromStr for OrderListPlaceOtocoPendingBelowTimeInForceEnum {
3135    type Err = Box<dyn std::error::Error + Send + Sync>;
3136
3137    fn from_str(s: &str) -> Result<Self, Self::Err> {
3138        match s {
3139            "GTC" => Ok(Self::Gtc),
3140            "IOC" => Ok(Self::Ioc),
3141            "FOK" => Ok(Self::Fok),
3142            other => Err(format!(
3143                "invalid OrderListPlaceOtocoPendingBelowTimeInForceEnum: {}",
3144                other
3145            )
3146            .into()),
3147        }
3148    }
3149}
3150
3151#[allow(non_camel_case_types)]
3152#[derive(Debug, Clone, Serialize, Deserialize)]
3153pub enum OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3154    #[serde(rename = "PRIMARY_PEG")]
3155    PrimaryPeg,
3156    #[serde(rename = "MARKET_PEG")]
3157    MarketPeg,
3158}
3159
3160impl OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3161    #[must_use]
3162    pub fn as_str(&self) -> &'static str {
3163        match self {
3164            Self::PrimaryPeg => "PRIMARY_PEG",
3165            Self::MarketPeg => "MARKET_PEG",
3166        }
3167    }
3168}
3169
3170impl std::str::FromStr for OrderListPlaceOtocoPendingBelowPegPriceTypeEnum {
3171    type Err = Box<dyn std::error::Error + Send + Sync>;
3172
3173    fn from_str(s: &str) -> Result<Self, Self::Err> {
3174        match s {
3175            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3176            "MARKET_PEG" => Ok(Self::MarketPeg),
3177            other => Err(format!(
3178                "invalid OrderListPlaceOtocoPendingBelowPegPriceTypeEnum: {}",
3179                other
3180            )
3181            .into()),
3182        }
3183    }
3184}
3185
3186#[allow(non_camel_case_types)]
3187#[derive(Debug, Clone, Serialize, Deserialize)]
3188pub enum OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3189    #[serde(rename = "PRICE_LEVEL")]
3190    PriceLevel,
3191}
3192
3193impl OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3194    #[must_use]
3195    pub fn as_str(&self) -> &'static str {
3196        match self {
3197            Self::PriceLevel => "PRICE_LEVEL",
3198        }
3199    }
3200}
3201
3202impl std::str::FromStr for OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum {
3203    type Err = Box<dyn std::error::Error + Send + Sync>;
3204
3205    fn from_str(s: &str) -> Result<Self, Self::Err> {
3206        match s {
3207            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3208            other => Err(format!(
3209                "invalid OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum: {}",
3210                other
3211            )
3212            .into()),
3213        }
3214    }
3215}
3216
3217#[allow(non_camel_case_types)]
3218#[derive(Debug, Clone, Serialize, Deserialize)]
3219pub enum OrderPlaceSideEnum {
3220    #[serde(rename = "BUY")]
3221    Buy,
3222    #[serde(rename = "SELL")]
3223    Sell,
3224}
3225
3226impl OrderPlaceSideEnum {
3227    #[must_use]
3228    pub fn as_str(&self) -> &'static str {
3229        match self {
3230            Self::Buy => "BUY",
3231            Self::Sell => "SELL",
3232        }
3233    }
3234}
3235
3236impl std::str::FromStr for OrderPlaceSideEnum {
3237    type Err = Box<dyn std::error::Error + Send + Sync>;
3238
3239    fn from_str(s: &str) -> Result<Self, Self::Err> {
3240        match s {
3241            "BUY" => Ok(Self::Buy),
3242            "SELL" => Ok(Self::Sell),
3243            other => Err(format!("invalid OrderPlaceSideEnum: {}", other).into()),
3244        }
3245    }
3246}
3247
3248#[allow(non_camel_case_types)]
3249#[derive(Debug, Clone, Serialize, Deserialize)]
3250pub enum OrderPlaceTypeEnum {
3251    #[serde(rename = "MARKET")]
3252    Market,
3253    #[serde(rename = "LIMIT")]
3254    Limit,
3255    #[serde(rename = "STOP_LOSS")]
3256    StopLoss,
3257    #[serde(rename = "STOP_LOSS_LIMIT")]
3258    StopLossLimit,
3259    #[serde(rename = "TAKE_PROFIT")]
3260    TakeProfit,
3261    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3262    TakeProfitLimit,
3263    #[serde(rename = "LIMIT_MAKER")]
3264    LimitMaker,
3265    #[serde(rename = "NON_REPRESENTABLE")]
3266    NonRepresentable,
3267}
3268
3269impl OrderPlaceTypeEnum {
3270    #[must_use]
3271    pub fn as_str(&self) -> &'static str {
3272        match self {
3273            Self::Market => "MARKET",
3274            Self::Limit => "LIMIT",
3275            Self::StopLoss => "STOP_LOSS",
3276            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3277            Self::TakeProfit => "TAKE_PROFIT",
3278            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3279            Self::LimitMaker => "LIMIT_MAKER",
3280            Self::NonRepresentable => "NON_REPRESENTABLE",
3281        }
3282    }
3283}
3284
3285impl std::str::FromStr for OrderPlaceTypeEnum {
3286    type Err = Box<dyn std::error::Error + Send + Sync>;
3287
3288    fn from_str(s: &str) -> Result<Self, Self::Err> {
3289        match s {
3290            "MARKET" => Ok(Self::Market),
3291            "LIMIT" => Ok(Self::Limit),
3292            "STOP_LOSS" => Ok(Self::StopLoss),
3293            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3294            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3295            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3296            "LIMIT_MAKER" => Ok(Self::LimitMaker),
3297            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3298            other => Err(format!("invalid OrderPlaceTypeEnum: {}", other).into()),
3299        }
3300    }
3301}
3302
3303#[allow(non_camel_case_types)]
3304#[derive(Debug, Clone, Serialize, Deserialize)]
3305pub enum OrderPlaceTimeInForceEnum {
3306    #[serde(rename = "GTC")]
3307    Gtc,
3308    #[serde(rename = "IOC")]
3309    Ioc,
3310    #[serde(rename = "FOK")]
3311    Fok,
3312    #[serde(rename = "NON_REPRESENTABLE")]
3313    NonRepresentable,
3314}
3315
3316impl OrderPlaceTimeInForceEnum {
3317    #[must_use]
3318    pub fn as_str(&self) -> &'static str {
3319        match self {
3320            Self::Gtc => "GTC",
3321            Self::Ioc => "IOC",
3322            Self::Fok => "FOK",
3323            Self::NonRepresentable => "NON_REPRESENTABLE",
3324        }
3325    }
3326}
3327
3328impl std::str::FromStr for OrderPlaceTimeInForceEnum {
3329    type Err = Box<dyn std::error::Error + Send + Sync>;
3330
3331    fn from_str(s: &str) -> Result<Self, Self::Err> {
3332        match s {
3333            "GTC" => Ok(Self::Gtc),
3334            "IOC" => Ok(Self::Ioc),
3335            "FOK" => Ok(Self::Fok),
3336            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3337            other => Err(format!("invalid OrderPlaceTimeInForceEnum: {}", other).into()),
3338        }
3339    }
3340}
3341
3342#[allow(non_camel_case_types)]
3343#[derive(Debug, Clone, Serialize, Deserialize)]
3344pub enum OrderPlaceNewOrderRespTypeEnum {
3345    #[serde(rename = "ACK")]
3346    Ack,
3347    #[serde(rename = "RESULT")]
3348    Result,
3349    #[serde(rename = "FULL")]
3350    Full,
3351    #[serde(rename = "MARKET")]
3352    Market,
3353    #[serde(rename = "LIMIT")]
3354    Limit,
3355}
3356
3357impl OrderPlaceNewOrderRespTypeEnum {
3358    #[must_use]
3359    pub fn as_str(&self) -> &'static str {
3360        match self {
3361            Self::Ack => "ACK",
3362            Self::Result => "RESULT",
3363            Self::Full => "FULL",
3364            Self::Market => "MARKET",
3365            Self::Limit => "LIMIT",
3366        }
3367    }
3368}
3369
3370impl std::str::FromStr for OrderPlaceNewOrderRespTypeEnum {
3371    type Err = Box<dyn std::error::Error + Send + Sync>;
3372
3373    fn from_str(s: &str) -> Result<Self, Self::Err> {
3374        match s {
3375            "ACK" => Ok(Self::Ack),
3376            "RESULT" => Ok(Self::Result),
3377            "FULL" => Ok(Self::Full),
3378            "MARKET" => Ok(Self::Market),
3379            "LIMIT" => Ok(Self::Limit),
3380            other => Err(format!("invalid OrderPlaceNewOrderRespTypeEnum: {}", other).into()),
3381        }
3382    }
3383}
3384
3385#[allow(non_camel_case_types)]
3386#[derive(Debug, Clone, Serialize, Deserialize)]
3387pub enum OrderPlaceSelfTradePreventionModeEnum {
3388    #[serde(rename = "NONE")]
3389    None,
3390    #[serde(rename = "EXPIRE_TAKER")]
3391    ExpireTaker,
3392    #[serde(rename = "EXPIRE_MAKER")]
3393    ExpireMaker,
3394    #[serde(rename = "EXPIRE_BOTH")]
3395    ExpireBoth,
3396    #[serde(rename = "DECREMENT")]
3397    Decrement,
3398    #[serde(rename = "TRANSFER")]
3399    Transfer,
3400    #[serde(rename = "NON_REPRESENTABLE")]
3401    NonRepresentable,
3402}
3403
3404impl OrderPlaceSelfTradePreventionModeEnum {
3405    #[must_use]
3406    pub fn as_str(&self) -> &'static str {
3407        match self {
3408            Self::None => "NONE",
3409            Self::ExpireTaker => "EXPIRE_TAKER",
3410            Self::ExpireMaker => "EXPIRE_MAKER",
3411            Self::ExpireBoth => "EXPIRE_BOTH",
3412            Self::Decrement => "DECREMENT",
3413            Self::Transfer => "TRANSFER",
3414            Self::NonRepresentable => "NON_REPRESENTABLE",
3415        }
3416    }
3417}
3418
3419impl std::str::FromStr for OrderPlaceSelfTradePreventionModeEnum {
3420    type Err = Box<dyn std::error::Error + Send + Sync>;
3421
3422    fn from_str(s: &str) -> Result<Self, Self::Err> {
3423        match s {
3424            "NONE" => Ok(Self::None),
3425            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3426            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3427            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3428            "DECREMENT" => Ok(Self::Decrement),
3429            "TRANSFER" => Ok(Self::Transfer),
3430            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3431            other => {
3432                Err(format!("invalid OrderPlaceSelfTradePreventionModeEnum: {}", other).into())
3433            }
3434        }
3435    }
3436}
3437
3438#[allow(non_camel_case_types)]
3439#[derive(Debug, Clone, Serialize, Deserialize)]
3440pub enum OrderPlacePegPriceTypeEnum {
3441    #[serde(rename = "PRIMARY_PEG")]
3442    PrimaryPeg,
3443    #[serde(rename = "MARKET_PEG")]
3444    MarketPeg,
3445    #[serde(rename = "NON_REPRESENTABLE")]
3446    NonRepresentable,
3447}
3448
3449impl OrderPlacePegPriceTypeEnum {
3450    #[must_use]
3451    pub fn as_str(&self) -> &'static str {
3452        match self {
3453            Self::PrimaryPeg => "PRIMARY_PEG",
3454            Self::MarketPeg => "MARKET_PEG",
3455            Self::NonRepresentable => "NON_REPRESENTABLE",
3456        }
3457    }
3458}
3459
3460impl std::str::FromStr for OrderPlacePegPriceTypeEnum {
3461    type Err = Box<dyn std::error::Error + Send + Sync>;
3462
3463    fn from_str(s: &str) -> Result<Self, Self::Err> {
3464        match s {
3465            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3466            "MARKET_PEG" => Ok(Self::MarketPeg),
3467            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3468            other => Err(format!("invalid OrderPlacePegPriceTypeEnum: {}", other).into()),
3469        }
3470    }
3471}
3472
3473#[allow(non_camel_case_types)]
3474#[derive(Debug, Clone, Serialize, Deserialize)]
3475pub enum OrderPlacePegOffsetTypeEnum {
3476    #[serde(rename = "PRICE_LEVEL")]
3477    PriceLevel,
3478    #[serde(rename = "NON_REPRESENTABLE")]
3479    NonRepresentable,
3480}
3481
3482impl OrderPlacePegOffsetTypeEnum {
3483    #[must_use]
3484    pub fn as_str(&self) -> &'static str {
3485        match self {
3486            Self::PriceLevel => "PRICE_LEVEL",
3487            Self::NonRepresentable => "NON_REPRESENTABLE",
3488        }
3489    }
3490}
3491
3492impl std::str::FromStr for OrderPlacePegOffsetTypeEnum {
3493    type Err = Box<dyn std::error::Error + Send + Sync>;
3494
3495    fn from_str(s: &str) -> Result<Self, Self::Err> {
3496        match s {
3497            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3498            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3499            other => Err(format!("invalid OrderPlacePegOffsetTypeEnum: {}", other).into()),
3500        }
3501    }
3502}
3503
3504#[allow(non_camel_case_types)]
3505#[derive(Debug, Clone, Serialize, Deserialize)]
3506pub enum OrderTestSideEnum {
3507    #[serde(rename = "BUY")]
3508    Buy,
3509    #[serde(rename = "SELL")]
3510    Sell,
3511}
3512
3513impl OrderTestSideEnum {
3514    #[must_use]
3515    pub fn as_str(&self) -> &'static str {
3516        match self {
3517            Self::Buy => "BUY",
3518            Self::Sell => "SELL",
3519        }
3520    }
3521}
3522
3523impl std::str::FromStr for OrderTestSideEnum {
3524    type Err = Box<dyn std::error::Error + Send + Sync>;
3525
3526    fn from_str(s: &str) -> Result<Self, Self::Err> {
3527        match s {
3528            "BUY" => Ok(Self::Buy),
3529            "SELL" => Ok(Self::Sell),
3530            other => Err(format!("invalid OrderTestSideEnum: {}", other).into()),
3531        }
3532    }
3533}
3534
3535#[allow(non_camel_case_types)]
3536#[derive(Debug, Clone, Serialize, Deserialize)]
3537pub enum OrderTestTypeEnum {
3538    #[serde(rename = "MARKET")]
3539    Market,
3540    #[serde(rename = "LIMIT")]
3541    Limit,
3542    #[serde(rename = "STOP_LOSS")]
3543    StopLoss,
3544    #[serde(rename = "STOP_LOSS_LIMIT")]
3545    StopLossLimit,
3546    #[serde(rename = "TAKE_PROFIT")]
3547    TakeProfit,
3548    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3549    TakeProfitLimit,
3550    #[serde(rename = "LIMIT_MAKER")]
3551    LimitMaker,
3552    #[serde(rename = "NON_REPRESENTABLE")]
3553    NonRepresentable,
3554}
3555
3556impl OrderTestTypeEnum {
3557    #[must_use]
3558    pub fn as_str(&self) -> &'static str {
3559        match self {
3560            Self::Market => "MARKET",
3561            Self::Limit => "LIMIT",
3562            Self::StopLoss => "STOP_LOSS",
3563            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3564            Self::TakeProfit => "TAKE_PROFIT",
3565            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3566            Self::LimitMaker => "LIMIT_MAKER",
3567            Self::NonRepresentable => "NON_REPRESENTABLE",
3568        }
3569    }
3570}
3571
3572impl std::str::FromStr for OrderTestTypeEnum {
3573    type Err = Box<dyn std::error::Error + Send + Sync>;
3574
3575    fn from_str(s: &str) -> Result<Self, Self::Err> {
3576        match s {
3577            "MARKET" => Ok(Self::Market),
3578            "LIMIT" => Ok(Self::Limit),
3579            "STOP_LOSS" => Ok(Self::StopLoss),
3580            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3581            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3582            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3583            "LIMIT_MAKER" => Ok(Self::LimitMaker),
3584            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3585            other => Err(format!("invalid OrderTestTypeEnum: {}", other).into()),
3586        }
3587    }
3588}
3589
3590#[allow(non_camel_case_types)]
3591#[derive(Debug, Clone, Serialize, Deserialize)]
3592pub enum OrderTestTimeInForceEnum {
3593    #[serde(rename = "GTC")]
3594    Gtc,
3595    #[serde(rename = "IOC")]
3596    Ioc,
3597    #[serde(rename = "FOK")]
3598    Fok,
3599    #[serde(rename = "NON_REPRESENTABLE")]
3600    NonRepresentable,
3601}
3602
3603impl OrderTestTimeInForceEnum {
3604    #[must_use]
3605    pub fn as_str(&self) -> &'static str {
3606        match self {
3607            Self::Gtc => "GTC",
3608            Self::Ioc => "IOC",
3609            Self::Fok => "FOK",
3610            Self::NonRepresentable => "NON_REPRESENTABLE",
3611        }
3612    }
3613}
3614
3615impl std::str::FromStr for OrderTestTimeInForceEnum {
3616    type Err = Box<dyn std::error::Error + Send + Sync>;
3617
3618    fn from_str(s: &str) -> Result<Self, Self::Err> {
3619        match s {
3620            "GTC" => Ok(Self::Gtc),
3621            "IOC" => Ok(Self::Ioc),
3622            "FOK" => Ok(Self::Fok),
3623            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3624            other => Err(format!("invalid OrderTestTimeInForceEnum: {}", other).into()),
3625        }
3626    }
3627}
3628
3629#[allow(non_camel_case_types)]
3630#[derive(Debug, Clone, Serialize, Deserialize)]
3631pub enum OrderTestNewOrderRespTypeEnum {
3632    #[serde(rename = "ACK")]
3633    Ack,
3634    #[serde(rename = "RESULT")]
3635    Result,
3636    #[serde(rename = "FULL")]
3637    Full,
3638    #[serde(rename = "MARKET")]
3639    Market,
3640    #[serde(rename = "LIMIT")]
3641    Limit,
3642}
3643
3644impl OrderTestNewOrderRespTypeEnum {
3645    #[must_use]
3646    pub fn as_str(&self) -> &'static str {
3647        match self {
3648            Self::Ack => "ACK",
3649            Self::Result => "RESULT",
3650            Self::Full => "FULL",
3651            Self::Market => "MARKET",
3652            Self::Limit => "LIMIT",
3653        }
3654    }
3655}
3656
3657impl std::str::FromStr for OrderTestNewOrderRespTypeEnum {
3658    type Err = Box<dyn std::error::Error + Send + Sync>;
3659
3660    fn from_str(s: &str) -> Result<Self, Self::Err> {
3661        match s {
3662            "ACK" => Ok(Self::Ack),
3663            "RESULT" => Ok(Self::Result),
3664            "FULL" => Ok(Self::Full),
3665            "MARKET" => Ok(Self::Market),
3666            "LIMIT" => Ok(Self::Limit),
3667            other => Err(format!("invalid OrderTestNewOrderRespTypeEnum: {}", other).into()),
3668        }
3669    }
3670}
3671
3672#[allow(non_camel_case_types)]
3673#[derive(Debug, Clone, Serialize, Deserialize)]
3674pub enum OrderTestSelfTradePreventionModeEnum {
3675    #[serde(rename = "NONE")]
3676    None,
3677    #[serde(rename = "EXPIRE_TAKER")]
3678    ExpireTaker,
3679    #[serde(rename = "EXPIRE_MAKER")]
3680    ExpireMaker,
3681    #[serde(rename = "EXPIRE_BOTH")]
3682    ExpireBoth,
3683    #[serde(rename = "DECREMENT")]
3684    Decrement,
3685    #[serde(rename = "TRANSFER")]
3686    Transfer,
3687    #[serde(rename = "NON_REPRESENTABLE")]
3688    NonRepresentable,
3689}
3690
3691impl OrderTestSelfTradePreventionModeEnum {
3692    #[must_use]
3693    pub fn as_str(&self) -> &'static str {
3694        match self {
3695            Self::None => "NONE",
3696            Self::ExpireTaker => "EXPIRE_TAKER",
3697            Self::ExpireMaker => "EXPIRE_MAKER",
3698            Self::ExpireBoth => "EXPIRE_BOTH",
3699            Self::Decrement => "DECREMENT",
3700            Self::Transfer => "TRANSFER",
3701            Self::NonRepresentable => "NON_REPRESENTABLE",
3702        }
3703    }
3704}
3705
3706impl std::str::FromStr for OrderTestSelfTradePreventionModeEnum {
3707    type Err = Box<dyn std::error::Error + Send + Sync>;
3708
3709    fn from_str(s: &str) -> Result<Self, Self::Err> {
3710        match s {
3711            "NONE" => Ok(Self::None),
3712            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3713            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3714            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
3715            "DECREMENT" => Ok(Self::Decrement),
3716            "TRANSFER" => Ok(Self::Transfer),
3717            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3718            other => Err(format!("invalid OrderTestSelfTradePreventionModeEnum: {}", other).into()),
3719        }
3720    }
3721}
3722
3723#[allow(non_camel_case_types)]
3724#[derive(Debug, Clone, Serialize, Deserialize)]
3725pub enum OrderTestPegPriceTypeEnum {
3726    #[serde(rename = "PRIMARY_PEG")]
3727    PrimaryPeg,
3728    #[serde(rename = "MARKET_PEG")]
3729    MarketPeg,
3730    #[serde(rename = "NON_REPRESENTABLE")]
3731    NonRepresentable,
3732}
3733
3734impl OrderTestPegPriceTypeEnum {
3735    #[must_use]
3736    pub fn as_str(&self) -> &'static str {
3737        match self {
3738            Self::PrimaryPeg => "PRIMARY_PEG",
3739            Self::MarketPeg => "MARKET_PEG",
3740            Self::NonRepresentable => "NON_REPRESENTABLE",
3741        }
3742    }
3743}
3744
3745impl std::str::FromStr for OrderTestPegPriceTypeEnum {
3746    type Err = Box<dyn std::error::Error + Send + Sync>;
3747
3748    fn from_str(s: &str) -> Result<Self, Self::Err> {
3749        match s {
3750            "PRIMARY_PEG" => Ok(Self::PrimaryPeg),
3751            "MARKET_PEG" => Ok(Self::MarketPeg),
3752            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3753            other => Err(format!("invalid OrderTestPegPriceTypeEnum: {}", other).into()),
3754        }
3755    }
3756}
3757
3758#[allow(non_camel_case_types)]
3759#[derive(Debug, Clone, Serialize, Deserialize)]
3760pub enum OrderTestPegOffsetTypeEnum {
3761    #[serde(rename = "PRICE_LEVEL")]
3762    PriceLevel,
3763    #[serde(rename = "NON_REPRESENTABLE")]
3764    NonRepresentable,
3765}
3766
3767impl OrderTestPegOffsetTypeEnum {
3768    #[must_use]
3769    pub fn as_str(&self) -> &'static str {
3770        match self {
3771            Self::PriceLevel => "PRICE_LEVEL",
3772            Self::NonRepresentable => "NON_REPRESENTABLE",
3773        }
3774    }
3775}
3776
3777impl std::str::FromStr for OrderTestPegOffsetTypeEnum {
3778    type Err = Box<dyn std::error::Error + Send + Sync>;
3779
3780    fn from_str(s: &str) -> Result<Self, Self::Err> {
3781        match s {
3782            "PRICE_LEVEL" => Ok(Self::PriceLevel),
3783            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3784            other => Err(format!("invalid OrderTestPegOffsetTypeEnum: {}", other).into()),
3785        }
3786    }
3787}
3788
3789#[allow(non_camel_case_types)]
3790#[derive(Debug, Clone, Serialize, Deserialize)]
3791pub enum SorOrderPlaceSideEnum {
3792    #[serde(rename = "BUY")]
3793    Buy,
3794    #[serde(rename = "SELL")]
3795    Sell,
3796}
3797
3798impl SorOrderPlaceSideEnum {
3799    #[must_use]
3800    pub fn as_str(&self) -> &'static str {
3801        match self {
3802            Self::Buy => "BUY",
3803            Self::Sell => "SELL",
3804        }
3805    }
3806}
3807
3808impl std::str::FromStr for SorOrderPlaceSideEnum {
3809    type Err = Box<dyn std::error::Error + Send + Sync>;
3810
3811    fn from_str(s: &str) -> Result<Self, Self::Err> {
3812        match s {
3813            "BUY" => Ok(Self::Buy),
3814            "SELL" => Ok(Self::Sell),
3815            other => Err(format!("invalid SorOrderPlaceSideEnum: {}", other).into()),
3816        }
3817    }
3818}
3819
3820#[allow(non_camel_case_types)]
3821#[derive(Debug, Clone, Serialize, Deserialize)]
3822pub enum SorOrderPlaceTypeEnum {
3823    #[serde(rename = "MARKET")]
3824    Market,
3825    #[serde(rename = "LIMIT")]
3826    Limit,
3827    #[serde(rename = "STOP_LOSS")]
3828    StopLoss,
3829    #[serde(rename = "STOP_LOSS_LIMIT")]
3830    StopLossLimit,
3831    #[serde(rename = "TAKE_PROFIT")]
3832    TakeProfit,
3833    #[serde(rename = "TAKE_PROFIT_LIMIT")]
3834    TakeProfitLimit,
3835    #[serde(rename = "LIMIT_MAKER")]
3836    LimitMaker,
3837    #[serde(rename = "NON_REPRESENTABLE")]
3838    NonRepresentable,
3839}
3840
3841impl SorOrderPlaceTypeEnum {
3842    #[must_use]
3843    pub fn as_str(&self) -> &'static str {
3844        match self {
3845            Self::Market => "MARKET",
3846            Self::Limit => "LIMIT",
3847            Self::StopLoss => "STOP_LOSS",
3848            Self::StopLossLimit => "STOP_LOSS_LIMIT",
3849            Self::TakeProfit => "TAKE_PROFIT",
3850            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
3851            Self::LimitMaker => "LIMIT_MAKER",
3852            Self::NonRepresentable => "NON_REPRESENTABLE",
3853        }
3854    }
3855}
3856
3857impl std::str::FromStr for SorOrderPlaceTypeEnum {
3858    type Err = Box<dyn std::error::Error + Send + Sync>;
3859
3860    fn from_str(s: &str) -> Result<Self, Self::Err> {
3861        match s {
3862            "MARKET" => Ok(Self::Market),
3863            "LIMIT" => Ok(Self::Limit),
3864            "STOP_LOSS" => Ok(Self::StopLoss),
3865            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
3866            "TAKE_PROFIT" => Ok(Self::TakeProfit),
3867            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
3868            "LIMIT_MAKER" => Ok(Self::LimitMaker),
3869            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3870            other => Err(format!("invalid SorOrderPlaceTypeEnum: {}", other).into()),
3871        }
3872    }
3873}
3874
3875#[allow(non_camel_case_types)]
3876#[derive(Debug, Clone, Serialize, Deserialize)]
3877pub enum SorOrderPlaceTimeInForceEnum {
3878    #[serde(rename = "GTC")]
3879    Gtc,
3880    #[serde(rename = "IOC")]
3881    Ioc,
3882    #[serde(rename = "FOK")]
3883    Fok,
3884    #[serde(rename = "NON_REPRESENTABLE")]
3885    NonRepresentable,
3886}
3887
3888impl SorOrderPlaceTimeInForceEnum {
3889    #[must_use]
3890    pub fn as_str(&self) -> &'static str {
3891        match self {
3892            Self::Gtc => "GTC",
3893            Self::Ioc => "IOC",
3894            Self::Fok => "FOK",
3895            Self::NonRepresentable => "NON_REPRESENTABLE",
3896        }
3897    }
3898}
3899
3900impl std::str::FromStr for SorOrderPlaceTimeInForceEnum {
3901    type Err = Box<dyn std::error::Error + Send + Sync>;
3902
3903    fn from_str(s: &str) -> Result<Self, Self::Err> {
3904        match s {
3905            "GTC" => Ok(Self::Gtc),
3906            "IOC" => Ok(Self::Ioc),
3907            "FOK" => Ok(Self::Fok),
3908            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
3909            other => Err(format!("invalid SorOrderPlaceTimeInForceEnum: {}", other).into()),
3910        }
3911    }
3912}
3913
3914#[allow(non_camel_case_types)]
3915#[derive(Debug, Clone, Serialize, Deserialize)]
3916pub enum SorOrderPlaceNewOrderRespTypeEnum {
3917    #[serde(rename = "ACK")]
3918    Ack,
3919    #[serde(rename = "RESULT")]
3920    Result,
3921    #[serde(rename = "FULL")]
3922    Full,
3923    #[serde(rename = "MARKET")]
3924    Market,
3925    #[serde(rename = "LIMIT")]
3926    Limit,
3927}
3928
3929impl SorOrderPlaceNewOrderRespTypeEnum {
3930    #[must_use]
3931    pub fn as_str(&self) -> &'static str {
3932        match self {
3933            Self::Ack => "ACK",
3934            Self::Result => "RESULT",
3935            Self::Full => "FULL",
3936            Self::Market => "MARKET",
3937            Self::Limit => "LIMIT",
3938        }
3939    }
3940}
3941
3942impl std::str::FromStr for SorOrderPlaceNewOrderRespTypeEnum {
3943    type Err = Box<dyn std::error::Error + Send + Sync>;
3944
3945    fn from_str(s: &str) -> Result<Self, Self::Err> {
3946        match s {
3947            "ACK" => Ok(Self::Ack),
3948            "RESULT" => Ok(Self::Result),
3949            "FULL" => Ok(Self::Full),
3950            "MARKET" => Ok(Self::Market),
3951            "LIMIT" => Ok(Self::Limit),
3952            other => Err(format!("invalid SorOrderPlaceNewOrderRespTypeEnum: {}", other).into()),
3953        }
3954    }
3955}
3956
3957#[allow(non_camel_case_types)]
3958#[derive(Debug, Clone, Serialize, Deserialize)]
3959pub enum SorOrderPlaceSelfTradePreventionModeEnum {
3960    #[serde(rename = "NONE")]
3961    None,
3962    #[serde(rename = "EXPIRE_TAKER")]
3963    ExpireTaker,
3964    #[serde(rename = "EXPIRE_MAKER")]
3965    ExpireMaker,
3966    #[serde(rename = "EXPIRE_BOTH")]
3967    ExpireBoth,
3968    #[serde(rename = "DECREMENT")]
3969    Decrement,
3970    #[serde(rename = "TRANSFER")]
3971    Transfer,
3972    #[serde(rename = "NON_REPRESENTABLE")]
3973    NonRepresentable,
3974}
3975
3976impl SorOrderPlaceSelfTradePreventionModeEnum {
3977    #[must_use]
3978    pub fn as_str(&self) -> &'static str {
3979        match self {
3980            Self::None => "NONE",
3981            Self::ExpireTaker => "EXPIRE_TAKER",
3982            Self::ExpireMaker => "EXPIRE_MAKER",
3983            Self::ExpireBoth => "EXPIRE_BOTH",
3984            Self::Decrement => "DECREMENT",
3985            Self::Transfer => "TRANSFER",
3986            Self::NonRepresentable => "NON_REPRESENTABLE",
3987        }
3988    }
3989}
3990
3991impl std::str::FromStr for SorOrderPlaceSelfTradePreventionModeEnum {
3992    type Err = Box<dyn std::error::Error + Send + Sync>;
3993
3994    fn from_str(s: &str) -> Result<Self, Self::Err> {
3995        match s {
3996            "NONE" => Ok(Self::None),
3997            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
3998            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
3999            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
4000            "DECREMENT" => Ok(Self::Decrement),
4001            "TRANSFER" => Ok(Self::Transfer),
4002            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
4003            other => Err(format!(
4004                "invalid SorOrderPlaceSelfTradePreventionModeEnum: {}",
4005                other
4006            )
4007            .into()),
4008        }
4009    }
4010}
4011
4012#[allow(non_camel_case_types)]
4013#[derive(Debug, Clone, Serialize, Deserialize)]
4014pub enum SorOrderTestSideEnum {
4015    #[serde(rename = "BUY")]
4016    Buy,
4017    #[serde(rename = "SELL")]
4018    Sell,
4019}
4020
4021impl SorOrderTestSideEnum {
4022    #[must_use]
4023    pub fn as_str(&self) -> &'static str {
4024        match self {
4025            Self::Buy => "BUY",
4026            Self::Sell => "SELL",
4027        }
4028    }
4029}
4030
4031impl std::str::FromStr for SorOrderTestSideEnum {
4032    type Err = Box<dyn std::error::Error + Send + Sync>;
4033
4034    fn from_str(s: &str) -> Result<Self, Self::Err> {
4035        match s {
4036            "BUY" => Ok(Self::Buy),
4037            "SELL" => Ok(Self::Sell),
4038            other => Err(format!("invalid SorOrderTestSideEnum: {}", other).into()),
4039        }
4040    }
4041}
4042
4043#[allow(non_camel_case_types)]
4044#[derive(Debug, Clone, Serialize, Deserialize)]
4045pub enum SorOrderTestTypeEnum {
4046    #[serde(rename = "MARKET")]
4047    Market,
4048    #[serde(rename = "LIMIT")]
4049    Limit,
4050    #[serde(rename = "STOP_LOSS")]
4051    StopLoss,
4052    #[serde(rename = "STOP_LOSS_LIMIT")]
4053    StopLossLimit,
4054    #[serde(rename = "TAKE_PROFIT")]
4055    TakeProfit,
4056    #[serde(rename = "TAKE_PROFIT_LIMIT")]
4057    TakeProfitLimit,
4058    #[serde(rename = "LIMIT_MAKER")]
4059    LimitMaker,
4060    #[serde(rename = "NON_REPRESENTABLE")]
4061    NonRepresentable,
4062}
4063
4064impl SorOrderTestTypeEnum {
4065    #[must_use]
4066    pub fn as_str(&self) -> &'static str {
4067        match self {
4068            Self::Market => "MARKET",
4069            Self::Limit => "LIMIT",
4070            Self::StopLoss => "STOP_LOSS",
4071            Self::StopLossLimit => "STOP_LOSS_LIMIT",
4072            Self::TakeProfit => "TAKE_PROFIT",
4073            Self::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
4074            Self::LimitMaker => "LIMIT_MAKER",
4075            Self::NonRepresentable => "NON_REPRESENTABLE",
4076        }
4077    }
4078}
4079
4080impl std::str::FromStr for SorOrderTestTypeEnum {
4081    type Err = Box<dyn std::error::Error + Send + Sync>;
4082
4083    fn from_str(s: &str) -> Result<Self, Self::Err> {
4084        match s {
4085            "MARKET" => Ok(Self::Market),
4086            "LIMIT" => Ok(Self::Limit),
4087            "STOP_LOSS" => Ok(Self::StopLoss),
4088            "STOP_LOSS_LIMIT" => Ok(Self::StopLossLimit),
4089            "TAKE_PROFIT" => Ok(Self::TakeProfit),
4090            "TAKE_PROFIT_LIMIT" => Ok(Self::TakeProfitLimit),
4091            "LIMIT_MAKER" => Ok(Self::LimitMaker),
4092            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
4093            other => Err(format!("invalid SorOrderTestTypeEnum: {}", other).into()),
4094        }
4095    }
4096}
4097
4098#[allow(non_camel_case_types)]
4099#[derive(Debug, Clone, Serialize, Deserialize)]
4100pub enum SorOrderTestTimeInForceEnum {
4101    #[serde(rename = "GTC")]
4102    Gtc,
4103    #[serde(rename = "IOC")]
4104    Ioc,
4105    #[serde(rename = "FOK")]
4106    Fok,
4107    #[serde(rename = "NON_REPRESENTABLE")]
4108    NonRepresentable,
4109}
4110
4111impl SorOrderTestTimeInForceEnum {
4112    #[must_use]
4113    pub fn as_str(&self) -> &'static str {
4114        match self {
4115            Self::Gtc => "GTC",
4116            Self::Ioc => "IOC",
4117            Self::Fok => "FOK",
4118            Self::NonRepresentable => "NON_REPRESENTABLE",
4119        }
4120    }
4121}
4122
4123impl std::str::FromStr for SorOrderTestTimeInForceEnum {
4124    type Err = Box<dyn std::error::Error + Send + Sync>;
4125
4126    fn from_str(s: &str) -> Result<Self, Self::Err> {
4127        match s {
4128            "GTC" => Ok(Self::Gtc),
4129            "IOC" => Ok(Self::Ioc),
4130            "FOK" => Ok(Self::Fok),
4131            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
4132            other => Err(format!("invalid SorOrderTestTimeInForceEnum: {}", other).into()),
4133        }
4134    }
4135}
4136
4137#[allow(non_camel_case_types)]
4138#[derive(Debug, Clone, Serialize, Deserialize)]
4139pub enum SorOrderTestNewOrderRespTypeEnum {
4140    #[serde(rename = "ACK")]
4141    Ack,
4142    #[serde(rename = "RESULT")]
4143    Result,
4144    #[serde(rename = "FULL")]
4145    Full,
4146    #[serde(rename = "MARKET")]
4147    Market,
4148    #[serde(rename = "LIMIT")]
4149    Limit,
4150}
4151
4152impl SorOrderTestNewOrderRespTypeEnum {
4153    #[must_use]
4154    pub fn as_str(&self) -> &'static str {
4155        match self {
4156            Self::Ack => "ACK",
4157            Self::Result => "RESULT",
4158            Self::Full => "FULL",
4159            Self::Market => "MARKET",
4160            Self::Limit => "LIMIT",
4161        }
4162    }
4163}
4164
4165impl std::str::FromStr for SorOrderTestNewOrderRespTypeEnum {
4166    type Err = Box<dyn std::error::Error + Send + Sync>;
4167
4168    fn from_str(s: &str) -> Result<Self, Self::Err> {
4169        match s {
4170            "ACK" => Ok(Self::Ack),
4171            "RESULT" => Ok(Self::Result),
4172            "FULL" => Ok(Self::Full),
4173            "MARKET" => Ok(Self::Market),
4174            "LIMIT" => Ok(Self::Limit),
4175            other => Err(format!("invalid SorOrderTestNewOrderRespTypeEnum: {}", other).into()),
4176        }
4177    }
4178}
4179
4180#[allow(non_camel_case_types)]
4181#[derive(Debug, Clone, Serialize, Deserialize)]
4182pub enum SorOrderTestSelfTradePreventionModeEnum {
4183    #[serde(rename = "NONE")]
4184    None,
4185    #[serde(rename = "EXPIRE_TAKER")]
4186    ExpireTaker,
4187    #[serde(rename = "EXPIRE_MAKER")]
4188    ExpireMaker,
4189    #[serde(rename = "EXPIRE_BOTH")]
4190    ExpireBoth,
4191    #[serde(rename = "DECREMENT")]
4192    Decrement,
4193    #[serde(rename = "TRANSFER")]
4194    Transfer,
4195    #[serde(rename = "NON_REPRESENTABLE")]
4196    NonRepresentable,
4197}
4198
4199impl SorOrderTestSelfTradePreventionModeEnum {
4200    #[must_use]
4201    pub fn as_str(&self) -> &'static str {
4202        match self {
4203            Self::None => "NONE",
4204            Self::ExpireTaker => "EXPIRE_TAKER",
4205            Self::ExpireMaker => "EXPIRE_MAKER",
4206            Self::ExpireBoth => "EXPIRE_BOTH",
4207            Self::Decrement => "DECREMENT",
4208            Self::Transfer => "TRANSFER",
4209            Self::NonRepresentable => "NON_REPRESENTABLE",
4210        }
4211    }
4212}
4213
4214impl std::str::FromStr for SorOrderTestSelfTradePreventionModeEnum {
4215    type Err = Box<dyn std::error::Error + Send + Sync>;
4216
4217    fn from_str(s: &str) -> Result<Self, Self::Err> {
4218        match s {
4219            "NONE" => Ok(Self::None),
4220            "EXPIRE_TAKER" => Ok(Self::ExpireTaker),
4221            "EXPIRE_MAKER" => Ok(Self::ExpireMaker),
4222            "EXPIRE_BOTH" => Ok(Self::ExpireBoth),
4223            "DECREMENT" => Ok(Self::Decrement),
4224            "TRANSFER" => Ok(Self::Transfer),
4225            "NON_REPRESENTABLE" => Ok(Self::NonRepresentable),
4226            other => {
4227                Err(format!("invalid SorOrderTestSelfTradePreventionModeEnum: {}", other).into())
4228            }
4229        }
4230    }
4231}
4232
4233/// Request parameters for the [`open_orders_cancel_all`] operation.
4234///
4235/// This struct holds all of the inputs you can pass when calling
4236/// [`open_orders_cancel_all`](#method.open_orders_cancel_all).
4237#[derive(Clone, Debug, Builder)]
4238#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4239pub struct OpenOrdersCancelAllParams {
4240    ///
4241    /// The `symbol` parameter.
4242    ///
4243    /// This field is **required.
4244    #[builder(setter(into))]
4245    pub symbol: String,
4246    /// Unique WebSocket request ID.
4247    ///
4248    /// This field is **optional.
4249    #[builder(setter(into), default)]
4250    pub id: Option<String>,
4251    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4252    ///
4253    /// This field is **optional.
4254    #[builder(setter(into), default)]
4255    pub recv_window: Option<rust_decimal::Decimal>,
4256}
4257
4258impl OpenOrdersCancelAllParams {
4259    /// Create a builder for [`open_orders_cancel_all`].
4260    ///
4261    /// Required parameters:
4262    ///
4263    /// * `symbol` — String
4264    ///
4265    #[must_use]
4266    pub fn builder(symbol: String) -> OpenOrdersCancelAllParamsBuilder {
4267        OpenOrdersCancelAllParamsBuilder::default().symbol(symbol)
4268    }
4269}
4270/// Request parameters for the [`order_amend_keep_priority`] operation.
4271///
4272/// This struct holds all of the inputs you can pass when calling
4273/// [`order_amend_keep_priority`](#method.order_amend_keep_priority).
4274#[derive(Clone, Debug, Builder)]
4275#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4276pub struct OrderAmendKeepPriorityParams {
4277    ///
4278    /// The `symbol` parameter.
4279    ///
4280    /// This field is **required.
4281    #[builder(setter(into))]
4282    pub symbol: String,
4283    /// `newQty` must be greater than 0 and less than the order's quantity.
4284    ///
4285    /// This field is **required.
4286    #[builder(setter(into))]
4287    pub new_qty: rust_decimal::Decimal,
4288    /// Unique WebSocket request ID.
4289    ///
4290    /// This field is **optional.
4291    #[builder(setter(into), default)]
4292    pub id: Option<String>,
4293    /// `orderId`or`origClientOrderId`mustbesent
4294    ///
4295    /// This field is **optional.
4296    #[builder(setter(into), default)]
4297    pub order_id: Option<i64>,
4298    /// `orderId`or`origClientOrderId`mustbesent
4299    ///
4300    /// This field is **optional.
4301    #[builder(setter(into), default)]
4302    pub orig_client_order_id: Option<String>,
4303    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
4304    ///
4305    /// This field is **optional.
4306    #[builder(setter(into), default)]
4307    pub new_client_order_id: Option<String>,
4308    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4309    ///
4310    /// This field is **optional.
4311    #[builder(setter(into), default)]
4312    pub recv_window: Option<rust_decimal::Decimal>,
4313}
4314
4315impl OrderAmendKeepPriorityParams {
4316    /// Create a builder for [`order_amend_keep_priority`].
4317    ///
4318    /// Required parameters:
4319    ///
4320    /// * `symbol` — String
4321    /// * `new_qty` — `newQty` must be greater than 0 and less than the order's quantity.
4322    ///
4323    #[must_use]
4324    pub fn builder(
4325        symbol: String,
4326        new_qty: rust_decimal::Decimal,
4327    ) -> OrderAmendKeepPriorityParamsBuilder {
4328        OrderAmendKeepPriorityParamsBuilder::default()
4329            .symbol(symbol)
4330            .new_qty(new_qty)
4331    }
4332}
4333/// Request parameters for the [`order_cancel`] operation.
4334///
4335/// This struct holds all of the inputs you can pass when calling
4336/// [`order_cancel`](#method.order_cancel).
4337#[derive(Clone, Debug, Builder)]
4338#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4339pub struct OrderCancelParams {
4340    ///
4341    /// The `symbol` parameter.
4342    ///
4343    /// This field is **required.
4344    #[builder(setter(into))]
4345    pub symbol: String,
4346    /// Unique WebSocket request ID.
4347    ///
4348    /// This field is **optional.
4349    #[builder(setter(into), default)]
4350    pub id: Option<String>,
4351    /// `orderId`or`origClientOrderId`mustbesent
4352    ///
4353    /// This field is **optional.
4354    #[builder(setter(into), default)]
4355    pub order_id: Option<i64>,
4356    /// `orderId`or`origClientOrderId`mustbesent
4357    ///
4358    /// This field is **optional.
4359    #[builder(setter(into), default)]
4360    pub orig_client_order_id: Option<String>,
4361    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
4362    ///
4363    /// This field is **optional.
4364    #[builder(setter(into), default)]
4365    pub new_client_order_id: Option<String>,
4366    ///
4367    /// The `cancel_restrictions` parameter.
4368    ///
4369    /// This field is **optional.
4370    #[builder(setter(into), default)]
4371    pub cancel_restrictions: Option<OrderCancelCancelRestrictionsEnum>,
4372    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4373    ///
4374    /// This field is **optional.
4375    #[builder(setter(into), default)]
4376    pub recv_window: Option<rust_decimal::Decimal>,
4377}
4378
4379impl OrderCancelParams {
4380    /// Create a builder for [`order_cancel`].
4381    ///
4382    /// Required parameters:
4383    ///
4384    /// * `symbol` — String
4385    ///
4386    #[must_use]
4387    pub fn builder(symbol: String) -> OrderCancelParamsBuilder {
4388        OrderCancelParamsBuilder::default().symbol(symbol)
4389    }
4390}
4391/// Request parameters for the [`order_cancel_replace`] operation.
4392///
4393/// This struct holds all of the inputs you can pass when calling
4394/// [`order_cancel_replace`](#method.order_cancel_replace).
4395#[derive(Clone, Debug, Builder)]
4396#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4397pub struct OrderCancelReplaceParams {
4398    ///
4399    /// The `symbol` parameter.
4400    ///
4401    /// This field is **required.
4402    #[builder(setter(into))]
4403    pub symbol: String,
4404    ///
4405    /// The `cancel_replace_mode` parameter.
4406    ///
4407    /// This field is **required.
4408    #[builder(setter(into))]
4409    pub cancel_replace_mode: OrderCancelReplaceCancelReplaceModeEnum,
4410    ///
4411    /// The `side` parameter.
4412    ///
4413    /// This field is **required.
4414    #[builder(setter(into))]
4415    pub side: OrderCancelReplaceSideEnum,
4416    ///
4417    /// The `r#type` parameter.
4418    ///
4419    /// This field is **required.
4420    #[builder(setter(into))]
4421    pub r#type: OrderCancelReplaceTypeEnum,
4422    /// Unique WebSocket request ID.
4423    ///
4424    /// This field is **optional.
4425    #[builder(setter(into), default)]
4426    pub id: Option<String>,
4427    /// Cancel order by orderId
4428    ///
4429    /// This field is **optional.
4430    #[builder(setter(into), default)]
4431    pub cancel_order_id: Option<i64>,
4432    ///
4433    /// The `cancel_orig_client_order_id` parameter.
4434    ///
4435    /// This field is **optional.
4436    #[builder(setter(into), default)]
4437    pub cancel_orig_client_order_id: Option<String>,
4438    /// New ID for the canceled order. Automatically generated if not sent
4439    ///
4440    /// This field is **optional.
4441    #[builder(setter(into), default)]
4442    pub cancel_new_client_order_id: Option<String>,
4443    ///
4444    /// The `time_in_force` parameter.
4445    ///
4446    /// This field is **optional.
4447    #[builder(setter(into), default)]
4448    pub time_in_force: Option<OrderCancelReplaceTimeInForceEnum>,
4449    ///
4450    /// The `price` parameter.
4451    ///
4452    /// This field is **optional.
4453    #[builder(setter(into), default)]
4454    pub price: Option<rust_decimal::Decimal>,
4455    ///
4456    /// The `quantity` parameter.
4457    ///
4458    /// This field is **optional.
4459    #[builder(setter(into), default)]
4460    pub quantity: Option<rust_decimal::Decimal>,
4461    ///
4462    /// The `quote_order_qty` parameter.
4463    ///
4464    /// This field is **optional.
4465    #[builder(setter(into), default)]
4466    pub quote_order_qty: Option<rust_decimal::Decimal>,
4467    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
4468    ///
4469    /// This field is **optional.
4470    #[builder(setter(into), default)]
4471    pub new_client_order_id: Option<String>,
4472    ///
4473    /// The `new_order_resp_type` parameter.
4474    ///
4475    /// This field is **optional.
4476    #[builder(setter(into), default)]
4477    pub new_order_resp_type: Option<OrderCancelReplaceNewOrderRespTypeEnum>,
4478    ///
4479    /// The `stop_price` parameter.
4480    ///
4481    /// This field is **optional.
4482    #[builder(setter(into), default)]
4483    pub stop_price: Option<rust_decimal::Decimal>,
4484    /// See Trailing Stop order FAQ
4485    ///
4486    /// This field is **optional.
4487    #[builder(setter(into), default)]
4488    pub trailing_delta: Option<rust_decimal::Decimal>,
4489    ///
4490    /// The `iceberg_qty` parameter.
4491    ///
4492    /// This field is **optional.
4493    #[builder(setter(into), default)]
4494    pub iceberg_qty: Option<rust_decimal::Decimal>,
4495    /// Arbitrary numeric value identifying the order within an order strategy.
4496    ///
4497    /// This field is **optional.
4498    #[builder(setter(into), default)]
4499    pub strategy_id: Option<i64>,
4500    /// Arbitrary numeric value identifying the order strategy.
4501    /// Values smaller than 1000000 are reserved and cannot be used.
4502    ///
4503    /// This field is **optional.
4504    #[builder(setter(into), default)]
4505    pub strategy_type: Option<i32>,
4506    ///
4507    /// The `self_trade_prevention_mode` parameter.
4508    ///
4509    /// This field is **optional.
4510    #[builder(setter(into), default)]
4511    pub self_trade_prevention_mode: Option<OrderCancelReplaceSelfTradePreventionModeEnum>,
4512    ///
4513    /// The `cancel_restrictions` parameter.
4514    ///
4515    /// This field is **optional.
4516    #[builder(setter(into), default)]
4517    pub cancel_restrictions: Option<OrderCancelReplaceCancelRestrictionsEnum>,
4518    ///
4519    /// The `order_rate_limit_exceeded_mode` parameter.
4520    ///
4521    /// This field is **optional.
4522    #[builder(setter(into), default)]
4523    pub order_rate_limit_exceeded_mode: Option<OrderCancelReplaceOrderRateLimitExceededModeEnum>,
4524    ///
4525    /// The `peg_price_type` parameter.
4526    ///
4527    /// This field is **optional.
4528    #[builder(setter(into), default)]
4529    pub peg_price_type: Option<OrderCancelReplacePegPriceTypeEnum>,
4530    /// Price level to peg the price to (max: 100)
4531    /// See Pegged Orders
4532    ///
4533    /// This field is **optional.
4534    #[builder(setter(into), default)]
4535    pub peg_offset_value: Option<i32>,
4536    ///
4537    /// The `peg_offset_type` parameter.
4538    ///
4539    /// This field is **optional.
4540    #[builder(setter(into), default)]
4541    pub peg_offset_type: Option<OrderCancelReplacePegOffsetTypeEnum>,
4542    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4543    ///
4544    /// This field is **optional.
4545    #[builder(setter(into), default)]
4546    pub recv_window: Option<rust_decimal::Decimal>,
4547}
4548
4549impl OrderCancelReplaceParams {
4550    /// Create a builder for [`order_cancel_replace`].
4551    ///
4552    /// Required parameters:
4553    ///
4554    /// * `symbol` — String
4555    /// * `cancel_replace_mode` — String
4556    /// * `side` — String
4557    /// * `r#type` — String
4558    ///
4559    #[must_use]
4560    pub fn builder(
4561        symbol: String,
4562        cancel_replace_mode: OrderCancelReplaceCancelReplaceModeEnum,
4563        side: OrderCancelReplaceSideEnum,
4564        r#type: OrderCancelReplaceTypeEnum,
4565    ) -> OrderCancelReplaceParamsBuilder {
4566        OrderCancelReplaceParamsBuilder::default()
4567            .symbol(symbol)
4568            .cancel_replace_mode(cancel_replace_mode)
4569            .side(side)
4570            .r#type(r#type)
4571    }
4572}
4573/// Request parameters for the [`order_list_cancel`] operation.
4574///
4575/// This struct holds all of the inputs you can pass when calling
4576/// [`order_list_cancel`](#method.order_list_cancel).
4577#[derive(Clone, Debug, Builder)]
4578#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4579pub struct OrderListCancelParams {
4580    ///
4581    /// The `symbol` parameter.
4582    ///
4583    /// This field is **required.
4584    #[builder(setter(into))]
4585    pub symbol: String,
4586    /// Unique WebSocket request ID.
4587    ///
4588    /// This field is **optional.
4589    #[builder(setter(into), default)]
4590    pub id: Option<String>,
4591    /// Cancel order list by orderListId
4592    ///
4593    /// This field is **optional.
4594    #[builder(setter(into), default)]
4595    pub order_list_id: Option<i32>,
4596    ///
4597    /// The `list_client_order_id` parameter.
4598    ///
4599    /// This field is **optional.
4600    #[builder(setter(into), default)]
4601    pub list_client_order_id: Option<String>,
4602    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
4603    ///
4604    /// This field is **optional.
4605    #[builder(setter(into), default)]
4606    pub new_client_order_id: Option<String>,
4607    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4608    ///
4609    /// This field is **optional.
4610    #[builder(setter(into), default)]
4611    pub recv_window: Option<rust_decimal::Decimal>,
4612}
4613
4614impl OrderListCancelParams {
4615    /// Create a builder for [`order_list_cancel`].
4616    ///
4617    /// Required parameters:
4618    ///
4619    /// * `symbol` — String
4620    ///
4621    #[must_use]
4622    pub fn builder(symbol: String) -> OrderListCancelParamsBuilder {
4623        OrderListCancelParamsBuilder::default().symbol(symbol)
4624    }
4625}
4626/// Request parameters for the [`order_list_place`] operation.
4627///
4628/// This struct holds all of the inputs you can pass when calling
4629/// [`order_list_place`](#method.order_list_place).
4630#[derive(Clone, Debug, Builder)]
4631#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4632pub struct OrderListPlaceParams {
4633    ///
4634    /// The `symbol` parameter.
4635    ///
4636    /// This field is **required.
4637    #[builder(setter(into))]
4638    pub symbol: String,
4639    ///
4640    /// The `side` parameter.
4641    ///
4642    /// This field is **required.
4643    #[builder(setter(into))]
4644    pub side: OrderListPlaceSideEnum,
4645    /// Price for the limit order
4646    ///
4647    /// This field is **required.
4648    #[builder(setter(into))]
4649    pub price: rust_decimal::Decimal,
4650    ///
4651    /// The `quantity` parameter.
4652    ///
4653    /// This field is **required.
4654    #[builder(setter(into))]
4655    pub quantity: rust_decimal::Decimal,
4656    /// Unique WebSocket request ID.
4657    ///
4658    /// This field is **optional.
4659    #[builder(setter(into), default)]
4660    pub id: Option<String>,
4661    ///
4662    /// The `list_client_order_id` parameter.
4663    ///
4664    /// This field is **optional.
4665    #[builder(setter(into), default)]
4666    pub list_client_order_id: Option<String>,
4667    /// Arbitrary unique ID among open orders for the limit order. Automatically generated if not sent
4668    ///
4669    /// This field is **optional.
4670    #[builder(setter(into), default)]
4671    pub limit_client_order_id: Option<String>,
4672    ///
4673    /// The `limit_iceberg_qty` parameter.
4674    ///
4675    /// This field is **optional.
4676    #[builder(setter(into), default)]
4677    pub limit_iceberg_qty: Option<rust_decimal::Decimal>,
4678    /// Arbitrary numeric value identifying the limit order within an order strategy.
4679    ///
4680    /// This field is **optional.
4681    #[builder(setter(into), default)]
4682    pub limit_strategy_id: Option<i64>,
4683    /// <p>Arbitrary numeric value identifying the limit order strategy.</p><p>Values smaller than `1000000` are reserved and cannot be used.</p>
4684    ///
4685    /// This field is **optional.
4686    #[builder(setter(into), default)]
4687    pub limit_strategy_type: Option<i32>,
4688    ///
4689    /// The `stop_price` parameter.
4690    ///
4691    /// This field is **optional.
4692    #[builder(setter(into), default)]
4693    pub stop_price: Option<rust_decimal::Decimal>,
4694    /// See [Trailing Stop order FAQ](faqs/trailing-stop-faq.md)
4695    ///
4696    /// This field is **optional.
4697    #[builder(setter(into), default)]
4698    pub trailing_delta: Option<i32>,
4699    /// Arbitrary unique ID among open orders for the stop order. Automatically generated if not sent
4700    ///
4701    /// This field is **optional.
4702    #[builder(setter(into), default)]
4703    pub stop_client_order_id: Option<String>,
4704    ///
4705    /// The `stop_limit_price` parameter.
4706    ///
4707    /// This field is **optional.
4708    #[builder(setter(into), default)]
4709    pub stop_limit_price: Option<rust_decimal::Decimal>,
4710    ///
4711    /// The `stop_limit_time_in_force` parameter.
4712    ///
4713    /// This field is **optional.
4714    #[builder(setter(into), default)]
4715    pub stop_limit_time_in_force: Option<OrderListPlaceStopLimitTimeInForceEnum>,
4716    ///
4717    /// The `stop_iceberg_qty` parameter.
4718    ///
4719    /// This field is **optional.
4720    #[builder(setter(into), default)]
4721    pub stop_iceberg_qty: Option<rust_decimal::Decimal>,
4722    /// Arbitrary numeric value identifying the stop order within an order strategy.
4723    ///
4724    /// This field is **optional.
4725    #[builder(setter(into), default)]
4726    pub stop_strategy_id: Option<i64>,
4727    /// <p>Arbitrary numeric value identifying the stop order strategy.</p><p>Values smaller than `1000000` are reserved and cannot be used.</p>
4728    ///
4729    /// This field is **optional.
4730    #[builder(setter(into), default)]
4731    pub stop_strategy_type: Option<i32>,
4732    ///
4733    /// The `new_order_resp_type` parameter.
4734    ///
4735    /// This field is **optional.
4736    #[builder(setter(into), default)]
4737    pub new_order_resp_type: Option<OrderListPlaceNewOrderRespTypeEnum>,
4738    ///
4739    /// The `self_trade_prevention_mode` parameter.
4740    ///
4741    /// This field is **optional.
4742    #[builder(setter(into), default)]
4743    pub self_trade_prevention_mode: Option<OrderListPlaceSelfTradePreventionModeEnum>,
4744    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4745    ///
4746    /// This field is **optional.
4747    #[builder(setter(into), default)]
4748    pub recv_window: Option<rust_decimal::Decimal>,
4749}
4750
4751impl OrderListPlaceParams {
4752    /// Create a builder for [`order_list_place`].
4753    ///
4754    /// Required parameters:
4755    ///
4756    /// * `symbol` — String
4757    /// * `side` — String
4758    /// * `price` — Price for the limit order
4759    /// * `quantity` — `rust_decimal::Decimal`
4760    ///
4761    #[must_use]
4762    pub fn builder(
4763        symbol: String,
4764        side: OrderListPlaceSideEnum,
4765        price: rust_decimal::Decimal,
4766        quantity: rust_decimal::Decimal,
4767    ) -> OrderListPlaceParamsBuilder {
4768        OrderListPlaceParamsBuilder::default()
4769            .symbol(symbol)
4770            .side(side)
4771            .price(price)
4772            .quantity(quantity)
4773    }
4774}
4775/// Request parameters for the [`order_list_place_oco`] operation.
4776///
4777/// This struct holds all of the inputs you can pass when calling
4778/// [`order_list_place_oco`](#method.order_list_place_oco).
4779#[derive(Clone, Debug, Builder)]
4780#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4781pub struct OrderListPlaceOcoParams {
4782    ///
4783    /// The `symbol` parameter.
4784    ///
4785    /// This field is **required.
4786    #[builder(setter(into))]
4787    pub symbol: String,
4788    ///
4789    /// The `side` parameter.
4790    ///
4791    /// This field is **required.
4792    #[builder(setter(into))]
4793    pub side: OrderListPlaceOcoSideEnum,
4794    ///
4795    /// The `quantity` parameter.
4796    ///
4797    /// This field is **required.
4798    #[builder(setter(into))]
4799    pub quantity: rust_decimal::Decimal,
4800    ///
4801    /// The `above_type` parameter.
4802    ///
4803    /// This field is **required.
4804    #[builder(setter(into))]
4805    pub above_type: OrderListPlaceOcoAboveTypeEnum,
4806    ///
4807    /// The `below_type` parameter.
4808    ///
4809    /// This field is **required.
4810    #[builder(setter(into))]
4811    pub below_type: OrderListPlaceOcoBelowTypeEnum,
4812    /// Unique WebSocket request ID.
4813    ///
4814    /// This field is **optional.
4815    #[builder(setter(into), default)]
4816    pub id: Option<String>,
4817    ///
4818    /// The `list_client_order_id` parameter.
4819    ///
4820    /// This field is **optional.
4821    #[builder(setter(into), default)]
4822    pub list_client_order_id: Option<String>,
4823    /// Arbitrary unique ID among open orders for the above order. Automatically generated if not sent
4824    ///
4825    /// This field is **optional.
4826    #[builder(setter(into), default)]
4827    pub above_client_order_id: Option<String>,
4828    /// Note that this can only be used if `aboveTimeInForce` is `GTC`.
4829    ///
4830    /// This field is **optional.
4831    #[builder(setter(into), default)]
4832    pub above_iceberg_qty: Option<i64>,
4833    /// Can be used if `aboveType` is `STOP_LOSS_LIMIT` , `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
4834    ///
4835    /// This field is **optional.
4836    #[builder(setter(into), default)]
4837    pub above_price: Option<rust_decimal::Decimal>,
4838    /// Can be used if `aboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`. <br>Either `aboveStopPrice` or `aboveTrailingDelta` or both, must be specified.
4839    ///
4840    /// This field is **optional.
4841    #[builder(setter(into), default)]
4842    pub above_stop_price: Option<rust_decimal::Decimal>,
4843    /// See [Trailing Stop order FAQ](faqs/trailing-stop-faq.md).
4844    ///
4845    /// This field is **optional.
4846    #[builder(setter(into), default)]
4847    pub above_trailing_delta: Option<i64>,
4848    ///
4849    /// The `above_time_in_force` parameter.
4850    ///
4851    /// This field is **optional.
4852    #[builder(setter(into), default)]
4853    pub above_time_in_force: Option<OrderListPlaceOcoAboveTimeInForceEnum>,
4854    /// Arbitrary numeric value identifying the above order within an order strategy.
4855    ///
4856    /// This field is **optional.
4857    #[builder(setter(into), default)]
4858    pub above_strategy_id: Option<i64>,
4859    /// Arbitrary numeric value identifying the above order strategy. <br>Values smaller than 1000000 are reserved and cannot be used.
4860    ///
4861    /// This field is **optional.
4862    #[builder(setter(into), default)]
4863    pub above_strategy_type: Option<i32>,
4864    ///
4865    /// The `above_peg_price_type` parameter.
4866    ///
4867    /// This field is **optional.
4868    #[builder(setter(into), default)]
4869    pub above_peg_price_type: Option<OrderListPlaceOcoAbovePegPriceTypeEnum>,
4870    ///
4871    /// The `above_peg_offset_type` parameter.
4872    ///
4873    /// This field is **optional.
4874    #[builder(setter(into), default)]
4875    pub above_peg_offset_type: Option<OrderListPlaceOcoAbovePegOffsetTypeEnum>,
4876    ///
4877    /// The `above_peg_offset_value` parameter.
4878    ///
4879    /// This field is **optional.
4880    #[builder(setter(into), default)]
4881    pub above_peg_offset_value: Option<i32>,
4882    ///
4883    /// The `below_client_order_id` parameter.
4884    ///
4885    /// This field is **optional.
4886    #[builder(setter(into), default)]
4887    pub below_client_order_id: Option<String>,
4888    /// Note that this can only be used if `belowTimeInForce` is `GTC`.
4889    ///
4890    /// This field is **optional.
4891    #[builder(setter(into), default)]
4892    pub below_iceberg_qty: Option<i64>,
4893    /// Can be used if `belowType` is `STOP_LOSS_LIMIT` , `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
4894    ///
4895    /// This field is **optional.
4896    #[builder(setter(into), default)]
4897    pub below_price: Option<rust_decimal::Decimal>,
4898    /// Can be used if `belowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT` or `TAKE_PROFIT_LIMIT`. <br>Either `belowStopPrice` or `belowTrailingDelta` or both, must be specified.
4899    ///
4900    /// This field is **optional.
4901    #[builder(setter(into), default)]
4902    pub below_stop_price: Option<rust_decimal::Decimal>,
4903    /// See [Trailing Stop order FAQ](faqs/trailing-stop-faq.md).
4904    ///
4905    /// This field is **optional.
4906    #[builder(setter(into), default)]
4907    pub below_trailing_delta: Option<i64>,
4908    ///
4909    /// The `below_time_in_force` parameter.
4910    ///
4911    /// This field is **optional.
4912    #[builder(setter(into), default)]
4913    pub below_time_in_force: Option<OrderListPlaceOcoBelowTimeInForceEnum>,
4914    /// Arbitrary numeric value identifying the below order within an order strategy.
4915    ///
4916    /// This field is **optional.
4917    #[builder(setter(into), default)]
4918    pub below_strategy_id: Option<i64>,
4919    /// Arbitrary numeric value identifying the below order strategy. <br>Values smaller than 1000000 are reserved and cannot be used.
4920    ///
4921    /// This field is **optional.
4922    #[builder(setter(into), default)]
4923    pub below_strategy_type: Option<i32>,
4924    ///
4925    /// The `below_peg_price_type` parameter.
4926    ///
4927    /// This field is **optional.
4928    #[builder(setter(into), default)]
4929    pub below_peg_price_type: Option<OrderListPlaceOcoBelowPegPriceTypeEnum>,
4930    ///
4931    /// The `below_peg_offset_type` parameter.
4932    ///
4933    /// This field is **optional.
4934    #[builder(setter(into), default)]
4935    pub below_peg_offset_type: Option<OrderListPlaceOcoBelowPegOffsetTypeEnum>,
4936    ///
4937    /// The `below_peg_offset_value` parameter.
4938    ///
4939    /// This field is **optional.
4940    #[builder(setter(into), default)]
4941    pub below_peg_offset_value: Option<i32>,
4942    ///
4943    /// The `new_order_resp_type` parameter.
4944    ///
4945    /// This field is **optional.
4946    #[builder(setter(into), default)]
4947    pub new_order_resp_type: Option<OrderListPlaceOcoNewOrderRespTypeEnum>,
4948    ///
4949    /// The `self_trade_prevention_mode` parameter.
4950    ///
4951    /// This field is **optional.
4952    #[builder(setter(into), default)]
4953    pub self_trade_prevention_mode: Option<OrderListPlaceOcoSelfTradePreventionModeEnum>,
4954    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
4955    ///
4956    /// This field is **optional.
4957    #[builder(setter(into), default)]
4958    pub recv_window: Option<rust_decimal::Decimal>,
4959}
4960
4961impl OrderListPlaceOcoParams {
4962    /// Create a builder for [`order_list_place_oco`].
4963    ///
4964    /// Required parameters:
4965    ///
4966    /// * `symbol` — String
4967    /// * `side` — String
4968    /// * `quantity` — `rust_decimal::Decimal`
4969    /// * `above_type` — String
4970    /// * `below_type` — String
4971    ///
4972    #[must_use]
4973    pub fn builder(
4974        symbol: String,
4975        side: OrderListPlaceOcoSideEnum,
4976        quantity: rust_decimal::Decimal,
4977        above_type: OrderListPlaceOcoAboveTypeEnum,
4978        below_type: OrderListPlaceOcoBelowTypeEnum,
4979    ) -> OrderListPlaceOcoParamsBuilder {
4980        OrderListPlaceOcoParamsBuilder::default()
4981            .symbol(symbol)
4982            .side(side)
4983            .quantity(quantity)
4984            .above_type(above_type)
4985            .below_type(below_type)
4986    }
4987}
4988/// Request parameters for the [`order_list_place_opo`] operation.
4989///
4990/// This struct holds all of the inputs you can pass when calling
4991/// [`order_list_place_opo`](#method.order_list_place_opo).
4992#[derive(Clone, Debug, Builder)]
4993#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
4994pub struct OrderListPlaceOpoParams {
4995    ///
4996    /// The `symbol` parameter.
4997    ///
4998    /// This field is **required.
4999    #[builder(setter(into))]
5000    pub symbol: String,
5001    ///
5002    /// The `working_type` parameter.
5003    ///
5004    /// This field is **required.
5005    #[builder(setter(into))]
5006    pub working_type: OrderListPlaceOpoWorkingTypeEnum,
5007    ///
5008    /// The `working_side` parameter.
5009    ///
5010    /// This field is **required.
5011    #[builder(setter(into))]
5012    pub working_side: OrderListPlaceOpoWorkingSideEnum,
5013    ///
5014    /// The `working_price` parameter.
5015    ///
5016    /// This field is **required.
5017    #[builder(setter(into))]
5018    pub working_price: rust_decimal::Decimal,
5019    /// Sets the quantity for the working order.
5020    ///
5021    /// This field is **required.
5022    #[builder(setter(into))]
5023    pub working_quantity: rust_decimal::Decimal,
5024    ///
5025    /// The `pending_type` parameter.
5026    ///
5027    /// This field is **required.
5028    #[builder(setter(into))]
5029    pub pending_type: OrderListPlaceOpoPendingTypeEnum,
5030    ///
5031    /// The `pending_side` parameter.
5032    ///
5033    /// This field is **required.
5034    #[builder(setter(into))]
5035    pub pending_side: OrderListPlaceOpoPendingSideEnum,
5036    /// Unique WebSocket request ID.
5037    ///
5038    /// This field is **optional.
5039    #[builder(setter(into), default)]
5040    pub id: Option<String>,
5041    ///
5042    /// The `list_client_order_id` parameter.
5043    ///
5044    /// This field is **optional.
5045    #[builder(setter(into), default)]
5046    pub list_client_order_id: Option<String>,
5047    ///
5048    /// The `new_order_resp_type` parameter.
5049    ///
5050    /// This field is **optional.
5051    #[builder(setter(into), default)]
5052    pub new_order_resp_type: Option<OrderListPlaceOpoNewOrderRespTypeEnum>,
5053    ///
5054    /// The `self_trade_prevention_mode` parameter.
5055    ///
5056    /// This field is **optional.
5057    #[builder(setter(into), default)]
5058    pub self_trade_prevention_mode: Option<OrderListPlaceOpoSelfTradePreventionModeEnum>,
5059    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5060    ///
5061    /// This field is **optional.
5062    #[builder(setter(into), default)]
5063    pub working_client_order_id: Option<String>,
5064    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5065    ///
5066    /// This field is **optional.
5067    #[builder(setter(into), default)]
5068    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5069    ///
5070    /// The `working_time_in_force` parameter.
5071    ///
5072    /// This field is **optional.
5073    #[builder(setter(into), default)]
5074    pub working_time_in_force: Option<OrderListPlaceOpoWorkingTimeInForceEnum>,
5075    /// Arbitrary numeric value identifying the working order within an order strategy.
5076    ///
5077    /// This field is **optional.
5078    #[builder(setter(into), default)]
5079    pub working_strategy_id: Option<i64>,
5080    /// Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used.
5081    ///
5082    /// This field is **optional.
5083    #[builder(setter(into), default)]
5084    pub working_strategy_type: Option<i32>,
5085    ///
5086    /// The `working_peg_price_type` parameter.
5087    ///
5088    /// This field is **optional.
5089    #[builder(setter(into), default)]
5090    pub working_peg_price_type: Option<OrderListPlaceOpoWorkingPegPriceTypeEnum>,
5091    ///
5092    /// The `working_peg_offset_type` parameter.
5093    ///
5094    /// This field is **optional.
5095    #[builder(setter(into), default)]
5096    pub working_peg_offset_type: Option<OrderListPlaceOpoWorkingPegOffsetTypeEnum>,
5097    ///
5098    /// The `working_peg_offset_value` parameter.
5099    ///
5100    /// This field is **optional.
5101    #[builder(setter(into), default)]
5102    pub working_peg_offset_value: Option<i32>,
5103    /// Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent.
5104    ///
5105    /// This field is **optional.
5106    #[builder(setter(into), default)]
5107    pub pending_client_order_id: Option<String>,
5108    ///
5109    /// The `pending_price` parameter.
5110    ///
5111    /// This field is **optional.
5112    #[builder(setter(into), default)]
5113    pub pending_price: Option<rust_decimal::Decimal>,
5114    ///
5115    /// The `pending_stop_price` parameter.
5116    ///
5117    /// This field is **optional.
5118    #[builder(setter(into), default)]
5119    pub pending_stop_price: Option<rust_decimal::Decimal>,
5120    ///
5121    /// The `pending_trailing_delta` parameter.
5122    ///
5123    /// This field is **optional.
5124    #[builder(setter(into), default)]
5125    pub pending_trailing_delta: Option<rust_decimal::Decimal>,
5126    /// This can only be used if `pendingTimeInForce` is `GTC` or if `pendingType` is `LIMIT_MAKER`.
5127    ///
5128    /// This field is **optional.
5129    #[builder(setter(into), default)]
5130    pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
5131    ///
5132    /// The `pending_time_in_force` parameter.
5133    ///
5134    /// This field is **optional.
5135    #[builder(setter(into), default)]
5136    pub pending_time_in_force: Option<OrderListPlaceOpoPendingTimeInForceEnum>,
5137    /// Arbitrary numeric value identifying the pending order within an order strategy.
5138    ///
5139    /// This field is **optional.
5140    #[builder(setter(into), default)]
5141    pub pending_strategy_id: Option<i64>,
5142    /// Arbitrary numeric value identifying the pending order strategy. Values smaller than 1000000 are reserved and cannot be used.
5143    ///
5144    /// This field is **optional.
5145    #[builder(setter(into), default)]
5146    pub pending_strategy_type: Option<i32>,
5147    ///
5148    /// The `pending_peg_price_type` parameter.
5149    ///
5150    /// This field is **optional.
5151    #[builder(setter(into), default)]
5152    pub pending_peg_price_type: Option<OrderListPlaceOpoPendingPegPriceTypeEnum>,
5153    ///
5154    /// The `pending_peg_offset_type` parameter.
5155    ///
5156    /// This field is **optional.
5157    #[builder(setter(into), default)]
5158    pub pending_peg_offset_type: Option<OrderListPlaceOpoPendingPegOffsetTypeEnum>,
5159    ///
5160    /// The `pending_peg_offset_value` parameter.
5161    ///
5162    /// This field is **optional.
5163    #[builder(setter(into), default)]
5164    pub pending_peg_offset_value: Option<i32>,
5165    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5166    ///
5167    /// This field is **optional.
5168    #[builder(setter(into), default)]
5169    pub recv_window: Option<rust_decimal::Decimal>,
5170}
5171
5172impl OrderListPlaceOpoParams {
5173    /// Create a builder for [`order_list_place_opo`].
5174    ///
5175    /// Required parameters:
5176    ///
5177    /// * `symbol` — String
5178    /// * `working_type` — String
5179    /// * `working_side` — String
5180    /// * `working_price` — `rust_decimal::Decimal`
5181    /// * `working_quantity` — Sets the quantity for the working order.
5182    /// * `pending_type` — String
5183    /// * `pending_side` — String
5184    ///
5185    #[must_use]
5186    pub fn builder(
5187        symbol: String,
5188        working_type: OrderListPlaceOpoWorkingTypeEnum,
5189        working_side: OrderListPlaceOpoWorkingSideEnum,
5190        working_price: rust_decimal::Decimal,
5191        working_quantity: rust_decimal::Decimal,
5192        pending_type: OrderListPlaceOpoPendingTypeEnum,
5193        pending_side: OrderListPlaceOpoPendingSideEnum,
5194    ) -> OrderListPlaceOpoParamsBuilder {
5195        OrderListPlaceOpoParamsBuilder::default()
5196            .symbol(symbol)
5197            .working_type(working_type)
5198            .working_side(working_side)
5199            .working_price(working_price)
5200            .working_quantity(working_quantity)
5201            .pending_type(pending_type)
5202            .pending_side(pending_side)
5203    }
5204}
5205/// Request parameters for the [`order_list_place_opoco`] operation.
5206///
5207/// This struct holds all of the inputs you can pass when calling
5208/// [`order_list_place_opoco`](#method.order_list_place_opoco).
5209#[derive(Clone, Debug, Builder)]
5210#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5211pub struct OrderListPlaceOpocoParams {
5212    ///
5213    /// The `symbol` parameter.
5214    ///
5215    /// This field is **required.
5216    #[builder(setter(into))]
5217    pub symbol: String,
5218    ///
5219    /// The `working_type` parameter.
5220    ///
5221    /// This field is **required.
5222    #[builder(setter(into))]
5223    pub working_type: OrderListPlaceOpocoWorkingTypeEnum,
5224    ///
5225    /// The `working_side` parameter.
5226    ///
5227    /// This field is **required.
5228    #[builder(setter(into))]
5229    pub working_side: OrderListPlaceOpocoWorkingSideEnum,
5230    ///
5231    /// The `working_price` parameter.
5232    ///
5233    /// This field is **required.
5234    #[builder(setter(into))]
5235    pub working_price: rust_decimal::Decimal,
5236    /// Sets the quantity for the working order.
5237    ///
5238    /// This field is **required.
5239    #[builder(setter(into))]
5240    pub working_quantity: rust_decimal::Decimal,
5241    ///
5242    /// The `pending_side` parameter.
5243    ///
5244    /// This field is **required.
5245    #[builder(setter(into))]
5246    pub pending_side: OrderListPlaceOpocoPendingSideEnum,
5247    ///
5248    /// The `pending_above_type` parameter.
5249    ///
5250    /// This field is **required.
5251    #[builder(setter(into))]
5252    pub pending_above_type: OrderListPlaceOpocoPendingAboveTypeEnum,
5253    /// Unique WebSocket request ID.
5254    ///
5255    /// This field is **optional.
5256    #[builder(setter(into), default)]
5257    pub id: Option<String>,
5258    ///
5259    /// The `list_client_order_id` parameter.
5260    ///
5261    /// This field is **optional.
5262    #[builder(setter(into), default)]
5263    pub list_client_order_id: Option<String>,
5264    ///
5265    /// The `new_order_resp_type` parameter.
5266    ///
5267    /// This field is **optional.
5268    #[builder(setter(into), default)]
5269    pub new_order_resp_type: Option<OrderListPlaceOpocoNewOrderRespTypeEnum>,
5270    ///
5271    /// The `self_trade_prevention_mode` parameter.
5272    ///
5273    /// This field is **optional.
5274    #[builder(setter(into), default)]
5275    pub self_trade_prevention_mode: Option<OrderListPlaceOpocoSelfTradePreventionModeEnum>,
5276    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5277    ///
5278    /// This field is **optional.
5279    #[builder(setter(into), default)]
5280    pub working_client_order_id: Option<String>,
5281    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5282    ///
5283    /// This field is **optional.
5284    #[builder(setter(into), default)]
5285    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5286    ///
5287    /// The `working_time_in_force` parameter.
5288    ///
5289    /// This field is **optional.
5290    #[builder(setter(into), default)]
5291    pub working_time_in_force: Option<OrderListPlaceOpocoWorkingTimeInForceEnum>,
5292    /// Arbitrary numeric value identifying the working order within an order strategy.
5293    ///
5294    /// This field is **optional.
5295    #[builder(setter(into), default)]
5296    pub working_strategy_id: Option<i64>,
5297    /// Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used.
5298    ///
5299    /// This field is **optional.
5300    #[builder(setter(into), default)]
5301    pub working_strategy_type: Option<i32>,
5302    ///
5303    /// The `working_peg_price_type` parameter.
5304    ///
5305    /// This field is **optional.
5306    #[builder(setter(into), default)]
5307    pub working_peg_price_type: Option<OrderListPlaceOpocoWorkingPegPriceTypeEnum>,
5308    ///
5309    /// The `working_peg_offset_type` parameter.
5310    ///
5311    /// This field is **optional.
5312    #[builder(setter(into), default)]
5313    pub working_peg_offset_type: Option<OrderListPlaceOpocoWorkingPegOffsetTypeEnum>,
5314    ///
5315    /// The `working_peg_offset_value` parameter.
5316    ///
5317    /// This field is **optional.
5318    #[builder(setter(into), default)]
5319    pub working_peg_offset_value: Option<i32>,
5320    /// Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent.
5321    ///
5322    /// This field is **optional.
5323    #[builder(setter(into), default)]
5324    pub pending_above_client_order_id: Option<String>,
5325    /// Can be used if `pendingAboveType` is `STOP_LOSS_LIMIT` , `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
5326    ///
5327    /// This field is **optional.
5328    #[builder(setter(into), default)]
5329    pub pending_above_price: Option<rust_decimal::Decimal>,
5330    /// Can be used if `pendingAboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5331    ///
5332    /// This field is **optional.
5333    #[builder(setter(into), default)]
5334    pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5335    /// See [Trailing Stop FAQ](./faqs/trailing-stop-faq.md)
5336    ///
5337    /// This field is **optional.
5338    #[builder(setter(into), default)]
5339    pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5340    /// This can only be used if `pendingAboveTimeInForce` is `GTC` or if `pendingAboveType` is `LIMIT_MAKER`.
5341    ///
5342    /// This field is **optional.
5343    #[builder(setter(into), default)]
5344    pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5345    ///
5346    /// The `pending_above_time_in_force` parameter.
5347    ///
5348    /// This field is **optional.
5349    #[builder(setter(into), default)]
5350    pub pending_above_time_in_force: Option<OrderListPlaceOpocoPendingAboveTimeInForceEnum>,
5351    /// Arbitrary numeric value identifying the pending above order within an order strategy.
5352    ///
5353    /// This field is **optional.
5354    #[builder(setter(into), default)]
5355    pub pending_above_strategy_id: Option<i64>,
5356    /// Arbitrary numeric value identifying the pending above order strategy. Values smaller than 1000000 are reserved and cannot be used.
5357    ///
5358    /// This field is **optional.
5359    #[builder(setter(into), default)]
5360    pub pending_above_strategy_type: Option<i32>,
5361    ///
5362    /// The `pending_above_peg_price_type` parameter.
5363    ///
5364    /// This field is **optional.
5365    #[builder(setter(into), default)]
5366    pub pending_above_peg_price_type: Option<OrderListPlaceOpocoPendingAbovePegPriceTypeEnum>,
5367    ///
5368    /// The `pending_above_peg_offset_type` parameter.
5369    ///
5370    /// This field is **optional.
5371    #[builder(setter(into), default)]
5372    pub pending_above_peg_offset_type: Option<OrderListPlaceOpocoPendingAbovePegOffsetTypeEnum>,
5373    ///
5374    /// The `pending_above_peg_offset_value` parameter.
5375    ///
5376    /// This field is **optional.
5377    #[builder(setter(into), default)]
5378    pub pending_above_peg_offset_value: Option<i32>,
5379    ///
5380    /// The `pending_below_type` parameter.
5381    ///
5382    /// This field is **optional.
5383    #[builder(setter(into), default)]
5384    pub pending_below_type: Option<OrderListPlaceOpocoPendingBelowTypeEnum>,
5385    /// Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent.
5386    ///
5387    /// This field is **optional.
5388    #[builder(setter(into), default)]
5389    pub pending_below_client_order_id: Option<String>,
5390    /// Can be used if `pendingBelowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT` to specify limit price
5391    ///
5392    /// This field is **optional.
5393    #[builder(setter(into), default)]
5394    pub pending_below_price: Option<rust_decimal::Decimal>,
5395    /// Can be used if `pendingBelowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT, TAKE_PROFIT or TAKE_PROFIT_LIMIT`. Either `pendingBelowStopPrice` or `pendingBelowTrailingDelta` or both, must be specified.
5396    ///
5397    /// This field is **optional.
5398    #[builder(setter(into), default)]
5399    pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5400    ///
5401    /// The `pending_below_trailing_delta` parameter.
5402    ///
5403    /// This field is **optional.
5404    #[builder(setter(into), default)]
5405    pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5406    /// This can only be used if `pendingBelowTimeInForce` is `GTC`, or if `pendingBelowType` is `LIMIT_MAKER`.
5407    ///
5408    /// This field is **optional.
5409    #[builder(setter(into), default)]
5410    pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5411    ///
5412    /// The `pending_below_time_in_force` parameter.
5413    ///
5414    /// This field is **optional.
5415    #[builder(setter(into), default)]
5416    pub pending_below_time_in_force: Option<OrderListPlaceOpocoPendingBelowTimeInForceEnum>,
5417    /// Arbitrary numeric value identifying the pending below order within an order strategy.
5418    ///
5419    /// This field is **optional.
5420    #[builder(setter(into), default)]
5421    pub pending_below_strategy_id: Option<i64>,
5422    /// Arbitrary numeric value identifying the pending below order strategy. Values smaller than 1000000 are reserved and cannot be used.
5423    ///
5424    /// This field is **optional.
5425    #[builder(setter(into), default)]
5426    pub pending_below_strategy_type: Option<i32>,
5427    ///
5428    /// The `pending_below_peg_price_type` parameter.
5429    ///
5430    /// This field is **optional.
5431    #[builder(setter(into), default)]
5432    pub pending_below_peg_price_type: Option<OrderListPlaceOpocoPendingBelowPegPriceTypeEnum>,
5433    ///
5434    /// The `pending_below_peg_offset_type` parameter.
5435    ///
5436    /// This field is **optional.
5437    #[builder(setter(into), default)]
5438    pub pending_below_peg_offset_type: Option<OrderListPlaceOpocoPendingBelowPegOffsetTypeEnum>,
5439    ///
5440    /// The `pending_below_peg_offset_value` parameter.
5441    ///
5442    /// This field is **optional.
5443    #[builder(setter(into), default)]
5444    pub pending_below_peg_offset_value: Option<i32>,
5445    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5446    ///
5447    /// This field is **optional.
5448    #[builder(setter(into), default)]
5449    pub recv_window: Option<rust_decimal::Decimal>,
5450}
5451
5452impl OrderListPlaceOpocoParams {
5453    /// Create a builder for [`order_list_place_opoco`].
5454    ///
5455    /// Required parameters:
5456    ///
5457    /// * `symbol` — String
5458    /// * `working_type` — String
5459    /// * `working_side` — String
5460    /// * `working_price` — `rust_decimal::Decimal`
5461    /// * `working_quantity` — Sets the quantity for the working order.
5462    /// * `pending_side` — String
5463    /// * `pending_above_type` — String
5464    ///
5465    #[must_use]
5466    pub fn builder(
5467        symbol: String,
5468        working_type: OrderListPlaceOpocoWorkingTypeEnum,
5469        working_side: OrderListPlaceOpocoWorkingSideEnum,
5470        working_price: rust_decimal::Decimal,
5471        working_quantity: rust_decimal::Decimal,
5472        pending_side: OrderListPlaceOpocoPendingSideEnum,
5473        pending_above_type: OrderListPlaceOpocoPendingAboveTypeEnum,
5474    ) -> OrderListPlaceOpocoParamsBuilder {
5475        OrderListPlaceOpocoParamsBuilder::default()
5476            .symbol(symbol)
5477            .working_type(working_type)
5478            .working_side(working_side)
5479            .working_price(working_price)
5480            .working_quantity(working_quantity)
5481            .pending_side(pending_side)
5482            .pending_above_type(pending_above_type)
5483    }
5484}
5485/// Request parameters for the [`order_list_place_oto`] operation.
5486///
5487/// This struct holds all of the inputs you can pass when calling
5488/// [`order_list_place_oto`](#method.order_list_place_oto).
5489#[derive(Clone, Debug, Builder)]
5490#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5491pub struct OrderListPlaceOtoParams {
5492    ///
5493    /// The `symbol` parameter.
5494    ///
5495    /// This field is **required.
5496    #[builder(setter(into))]
5497    pub symbol: String,
5498    ///
5499    /// The `working_type` parameter.
5500    ///
5501    /// This field is **required.
5502    #[builder(setter(into))]
5503    pub working_type: OrderListPlaceOtoWorkingTypeEnum,
5504    ///
5505    /// The `working_side` parameter.
5506    ///
5507    /// This field is **required.
5508    #[builder(setter(into))]
5509    pub working_side: OrderListPlaceOtoWorkingSideEnum,
5510    ///
5511    /// The `working_price` parameter.
5512    ///
5513    /// This field is **required.
5514    #[builder(setter(into))]
5515    pub working_price: rust_decimal::Decimal,
5516    /// Sets the quantity for the working order.
5517    ///
5518    /// This field is **required.
5519    #[builder(setter(into))]
5520    pub working_quantity: rust_decimal::Decimal,
5521    ///
5522    /// The `pending_type` parameter.
5523    ///
5524    /// This field is **required.
5525    #[builder(setter(into))]
5526    pub pending_type: OrderListPlaceOtoPendingTypeEnum,
5527    ///
5528    /// The `pending_side` parameter.
5529    ///
5530    /// This field is **required.
5531    #[builder(setter(into))]
5532    pub pending_side: OrderListPlaceOtoPendingSideEnum,
5533    /// Sets the quantity for the pending order.
5534    ///
5535    /// This field is **required.
5536    #[builder(setter(into))]
5537    pub pending_quantity: rust_decimal::Decimal,
5538    /// Unique WebSocket request ID.
5539    ///
5540    /// This field is **optional.
5541    #[builder(setter(into), default)]
5542    pub id: Option<String>,
5543    ///
5544    /// The `list_client_order_id` parameter.
5545    ///
5546    /// This field is **optional.
5547    #[builder(setter(into), default)]
5548    pub list_client_order_id: Option<String>,
5549    ///
5550    /// The `new_order_resp_type` parameter.
5551    ///
5552    /// This field is **optional.
5553    #[builder(setter(into), default)]
5554    pub new_order_resp_type: Option<OrderListPlaceOtoNewOrderRespTypeEnum>,
5555    ///
5556    /// The `self_trade_prevention_mode` parameter.
5557    ///
5558    /// This field is **optional.
5559    #[builder(setter(into), default)]
5560    pub self_trade_prevention_mode: Option<OrderListPlaceOtoSelfTradePreventionModeEnum>,
5561    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5562    ///
5563    /// This field is **optional.
5564    #[builder(setter(into), default)]
5565    pub working_client_order_id: Option<String>,
5566    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5567    ///
5568    /// This field is **optional.
5569    #[builder(setter(into), default)]
5570    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5571    ///
5572    /// The `working_time_in_force` parameter.
5573    ///
5574    /// This field is **optional.
5575    #[builder(setter(into), default)]
5576    pub working_time_in_force: Option<OrderListPlaceOtoWorkingTimeInForceEnum>,
5577    /// Arbitrary numeric value identifying the working order within an order strategy.
5578    ///
5579    /// This field is **optional.
5580    #[builder(setter(into), default)]
5581    pub working_strategy_id: Option<i64>,
5582    /// Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used.
5583    ///
5584    /// This field is **optional.
5585    #[builder(setter(into), default)]
5586    pub working_strategy_type: Option<i32>,
5587    ///
5588    /// The `working_peg_price_type` parameter.
5589    ///
5590    /// This field is **optional.
5591    #[builder(setter(into), default)]
5592    pub working_peg_price_type: Option<OrderListPlaceOtoWorkingPegPriceTypeEnum>,
5593    ///
5594    /// The `working_peg_offset_type` parameter.
5595    ///
5596    /// This field is **optional.
5597    #[builder(setter(into), default)]
5598    pub working_peg_offset_type: Option<OrderListPlaceOtoWorkingPegOffsetTypeEnum>,
5599    ///
5600    /// The `working_peg_offset_value` parameter.
5601    ///
5602    /// This field is **optional.
5603    #[builder(setter(into), default)]
5604    pub working_peg_offset_value: Option<i32>,
5605    /// Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent.
5606    ///
5607    /// This field is **optional.
5608    #[builder(setter(into), default)]
5609    pub pending_client_order_id: Option<String>,
5610    ///
5611    /// The `pending_price` parameter.
5612    ///
5613    /// This field is **optional.
5614    #[builder(setter(into), default)]
5615    pub pending_price: Option<rust_decimal::Decimal>,
5616    ///
5617    /// The `pending_stop_price` parameter.
5618    ///
5619    /// This field is **optional.
5620    #[builder(setter(into), default)]
5621    pub pending_stop_price: Option<rust_decimal::Decimal>,
5622    ///
5623    /// The `pending_trailing_delta` parameter.
5624    ///
5625    /// This field is **optional.
5626    #[builder(setter(into), default)]
5627    pub pending_trailing_delta: Option<rust_decimal::Decimal>,
5628    /// This can only be used if `pendingTimeInForce` is `GTC` or if `pendingType` is `LIMIT_MAKER`.
5629    ///
5630    /// This field is **optional.
5631    #[builder(setter(into), default)]
5632    pub pending_iceberg_qty: Option<rust_decimal::Decimal>,
5633    ///
5634    /// The `pending_time_in_force` parameter.
5635    ///
5636    /// This field is **optional.
5637    #[builder(setter(into), default)]
5638    pub pending_time_in_force: Option<OrderListPlaceOtoPendingTimeInForceEnum>,
5639    /// Arbitrary numeric value identifying the pending order within an order strategy.
5640    ///
5641    /// This field is **optional.
5642    #[builder(setter(into), default)]
5643    pub pending_strategy_id: Option<i64>,
5644    /// Arbitrary numeric value identifying the pending order strategy. Values smaller than 1000000 are reserved and cannot be used.
5645    ///
5646    /// This field is **optional.
5647    #[builder(setter(into), default)]
5648    pub pending_strategy_type: Option<i32>,
5649    ///
5650    /// The `pending_peg_offset_type` parameter.
5651    ///
5652    /// This field is **optional.
5653    #[builder(setter(into), default)]
5654    pub pending_peg_offset_type: Option<OrderListPlaceOtoPendingPegOffsetTypeEnum>,
5655    ///
5656    /// The `pending_peg_price_type` parameter.
5657    ///
5658    /// This field is **optional.
5659    #[builder(setter(into), default)]
5660    pub pending_peg_price_type: Option<OrderListPlaceOtoPendingPegPriceTypeEnum>,
5661    ///
5662    /// The `pending_peg_offset_value` parameter.
5663    ///
5664    /// This field is **optional.
5665    #[builder(setter(into), default)]
5666    pub pending_peg_offset_value: Option<i32>,
5667    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5668    ///
5669    /// This field is **optional.
5670    #[builder(setter(into), default)]
5671    pub recv_window: Option<rust_decimal::Decimal>,
5672}
5673
5674impl OrderListPlaceOtoParams {
5675    /// Create a builder for [`order_list_place_oto`].
5676    ///
5677    /// Required parameters:
5678    ///
5679    /// * `symbol` — String
5680    /// * `working_type` — String
5681    /// * `working_side` — String
5682    /// * `working_price` — `rust_decimal::Decimal`
5683    /// * `working_quantity` — Sets the quantity for the working order.
5684    /// * `pending_type` — String
5685    /// * `pending_side` — String
5686    /// * `pending_quantity` — Sets the quantity for the pending order.
5687    ///
5688    #[must_use]
5689    pub fn builder(
5690        symbol: String,
5691        working_type: OrderListPlaceOtoWorkingTypeEnum,
5692        working_side: OrderListPlaceOtoWorkingSideEnum,
5693        working_price: rust_decimal::Decimal,
5694        working_quantity: rust_decimal::Decimal,
5695        pending_type: OrderListPlaceOtoPendingTypeEnum,
5696        pending_side: OrderListPlaceOtoPendingSideEnum,
5697        pending_quantity: rust_decimal::Decimal,
5698    ) -> OrderListPlaceOtoParamsBuilder {
5699        OrderListPlaceOtoParamsBuilder::default()
5700            .symbol(symbol)
5701            .working_type(working_type)
5702            .working_side(working_side)
5703            .working_price(working_price)
5704            .working_quantity(working_quantity)
5705            .pending_type(pending_type)
5706            .pending_side(pending_side)
5707            .pending_quantity(pending_quantity)
5708    }
5709}
5710/// Request parameters for the [`order_list_place_otoco`] operation.
5711///
5712/// This struct holds all of the inputs you can pass when calling
5713/// [`order_list_place_otoco`](#method.order_list_place_otoco).
5714#[derive(Clone, Debug, Builder)]
5715#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
5716pub struct OrderListPlaceOtocoParams {
5717    ///
5718    /// The `symbol` parameter.
5719    ///
5720    /// This field is **required.
5721    #[builder(setter(into))]
5722    pub symbol: String,
5723    ///
5724    /// The `working_type` parameter.
5725    ///
5726    /// This field is **required.
5727    #[builder(setter(into))]
5728    pub working_type: OrderListPlaceOtocoWorkingTypeEnum,
5729    ///
5730    /// The `working_side` parameter.
5731    ///
5732    /// This field is **required.
5733    #[builder(setter(into))]
5734    pub working_side: OrderListPlaceOtocoWorkingSideEnum,
5735    ///
5736    /// The `working_price` parameter.
5737    ///
5738    /// This field is **required.
5739    #[builder(setter(into))]
5740    pub working_price: rust_decimal::Decimal,
5741    /// Sets the quantity for the working order.
5742    ///
5743    /// This field is **required.
5744    #[builder(setter(into))]
5745    pub working_quantity: rust_decimal::Decimal,
5746    ///
5747    /// The `pending_side` parameter.
5748    ///
5749    /// This field is **required.
5750    #[builder(setter(into))]
5751    pub pending_side: OrderListPlaceOtocoPendingSideEnum,
5752    /// Sets the quantity for the pending order.
5753    ///
5754    /// This field is **required.
5755    #[builder(setter(into))]
5756    pub pending_quantity: rust_decimal::Decimal,
5757    ///
5758    /// The `pending_above_type` parameter.
5759    ///
5760    /// This field is **required.
5761    #[builder(setter(into))]
5762    pub pending_above_type: OrderListPlaceOtocoPendingAboveTypeEnum,
5763    /// Unique WebSocket request ID.
5764    ///
5765    /// This field is **optional.
5766    #[builder(setter(into), default)]
5767    pub id: Option<String>,
5768    ///
5769    /// The `list_client_order_id` parameter.
5770    ///
5771    /// This field is **optional.
5772    #[builder(setter(into), default)]
5773    pub list_client_order_id: Option<String>,
5774    ///
5775    /// The `new_order_resp_type` parameter.
5776    ///
5777    /// This field is **optional.
5778    #[builder(setter(into), default)]
5779    pub new_order_resp_type: Option<OrderListPlaceOtocoNewOrderRespTypeEnum>,
5780    ///
5781    /// The `self_trade_prevention_mode` parameter.
5782    ///
5783    /// This field is **optional.
5784    #[builder(setter(into), default)]
5785    pub self_trade_prevention_mode: Option<OrderListPlaceOtocoSelfTradePreventionModeEnum>,
5786    /// Arbitrary unique ID among open orders for the working order. Automatically generated if not sent.
5787    ///
5788    /// This field is **optional.
5789    #[builder(setter(into), default)]
5790    pub working_client_order_id: Option<String>,
5791    /// This can only be used if `workingTimeInForce` is `GTC`, or if `workingType` is `LIMIT_MAKER`.
5792    ///
5793    /// This field is **optional.
5794    #[builder(setter(into), default)]
5795    pub working_iceberg_qty: Option<rust_decimal::Decimal>,
5796    ///
5797    /// The `working_time_in_force` parameter.
5798    ///
5799    /// This field is **optional.
5800    #[builder(setter(into), default)]
5801    pub working_time_in_force: Option<OrderListPlaceOtocoWorkingTimeInForceEnum>,
5802    /// Arbitrary numeric value identifying the working order within an order strategy.
5803    ///
5804    /// This field is **optional.
5805    #[builder(setter(into), default)]
5806    pub working_strategy_id: Option<i64>,
5807    /// Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used.
5808    ///
5809    /// This field is **optional.
5810    #[builder(setter(into), default)]
5811    pub working_strategy_type: Option<i32>,
5812    ///
5813    /// The `working_peg_price_type` parameter.
5814    ///
5815    /// This field is **optional.
5816    #[builder(setter(into), default)]
5817    pub working_peg_price_type: Option<OrderListPlaceOtocoWorkingPegPriceTypeEnum>,
5818    ///
5819    /// The `working_peg_offset_type` parameter.
5820    ///
5821    /// This field is **optional.
5822    #[builder(setter(into), default)]
5823    pub working_peg_offset_type: Option<OrderListPlaceOtocoWorkingPegOffsetTypeEnum>,
5824    ///
5825    /// The `working_peg_offset_value` parameter.
5826    ///
5827    /// This field is **optional.
5828    #[builder(setter(into), default)]
5829    pub working_peg_offset_value: Option<i32>,
5830    /// Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent.
5831    ///
5832    /// This field is **optional.
5833    #[builder(setter(into), default)]
5834    pub pending_above_client_order_id: Option<String>,
5835    /// Can be used if `pendingAboveType` is `STOP_LOSS_LIMIT` , `LIMIT_MAKER`, or `TAKE_PROFIT_LIMIT` to specify the limit price.
5836    ///
5837    /// This field is **optional.
5838    #[builder(setter(into), default)]
5839    pub pending_above_price: Option<rust_decimal::Decimal>,
5840    /// Can be used if `pendingAboveType` is `STOP_LOSS`, `STOP_LOSS_LIMIT`, `TAKE_PROFIT`, `TAKE_PROFIT_LIMIT`
5841    ///
5842    /// This field is **optional.
5843    #[builder(setter(into), default)]
5844    pub pending_above_stop_price: Option<rust_decimal::Decimal>,
5845    /// See [Trailing Stop FAQ](./faqs/trailing-stop-faq.md)
5846    ///
5847    /// This field is **optional.
5848    #[builder(setter(into), default)]
5849    pub pending_above_trailing_delta: Option<rust_decimal::Decimal>,
5850    /// This can only be used if `pendingAboveTimeInForce` is `GTC` or if `pendingAboveType` is `LIMIT_MAKER`.
5851    ///
5852    /// This field is **optional.
5853    #[builder(setter(into), default)]
5854    pub pending_above_iceberg_qty: Option<rust_decimal::Decimal>,
5855    ///
5856    /// The `pending_above_time_in_force` parameter.
5857    ///
5858    /// This field is **optional.
5859    #[builder(setter(into), default)]
5860    pub pending_above_time_in_force: Option<OrderListPlaceOtocoPendingAboveTimeInForceEnum>,
5861    /// Arbitrary numeric value identifying the pending above order within an order strategy.
5862    ///
5863    /// This field is **optional.
5864    #[builder(setter(into), default)]
5865    pub pending_above_strategy_id: Option<i64>,
5866    /// Arbitrary numeric value identifying the pending above order strategy. Values smaller than 1000000 are reserved and cannot be used.
5867    ///
5868    /// This field is **optional.
5869    #[builder(setter(into), default)]
5870    pub pending_above_strategy_type: Option<i32>,
5871    ///
5872    /// The `pending_above_peg_price_type` parameter.
5873    ///
5874    /// This field is **optional.
5875    #[builder(setter(into), default)]
5876    pub pending_above_peg_price_type: Option<OrderListPlaceOtocoPendingAbovePegPriceTypeEnum>,
5877    ///
5878    /// The `pending_above_peg_offset_type` parameter.
5879    ///
5880    /// This field is **optional.
5881    #[builder(setter(into), default)]
5882    pub pending_above_peg_offset_type: Option<OrderListPlaceOtocoPendingAbovePegOffsetTypeEnum>,
5883    ///
5884    /// The `pending_above_peg_offset_value` parameter.
5885    ///
5886    /// This field is **optional.
5887    #[builder(setter(into), default)]
5888    pub pending_above_peg_offset_value: Option<i32>,
5889    ///
5890    /// The `pending_below_type` parameter.
5891    ///
5892    /// This field is **optional.
5893    #[builder(setter(into), default)]
5894    pub pending_below_type: Option<OrderListPlaceOtocoPendingBelowTypeEnum>,
5895    /// Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent.
5896    ///
5897    /// This field is **optional.
5898    #[builder(setter(into), default)]
5899    pub pending_below_client_order_id: Option<String>,
5900    /// Can be used if `pendingBelowType` is `STOP_LOSS_LIMIT` or `TAKE_PROFIT_LIMIT` to specify limit price
5901    ///
5902    /// This field is **optional.
5903    #[builder(setter(into), default)]
5904    pub pending_below_price: Option<rust_decimal::Decimal>,
5905    /// Can be used if `pendingBelowType` is `STOP_LOSS`, `STOP_LOSS_LIMIT, TAKE_PROFIT or TAKE_PROFIT_LIMIT`. Either `pendingBelowStopPrice` or `pendingBelowTrailingDelta` or both, must be specified.
5906    ///
5907    /// This field is **optional.
5908    #[builder(setter(into), default)]
5909    pub pending_below_stop_price: Option<rust_decimal::Decimal>,
5910    ///
5911    /// The `pending_below_trailing_delta` parameter.
5912    ///
5913    /// This field is **optional.
5914    #[builder(setter(into), default)]
5915    pub pending_below_trailing_delta: Option<rust_decimal::Decimal>,
5916    /// This can only be used if `pendingBelowTimeInForce` is `GTC`, or if `pendingBelowType` is `LIMIT_MAKER`.
5917    ///
5918    /// This field is **optional.
5919    #[builder(setter(into), default)]
5920    pub pending_below_iceberg_qty: Option<rust_decimal::Decimal>,
5921    ///
5922    /// The `pending_below_time_in_force` parameter.
5923    ///
5924    /// This field is **optional.
5925    #[builder(setter(into), default)]
5926    pub pending_below_time_in_force: Option<OrderListPlaceOtocoPendingBelowTimeInForceEnum>,
5927    /// Arbitrary numeric value identifying the pending below order within an order strategy.
5928    ///
5929    /// This field is **optional.
5930    #[builder(setter(into), default)]
5931    pub pending_below_strategy_id: Option<i64>,
5932    /// Arbitrary numeric value identifying the pending below order strategy. Values smaller than 1000000 are reserved and cannot be used.
5933    ///
5934    /// This field is **optional.
5935    #[builder(setter(into), default)]
5936    pub pending_below_strategy_type: Option<i32>,
5937    ///
5938    /// The `pending_below_peg_price_type` parameter.
5939    ///
5940    /// This field is **optional.
5941    #[builder(setter(into), default)]
5942    pub pending_below_peg_price_type: Option<OrderListPlaceOtocoPendingBelowPegPriceTypeEnum>,
5943    ///
5944    /// The `pending_below_peg_offset_type` parameter.
5945    ///
5946    /// This field is **optional.
5947    #[builder(setter(into), default)]
5948    pub pending_below_peg_offset_type: Option<OrderListPlaceOtocoPendingBelowPegOffsetTypeEnum>,
5949    ///
5950    /// The `pending_below_peg_offset_value` parameter.
5951    ///
5952    /// This field is **optional.
5953    #[builder(setter(into), default)]
5954    pub pending_below_peg_offset_value: Option<i32>,
5955    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
5956    ///
5957    /// This field is **optional.
5958    #[builder(setter(into), default)]
5959    pub recv_window: Option<rust_decimal::Decimal>,
5960}
5961
5962impl OrderListPlaceOtocoParams {
5963    /// Create a builder for [`order_list_place_otoco`].
5964    ///
5965    /// Required parameters:
5966    ///
5967    /// * `symbol` — String
5968    /// * `working_type` — String
5969    /// * `working_side` — String
5970    /// * `working_price` — `rust_decimal::Decimal`
5971    /// * `working_quantity` — Sets the quantity for the working order.
5972    /// * `pending_side` — String
5973    /// * `pending_quantity` — Sets the quantity for the pending order.
5974    /// * `pending_above_type` — String
5975    ///
5976    #[must_use]
5977    pub fn builder(
5978        symbol: String,
5979        working_type: OrderListPlaceOtocoWorkingTypeEnum,
5980        working_side: OrderListPlaceOtocoWorkingSideEnum,
5981        working_price: rust_decimal::Decimal,
5982        working_quantity: rust_decimal::Decimal,
5983        pending_side: OrderListPlaceOtocoPendingSideEnum,
5984        pending_quantity: rust_decimal::Decimal,
5985        pending_above_type: OrderListPlaceOtocoPendingAboveTypeEnum,
5986    ) -> OrderListPlaceOtocoParamsBuilder {
5987        OrderListPlaceOtocoParamsBuilder::default()
5988            .symbol(symbol)
5989            .working_type(working_type)
5990            .working_side(working_side)
5991            .working_price(working_price)
5992            .working_quantity(working_quantity)
5993            .pending_side(pending_side)
5994            .pending_quantity(pending_quantity)
5995            .pending_above_type(pending_above_type)
5996    }
5997}
5998/// Request parameters for the [`order_place`] operation.
5999///
6000/// This struct holds all of the inputs you can pass when calling
6001/// [`order_place`](#method.order_place).
6002#[derive(Clone, Debug, Builder)]
6003#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6004pub struct OrderPlaceParams {
6005    ///
6006    /// The `symbol` parameter.
6007    ///
6008    /// This field is **required.
6009    #[builder(setter(into))]
6010    pub symbol: String,
6011    ///
6012    /// The `side` parameter.
6013    ///
6014    /// This field is **required.
6015    #[builder(setter(into))]
6016    pub side: OrderPlaceSideEnum,
6017    ///
6018    /// The `r#type` parameter.
6019    ///
6020    /// This field is **required.
6021    #[builder(setter(into))]
6022    pub r#type: OrderPlaceTypeEnum,
6023    /// Unique WebSocket request ID.
6024    ///
6025    /// This field is **optional.
6026    #[builder(setter(into), default)]
6027    pub id: Option<String>,
6028    ///
6029    /// The `time_in_force` parameter.
6030    ///
6031    /// This field is **optional.
6032    #[builder(setter(into), default)]
6033    pub time_in_force: Option<OrderPlaceTimeInForceEnum>,
6034    ///
6035    /// The `price` parameter.
6036    ///
6037    /// This field is **optional.
6038    #[builder(setter(into), default)]
6039    pub price: Option<rust_decimal::Decimal>,
6040    ///
6041    /// The `quantity` parameter.
6042    ///
6043    /// This field is **optional.
6044    #[builder(setter(into), default)]
6045    pub quantity: Option<rust_decimal::Decimal>,
6046    ///
6047    /// The `quote_order_qty` parameter.
6048    ///
6049    /// This field is **optional.
6050    #[builder(setter(into), default)]
6051    pub quote_order_qty: Option<rust_decimal::Decimal>,
6052    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
6053    ///
6054    /// This field is **optional.
6055    #[builder(setter(into), default)]
6056    pub new_client_order_id: Option<String>,
6057    ///
6058    /// The `new_order_resp_type` parameter.
6059    ///
6060    /// This field is **optional.
6061    #[builder(setter(into), default)]
6062    pub new_order_resp_type: Option<OrderPlaceNewOrderRespTypeEnum>,
6063    ///
6064    /// The `stop_price` parameter.
6065    ///
6066    /// This field is **optional.
6067    #[builder(setter(into), default)]
6068    pub stop_price: Option<rust_decimal::Decimal>,
6069    /// See [Trailing Stop order FAQ](faqs/trailing-stop-faq.md)
6070    ///
6071    /// This field is **optional.
6072    #[builder(setter(into), default)]
6073    pub trailing_delta: Option<i32>,
6074    ///
6075    /// The `iceberg_qty` parameter.
6076    ///
6077    /// This field is **optional.
6078    #[builder(setter(into), default)]
6079    pub iceberg_qty: Option<rust_decimal::Decimal>,
6080    /// Arbitrary numeric value identifying the order within an order strategy.
6081    ///
6082    /// This field is **optional.
6083    #[builder(setter(into), default)]
6084    pub strategy_id: Option<i64>,
6085    /// Arbitrary numeric value identifying the order strategy.
6086    /// Values smaller than 1000000 are reserved and cannot be used.
6087    ///
6088    /// This field is **optional.
6089    #[builder(setter(into), default)]
6090    pub strategy_type: Option<i32>,
6091    ///
6092    /// The `self_trade_prevention_mode` parameter.
6093    ///
6094    /// This field is **optional.
6095    #[builder(setter(into), default)]
6096    pub self_trade_prevention_mode: Option<OrderPlaceSelfTradePreventionModeEnum>,
6097    ///
6098    /// The `peg_price_type` parameter.
6099    ///
6100    /// This field is **optional.
6101    #[builder(setter(into), default)]
6102    pub peg_price_type: Option<OrderPlacePegPriceTypeEnum>,
6103    /// Price level to peg the price to (max: 100)
6104    /// See Pegged Orders
6105    ///
6106    /// This field is **optional.
6107    #[builder(setter(into), default)]
6108    pub peg_offset_value: Option<i32>,
6109    ///
6110    /// The `peg_offset_type` parameter.
6111    ///
6112    /// This field is **optional.
6113    #[builder(setter(into), default)]
6114    pub peg_offset_type: Option<OrderPlacePegOffsetTypeEnum>,
6115    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6116    ///
6117    /// This field is **optional.
6118    #[builder(setter(into), default)]
6119    pub recv_window: Option<rust_decimal::Decimal>,
6120}
6121
6122impl OrderPlaceParams {
6123    /// Create a builder for [`order_place`].
6124    ///
6125    /// Required parameters:
6126    ///
6127    /// * `symbol` — String
6128    /// * `side` — String
6129    /// * `r#type` — String
6130    ///
6131    #[must_use]
6132    pub fn builder(
6133        symbol: String,
6134        side: OrderPlaceSideEnum,
6135        r#type: OrderPlaceTypeEnum,
6136    ) -> OrderPlaceParamsBuilder {
6137        OrderPlaceParamsBuilder::default()
6138            .symbol(symbol)
6139            .side(side)
6140            .r#type(r#type)
6141    }
6142}
6143/// Request parameters for the [`order_test`] operation.
6144///
6145/// This struct holds all of the inputs you can pass when calling
6146/// [`order_test`](#method.order_test).
6147#[derive(Clone, Debug, Builder)]
6148#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6149pub struct OrderTestParams {
6150    ///
6151    /// The `symbol` parameter.
6152    ///
6153    /// This field is **required.
6154    #[builder(setter(into))]
6155    pub symbol: String,
6156    ///
6157    /// The `side` parameter.
6158    ///
6159    /// This field is **required.
6160    #[builder(setter(into))]
6161    pub side: OrderTestSideEnum,
6162    ///
6163    /// The `r#type` parameter.
6164    ///
6165    /// This field is **required.
6166    #[builder(setter(into))]
6167    pub r#type: OrderTestTypeEnum,
6168    /// Unique WebSocket request ID.
6169    ///
6170    /// This field is **optional.
6171    #[builder(setter(into), default)]
6172    pub id: Option<String>,
6173    /// Default: `false` <br> See [Commissions FAQ](faqs/commission_faq.md#test-order-diferences) to learn more.
6174    ///
6175    /// This field is **optional.
6176    #[builder(setter(into), default)]
6177    pub compute_commission_rates: Option<bool>,
6178    ///
6179    /// The `time_in_force` parameter.
6180    ///
6181    /// This field is **optional.
6182    #[builder(setter(into), default)]
6183    pub time_in_force: Option<OrderTestTimeInForceEnum>,
6184    ///
6185    /// The `price` parameter.
6186    ///
6187    /// This field is **optional.
6188    #[builder(setter(into), default)]
6189    pub price: Option<rust_decimal::Decimal>,
6190    ///
6191    /// The `quantity` parameter.
6192    ///
6193    /// This field is **optional.
6194    #[builder(setter(into), default)]
6195    pub quantity: Option<rust_decimal::Decimal>,
6196    ///
6197    /// The `quote_order_qty` parameter.
6198    ///
6199    /// This field is **optional.
6200    #[builder(setter(into), default)]
6201    pub quote_order_qty: Option<rust_decimal::Decimal>,
6202    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
6203    ///
6204    /// This field is **optional.
6205    #[builder(setter(into), default)]
6206    pub new_client_order_id: Option<String>,
6207    ///
6208    /// The `new_order_resp_type` parameter.
6209    ///
6210    /// This field is **optional.
6211    #[builder(setter(into), default)]
6212    pub new_order_resp_type: Option<OrderTestNewOrderRespTypeEnum>,
6213    ///
6214    /// The `stop_price` parameter.
6215    ///
6216    /// This field is **optional.
6217    #[builder(setter(into), default)]
6218    pub stop_price: Option<rust_decimal::Decimal>,
6219    /// See [Trailing Stop order FAQ](faqs/trailing-stop-faq.md)
6220    ///
6221    /// This field is **optional.
6222    #[builder(setter(into), default)]
6223    pub trailing_delta: Option<i32>,
6224    ///
6225    /// The `iceberg_qty` parameter.
6226    ///
6227    /// This field is **optional.
6228    #[builder(setter(into), default)]
6229    pub iceberg_qty: Option<rust_decimal::Decimal>,
6230    /// Arbitrary numeric value identifying the order within an order strategy.
6231    ///
6232    /// This field is **optional.
6233    #[builder(setter(into), default)]
6234    pub strategy_id: Option<i64>,
6235    /// Arbitrary numeric value identifying the order strategy.
6236    /// Values smaller than 1000000 are reserved and cannot be used.
6237    ///
6238    /// This field is **optional.
6239    #[builder(setter(into), default)]
6240    pub strategy_type: Option<i32>,
6241    ///
6242    /// The `self_trade_prevention_mode` parameter.
6243    ///
6244    /// This field is **optional.
6245    #[builder(setter(into), default)]
6246    pub self_trade_prevention_mode: Option<OrderTestSelfTradePreventionModeEnum>,
6247    ///
6248    /// The `peg_price_type` parameter.
6249    ///
6250    /// This field is **optional.
6251    #[builder(setter(into), default)]
6252    pub peg_price_type: Option<OrderTestPegPriceTypeEnum>,
6253    /// Price level to peg the price to (max: 100)
6254    /// See Pegged Orders
6255    ///
6256    /// This field is **optional.
6257    #[builder(setter(into), default)]
6258    pub peg_offset_value: Option<i32>,
6259    ///
6260    /// The `peg_offset_type` parameter.
6261    ///
6262    /// This field is **optional.
6263    #[builder(setter(into), default)]
6264    pub peg_offset_type: Option<OrderTestPegOffsetTypeEnum>,
6265    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6266    ///
6267    /// This field is **optional.
6268    #[builder(setter(into), default)]
6269    pub recv_window: Option<rust_decimal::Decimal>,
6270}
6271
6272impl OrderTestParams {
6273    /// Create a builder for [`order_test`].
6274    ///
6275    /// Required parameters:
6276    ///
6277    /// * `symbol` — String
6278    /// * `side` — String
6279    /// * `r#type` — String
6280    ///
6281    #[must_use]
6282    pub fn builder(
6283        symbol: String,
6284        side: OrderTestSideEnum,
6285        r#type: OrderTestTypeEnum,
6286    ) -> OrderTestParamsBuilder {
6287        OrderTestParamsBuilder::default()
6288            .symbol(symbol)
6289            .side(side)
6290            .r#type(r#type)
6291    }
6292}
6293/// Request parameters for the [`sor_order_place`] operation.
6294///
6295/// This struct holds all of the inputs you can pass when calling
6296/// [`sor_order_place`](#method.sor_order_place).
6297#[derive(Clone, Debug, Builder)]
6298#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6299pub struct SorOrderPlaceParams {
6300    ///
6301    /// The `symbol` parameter.
6302    ///
6303    /// This field is **required.
6304    #[builder(setter(into))]
6305    pub symbol: String,
6306    ///
6307    /// The `side` parameter.
6308    ///
6309    /// This field is **required.
6310    #[builder(setter(into))]
6311    pub side: SorOrderPlaceSideEnum,
6312    ///
6313    /// The `r#type` parameter.
6314    ///
6315    /// This field is **required.
6316    #[builder(setter(into))]
6317    pub r#type: SorOrderPlaceTypeEnum,
6318    ///
6319    /// The `quantity` parameter.
6320    ///
6321    /// This field is **required.
6322    #[builder(setter(into))]
6323    pub quantity: rust_decimal::Decimal,
6324    /// Unique WebSocket request ID.
6325    ///
6326    /// This field is **optional.
6327    #[builder(setter(into), default)]
6328    pub id: Option<String>,
6329    ///
6330    /// The `time_in_force` parameter.
6331    ///
6332    /// This field is **optional.
6333    #[builder(setter(into), default)]
6334    pub time_in_force: Option<SorOrderPlaceTimeInForceEnum>,
6335    ///
6336    /// The `price` parameter.
6337    ///
6338    /// This field is **optional.
6339    #[builder(setter(into), default)]
6340    pub price: Option<rust_decimal::Decimal>,
6341    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
6342    ///
6343    /// This field is **optional.
6344    #[builder(setter(into), default)]
6345    pub new_client_order_id: Option<String>,
6346    ///
6347    /// The `new_order_resp_type` parameter.
6348    ///
6349    /// This field is **optional.
6350    #[builder(setter(into), default)]
6351    pub new_order_resp_type: Option<SorOrderPlaceNewOrderRespTypeEnum>,
6352    ///
6353    /// The `iceberg_qty` parameter.
6354    ///
6355    /// This field is **optional.
6356    #[builder(setter(into), default)]
6357    pub iceberg_qty: Option<rust_decimal::Decimal>,
6358    /// Arbitrary numeric value identifying the order within an order strategy.
6359    ///
6360    /// This field is **optional.
6361    #[builder(setter(into), default)]
6362    pub strategy_id: Option<i64>,
6363    /// Arbitrary numeric value identifying the order strategy.
6364    /// Values smaller than 1000000 are reserved and cannot be used.
6365    ///
6366    /// This field is **optional.
6367    #[builder(setter(into), default)]
6368    pub strategy_type: Option<i32>,
6369    ///
6370    /// The `self_trade_prevention_mode` parameter.
6371    ///
6372    /// This field is **optional.
6373    #[builder(setter(into), default)]
6374    pub self_trade_prevention_mode: Option<SorOrderPlaceSelfTradePreventionModeEnum>,
6375    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6376    ///
6377    /// This field is **optional.
6378    #[builder(setter(into), default)]
6379    pub recv_window: Option<rust_decimal::Decimal>,
6380}
6381
6382impl SorOrderPlaceParams {
6383    /// Create a builder for [`sor_order_place`].
6384    ///
6385    /// Required parameters:
6386    ///
6387    /// * `symbol` — String
6388    /// * `side` — String
6389    /// * `r#type` — String
6390    /// * `quantity` — `rust_decimal::Decimal`
6391    ///
6392    #[must_use]
6393    pub fn builder(
6394        symbol: String,
6395        side: SorOrderPlaceSideEnum,
6396        r#type: SorOrderPlaceTypeEnum,
6397        quantity: rust_decimal::Decimal,
6398    ) -> SorOrderPlaceParamsBuilder {
6399        SorOrderPlaceParamsBuilder::default()
6400            .symbol(symbol)
6401            .side(side)
6402            .r#type(r#type)
6403            .quantity(quantity)
6404    }
6405}
6406/// Request parameters for the [`sor_order_test`] operation.
6407///
6408/// This struct holds all of the inputs you can pass when calling
6409/// [`sor_order_test`](#method.sor_order_test).
6410#[derive(Clone, Debug, Builder)]
6411#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
6412pub struct SorOrderTestParams {
6413    ///
6414    /// The `symbol` parameter.
6415    ///
6416    /// This field is **required.
6417    #[builder(setter(into))]
6418    pub symbol: String,
6419    ///
6420    /// The `side` parameter.
6421    ///
6422    /// This field is **required.
6423    #[builder(setter(into))]
6424    pub side: SorOrderTestSideEnum,
6425    ///
6426    /// The `r#type` parameter.
6427    ///
6428    /// This field is **required.
6429    #[builder(setter(into))]
6430    pub r#type: SorOrderTestTypeEnum,
6431    ///
6432    /// The `quantity` parameter.
6433    ///
6434    /// This field is **required.
6435    #[builder(setter(into))]
6436    pub quantity: rust_decimal::Decimal,
6437    /// Unique WebSocket request ID.
6438    ///
6439    /// This field is **optional.
6440    #[builder(setter(into), default)]
6441    pub id: Option<String>,
6442    /// Default: `false` <br> See [Commissions FAQ](faqs/commission_faq.md#test-order-diferences) to learn more.
6443    ///
6444    /// This field is **optional.
6445    #[builder(setter(into), default)]
6446    pub compute_commission_rates: Option<bool>,
6447    ///
6448    /// The `time_in_force` parameter.
6449    ///
6450    /// This field is **optional.
6451    #[builder(setter(into), default)]
6452    pub time_in_force: Option<SorOrderTestTimeInForceEnum>,
6453    ///
6454    /// The `price` parameter.
6455    ///
6456    /// This field is **optional.
6457    #[builder(setter(into), default)]
6458    pub price: Option<rust_decimal::Decimal>,
6459    /// The new client order ID for the order after being amended. <br> If not sent, one will be randomly generated. <br> It is possible to reuse the current clientOrderId by sending it as the `newClientOrderId`.
6460    ///
6461    /// This field is **optional.
6462    #[builder(setter(into), default)]
6463    pub new_client_order_id: Option<String>,
6464    ///
6465    /// The `new_order_resp_type` parameter.
6466    ///
6467    /// This field is **optional.
6468    #[builder(setter(into), default)]
6469    pub new_order_resp_type: Option<SorOrderTestNewOrderRespTypeEnum>,
6470    ///
6471    /// The `iceberg_qty` parameter.
6472    ///
6473    /// This field is **optional.
6474    #[builder(setter(into), default)]
6475    pub iceberg_qty: Option<rust_decimal::Decimal>,
6476    /// Arbitrary numeric value identifying the order within an order strategy.
6477    ///
6478    /// This field is **optional.
6479    #[builder(setter(into), default)]
6480    pub strategy_id: Option<i64>,
6481    /// Arbitrary numeric value identifying the order strategy.
6482    /// Values smaller than 1000000 are reserved and cannot be used.
6483    ///
6484    /// This field is **optional.
6485    #[builder(setter(into), default)]
6486    pub strategy_type: Option<i32>,
6487    ///
6488    /// The `self_trade_prevention_mode` parameter.
6489    ///
6490    /// This field is **optional.
6491    #[builder(setter(into), default)]
6492    pub self_trade_prevention_mode: Option<SorOrderTestSelfTradePreventionModeEnum>,
6493    /// The value cannot be greater than `60000`. <br> Supports up to three decimal places of precision (e.g., 6000.346) so that microseconds may be specified.
6494    ///
6495    /// This field is **optional.
6496    #[builder(setter(into), default)]
6497    pub recv_window: Option<rust_decimal::Decimal>,
6498}
6499
6500impl SorOrderTestParams {
6501    /// Create a builder for [`sor_order_test`].
6502    ///
6503    /// Required parameters:
6504    ///
6505    /// * `symbol` — String
6506    /// * `side` — String
6507    /// * `r#type` — String
6508    /// * `quantity` — `rust_decimal::Decimal`
6509    ///
6510    #[must_use]
6511    pub fn builder(
6512        symbol: String,
6513        side: SorOrderTestSideEnum,
6514        r#type: SorOrderTestTypeEnum,
6515        quantity: rust_decimal::Decimal,
6516    ) -> SorOrderTestParamsBuilder {
6517        SorOrderTestParamsBuilder::default()
6518            .symbol(symbol)
6519            .side(side)
6520            .r#type(r#type)
6521            .quantity(quantity)
6522    }
6523}
6524
6525#[async_trait]
6526impl TradeApi for TradeApiClient {
6527    async fn open_orders_cancel_all(
6528        &self,
6529        params: OpenOrdersCancelAllParams,
6530    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::OpenOrdersCancelAllResponseResultInner>>>
6531    {
6532        let OpenOrdersCancelAllParams {
6533            symbol,
6534            id,
6535            recv_window,
6536        } = params;
6537
6538        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6539        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6540        if let Some(value) = id {
6541            payload.insert("id".to_string(), serde_json::json!(value));
6542        }
6543        if let Some(value) = recv_window {
6544            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6545        }
6546        let payload = remove_empty_value(payload);
6547
6548        self.websocket_api_base
6549            .send_message::<Vec<models::OpenOrdersCancelAllResponseResultInner>>(
6550                "/openOrders.cancelAll".trim_start_matches('/'),
6551                payload,
6552                WebsocketMessageSendOptions::new().signed(),
6553            )
6554            .await
6555            .map_err(anyhow::Error::from)?
6556            .into_iter()
6557            .next()
6558            .ok_or(WebsocketError::NoResponse)
6559            .map_err(anyhow::Error::from)
6560    }
6561
6562    async fn order_amend_keep_priority(
6563        &self,
6564        params: OrderAmendKeepPriorityParams,
6565    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderAmendKeepPriorityResponseResult>>>
6566    {
6567        let OrderAmendKeepPriorityParams {
6568            symbol,
6569            new_qty,
6570            id,
6571            order_id,
6572            orig_client_order_id,
6573            new_client_order_id,
6574            recv_window,
6575        } = params;
6576
6577        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6578        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6579        payload.insert("newQty".to_string(), serde_json::json!(new_qty));
6580        if let Some(value) = id {
6581            payload.insert("id".to_string(), serde_json::json!(value));
6582        }
6583        if let Some(value) = order_id {
6584            payload.insert("orderId".to_string(), serde_json::json!(value));
6585        }
6586        if let Some(value) = orig_client_order_id {
6587            payload.insert("origClientOrderId".to_string(), serde_json::json!(value));
6588        }
6589        if let Some(value) = new_client_order_id {
6590            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6591        }
6592        if let Some(value) = recv_window {
6593            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6594        }
6595        let payload = remove_empty_value(payload);
6596
6597        self.websocket_api_base
6598            .send_message::<Box<models::OrderAmendKeepPriorityResponseResult>>(
6599                "/order.amend.keepPriority".trim_start_matches('/'),
6600                payload,
6601                WebsocketMessageSendOptions::new().signed(),
6602            )
6603            .await
6604            .map_err(anyhow::Error::from)?
6605            .into_iter()
6606            .next()
6607            .ok_or(WebsocketError::NoResponse)
6608            .map_err(anyhow::Error::from)
6609    }
6610
6611    async fn order_cancel(
6612        &self,
6613        params: OrderCancelParams,
6614    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelResponseResult>>> {
6615        let OrderCancelParams {
6616            symbol,
6617            id,
6618            order_id,
6619            orig_client_order_id,
6620            new_client_order_id,
6621            cancel_restrictions,
6622            recv_window,
6623        } = params;
6624
6625        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6626        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6627        if let Some(value) = id {
6628            payload.insert("id".to_string(), serde_json::json!(value));
6629        }
6630        if let Some(value) = order_id {
6631            payload.insert("orderId".to_string(), serde_json::json!(value));
6632        }
6633        if let Some(value) = orig_client_order_id {
6634            payload.insert("origClientOrderId".to_string(), serde_json::json!(value));
6635        }
6636        if let Some(value) = new_client_order_id {
6637            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6638        }
6639        if let Some(value) = cancel_restrictions {
6640            payload.insert("cancelRestrictions".to_string(), serde_json::json!(value));
6641        }
6642        if let Some(value) = recv_window {
6643            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6644        }
6645        let payload = remove_empty_value(payload);
6646
6647        self.websocket_api_base
6648            .send_message::<Box<models::OrderCancelResponseResult>>(
6649                "/order.cancel".trim_start_matches('/'),
6650                payload,
6651                WebsocketMessageSendOptions::new().signed(),
6652            )
6653            .await
6654            .map_err(anyhow::Error::from)?
6655            .into_iter()
6656            .next()
6657            .ok_or(WebsocketError::NoResponse)
6658            .map_err(anyhow::Error::from)
6659    }
6660
6661    async fn order_cancel_replace(
6662        &self,
6663        params: OrderCancelReplaceParams,
6664    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderCancelReplaceResponseResult>>> {
6665        let OrderCancelReplaceParams {
6666            symbol,
6667            cancel_replace_mode,
6668            side,
6669            r#type,
6670            id,
6671            cancel_order_id,
6672            cancel_orig_client_order_id,
6673            cancel_new_client_order_id,
6674            time_in_force,
6675            price,
6676            quantity,
6677            quote_order_qty,
6678            new_client_order_id,
6679            new_order_resp_type,
6680            stop_price,
6681            trailing_delta,
6682            iceberg_qty,
6683            strategy_id,
6684            strategy_type,
6685            self_trade_prevention_mode,
6686            cancel_restrictions,
6687            order_rate_limit_exceeded_mode,
6688            peg_price_type,
6689            peg_offset_value,
6690            peg_offset_type,
6691            recv_window,
6692        } = params;
6693
6694        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6695        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6696        payload.insert(
6697            "cancelReplaceMode".to_string(),
6698            serde_json::json!(cancel_replace_mode),
6699        );
6700        payload.insert("side".to_string(), serde_json::json!(side));
6701        payload.insert("type".to_string(), serde_json::json!(r#type));
6702        if let Some(value) = id {
6703            payload.insert("id".to_string(), serde_json::json!(value));
6704        }
6705        if let Some(value) = cancel_order_id {
6706            payload.insert("cancelOrderId".to_string(), serde_json::json!(value));
6707        }
6708        if let Some(value) = cancel_orig_client_order_id {
6709            payload.insert(
6710                "cancelOrigClientOrderId".to_string(),
6711                serde_json::json!(value),
6712            );
6713        }
6714        if let Some(value) = cancel_new_client_order_id {
6715            payload.insert(
6716                "cancelNewClientOrderId".to_string(),
6717                serde_json::json!(value),
6718            );
6719        }
6720        if let Some(value) = time_in_force {
6721            payload.insert("timeInForce".to_string(), serde_json::json!(value));
6722        }
6723        if let Some(value) = price {
6724            payload.insert("price".to_string(), serde_json::json!(value));
6725        }
6726        if let Some(value) = quantity {
6727            payload.insert("quantity".to_string(), serde_json::json!(value));
6728        }
6729        if let Some(value) = quote_order_qty {
6730            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
6731        }
6732        if let Some(value) = new_client_order_id {
6733            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6734        }
6735        if let Some(value) = new_order_resp_type {
6736            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
6737        }
6738        if let Some(value) = stop_price {
6739            payload.insert("stopPrice".to_string(), serde_json::json!(value));
6740        }
6741        if let Some(value) = trailing_delta {
6742            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
6743        }
6744        if let Some(value) = iceberg_qty {
6745            payload.insert("icebergQty".to_string(), serde_json::json!(value));
6746        }
6747        if let Some(value) = strategy_id {
6748            payload.insert("strategyId".to_string(), serde_json::json!(value));
6749        }
6750        if let Some(value) = strategy_type {
6751            payload.insert("strategyType".to_string(), serde_json::json!(value));
6752        }
6753        if let Some(value) = self_trade_prevention_mode {
6754            payload.insert(
6755                "selfTradePreventionMode".to_string(),
6756                serde_json::json!(value),
6757            );
6758        }
6759        if let Some(value) = cancel_restrictions {
6760            payload.insert("cancelRestrictions".to_string(), serde_json::json!(value));
6761        }
6762        if let Some(value) = order_rate_limit_exceeded_mode {
6763            payload.insert(
6764                "orderRateLimitExceededMode".to_string(),
6765                serde_json::json!(value),
6766            );
6767        }
6768        if let Some(value) = peg_price_type {
6769            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
6770        }
6771        if let Some(value) = peg_offset_value {
6772            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
6773        }
6774        if let Some(value) = peg_offset_type {
6775            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
6776        }
6777        if let Some(value) = recv_window {
6778            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6779        }
6780        let payload = remove_empty_value(payload);
6781
6782        self.websocket_api_base
6783            .send_message::<Box<models::OrderCancelReplaceResponseResult>>(
6784                "/order.cancelReplace".trim_start_matches('/'),
6785                payload,
6786                WebsocketMessageSendOptions::new().signed(),
6787            )
6788            .await
6789            .map_err(anyhow::Error::from)?
6790            .into_iter()
6791            .next()
6792            .ok_or(WebsocketError::NoResponse)
6793            .map_err(anyhow::Error::from)
6794    }
6795
6796    async fn order_list_cancel(
6797        &self,
6798        params: OrderListCancelParams,
6799    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListCancelResponseResult>>> {
6800        let OrderListCancelParams {
6801            symbol,
6802            id,
6803            order_list_id,
6804            list_client_order_id,
6805            new_client_order_id,
6806            recv_window,
6807        } = params;
6808
6809        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6810        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6811        if let Some(value) = id {
6812            payload.insert("id".to_string(), serde_json::json!(value));
6813        }
6814        if let Some(value) = order_list_id {
6815            payload.insert("orderListId".to_string(), serde_json::json!(value));
6816        }
6817        if let Some(value) = list_client_order_id {
6818            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6819        }
6820        if let Some(value) = new_client_order_id {
6821            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
6822        }
6823        if let Some(value) = recv_window {
6824            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6825        }
6826        let payload = remove_empty_value(payload);
6827
6828        self.websocket_api_base
6829            .send_message::<Box<models::OrderListCancelResponseResult>>(
6830                "/orderList.cancel".trim_start_matches('/'),
6831                payload,
6832                WebsocketMessageSendOptions::new().signed(),
6833            )
6834            .await
6835            .map_err(anyhow::Error::from)?
6836            .into_iter()
6837            .next()
6838            .ok_or(WebsocketError::NoResponse)
6839            .map_err(anyhow::Error::from)
6840    }
6841
6842    async fn order_list_place(
6843        &self,
6844        params: OrderListPlaceParams,
6845    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceResponseResult>>> {
6846        let OrderListPlaceParams {
6847            symbol,
6848            side,
6849            price,
6850            quantity,
6851            id,
6852            list_client_order_id,
6853            limit_client_order_id,
6854            limit_iceberg_qty,
6855            limit_strategy_id,
6856            limit_strategy_type,
6857            stop_price,
6858            trailing_delta,
6859            stop_client_order_id,
6860            stop_limit_price,
6861            stop_limit_time_in_force,
6862            stop_iceberg_qty,
6863            stop_strategy_id,
6864            stop_strategy_type,
6865            new_order_resp_type,
6866            self_trade_prevention_mode,
6867            recv_window,
6868        } = params;
6869
6870        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6871        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6872        payload.insert("side".to_string(), serde_json::json!(side));
6873        payload.insert("price".to_string(), serde_json::json!(price));
6874        payload.insert("quantity".to_string(), serde_json::json!(quantity));
6875        if let Some(value) = id {
6876            payload.insert("id".to_string(), serde_json::json!(value));
6877        }
6878        if let Some(value) = list_client_order_id {
6879            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6880        }
6881        if let Some(value) = limit_client_order_id {
6882            payload.insert("limitClientOrderId".to_string(), serde_json::json!(value));
6883        }
6884        if let Some(value) = limit_iceberg_qty {
6885            payload.insert("limitIcebergQty".to_string(), serde_json::json!(value));
6886        }
6887        if let Some(value) = limit_strategy_id {
6888            payload.insert("limitStrategyId".to_string(), serde_json::json!(value));
6889        }
6890        if let Some(value) = limit_strategy_type {
6891            payload.insert("limitStrategyType".to_string(), serde_json::json!(value));
6892        }
6893        if let Some(value) = stop_price {
6894            payload.insert("stopPrice".to_string(), serde_json::json!(value));
6895        }
6896        if let Some(value) = trailing_delta {
6897            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
6898        }
6899        if let Some(value) = stop_client_order_id {
6900            payload.insert("stopClientOrderId".to_string(), serde_json::json!(value));
6901        }
6902        if let Some(value) = stop_limit_price {
6903            payload.insert("stopLimitPrice".to_string(), serde_json::json!(value));
6904        }
6905        if let Some(value) = stop_limit_time_in_force {
6906            payload.insert("stopLimitTimeInForce".to_string(), serde_json::json!(value));
6907        }
6908        if let Some(value) = stop_iceberg_qty {
6909            payload.insert("stopIcebergQty".to_string(), serde_json::json!(value));
6910        }
6911        if let Some(value) = stop_strategy_id {
6912            payload.insert("stopStrategyId".to_string(), serde_json::json!(value));
6913        }
6914        if let Some(value) = stop_strategy_type {
6915            payload.insert("stopStrategyType".to_string(), serde_json::json!(value));
6916        }
6917        if let Some(value) = new_order_resp_type {
6918            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
6919        }
6920        if let Some(value) = self_trade_prevention_mode {
6921            payload.insert(
6922                "selfTradePreventionMode".to_string(),
6923                serde_json::json!(value),
6924            );
6925        }
6926        if let Some(value) = recv_window {
6927            payload.insert("recvWindow".to_string(), serde_json::json!(value));
6928        }
6929        let payload = remove_empty_value(payload);
6930
6931        self.websocket_api_base
6932            .send_message::<Box<models::OrderListPlaceResponseResult>>(
6933                "/orderList.place".trim_start_matches('/'),
6934                payload,
6935                WebsocketMessageSendOptions::new().signed(),
6936            )
6937            .await
6938            .map_err(anyhow::Error::from)?
6939            .into_iter()
6940            .next()
6941            .ok_or(WebsocketError::NoResponse)
6942            .map_err(anyhow::Error::from)
6943    }
6944
6945    async fn order_list_place_oco(
6946        &self,
6947        params: OrderListPlaceOcoParams,
6948    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOcoResponseResult>>> {
6949        let OrderListPlaceOcoParams {
6950            symbol,
6951            side,
6952            quantity,
6953            above_type,
6954            below_type,
6955            id,
6956            list_client_order_id,
6957            above_client_order_id,
6958            above_iceberg_qty,
6959            above_price,
6960            above_stop_price,
6961            above_trailing_delta,
6962            above_time_in_force,
6963            above_strategy_id,
6964            above_strategy_type,
6965            above_peg_price_type,
6966            above_peg_offset_type,
6967            above_peg_offset_value,
6968            below_client_order_id,
6969            below_iceberg_qty,
6970            below_price,
6971            below_stop_price,
6972            below_trailing_delta,
6973            below_time_in_force,
6974            below_strategy_id,
6975            below_strategy_type,
6976            below_peg_price_type,
6977            below_peg_offset_type,
6978            below_peg_offset_value,
6979            new_order_resp_type,
6980            self_trade_prevention_mode,
6981            recv_window,
6982        } = params;
6983
6984        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
6985        payload.insert("symbol".to_string(), serde_json::json!(symbol));
6986        payload.insert("side".to_string(), serde_json::json!(side));
6987        payload.insert("quantity".to_string(), serde_json::json!(quantity));
6988        payload.insert("aboveType".to_string(), serde_json::json!(above_type));
6989        payload.insert("belowType".to_string(), serde_json::json!(below_type));
6990        if let Some(value) = id {
6991            payload.insert("id".to_string(), serde_json::json!(value));
6992        }
6993        if let Some(value) = list_client_order_id {
6994            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
6995        }
6996        if let Some(value) = above_client_order_id {
6997            payload.insert("aboveClientOrderId".to_string(), serde_json::json!(value));
6998        }
6999        if let Some(value) = above_iceberg_qty {
7000            payload.insert("aboveIcebergQty".to_string(), serde_json::json!(value));
7001        }
7002        if let Some(value) = above_price {
7003            payload.insert("abovePrice".to_string(), serde_json::json!(value));
7004        }
7005        if let Some(value) = above_stop_price {
7006            payload.insert("aboveStopPrice".to_string(), serde_json::json!(value));
7007        }
7008        if let Some(value) = above_trailing_delta {
7009            payload.insert("aboveTrailingDelta".to_string(), serde_json::json!(value));
7010        }
7011        if let Some(value) = above_time_in_force {
7012            payload.insert("aboveTimeInForce".to_string(), serde_json::json!(value));
7013        }
7014        if let Some(value) = above_strategy_id {
7015            payload.insert("aboveStrategyId".to_string(), serde_json::json!(value));
7016        }
7017        if let Some(value) = above_strategy_type {
7018            payload.insert("aboveStrategyType".to_string(), serde_json::json!(value));
7019        }
7020        if let Some(value) = above_peg_price_type {
7021            payload.insert("abovePegPriceType".to_string(), serde_json::json!(value));
7022        }
7023        if let Some(value) = above_peg_offset_type {
7024            payload.insert("abovePegOffsetType".to_string(), serde_json::json!(value));
7025        }
7026        if let Some(value) = above_peg_offset_value {
7027            payload.insert("abovePegOffsetValue".to_string(), serde_json::json!(value));
7028        }
7029        if let Some(value) = below_client_order_id {
7030            payload.insert("belowClientOrderId".to_string(), serde_json::json!(value));
7031        }
7032        if let Some(value) = below_iceberg_qty {
7033            payload.insert("belowIcebergQty".to_string(), serde_json::json!(value));
7034        }
7035        if let Some(value) = below_price {
7036            payload.insert("belowPrice".to_string(), serde_json::json!(value));
7037        }
7038        if let Some(value) = below_stop_price {
7039            payload.insert("belowStopPrice".to_string(), serde_json::json!(value));
7040        }
7041        if let Some(value) = below_trailing_delta {
7042            payload.insert("belowTrailingDelta".to_string(), serde_json::json!(value));
7043        }
7044        if let Some(value) = below_time_in_force {
7045            payload.insert("belowTimeInForce".to_string(), serde_json::json!(value));
7046        }
7047        if let Some(value) = below_strategy_id {
7048            payload.insert("belowStrategyId".to_string(), serde_json::json!(value));
7049        }
7050        if let Some(value) = below_strategy_type {
7051            payload.insert("belowStrategyType".to_string(), serde_json::json!(value));
7052        }
7053        if let Some(value) = below_peg_price_type {
7054            payload.insert("belowPegPriceType".to_string(), serde_json::json!(value));
7055        }
7056        if let Some(value) = below_peg_offset_type {
7057            payload.insert("belowPegOffsetType".to_string(), serde_json::json!(value));
7058        }
7059        if let Some(value) = below_peg_offset_value {
7060            payload.insert("belowPegOffsetValue".to_string(), serde_json::json!(value));
7061        }
7062        if let Some(value) = new_order_resp_type {
7063            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7064        }
7065        if let Some(value) = self_trade_prevention_mode {
7066            payload.insert(
7067                "selfTradePreventionMode".to_string(),
7068                serde_json::json!(value),
7069            );
7070        }
7071        if let Some(value) = recv_window {
7072            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7073        }
7074        let payload = remove_empty_value(payload);
7075
7076        self.websocket_api_base
7077            .send_message::<Box<models::OrderListPlaceOcoResponseResult>>(
7078                "/orderList.place.oco".trim_start_matches('/'),
7079                payload,
7080                WebsocketMessageSendOptions::new().signed(),
7081            )
7082            .await
7083            .map_err(anyhow::Error::from)?
7084            .into_iter()
7085            .next()
7086            .ok_or(WebsocketError::NoResponse)
7087            .map_err(anyhow::Error::from)
7088    }
7089
7090    async fn order_list_place_opo(
7091        &self,
7092        params: OrderListPlaceOpoParams,
7093    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpoResponseResult>>> {
7094        let OrderListPlaceOpoParams {
7095            symbol,
7096            working_type,
7097            working_side,
7098            working_price,
7099            working_quantity,
7100            pending_type,
7101            pending_side,
7102            id,
7103            list_client_order_id,
7104            new_order_resp_type,
7105            self_trade_prevention_mode,
7106            working_client_order_id,
7107            working_iceberg_qty,
7108            working_time_in_force,
7109            working_strategy_id,
7110            working_strategy_type,
7111            working_peg_price_type,
7112            working_peg_offset_type,
7113            working_peg_offset_value,
7114            pending_client_order_id,
7115            pending_price,
7116            pending_stop_price,
7117            pending_trailing_delta,
7118            pending_iceberg_qty,
7119            pending_time_in_force,
7120            pending_strategy_id,
7121            pending_strategy_type,
7122            pending_peg_price_type,
7123            pending_peg_offset_type,
7124            pending_peg_offset_value,
7125            recv_window,
7126        } = params;
7127
7128        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7129        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7130        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7131        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7132        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7133        payload.insert(
7134            "workingQuantity".to_string(),
7135            serde_json::json!(working_quantity),
7136        );
7137        payload.insert("pendingType".to_string(), serde_json::json!(pending_type));
7138        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7139        if let Some(value) = id {
7140            payload.insert("id".to_string(), serde_json::json!(value));
7141        }
7142        if let Some(value) = list_client_order_id {
7143            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7144        }
7145        if let Some(value) = new_order_resp_type {
7146            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7147        }
7148        if let Some(value) = self_trade_prevention_mode {
7149            payload.insert(
7150                "selfTradePreventionMode".to_string(),
7151                serde_json::json!(value),
7152            );
7153        }
7154        if let Some(value) = working_client_order_id {
7155            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7156        }
7157        if let Some(value) = working_iceberg_qty {
7158            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7159        }
7160        if let Some(value) = working_time_in_force {
7161            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7162        }
7163        if let Some(value) = working_strategy_id {
7164            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7165        }
7166        if let Some(value) = working_strategy_type {
7167            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7168        }
7169        if let Some(value) = working_peg_price_type {
7170            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7171        }
7172        if let Some(value) = working_peg_offset_type {
7173            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7174        }
7175        if let Some(value) = working_peg_offset_value {
7176            payload.insert(
7177                "workingPegOffsetValue".to_string(),
7178                serde_json::json!(value),
7179            );
7180        }
7181        if let Some(value) = pending_client_order_id {
7182            payload.insert("pendingClientOrderId".to_string(), serde_json::json!(value));
7183        }
7184        if let Some(value) = pending_price {
7185            payload.insert("pendingPrice".to_string(), serde_json::json!(value));
7186        }
7187        if let Some(value) = pending_stop_price {
7188            payload.insert("pendingStopPrice".to_string(), serde_json::json!(value));
7189        }
7190        if let Some(value) = pending_trailing_delta {
7191            payload.insert("pendingTrailingDelta".to_string(), serde_json::json!(value));
7192        }
7193        if let Some(value) = pending_iceberg_qty {
7194            payload.insert("pendingIcebergQty".to_string(), serde_json::json!(value));
7195        }
7196        if let Some(value) = pending_time_in_force {
7197            payload.insert("pendingTimeInForce".to_string(), serde_json::json!(value));
7198        }
7199        if let Some(value) = pending_strategy_id {
7200            payload.insert("pendingStrategyId".to_string(), serde_json::json!(value));
7201        }
7202        if let Some(value) = pending_strategy_type {
7203            payload.insert("pendingStrategyType".to_string(), serde_json::json!(value));
7204        }
7205        if let Some(value) = pending_peg_price_type {
7206            payload.insert("pendingPegPriceType".to_string(), serde_json::json!(value));
7207        }
7208        if let Some(value) = pending_peg_offset_type {
7209            payload.insert("pendingPegOffsetType".to_string(), serde_json::json!(value));
7210        }
7211        if let Some(value) = pending_peg_offset_value {
7212            payload.insert(
7213                "pendingPegOffsetValue".to_string(),
7214                serde_json::json!(value),
7215            );
7216        }
7217        if let Some(value) = recv_window {
7218            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7219        }
7220        let payload = remove_empty_value(payload);
7221
7222        self.websocket_api_base
7223            .send_message::<Box<models::OrderListPlaceOpoResponseResult>>(
7224                "/orderList.place.opo".trim_start_matches('/'),
7225                payload,
7226                WebsocketMessageSendOptions::new().signed(),
7227            )
7228            .await
7229            .map_err(anyhow::Error::from)?
7230            .into_iter()
7231            .next()
7232            .ok_or(WebsocketError::NoResponse)
7233            .map_err(anyhow::Error::from)
7234    }
7235
7236    async fn order_list_place_opoco(
7237        &self,
7238        params: OrderListPlaceOpocoParams,
7239    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOpocoResponseResult>>> {
7240        let OrderListPlaceOpocoParams {
7241            symbol,
7242            working_type,
7243            working_side,
7244            working_price,
7245            working_quantity,
7246            pending_side,
7247            pending_above_type,
7248            id,
7249            list_client_order_id,
7250            new_order_resp_type,
7251            self_trade_prevention_mode,
7252            working_client_order_id,
7253            working_iceberg_qty,
7254            working_time_in_force,
7255            working_strategy_id,
7256            working_strategy_type,
7257            working_peg_price_type,
7258            working_peg_offset_type,
7259            working_peg_offset_value,
7260            pending_above_client_order_id,
7261            pending_above_price,
7262            pending_above_stop_price,
7263            pending_above_trailing_delta,
7264            pending_above_iceberg_qty,
7265            pending_above_time_in_force,
7266            pending_above_strategy_id,
7267            pending_above_strategy_type,
7268            pending_above_peg_price_type,
7269            pending_above_peg_offset_type,
7270            pending_above_peg_offset_value,
7271            pending_below_type,
7272            pending_below_client_order_id,
7273            pending_below_price,
7274            pending_below_stop_price,
7275            pending_below_trailing_delta,
7276            pending_below_iceberg_qty,
7277            pending_below_time_in_force,
7278            pending_below_strategy_id,
7279            pending_below_strategy_type,
7280            pending_below_peg_price_type,
7281            pending_below_peg_offset_type,
7282            pending_below_peg_offset_value,
7283            recv_window,
7284        } = params;
7285
7286        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7287        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7288        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7289        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7290        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7291        payload.insert(
7292            "workingQuantity".to_string(),
7293            serde_json::json!(working_quantity),
7294        );
7295        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7296        payload.insert(
7297            "pendingAboveType".to_string(),
7298            serde_json::json!(pending_above_type),
7299        );
7300        if let Some(value) = id {
7301            payload.insert("id".to_string(), serde_json::json!(value));
7302        }
7303        if let Some(value) = list_client_order_id {
7304            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7305        }
7306        if let Some(value) = new_order_resp_type {
7307            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7308        }
7309        if let Some(value) = self_trade_prevention_mode {
7310            payload.insert(
7311                "selfTradePreventionMode".to_string(),
7312                serde_json::json!(value),
7313            );
7314        }
7315        if let Some(value) = working_client_order_id {
7316            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7317        }
7318        if let Some(value) = working_iceberg_qty {
7319            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7320        }
7321        if let Some(value) = working_time_in_force {
7322            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7323        }
7324        if let Some(value) = working_strategy_id {
7325            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7326        }
7327        if let Some(value) = working_strategy_type {
7328            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7329        }
7330        if let Some(value) = working_peg_price_type {
7331            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7332        }
7333        if let Some(value) = working_peg_offset_type {
7334            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7335        }
7336        if let Some(value) = working_peg_offset_value {
7337            payload.insert(
7338                "workingPegOffsetValue".to_string(),
7339                serde_json::json!(value),
7340            );
7341        }
7342        if let Some(value) = pending_above_client_order_id {
7343            payload.insert(
7344                "pendingAboveClientOrderId".to_string(),
7345                serde_json::json!(value),
7346            );
7347        }
7348        if let Some(value) = pending_above_price {
7349            payload.insert("pendingAbovePrice".to_string(), serde_json::json!(value));
7350        }
7351        if let Some(value) = pending_above_stop_price {
7352            payload.insert(
7353                "pendingAboveStopPrice".to_string(),
7354                serde_json::json!(value),
7355            );
7356        }
7357        if let Some(value) = pending_above_trailing_delta {
7358            payload.insert(
7359                "pendingAboveTrailingDelta".to_string(),
7360                serde_json::json!(value),
7361            );
7362        }
7363        if let Some(value) = pending_above_iceberg_qty {
7364            payload.insert(
7365                "pendingAboveIcebergQty".to_string(),
7366                serde_json::json!(value),
7367            );
7368        }
7369        if let Some(value) = pending_above_time_in_force {
7370            payload.insert(
7371                "pendingAboveTimeInForce".to_string(),
7372                serde_json::json!(value),
7373            );
7374        }
7375        if let Some(value) = pending_above_strategy_id {
7376            payload.insert(
7377                "pendingAboveStrategyId".to_string(),
7378                serde_json::json!(value),
7379            );
7380        }
7381        if let Some(value) = pending_above_strategy_type {
7382            payload.insert(
7383                "pendingAboveStrategyType".to_string(),
7384                serde_json::json!(value),
7385            );
7386        }
7387        if let Some(value) = pending_above_peg_price_type {
7388            payload.insert(
7389                "pendingAbovePegPriceType".to_string(),
7390                serde_json::json!(value),
7391            );
7392        }
7393        if let Some(value) = pending_above_peg_offset_type {
7394            payload.insert(
7395                "pendingAbovePegOffsetType".to_string(),
7396                serde_json::json!(value),
7397            );
7398        }
7399        if let Some(value) = pending_above_peg_offset_value {
7400            payload.insert(
7401                "pendingAbovePegOffsetValue".to_string(),
7402                serde_json::json!(value),
7403            );
7404        }
7405        if let Some(value) = pending_below_type {
7406            payload.insert("pendingBelowType".to_string(), serde_json::json!(value));
7407        }
7408        if let Some(value) = pending_below_client_order_id {
7409            payload.insert(
7410                "pendingBelowClientOrderId".to_string(),
7411                serde_json::json!(value),
7412            );
7413        }
7414        if let Some(value) = pending_below_price {
7415            payload.insert("pendingBelowPrice".to_string(), serde_json::json!(value));
7416        }
7417        if let Some(value) = pending_below_stop_price {
7418            payload.insert(
7419                "pendingBelowStopPrice".to_string(),
7420                serde_json::json!(value),
7421            );
7422        }
7423        if let Some(value) = pending_below_trailing_delta {
7424            payload.insert(
7425                "pendingBelowTrailingDelta".to_string(),
7426                serde_json::json!(value),
7427            );
7428        }
7429        if let Some(value) = pending_below_iceberg_qty {
7430            payload.insert(
7431                "pendingBelowIcebergQty".to_string(),
7432                serde_json::json!(value),
7433            );
7434        }
7435        if let Some(value) = pending_below_time_in_force {
7436            payload.insert(
7437                "pendingBelowTimeInForce".to_string(),
7438                serde_json::json!(value),
7439            );
7440        }
7441        if let Some(value) = pending_below_strategy_id {
7442            payload.insert(
7443                "pendingBelowStrategyId".to_string(),
7444                serde_json::json!(value),
7445            );
7446        }
7447        if let Some(value) = pending_below_strategy_type {
7448            payload.insert(
7449                "pendingBelowStrategyType".to_string(),
7450                serde_json::json!(value),
7451            );
7452        }
7453        if let Some(value) = pending_below_peg_price_type {
7454            payload.insert(
7455                "pendingBelowPegPriceType".to_string(),
7456                serde_json::json!(value),
7457            );
7458        }
7459        if let Some(value) = pending_below_peg_offset_type {
7460            payload.insert(
7461                "pendingBelowPegOffsetType".to_string(),
7462                serde_json::json!(value),
7463            );
7464        }
7465        if let Some(value) = pending_below_peg_offset_value {
7466            payload.insert(
7467                "pendingBelowPegOffsetValue".to_string(),
7468                serde_json::json!(value),
7469            );
7470        }
7471        if let Some(value) = recv_window {
7472            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7473        }
7474        let payload = remove_empty_value(payload);
7475
7476        self.websocket_api_base
7477            .send_message::<Box<models::OrderListPlaceOpocoResponseResult>>(
7478                "/orderList.place.opoco".trim_start_matches('/'),
7479                payload,
7480                WebsocketMessageSendOptions::new().signed(),
7481            )
7482            .await
7483            .map_err(anyhow::Error::from)?
7484            .into_iter()
7485            .next()
7486            .ok_or(WebsocketError::NoResponse)
7487            .map_err(anyhow::Error::from)
7488    }
7489
7490    async fn order_list_place_oto(
7491        &self,
7492        params: OrderListPlaceOtoParams,
7493    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtoResponseResult>>> {
7494        let OrderListPlaceOtoParams {
7495            symbol,
7496            working_type,
7497            working_side,
7498            working_price,
7499            working_quantity,
7500            pending_type,
7501            pending_side,
7502            pending_quantity,
7503            id,
7504            list_client_order_id,
7505            new_order_resp_type,
7506            self_trade_prevention_mode,
7507            working_client_order_id,
7508            working_iceberg_qty,
7509            working_time_in_force,
7510            working_strategy_id,
7511            working_strategy_type,
7512            working_peg_price_type,
7513            working_peg_offset_type,
7514            working_peg_offset_value,
7515            pending_client_order_id,
7516            pending_price,
7517            pending_stop_price,
7518            pending_trailing_delta,
7519            pending_iceberg_qty,
7520            pending_time_in_force,
7521            pending_strategy_id,
7522            pending_strategy_type,
7523            pending_peg_offset_type,
7524            pending_peg_price_type,
7525            pending_peg_offset_value,
7526            recv_window,
7527        } = params;
7528
7529        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7530        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7531        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7532        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7533        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7534        payload.insert(
7535            "workingQuantity".to_string(),
7536            serde_json::json!(working_quantity),
7537        );
7538        payload.insert("pendingType".to_string(), serde_json::json!(pending_type));
7539        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7540        payload.insert(
7541            "pendingQuantity".to_string(),
7542            serde_json::json!(pending_quantity),
7543        );
7544        if let Some(value) = id {
7545            payload.insert("id".to_string(), serde_json::json!(value));
7546        }
7547        if let Some(value) = list_client_order_id {
7548            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7549        }
7550        if let Some(value) = new_order_resp_type {
7551            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7552        }
7553        if let Some(value) = self_trade_prevention_mode {
7554            payload.insert(
7555                "selfTradePreventionMode".to_string(),
7556                serde_json::json!(value),
7557            );
7558        }
7559        if let Some(value) = working_client_order_id {
7560            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7561        }
7562        if let Some(value) = working_iceberg_qty {
7563            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7564        }
7565        if let Some(value) = working_time_in_force {
7566            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7567        }
7568        if let Some(value) = working_strategy_id {
7569            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7570        }
7571        if let Some(value) = working_strategy_type {
7572            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7573        }
7574        if let Some(value) = working_peg_price_type {
7575            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7576        }
7577        if let Some(value) = working_peg_offset_type {
7578            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7579        }
7580        if let Some(value) = working_peg_offset_value {
7581            payload.insert(
7582                "workingPegOffsetValue".to_string(),
7583                serde_json::json!(value),
7584            );
7585        }
7586        if let Some(value) = pending_client_order_id {
7587            payload.insert("pendingClientOrderId".to_string(), serde_json::json!(value));
7588        }
7589        if let Some(value) = pending_price {
7590            payload.insert("pendingPrice".to_string(), serde_json::json!(value));
7591        }
7592        if let Some(value) = pending_stop_price {
7593            payload.insert("pendingStopPrice".to_string(), serde_json::json!(value));
7594        }
7595        if let Some(value) = pending_trailing_delta {
7596            payload.insert("pendingTrailingDelta".to_string(), serde_json::json!(value));
7597        }
7598        if let Some(value) = pending_iceberg_qty {
7599            payload.insert("pendingIcebergQty".to_string(), serde_json::json!(value));
7600        }
7601        if let Some(value) = pending_time_in_force {
7602            payload.insert("pendingTimeInForce".to_string(), serde_json::json!(value));
7603        }
7604        if let Some(value) = pending_strategy_id {
7605            payload.insert("pendingStrategyId".to_string(), serde_json::json!(value));
7606        }
7607        if let Some(value) = pending_strategy_type {
7608            payload.insert("pendingStrategyType".to_string(), serde_json::json!(value));
7609        }
7610        if let Some(value) = pending_peg_offset_type {
7611            payload.insert("pendingPegOffsetType".to_string(), serde_json::json!(value));
7612        }
7613        if let Some(value) = pending_peg_price_type {
7614            payload.insert("pendingPegPriceType".to_string(), serde_json::json!(value));
7615        }
7616        if let Some(value) = pending_peg_offset_value {
7617            payload.insert(
7618                "pendingPegOffsetValue".to_string(),
7619                serde_json::json!(value),
7620            );
7621        }
7622        if let Some(value) = recv_window {
7623            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7624        }
7625        let payload = remove_empty_value(payload);
7626
7627        self.websocket_api_base
7628            .send_message::<Box<models::OrderListPlaceOtoResponseResult>>(
7629                "/orderList.place.oto".trim_start_matches('/'),
7630                payload,
7631                WebsocketMessageSendOptions::new().signed(),
7632            )
7633            .await
7634            .map_err(anyhow::Error::from)?
7635            .into_iter()
7636            .next()
7637            .ok_or(WebsocketError::NoResponse)
7638            .map_err(anyhow::Error::from)
7639    }
7640
7641    async fn order_list_place_otoco(
7642        &self,
7643        params: OrderListPlaceOtocoParams,
7644    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderListPlaceOtocoResponseResult>>> {
7645        let OrderListPlaceOtocoParams {
7646            symbol,
7647            working_type,
7648            working_side,
7649            working_price,
7650            working_quantity,
7651            pending_side,
7652            pending_quantity,
7653            pending_above_type,
7654            id,
7655            list_client_order_id,
7656            new_order_resp_type,
7657            self_trade_prevention_mode,
7658            working_client_order_id,
7659            working_iceberg_qty,
7660            working_time_in_force,
7661            working_strategy_id,
7662            working_strategy_type,
7663            working_peg_price_type,
7664            working_peg_offset_type,
7665            working_peg_offset_value,
7666            pending_above_client_order_id,
7667            pending_above_price,
7668            pending_above_stop_price,
7669            pending_above_trailing_delta,
7670            pending_above_iceberg_qty,
7671            pending_above_time_in_force,
7672            pending_above_strategy_id,
7673            pending_above_strategy_type,
7674            pending_above_peg_price_type,
7675            pending_above_peg_offset_type,
7676            pending_above_peg_offset_value,
7677            pending_below_type,
7678            pending_below_client_order_id,
7679            pending_below_price,
7680            pending_below_stop_price,
7681            pending_below_trailing_delta,
7682            pending_below_iceberg_qty,
7683            pending_below_time_in_force,
7684            pending_below_strategy_id,
7685            pending_below_strategy_type,
7686            pending_below_peg_price_type,
7687            pending_below_peg_offset_type,
7688            pending_below_peg_offset_value,
7689            recv_window,
7690        } = params;
7691
7692        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7693        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7694        payload.insert("workingType".to_string(), serde_json::json!(working_type));
7695        payload.insert("workingSide".to_string(), serde_json::json!(working_side));
7696        payload.insert("workingPrice".to_string(), serde_json::json!(working_price));
7697        payload.insert(
7698            "workingQuantity".to_string(),
7699            serde_json::json!(working_quantity),
7700        );
7701        payload.insert("pendingSide".to_string(), serde_json::json!(pending_side));
7702        payload.insert(
7703            "pendingQuantity".to_string(),
7704            serde_json::json!(pending_quantity),
7705        );
7706        payload.insert(
7707            "pendingAboveType".to_string(),
7708            serde_json::json!(pending_above_type),
7709        );
7710        if let Some(value) = id {
7711            payload.insert("id".to_string(), serde_json::json!(value));
7712        }
7713        if let Some(value) = list_client_order_id {
7714            payload.insert("listClientOrderId".to_string(), serde_json::json!(value));
7715        }
7716        if let Some(value) = new_order_resp_type {
7717            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7718        }
7719        if let Some(value) = self_trade_prevention_mode {
7720            payload.insert(
7721                "selfTradePreventionMode".to_string(),
7722                serde_json::json!(value),
7723            );
7724        }
7725        if let Some(value) = working_client_order_id {
7726            payload.insert("workingClientOrderId".to_string(), serde_json::json!(value));
7727        }
7728        if let Some(value) = working_iceberg_qty {
7729            payload.insert("workingIcebergQty".to_string(), serde_json::json!(value));
7730        }
7731        if let Some(value) = working_time_in_force {
7732            payload.insert("workingTimeInForce".to_string(), serde_json::json!(value));
7733        }
7734        if let Some(value) = working_strategy_id {
7735            payload.insert("workingStrategyId".to_string(), serde_json::json!(value));
7736        }
7737        if let Some(value) = working_strategy_type {
7738            payload.insert("workingStrategyType".to_string(), serde_json::json!(value));
7739        }
7740        if let Some(value) = working_peg_price_type {
7741            payload.insert("workingPegPriceType".to_string(), serde_json::json!(value));
7742        }
7743        if let Some(value) = working_peg_offset_type {
7744            payload.insert("workingPegOffsetType".to_string(), serde_json::json!(value));
7745        }
7746        if let Some(value) = working_peg_offset_value {
7747            payload.insert(
7748                "workingPegOffsetValue".to_string(),
7749                serde_json::json!(value),
7750            );
7751        }
7752        if let Some(value) = pending_above_client_order_id {
7753            payload.insert(
7754                "pendingAboveClientOrderId".to_string(),
7755                serde_json::json!(value),
7756            );
7757        }
7758        if let Some(value) = pending_above_price {
7759            payload.insert("pendingAbovePrice".to_string(), serde_json::json!(value));
7760        }
7761        if let Some(value) = pending_above_stop_price {
7762            payload.insert(
7763                "pendingAboveStopPrice".to_string(),
7764                serde_json::json!(value),
7765            );
7766        }
7767        if let Some(value) = pending_above_trailing_delta {
7768            payload.insert(
7769                "pendingAboveTrailingDelta".to_string(),
7770                serde_json::json!(value),
7771            );
7772        }
7773        if let Some(value) = pending_above_iceberg_qty {
7774            payload.insert(
7775                "pendingAboveIcebergQty".to_string(),
7776                serde_json::json!(value),
7777            );
7778        }
7779        if let Some(value) = pending_above_time_in_force {
7780            payload.insert(
7781                "pendingAboveTimeInForce".to_string(),
7782                serde_json::json!(value),
7783            );
7784        }
7785        if let Some(value) = pending_above_strategy_id {
7786            payload.insert(
7787                "pendingAboveStrategyId".to_string(),
7788                serde_json::json!(value),
7789            );
7790        }
7791        if let Some(value) = pending_above_strategy_type {
7792            payload.insert(
7793                "pendingAboveStrategyType".to_string(),
7794                serde_json::json!(value),
7795            );
7796        }
7797        if let Some(value) = pending_above_peg_price_type {
7798            payload.insert(
7799                "pendingAbovePegPriceType".to_string(),
7800                serde_json::json!(value),
7801            );
7802        }
7803        if let Some(value) = pending_above_peg_offset_type {
7804            payload.insert(
7805                "pendingAbovePegOffsetType".to_string(),
7806                serde_json::json!(value),
7807            );
7808        }
7809        if let Some(value) = pending_above_peg_offset_value {
7810            payload.insert(
7811                "pendingAbovePegOffsetValue".to_string(),
7812                serde_json::json!(value),
7813            );
7814        }
7815        if let Some(value) = pending_below_type {
7816            payload.insert("pendingBelowType".to_string(), serde_json::json!(value));
7817        }
7818        if let Some(value) = pending_below_client_order_id {
7819            payload.insert(
7820                "pendingBelowClientOrderId".to_string(),
7821                serde_json::json!(value),
7822            );
7823        }
7824        if let Some(value) = pending_below_price {
7825            payload.insert("pendingBelowPrice".to_string(), serde_json::json!(value));
7826        }
7827        if let Some(value) = pending_below_stop_price {
7828            payload.insert(
7829                "pendingBelowStopPrice".to_string(),
7830                serde_json::json!(value),
7831            );
7832        }
7833        if let Some(value) = pending_below_trailing_delta {
7834            payload.insert(
7835                "pendingBelowTrailingDelta".to_string(),
7836                serde_json::json!(value),
7837            );
7838        }
7839        if let Some(value) = pending_below_iceberg_qty {
7840            payload.insert(
7841                "pendingBelowIcebergQty".to_string(),
7842                serde_json::json!(value),
7843            );
7844        }
7845        if let Some(value) = pending_below_time_in_force {
7846            payload.insert(
7847                "pendingBelowTimeInForce".to_string(),
7848                serde_json::json!(value),
7849            );
7850        }
7851        if let Some(value) = pending_below_strategy_id {
7852            payload.insert(
7853                "pendingBelowStrategyId".to_string(),
7854                serde_json::json!(value),
7855            );
7856        }
7857        if let Some(value) = pending_below_strategy_type {
7858            payload.insert(
7859                "pendingBelowStrategyType".to_string(),
7860                serde_json::json!(value),
7861            );
7862        }
7863        if let Some(value) = pending_below_peg_price_type {
7864            payload.insert(
7865                "pendingBelowPegPriceType".to_string(),
7866                serde_json::json!(value),
7867            );
7868        }
7869        if let Some(value) = pending_below_peg_offset_type {
7870            payload.insert(
7871                "pendingBelowPegOffsetType".to_string(),
7872                serde_json::json!(value),
7873            );
7874        }
7875        if let Some(value) = pending_below_peg_offset_value {
7876            payload.insert(
7877                "pendingBelowPegOffsetValue".to_string(),
7878                serde_json::json!(value),
7879            );
7880        }
7881        if let Some(value) = recv_window {
7882            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7883        }
7884        let payload = remove_empty_value(payload);
7885
7886        self.websocket_api_base
7887            .send_message::<Box<models::OrderListPlaceOtocoResponseResult>>(
7888                "/orderList.place.otoco".trim_start_matches('/'),
7889                payload,
7890                WebsocketMessageSendOptions::new().signed(),
7891            )
7892            .await
7893            .map_err(anyhow::Error::from)?
7894            .into_iter()
7895            .next()
7896            .ok_or(WebsocketError::NoResponse)
7897            .map_err(anyhow::Error::from)
7898    }
7899
7900    async fn order_place(
7901        &self,
7902        params: OrderPlaceParams,
7903    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderPlaceResponseResult>>> {
7904        let OrderPlaceParams {
7905            symbol,
7906            side,
7907            r#type,
7908            id,
7909            time_in_force,
7910            price,
7911            quantity,
7912            quote_order_qty,
7913            new_client_order_id,
7914            new_order_resp_type,
7915            stop_price,
7916            trailing_delta,
7917            iceberg_qty,
7918            strategy_id,
7919            strategy_type,
7920            self_trade_prevention_mode,
7921            peg_price_type,
7922            peg_offset_value,
7923            peg_offset_type,
7924            recv_window,
7925        } = params;
7926
7927        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
7928        payload.insert("symbol".to_string(), serde_json::json!(symbol));
7929        payload.insert("side".to_string(), serde_json::json!(side));
7930        payload.insert("type".to_string(), serde_json::json!(r#type));
7931        if let Some(value) = id {
7932            payload.insert("id".to_string(), serde_json::json!(value));
7933        }
7934        if let Some(value) = time_in_force {
7935            payload.insert("timeInForce".to_string(), serde_json::json!(value));
7936        }
7937        if let Some(value) = price {
7938            payload.insert("price".to_string(), serde_json::json!(value));
7939        }
7940        if let Some(value) = quantity {
7941            payload.insert("quantity".to_string(), serde_json::json!(value));
7942        }
7943        if let Some(value) = quote_order_qty {
7944            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
7945        }
7946        if let Some(value) = new_client_order_id {
7947            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
7948        }
7949        if let Some(value) = new_order_resp_type {
7950            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
7951        }
7952        if let Some(value) = stop_price {
7953            payload.insert("stopPrice".to_string(), serde_json::json!(value));
7954        }
7955        if let Some(value) = trailing_delta {
7956            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
7957        }
7958        if let Some(value) = iceberg_qty {
7959            payload.insert("icebergQty".to_string(), serde_json::json!(value));
7960        }
7961        if let Some(value) = strategy_id {
7962            payload.insert("strategyId".to_string(), serde_json::json!(value));
7963        }
7964        if let Some(value) = strategy_type {
7965            payload.insert("strategyType".to_string(), serde_json::json!(value));
7966        }
7967        if let Some(value) = self_trade_prevention_mode {
7968            payload.insert(
7969                "selfTradePreventionMode".to_string(),
7970                serde_json::json!(value),
7971            );
7972        }
7973        if let Some(value) = peg_price_type {
7974            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
7975        }
7976        if let Some(value) = peg_offset_value {
7977            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
7978        }
7979        if let Some(value) = peg_offset_type {
7980            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
7981        }
7982        if let Some(value) = recv_window {
7983            payload.insert("recvWindow".to_string(), serde_json::json!(value));
7984        }
7985        let payload = remove_empty_value(payload);
7986
7987        self.websocket_api_base
7988            .send_message::<Box<models::OrderPlaceResponseResult>>(
7989                "/order.place".trim_start_matches('/'),
7990                payload,
7991                WebsocketMessageSendOptions::new().signed(),
7992            )
7993            .await
7994            .map_err(anyhow::Error::from)?
7995            .into_iter()
7996            .next()
7997            .ok_or(WebsocketError::NoResponse)
7998            .map_err(anyhow::Error::from)
7999    }
8000
8001    async fn order_test(
8002        &self,
8003        params: OrderTestParams,
8004    ) -> anyhow::Result<WebsocketApiResponse<Box<models::OrderTestResponseResult>>> {
8005        let OrderTestParams {
8006            symbol,
8007            side,
8008            r#type,
8009            id,
8010            compute_commission_rates,
8011            time_in_force,
8012            price,
8013            quantity,
8014            quote_order_qty,
8015            new_client_order_id,
8016            new_order_resp_type,
8017            stop_price,
8018            trailing_delta,
8019            iceberg_qty,
8020            strategy_id,
8021            strategy_type,
8022            self_trade_prevention_mode,
8023            peg_price_type,
8024            peg_offset_value,
8025            peg_offset_type,
8026            recv_window,
8027        } = params;
8028
8029        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
8030        payload.insert("symbol".to_string(), serde_json::json!(symbol));
8031        payload.insert("side".to_string(), serde_json::json!(side));
8032        payload.insert("type".to_string(), serde_json::json!(r#type));
8033        if let Some(value) = id {
8034            payload.insert("id".to_string(), serde_json::json!(value));
8035        }
8036        if let Some(value) = compute_commission_rates {
8037            payload.insert(
8038                "computeCommissionRates".to_string(),
8039                serde_json::json!(value),
8040            );
8041        }
8042        if let Some(value) = time_in_force {
8043            payload.insert("timeInForce".to_string(), serde_json::json!(value));
8044        }
8045        if let Some(value) = price {
8046            payload.insert("price".to_string(), serde_json::json!(value));
8047        }
8048        if let Some(value) = quantity {
8049            payload.insert("quantity".to_string(), serde_json::json!(value));
8050        }
8051        if let Some(value) = quote_order_qty {
8052            payload.insert("quoteOrderQty".to_string(), serde_json::json!(value));
8053        }
8054        if let Some(value) = new_client_order_id {
8055            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8056        }
8057        if let Some(value) = new_order_resp_type {
8058            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8059        }
8060        if let Some(value) = stop_price {
8061            payload.insert("stopPrice".to_string(), serde_json::json!(value));
8062        }
8063        if let Some(value) = trailing_delta {
8064            payload.insert("trailingDelta".to_string(), serde_json::json!(value));
8065        }
8066        if let Some(value) = iceberg_qty {
8067            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8068        }
8069        if let Some(value) = strategy_id {
8070            payload.insert("strategyId".to_string(), serde_json::json!(value));
8071        }
8072        if let Some(value) = strategy_type {
8073            payload.insert("strategyType".to_string(), serde_json::json!(value));
8074        }
8075        if let Some(value) = self_trade_prevention_mode {
8076            payload.insert(
8077                "selfTradePreventionMode".to_string(),
8078                serde_json::json!(value),
8079            );
8080        }
8081        if let Some(value) = peg_price_type {
8082            payload.insert("pegPriceType".to_string(), serde_json::json!(value));
8083        }
8084        if let Some(value) = peg_offset_value {
8085            payload.insert("pegOffsetValue".to_string(), serde_json::json!(value));
8086        }
8087        if let Some(value) = peg_offset_type {
8088            payload.insert("pegOffsetType".to_string(), serde_json::json!(value));
8089        }
8090        if let Some(value) = recv_window {
8091            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8092        }
8093        let payload = remove_empty_value(payload);
8094
8095        self.websocket_api_base
8096            .send_message::<Box<models::OrderTestResponseResult>>(
8097                "/order.test".trim_start_matches('/'),
8098                payload,
8099                WebsocketMessageSendOptions::new().signed(),
8100            )
8101            .await
8102            .map_err(anyhow::Error::from)?
8103            .into_iter()
8104            .next()
8105            .ok_or(WebsocketError::NoResponse)
8106            .map_err(anyhow::Error::from)
8107    }
8108
8109    async fn sor_order_place(
8110        &self,
8111        params: SorOrderPlaceParams,
8112    ) -> anyhow::Result<WebsocketApiResponse<Vec<models::SorOrderPlaceResponseResultInner>>> {
8113        let SorOrderPlaceParams {
8114            symbol,
8115            side,
8116            r#type,
8117            quantity,
8118            id,
8119            time_in_force,
8120            price,
8121            new_client_order_id,
8122            new_order_resp_type,
8123            iceberg_qty,
8124            strategy_id,
8125            strategy_type,
8126            self_trade_prevention_mode,
8127            recv_window,
8128        } = params;
8129
8130        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
8131        payload.insert("symbol".to_string(), serde_json::json!(symbol));
8132        payload.insert("side".to_string(), serde_json::json!(side));
8133        payload.insert("type".to_string(), serde_json::json!(r#type));
8134        payload.insert("quantity".to_string(), serde_json::json!(quantity));
8135        if let Some(value) = id {
8136            payload.insert("id".to_string(), serde_json::json!(value));
8137        }
8138        if let Some(value) = time_in_force {
8139            payload.insert("timeInForce".to_string(), serde_json::json!(value));
8140        }
8141        if let Some(value) = price {
8142            payload.insert("price".to_string(), serde_json::json!(value));
8143        }
8144        if let Some(value) = new_client_order_id {
8145            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8146        }
8147        if let Some(value) = new_order_resp_type {
8148            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8149        }
8150        if let Some(value) = iceberg_qty {
8151            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8152        }
8153        if let Some(value) = strategy_id {
8154            payload.insert("strategyId".to_string(), serde_json::json!(value));
8155        }
8156        if let Some(value) = strategy_type {
8157            payload.insert("strategyType".to_string(), serde_json::json!(value));
8158        }
8159        if let Some(value) = self_trade_prevention_mode {
8160            payload.insert(
8161                "selfTradePreventionMode".to_string(),
8162                serde_json::json!(value),
8163            );
8164        }
8165        if let Some(value) = recv_window {
8166            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8167        }
8168        let payload = remove_empty_value(payload);
8169
8170        self.websocket_api_base
8171            .send_message::<Vec<models::SorOrderPlaceResponseResultInner>>(
8172                "/sor.order.place".trim_start_matches('/'),
8173                payload,
8174                WebsocketMessageSendOptions::new().signed(),
8175            )
8176            .await
8177            .map_err(anyhow::Error::from)?
8178            .into_iter()
8179            .next()
8180            .ok_or(WebsocketError::NoResponse)
8181            .map_err(anyhow::Error::from)
8182    }
8183
8184    async fn sor_order_test(
8185        &self,
8186        params: SorOrderTestParams,
8187    ) -> anyhow::Result<WebsocketApiResponse<Box<models::SorOrderTestResponseResult>>> {
8188        let SorOrderTestParams {
8189            symbol,
8190            side,
8191            r#type,
8192            quantity,
8193            id,
8194            compute_commission_rates,
8195            time_in_force,
8196            price,
8197            new_client_order_id,
8198            new_order_resp_type,
8199            iceberg_qty,
8200            strategy_id,
8201            strategy_type,
8202            self_trade_prevention_mode,
8203            recv_window,
8204        } = params;
8205
8206        let mut payload: BTreeMap<String, Value> = BTreeMap::new();
8207        payload.insert("symbol".to_string(), serde_json::json!(symbol));
8208        payload.insert("side".to_string(), serde_json::json!(side));
8209        payload.insert("type".to_string(), serde_json::json!(r#type));
8210        payload.insert("quantity".to_string(), serde_json::json!(quantity));
8211        if let Some(value) = id {
8212            payload.insert("id".to_string(), serde_json::json!(value));
8213        }
8214        if let Some(value) = compute_commission_rates {
8215            payload.insert(
8216                "computeCommissionRates".to_string(),
8217                serde_json::json!(value),
8218            );
8219        }
8220        if let Some(value) = time_in_force {
8221            payload.insert("timeInForce".to_string(), serde_json::json!(value));
8222        }
8223        if let Some(value) = price {
8224            payload.insert("price".to_string(), serde_json::json!(value));
8225        }
8226        if let Some(value) = new_client_order_id {
8227            payload.insert("newClientOrderId".to_string(), serde_json::json!(value));
8228        }
8229        if let Some(value) = new_order_resp_type {
8230            payload.insert("newOrderRespType".to_string(), serde_json::json!(value));
8231        }
8232        if let Some(value) = iceberg_qty {
8233            payload.insert("icebergQty".to_string(), serde_json::json!(value));
8234        }
8235        if let Some(value) = strategy_id {
8236            payload.insert("strategyId".to_string(), serde_json::json!(value));
8237        }
8238        if let Some(value) = strategy_type {
8239            payload.insert("strategyType".to_string(), serde_json::json!(value));
8240        }
8241        if let Some(value) = self_trade_prevention_mode {
8242            payload.insert(
8243                "selfTradePreventionMode".to_string(),
8244                serde_json::json!(value),
8245            );
8246        }
8247        if let Some(value) = recv_window {
8248            payload.insert("recvWindow".to_string(), serde_json::json!(value));
8249        }
8250        let payload = remove_empty_value(payload);
8251
8252        self.websocket_api_base
8253            .send_message::<Box<models::SorOrderTestResponseResult>>(
8254                "/sor.order.test".trim_start_matches('/'),
8255                payload,
8256                WebsocketMessageSendOptions::new().signed(),
8257            )
8258            .await
8259            .map_err(anyhow::Error::from)?
8260            .into_iter()
8261            .next()
8262            .ok_or(WebsocketError::NoResponse)
8263            .map_err(anyhow::Error::from)
8264    }
8265}
8266
8267#[cfg(all(test, feature = "spot"))]
8268mod tests {
8269    use super::*;
8270    use crate::TOKIO_SHARED_RT;
8271    use crate::common::websocket::{WebsocketApi, WebsocketConnection, WebsocketHandler};
8272    use crate::config::ConfigurationWebsocketApi;
8273    use crate::errors::WebsocketError;
8274    use crate::models::WebsocketApiRateLimit;
8275    use serde_json::{Value, json};
8276    use tokio::spawn;
8277    use tokio::sync::mpsc::{UnboundedReceiver, unbounded_channel};
8278    use tokio::time::{Duration, timeout};
8279    use tokio_tungstenite::tungstenite::Message;
8280
8281    async fn setup() -> (
8282        Arc<WebsocketApi>,
8283        Arc<WebsocketConnection>,
8284        UnboundedReceiver<Message>,
8285    ) {
8286        let conn = WebsocketConnection::new("test-conn");
8287        let (tx, rx) = unbounded_channel::<Message>();
8288        {
8289            let mut conn_state = conn.state.lock().await;
8290            conn_state.ws_write_tx = Some(tx);
8291        }
8292
8293        let config = ConfigurationWebsocketApi::builder()
8294            .api_key("key")
8295            .api_secret("secret")
8296            .build()
8297            .expect("Failed to build configuration");
8298        let ws_api = WebsocketApi::new(config, vec![conn.clone()]);
8299        conn.set_handler(ws_api.clone() as Arc<dyn WebsocketHandler>)
8300            .await;
8301        ws_api.clone().connect().await.unwrap();
8302
8303        (ws_api, conn, rx)
8304    }
8305
8306    #[test]
8307    fn open_orders_cancel_all_success() {
8308        TOKIO_SHARED_RT.block_on(async {
8309            let (ws_api, conn, mut rx) = setup().await;
8310            let client = TradeApiClient::new(ws_api.clone());
8311
8312            let handle = spawn(async move {
8313                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string(),).build().unwrap();
8314                client.open_orders_cancel_all(params).await
8315            });
8316
8317            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8318            let Message::Text(text) = sent else { panic!() };
8319            let v: Value = serde_json::from_str(&text).unwrap();
8320            let id = v["id"].as_str().unwrap();
8321            assert_eq!(v["method"], "/openOrders.cancelAll".trim_start_matches('/'));
8322
8323            let mut resp_json: Value = serde_json::from_str(r#"{"id":"778f938f-9041-4b88-9914-efbf64eeacc8","status":200,"result":[{"orderListId":19431,"contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"iuVNVJYYrByz6C4yGOPPK0","transactionTime":1660803702431,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569099454,"clientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW"},{"symbol":"BTCUSDT","orderId":12569099453,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY"}],"orderReports":[{"symbol":"BTCUSDT","origClientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW","orderId":12569099454,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23400.00000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT_MAKER","side":"BUY","selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","origClientOrderId":"bX5wROblo6YeDwa9iTLeyY","orderId":12569099453,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23450.50000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","stopPrice":"23430.00000000","selfTradePreventionMode":"NONE"}]},{"symbol":"BTCUSDT","origClientOrderId":"4d96324ff9d44481926157","orderId":12569099453,"orderListId":-1,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"price":"23416.10000000","origQty":"0.00847000","executedQty":"0.00001000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.23416100","status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","stopPrice":"0.00000000","trailingDelta":0,"trailingTime":-1,"icebergQty":"0.00000000","strategyId":37463720,"strategyType":1000000,"selfTradePreventionMode":"NONE"}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8324            resp_json["id"] = id.into();
8325
8326            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8327            let expected_data: Vec<models::OpenOrdersCancelAllResponseResultInner> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8328            let empty_array = Value::Array(vec![]);
8329            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8330            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8331                match raw_rate_limits.as_array() {
8332                    Some(arr) if arr.is_empty() => None,
8333                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8334                    None => None,
8335                };
8336
8337            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8338
8339            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8340
8341
8342            let response_rate_limits = response.rate_limits.clone();
8343            let response_data = response.data().expect("deserialize data");
8344
8345            assert_eq!(response_rate_limits, expected_rate_limits);
8346            assert_eq!(response_data, expected_data);
8347        });
8348    }
8349
8350    #[test]
8351    fn open_orders_cancel_all_error_response() {
8352        TOKIO_SHARED_RT.block_on(async {
8353            let (ws_api, conn, mut rx) = setup().await;
8354            let client = TradeApiClient::new(ws_api.clone());
8355
8356            let handle = tokio::spawn(async move {
8357                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string(),).build().unwrap();
8358                client.open_orders_cancel_all(params).await
8359            });
8360
8361            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8362            let Message::Text(text) = sent else { panic!() };
8363            let v: Value = serde_json::from_str(&text).unwrap();
8364            let id = v["id"].as_str().unwrap().to_string();
8365
8366            let resp_json = json!({
8367                "id": id,
8368                "status": 400,
8369                    "error": {
8370                        "code": -2010,
8371                        "msg": "Account has insufficient balance for requested action.",
8372                    },
8373                    "rateLimits": [
8374                        {
8375                            "rateLimitType": "ORDERS",
8376                            "interval": "SECOND",
8377                            "intervalNum": 10,
8378                            "limit": 50,
8379                            "count": 13
8380                        },
8381                    ],
8382            });
8383            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8384
8385            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8386            match join {
8387                Ok(Err(e)) => {
8388                    let msg = e.to_string();
8389                    assert!(
8390                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8391                        "Expected error msg to contain server error, got: {msg}"
8392                    );
8393                }
8394                Ok(Ok(_)) => panic!("Expected error"),
8395                Err(_) => panic!("Task panicked"),
8396            }
8397        });
8398    }
8399
8400    #[test]
8401    fn open_orders_cancel_all_request_timeout() {
8402        TOKIO_SHARED_RT.block_on(async {
8403            let (ws_api, _conn, mut rx) = setup().await;
8404            let client = TradeApiClient::new(ws_api.clone());
8405
8406            let handle = spawn(async move {
8407                let params = OpenOrdersCancelAllParams::builder("BNBUSDT".to_string())
8408                    .build()
8409                    .unwrap();
8410                client.open_orders_cancel_all(params).await
8411            });
8412
8413            let sent = timeout(Duration::from_secs(1), rx.recv())
8414                .await
8415                .expect("send should occur")
8416                .expect("channel closed");
8417            let Message::Text(text) = sent else {
8418                panic!("expected Message Text")
8419            };
8420
8421            let _: Value = serde_json::from_str(&text).unwrap();
8422
8423            let result = handle.await.expect("task completed");
8424            match result {
8425                Err(e) => {
8426                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8427                        assert!(matches!(inner, WebsocketError::Timeout));
8428                    } else {
8429                        panic!("Unexpected error type: {:?}", e);
8430                    }
8431                }
8432                Ok(_) => panic!("Expected timeout error"),
8433            }
8434        });
8435    }
8436
8437    #[test]
8438    fn order_amend_keep_priority_success() {
8439        TOKIO_SHARED_RT.block_on(async {
8440            let (ws_api, conn, mut rx) = setup().await;
8441            let client = TradeApiClient::new(ws_api.clone());
8442
8443            let handle = spawn(async move {
8444                let params = OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(),dec!(1.0),).build().unwrap();
8445                client.order_amend_keep_priority(params).await
8446            });
8447
8448            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8449            let Message::Text(text) = sent else { panic!() };
8450            let v: Value = serde_json::from_str(&text).unwrap();
8451            let id = v["id"].as_str().unwrap();
8452            assert_eq!(v["method"], "/order.amend.keepPriority".trim_start_matches('/'));
8453
8454            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374b46-3061-486b-a311-89ee972eb648","status":200,"result":{"transactTime":1741924229819,"executionId":60,"amendedOrder":{"symbol":"BTUCSDT","orderId":23,"orderListId":4,"origClientOrderId":"my_pending_order","clientOrderId":"xbxXh5SSwaHS7oUEOCI88B","price":"1.00000000","qty":"5.00000000","executedQty":"0.00000000","preventedQty":"0.00000000","quoteOrderQty":"0.00000000","cumulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1741924204920,"selfTradePreventionMode":"NONE"},"listStatus":{"orderListId":4,"contingencyType":"OTO","listOrderStatus":"EXECUTING","listClientOrderId":"8nOGLLawudj1QoOiwbroRH","symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":23,"clientOrderId":"xbxXh5SSwaHS7oUEOCI88B"},{"symbol":"BTCUSDT","orderId":22,"clientOrderId":"g04EWsjaackzedjC9wRkWD"},{"symbol":"BTCUSDT","orderId":23,"clientOrderId":"xbxXh5SSwaHS7oUEOCI88B"},{"symbol":"BTCUSDT","orderId":22,"clientOrderId":"g04EWsjaackzedjC9wRkWD"}]}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8455            resp_json["id"] = id.into();
8456
8457            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8458            let expected_data: Box<models::OrderAmendKeepPriorityResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8459            let empty_array = Value::Array(vec![]);
8460            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8461            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8462                match raw_rate_limits.as_array() {
8463                    Some(arr) if arr.is_empty() => None,
8464                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8465                    None => None,
8466                };
8467
8468            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8469
8470            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8471
8472
8473            let response_rate_limits = response.rate_limits.clone();
8474            let response_data = response.data().expect("deserialize data");
8475
8476            assert_eq!(response_rate_limits, expected_rate_limits);
8477            assert_eq!(response_data, expected_data);
8478        });
8479    }
8480
8481    #[test]
8482    fn order_amend_keep_priority_error_response() {
8483        TOKIO_SHARED_RT.block_on(async {
8484            let (ws_api, conn, mut rx) = setup().await;
8485            let client = TradeApiClient::new(ws_api.clone());
8486
8487            let handle = tokio::spawn(async move {
8488                let params = OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(),dec!(1.0),).build().unwrap();
8489                client.order_amend_keep_priority(params).await
8490            });
8491
8492            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8493            let Message::Text(text) = sent else { panic!() };
8494            let v: Value = serde_json::from_str(&text).unwrap();
8495            let id = v["id"].as_str().unwrap().to_string();
8496
8497            let resp_json = json!({
8498                "id": id,
8499                "status": 400,
8500                    "error": {
8501                        "code": -2010,
8502                        "msg": "Account has insufficient balance for requested action.",
8503                    },
8504                    "rateLimits": [
8505                        {
8506                            "rateLimitType": "ORDERS",
8507                            "interval": "SECOND",
8508                            "intervalNum": 10,
8509                            "limit": 50,
8510                            "count": 13
8511                        },
8512                    ],
8513            });
8514            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8515
8516            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8517            match join {
8518                Ok(Err(e)) => {
8519                    let msg = e.to_string();
8520                    assert!(
8521                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8522                        "Expected error msg to contain server error, got: {msg}"
8523                    );
8524                }
8525                Ok(Ok(_)) => panic!("Expected error"),
8526                Err(_) => panic!("Task panicked"),
8527            }
8528        });
8529    }
8530
8531    #[test]
8532    fn order_amend_keep_priority_request_timeout() {
8533        TOKIO_SHARED_RT.block_on(async {
8534            let (ws_api, _conn, mut rx) = setup().await;
8535            let client = TradeApiClient::new(ws_api.clone());
8536
8537            let handle = spawn(async move {
8538                let params =
8539                    OrderAmendKeepPriorityParams::builder("BNBUSDT".to_string(), dec!(1.0))
8540                        .build()
8541                        .unwrap();
8542                client.order_amend_keep_priority(params).await
8543            });
8544
8545            let sent = timeout(Duration::from_secs(1), rx.recv())
8546                .await
8547                .expect("send should occur")
8548                .expect("channel closed");
8549            let Message::Text(text) = sent else {
8550                panic!("expected Message Text")
8551            };
8552
8553            let _: Value = serde_json::from_str(&text).unwrap();
8554
8555            let result = handle.await.expect("task completed");
8556            match result {
8557                Err(e) => {
8558                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8559                        assert!(matches!(inner, WebsocketError::Timeout));
8560                    } else {
8561                        panic!("Unexpected error type: {:?}", e);
8562                    }
8563                }
8564                Ok(_) => panic!("Expected timeout error"),
8565            }
8566        });
8567    }
8568
8569    #[test]
8570    fn order_cancel_success() {
8571        TOKIO_SHARED_RT.block_on(async {
8572            let (ws_api, conn, mut rx) = setup().await;
8573            let client = TradeApiClient::new(ws_api.clone());
8574
8575            let handle = spawn(async move {
8576                let params = OrderCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8577                client.order_cancel(params).await
8578            });
8579
8580            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8581            let Message::Text(text) = sent else { panic!() };
8582            let v: Value = serde_json::from_str(&text).unwrap();
8583            let id = v["id"].as_str().unwrap();
8584            assert_eq!(v["method"], "/order.cancel".trim_start_matches('/'));
8585
8586            let mut resp_json: Value = serde_json::from_str(r#"{"id":"16eaf097-bbec-44b9-96ff-e97e6e875870","status":200,"result":{"symbol":"BTCUSDT","origClientOrderId":"4d96324ff9d44481926157","orderId":12569099453,"orderListId":19431,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"price":"23416.10000000","origQty":"0.00847000","executedQty":"0.00001000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.23416100","status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","stopPrice":"0.00000000","trailingDelta":0,"icebergQty":"0.00000000","strategyId":37463720,"strategyType":1000000,"selfTradePreventionMode":"NONE","contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"iuVNVJYYrByz6C4yGOPPK0","transactionTime":1660803702431,"orders":[{"symbol":"BTCUSDT","orderId":12569099454,"clientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW"},{"symbol":"BTCUSDT","orderId":12569099453,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY"},{"symbol":"BTCUSDT","orderId":12569099454,"clientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW"},{"symbol":"BTCUSDT","orderId":12569099453,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY"}],"orderReports":[{"symbol":"BTCUSDT","origClientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW","orderId":12569099454,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23400.00000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT_MAKER","side":"BUY","selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","origClientOrderId":"bX5wROblo6YeDwa9iTLeyY","orderId":12569099453,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23450.50000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","stopPrice":"23430.00000000","selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","origClientOrderId":"Tnu2IP0J5Y4mxw3IATBfmW","orderId":12569099454,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23400.00000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT_MAKER","side":"BUY","selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","origClientOrderId":"bX5wROblo6YeDwa9iTLeyY","orderId":12569099453,"orderListId":19431,"clientOrderId":"OFFXQtxVFZ6Nbcg4PgE2DA","transactTime":1684804350068,"price":"23450.50000000","origQty":"0.00850000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","stopPrice":"23430.00000000","selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8587            resp_json["id"] = id.into();
8588
8589            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8590            let expected_data: Box<models::OrderCancelResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8591            let empty_array = Value::Array(vec![]);
8592            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8593            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8594                match raw_rate_limits.as_array() {
8595                    Some(arr) if arr.is_empty() => None,
8596                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8597                    None => None,
8598                };
8599
8600            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8601
8602            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8603
8604
8605            let response_rate_limits = response.rate_limits.clone();
8606            let response_data = response.data().expect("deserialize data");
8607
8608            assert_eq!(response_rate_limits, expected_rate_limits);
8609            assert_eq!(response_data, expected_data);
8610        });
8611    }
8612
8613    #[test]
8614    fn order_cancel_error_response() {
8615        TOKIO_SHARED_RT.block_on(async {
8616            let (ws_api, conn, mut rx) = setup().await;
8617            let client = TradeApiClient::new(ws_api.clone());
8618
8619            let handle = tokio::spawn(async move {
8620                let params = OrderCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8621                client.order_cancel(params).await
8622            });
8623
8624            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8625            let Message::Text(text) = sent else { panic!() };
8626            let v: Value = serde_json::from_str(&text).unwrap();
8627            let id = v["id"].as_str().unwrap().to_string();
8628
8629            let resp_json = json!({
8630                "id": id,
8631                "status": 400,
8632                    "error": {
8633                        "code": -2010,
8634                        "msg": "Account has insufficient balance for requested action.",
8635                    },
8636                    "rateLimits": [
8637                        {
8638                            "rateLimitType": "ORDERS",
8639                            "interval": "SECOND",
8640                            "intervalNum": 10,
8641                            "limit": 50,
8642                            "count": 13
8643                        },
8644                    ],
8645            });
8646            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8647
8648            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8649            match join {
8650                Ok(Err(e)) => {
8651                    let msg = e.to_string();
8652                    assert!(
8653                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8654                        "Expected error msg to contain server error, got: {msg}"
8655                    );
8656                }
8657                Ok(Ok(_)) => panic!("Expected error"),
8658                Err(_) => panic!("Task panicked"),
8659            }
8660        });
8661    }
8662
8663    #[test]
8664    fn order_cancel_request_timeout() {
8665        TOKIO_SHARED_RT.block_on(async {
8666            let (ws_api, _conn, mut rx) = setup().await;
8667            let client = TradeApiClient::new(ws_api.clone());
8668
8669            let handle = spawn(async move {
8670                let params = OrderCancelParams::builder("BNBUSDT".to_string())
8671                    .build()
8672                    .unwrap();
8673                client.order_cancel(params).await
8674            });
8675
8676            let sent = timeout(Duration::from_secs(1), rx.recv())
8677                .await
8678                .expect("send should occur")
8679                .expect("channel closed");
8680            let Message::Text(text) = sent else {
8681                panic!("expected Message Text")
8682            };
8683
8684            let _: Value = serde_json::from_str(&text).unwrap();
8685
8686            let result = handle.await.expect("task completed");
8687            match result {
8688                Err(e) => {
8689                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8690                        assert!(matches!(inner, WebsocketError::Timeout));
8691                    } else {
8692                        panic!("Unexpected error type: {:?}", e);
8693                    }
8694                }
8695                Ok(_) => panic!("Expected timeout error"),
8696            }
8697        });
8698    }
8699
8700    #[test]
8701    fn order_cancel_replace_success() {
8702        TOKIO_SHARED_RT.block_on(async {
8703            let (ws_api, conn, mut rx) = setup().await;
8704            let client = TradeApiClient::new(ws_api.clone());
8705
8706            let handle = spawn(async move {
8707                let params = OrderCancelReplaceParams::builder("BNBUSDT".to_string(),OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,OrderCancelReplaceSideEnum::Buy,OrderCancelReplaceTypeEnum::Market,).build().unwrap();
8708                client.order_cancel_replace(params).await
8709            });
8710
8711            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8712            let Message::Text(text) = sent else { panic!() };
8713            let v: Value = serde_json::from_str(&text).unwrap();
8714            let id = v["id"].as_str().unwrap();
8715            assert_eq!(v["method"], "/order.cancelReplace".trim_start_matches('/'));
8716
8717            let mut resp_json: Value = serde_json::from_str(r#"{"id":"99de1036-b5e2-4e0f-9b5c-13d751c93a1a","status":200,"result":{"cancelResult":"SUCCESS","newOrderResult":"SUCCESS","cancelResponse":{"symbol":"BTCUSDT","origClientOrderId":"4d96324ff9d44481926157","orderId":125690984230,"orderListId":-1,"clientOrderId":"91fe37ce9e69c90d6358c0","transactTime":1684804350068,"price":"23450.00000000","origQty":"0.00847000","executedQty":"0.00001000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.23450000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT","side":"SELL","selfTradePreventionMode":"NONE"},"newOrderResponse":{"symbol":"BTCUSDT","orderId":12569099453,"orderListId":-1,"clientOrderId":"bX5wROblo6YeDwa9iTLeyY","transactTime":1660813156959,"price":"23416.10000000","origQty":"0.00847000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"SELL","selfTradePreventionMode":"NONE"}},"rateLimits":[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":1},{"rateLimitType":"ORDERS","interval":"DAY","intervalNum":1,"limit":160000,"count":1},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8718            resp_json["id"] = id.into();
8719
8720            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8721            let expected_data: Box<models::OrderCancelReplaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8722            let empty_array = Value::Array(vec![]);
8723            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8724            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8725                match raw_rate_limits.as_array() {
8726                    Some(arr) if arr.is_empty() => None,
8727                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8728                    None => None,
8729                };
8730
8731            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8732
8733            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8734
8735
8736            let response_rate_limits = response.rate_limits.clone();
8737            let response_data = response.data().expect("deserialize data");
8738
8739            assert_eq!(response_rate_limits, expected_rate_limits);
8740            assert_eq!(response_data, expected_data);
8741        });
8742    }
8743
8744    #[test]
8745    fn order_cancel_replace_error_response() {
8746        TOKIO_SHARED_RT.block_on(async {
8747            let (ws_api, conn, mut rx) = setup().await;
8748            let client = TradeApiClient::new(ws_api.clone());
8749
8750            let handle = tokio::spawn(async move {
8751                let params = OrderCancelReplaceParams::builder("BNBUSDT".to_string(),OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,OrderCancelReplaceSideEnum::Buy,OrderCancelReplaceTypeEnum::Market,).build().unwrap();
8752                client.order_cancel_replace(params).await
8753            });
8754
8755            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8756            let Message::Text(text) = sent else { panic!() };
8757            let v: Value = serde_json::from_str(&text).unwrap();
8758            let id = v["id"].as_str().unwrap().to_string();
8759
8760            let resp_json = json!({
8761                "id": id,
8762                "status": 400,
8763                    "error": {
8764                        "code": -2010,
8765                        "msg": "Account has insufficient balance for requested action.",
8766                    },
8767                    "rateLimits": [
8768                        {
8769                            "rateLimitType": "ORDERS",
8770                            "interval": "SECOND",
8771                            "intervalNum": 10,
8772                            "limit": 50,
8773                            "count": 13
8774                        },
8775                    ],
8776            });
8777            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8778
8779            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8780            match join {
8781                Ok(Err(e)) => {
8782                    let msg = e.to_string();
8783                    assert!(
8784                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8785                        "Expected error msg to contain server error, got: {msg}"
8786                    );
8787                }
8788                Ok(Ok(_)) => panic!("Expected error"),
8789                Err(_) => panic!("Task panicked"),
8790            }
8791        });
8792    }
8793
8794    #[test]
8795    fn order_cancel_replace_request_timeout() {
8796        TOKIO_SHARED_RT.block_on(async {
8797            let (ws_api, _conn, mut rx) = setup().await;
8798            let client = TradeApiClient::new(ws_api.clone());
8799
8800            let handle = spawn(async move {
8801                let params = OrderCancelReplaceParams::builder(
8802                    "BNBUSDT".to_string(),
8803                    OrderCancelReplaceCancelReplaceModeEnum::StopOnFailure,
8804                    OrderCancelReplaceSideEnum::Buy,
8805                    OrderCancelReplaceTypeEnum::Market,
8806                )
8807                .build()
8808                .unwrap();
8809                client.order_cancel_replace(params).await
8810            });
8811
8812            let sent = timeout(Duration::from_secs(1), rx.recv())
8813                .await
8814                .expect("send should occur")
8815                .expect("channel closed");
8816            let Message::Text(text) = sent else {
8817                panic!("expected Message Text")
8818            };
8819
8820            let _: Value = serde_json::from_str(&text).unwrap();
8821
8822            let result = handle.await.expect("task completed");
8823            match result {
8824                Err(e) => {
8825                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8826                        assert!(matches!(inner, WebsocketError::Timeout));
8827                    } else {
8828                        panic!("Unexpected error type: {:?}", e);
8829                    }
8830                }
8831                Ok(_) => panic!("Expected timeout error"),
8832            }
8833        });
8834    }
8835
8836    #[test]
8837    fn order_list_cancel_success() {
8838        TOKIO_SHARED_RT.block_on(async {
8839            let (ws_api, conn, mut rx) = setup().await;
8840            let client = TradeApiClient::new(ws_api.clone());
8841
8842            let handle = spawn(async move {
8843                let params = OrderListCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8844                client.order_list_cancel(params).await
8845            });
8846
8847            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8848            let Message::Text(text) = sent else { panic!() };
8849            let v: Value = serde_json::from_str(&text).unwrap();
8850            let id = v["id"].as_str().unwrap();
8851            assert_eq!(v["method"], "/orderList.cancel".trim_start_matches('/'));
8852
8853            let mut resp_json: Value = serde_json::from_str(r#"{"id":"c5899911-d3f4-47ae-8835-97da553d27d0","status":200,"result":{"orderListId":1274512,"contingencyType":"OCO","listStatusType":"ALL_DONE","listOrderStatus":"ALL_DONE","listClientOrderId":"6023531d7edaad348f5aff","transactionTime":1660801720215,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569138902,"clientOrderId":"jLnZpj5enfMXTuhKB1d0us"},{"symbol":"BTCUSDT","orderId":12569138901,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU"}],"orderReports":[{"symbol":"BTCUSDT","orderId":12569138902,"orderListId":1274512,"clientOrderId":"jLnZpj5enfMXTuhKB1d0us","transactTime":1660801720215,"price":"23420.00000000","origQty":"0.00650000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"LIMIT_MAKER","side":"SELL","selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","orderId":12569138901,"orderListId":1274512,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU","transactTime":1660801720215,"price":"23410.00000000","origQty":"0.00650000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"CANCELED","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"SELL","stopPrice":"23405.00000000","selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8854            resp_json["id"] = id.into();
8855
8856            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8857            let expected_data: Box<models::OrderListCancelResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8858            let empty_array = Value::Array(vec![]);
8859            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8860            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8861                match raw_rate_limits.as_array() {
8862                    Some(arr) if arr.is_empty() => None,
8863                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8864                    None => None,
8865                };
8866
8867            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8868
8869            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
8870
8871
8872            let response_rate_limits = response.rate_limits.clone();
8873            let response_data = response.data().expect("deserialize data");
8874
8875            assert_eq!(response_rate_limits, expected_rate_limits);
8876            assert_eq!(response_data, expected_data);
8877        });
8878    }
8879
8880    #[test]
8881    fn order_list_cancel_error_response() {
8882        TOKIO_SHARED_RT.block_on(async {
8883            let (ws_api, conn, mut rx) = setup().await;
8884            let client = TradeApiClient::new(ws_api.clone());
8885
8886            let handle = tokio::spawn(async move {
8887                let params = OrderListCancelParams::builder("BNBUSDT".to_string(),).build().unwrap();
8888                client.order_list_cancel(params).await
8889            });
8890
8891            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
8892            let Message::Text(text) = sent else { panic!() };
8893            let v: Value = serde_json::from_str(&text).unwrap();
8894            let id = v["id"].as_str().unwrap().to_string();
8895
8896            let resp_json = json!({
8897                "id": id,
8898                "status": 400,
8899                    "error": {
8900                        "code": -2010,
8901                        "msg": "Account has insufficient balance for requested action.",
8902                    },
8903                    "rateLimits": [
8904                        {
8905                            "rateLimitType": "ORDERS",
8906                            "interval": "SECOND",
8907                            "intervalNum": 10,
8908                            "limit": 50,
8909                            "count": 13
8910                        },
8911                    ],
8912            });
8913            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8914
8915            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
8916            match join {
8917                Ok(Err(e)) => {
8918                    let msg = e.to_string();
8919                    assert!(
8920                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
8921                        "Expected error msg to contain server error, got: {msg}"
8922                    );
8923                }
8924                Ok(Ok(_)) => panic!("Expected error"),
8925                Err(_) => panic!("Task panicked"),
8926            }
8927        });
8928    }
8929
8930    #[test]
8931    fn order_list_cancel_request_timeout() {
8932        TOKIO_SHARED_RT.block_on(async {
8933            let (ws_api, _conn, mut rx) = setup().await;
8934            let client = TradeApiClient::new(ws_api.clone());
8935
8936            let handle = spawn(async move {
8937                let params = OrderListCancelParams::builder("BNBUSDT".to_string())
8938                    .build()
8939                    .unwrap();
8940                client.order_list_cancel(params).await
8941            });
8942
8943            let sent = timeout(Duration::from_secs(1), rx.recv())
8944                .await
8945                .expect("send should occur")
8946                .expect("channel closed");
8947            let Message::Text(text) = sent else {
8948                panic!("expected Message Text")
8949            };
8950
8951            let _: Value = serde_json::from_str(&text).unwrap();
8952
8953            let result = handle.await.expect("task completed");
8954            match result {
8955                Err(e) => {
8956                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
8957                        assert!(matches!(inner, WebsocketError::Timeout));
8958                    } else {
8959                        panic!("Unexpected error type: {:?}", e);
8960                    }
8961                }
8962                Ok(_) => panic!("Expected timeout error"),
8963            }
8964        });
8965    }
8966
8967    #[test]
8968    fn order_list_place_success() {
8969        TOKIO_SHARED_RT.block_on(async {
8970            let (ws_api, conn, mut rx) = setup().await;
8971            let client = TradeApiClient::new(ws_api.clone());
8972
8973            let handle = spawn(async move {
8974                let params = OrderListPlaceParams::builder("BNBUSDT".to_string(),OrderListPlaceSideEnum::Buy,dec!(1.0),dec!(1.0),).build().unwrap();
8975                client.order_list_place(params).await
8976            });
8977
8978            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
8979            let Message::Text(text) = sent else { panic!() };
8980            let v: Value = serde_json::from_str(&text).unwrap();
8981            let id = v["id"].as_str().unwrap();
8982            assert_eq!(v["method"], "/orderList.place".trim_start_matches('/'));
8983
8984            let mut resp_json: Value = serde_json::from_str(r#"{"id":"57833dc0-e3f2-43fb-ba20-46480973b0aa","status":200,"result":{"orderListId":1274512,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"08985fedd9ea2cf6b28996","transactionTime":1660801713793,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":12569138902,"clientOrderId":"jLnZpj5enfMXTuhKB1d0us"},{"symbol":"BTCUSDT","orderId":12569138901,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU"}],"orderReports":[{"symbol":"BTCUSDT","orderId":12569138902,"orderListId":1274512,"clientOrderId":"jLnZpj5enfMXTuhKB1d0us","transactTime":1660801713793,"price":"23420.00000000","origQty":"0.00650000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT_MAKER","side":"SELL","workingTime":1660801713793,"selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","orderId":12569138901,"orderListId":1274512,"clientOrderId":"BqtFCj5odMoWtSqGk2X9tU","transactTime":1660801713793,"price":"23410.00000000","origQty":"0.00650000","executedQty":"0.00000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"SELL","stopPrice":"23405.00000000","workingTime":-1,"selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":2},{"rateLimitType":"ORDERS","interval":"DAY","intervalNum":1,"limit":160000,"count":2},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
8985            resp_json["id"] = id.into();
8986
8987            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
8988            let expected_data: Box<models::OrderListPlaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
8989            let empty_array = Value::Array(vec![]);
8990            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
8991            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
8992                match raw_rate_limits.as_array() {
8993                    Some(arr) if arr.is_empty() => None,
8994                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
8995                    None => None,
8996                };
8997
8998            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
8999
9000            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9001
9002
9003            let response_rate_limits = response.rate_limits.clone();
9004            let response_data = response.data().expect("deserialize data");
9005
9006            assert_eq!(response_rate_limits, expected_rate_limits);
9007            assert_eq!(response_data, expected_data);
9008        });
9009    }
9010
9011    #[test]
9012    fn order_list_place_error_response() {
9013        TOKIO_SHARED_RT.block_on(async {
9014            let (ws_api, conn, mut rx) = setup().await;
9015            let client = TradeApiClient::new(ws_api.clone());
9016
9017            let handle = tokio::spawn(async move {
9018                let params = OrderListPlaceParams::builder("BNBUSDT".to_string(),OrderListPlaceSideEnum::Buy,dec!(1.0),dec!(1.0),).build().unwrap();
9019                client.order_list_place(params).await
9020            });
9021
9022            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9023            let Message::Text(text) = sent else { panic!() };
9024            let v: Value = serde_json::from_str(&text).unwrap();
9025            let id = v["id"].as_str().unwrap().to_string();
9026
9027            let resp_json = json!({
9028                "id": id,
9029                "status": 400,
9030                    "error": {
9031                        "code": -2010,
9032                        "msg": "Account has insufficient balance for requested action.",
9033                    },
9034                    "rateLimits": [
9035                        {
9036                            "rateLimitType": "ORDERS",
9037                            "interval": "SECOND",
9038                            "intervalNum": 10,
9039                            "limit": 50,
9040                            "count": 13
9041                        },
9042                    ],
9043            });
9044            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9045
9046            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9047            match join {
9048                Ok(Err(e)) => {
9049                    let msg = e.to_string();
9050                    assert!(
9051                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9052                        "Expected error msg to contain server error, got: {msg}"
9053                    );
9054                }
9055                Ok(Ok(_)) => panic!("Expected error"),
9056                Err(_) => panic!("Task panicked"),
9057            }
9058        });
9059    }
9060
9061    #[test]
9062    fn order_list_place_request_timeout() {
9063        TOKIO_SHARED_RT.block_on(async {
9064            let (ws_api, _conn, mut rx) = setup().await;
9065            let client = TradeApiClient::new(ws_api.clone());
9066
9067            let handle = spawn(async move {
9068                let params = OrderListPlaceParams::builder(
9069                    "BNBUSDT".to_string(),
9070                    OrderListPlaceSideEnum::Buy,
9071                    dec!(1.0),
9072                    dec!(1.0),
9073                )
9074                .build()
9075                .unwrap();
9076                client.order_list_place(params).await
9077            });
9078
9079            let sent = timeout(Duration::from_secs(1), rx.recv())
9080                .await
9081                .expect("send should occur")
9082                .expect("channel closed");
9083            let Message::Text(text) = sent else {
9084                panic!("expected Message Text")
9085            };
9086
9087            let _: Value = serde_json::from_str(&text).unwrap();
9088
9089            let result = handle.await.expect("task completed");
9090            match result {
9091                Err(e) => {
9092                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9093                        assert!(matches!(inner, WebsocketError::Timeout));
9094                    } else {
9095                        panic!("Unexpected error type: {:?}", e);
9096                    }
9097                }
9098                Ok(_) => panic!("Expected timeout error"),
9099            }
9100        });
9101    }
9102
9103    #[test]
9104    fn order_list_place_oco_success() {
9105        TOKIO_SHARED_RT.block_on(async {
9106            let (ws_api, conn, mut rx) = setup().await;
9107            let client = TradeApiClient::new(ws_api.clone());
9108
9109            let handle = spawn(async move {
9110                let params = OrderListPlaceOcoParams::builder("BNBUSDT".to_string(),OrderListPlaceOcoSideEnum::Buy,dec!(1.0),OrderListPlaceOcoAboveTypeEnum::StopLossLimit,OrderListPlaceOcoBelowTypeEnum::StopLoss,).build().unwrap();
9111                client.order_list_place_oco(params).await
9112            });
9113
9114            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9115            let Message::Text(text) = sent else { panic!() };
9116            let v: Value = serde_json::from_str(&text).unwrap();
9117            let id = v["id"].as_str().unwrap();
9118            assert_eq!(v["method"], "/orderList.place.oco".trim_start_matches('/'));
9119
9120            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374a46-3261-486b-a211-99ed972eb648","status":200,"result":{"orderListId":2,"contingencyType":"OCO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"cKPMnDCbcLQILtDYM4f4fX","transactionTime":1711062760648,"symbol":"LTCBNB","orders":[{"symbol":"LTCBNB","orderId":3,"clientOrderId":"Z2IMlR79XNY5LU0tOxrWyW"},{"symbol":"LTCBNB","orderId":2,"clientOrderId":"0m6I4wfxvTUrOBSMUl0OPU"}],"orderReports":[{"symbol":"LTCBNB","orderId":3,"orderListId":2,"clientOrderId":"Z2IMlR79XNY5LU0tOxrWyW","transactTime":1711062760648,"price":"1.49999999","origQty":"1.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT_MAKER","side":"BUY","workingTime":1711062760648,"selfTradePreventionMode":"NONE"},{"symbol":"LTCBNB","orderId":2,"orderListId":2,"clientOrderId":"0m6I4wfxvTUrOBSMUl0OPU","transactTime":1711062760648,"price":"1.50000000","origQty":"1.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"STOP_LOSS_LIMIT","side":"BUY","stopPrice":"1.50000001","workingTime":-1,"selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":2},{"rateLimitType":"ORDERS","interval":"DAY","intervalNum":1,"limit":160000,"count":2},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
9121            resp_json["id"] = id.into();
9122
9123            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9124            let expected_data: Box<models::OrderListPlaceOcoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9125            let empty_array = Value::Array(vec![]);
9126            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9127            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9128                match raw_rate_limits.as_array() {
9129                    Some(arr) if arr.is_empty() => None,
9130                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9131                    None => None,
9132                };
9133
9134            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9135
9136            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9137
9138
9139            let response_rate_limits = response.rate_limits.clone();
9140            let response_data = response.data().expect("deserialize data");
9141
9142            assert_eq!(response_rate_limits, expected_rate_limits);
9143            assert_eq!(response_data, expected_data);
9144        });
9145    }
9146
9147    #[test]
9148    fn order_list_place_oco_error_response() {
9149        TOKIO_SHARED_RT.block_on(async {
9150            let (ws_api, conn, mut rx) = setup().await;
9151            let client = TradeApiClient::new(ws_api.clone());
9152
9153            let handle = tokio::spawn(async move {
9154                let params = OrderListPlaceOcoParams::builder("BNBUSDT".to_string(),OrderListPlaceOcoSideEnum::Buy,dec!(1.0),OrderListPlaceOcoAboveTypeEnum::StopLossLimit,OrderListPlaceOcoBelowTypeEnum::StopLoss,).build().unwrap();
9155                client.order_list_place_oco(params).await
9156            });
9157
9158            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9159            let Message::Text(text) = sent else { panic!() };
9160            let v: Value = serde_json::from_str(&text).unwrap();
9161            let id = v["id"].as_str().unwrap().to_string();
9162
9163            let resp_json = json!({
9164                "id": id,
9165                "status": 400,
9166                    "error": {
9167                        "code": -2010,
9168                        "msg": "Account has insufficient balance for requested action.",
9169                    },
9170                    "rateLimits": [
9171                        {
9172                            "rateLimitType": "ORDERS",
9173                            "interval": "SECOND",
9174                            "intervalNum": 10,
9175                            "limit": 50,
9176                            "count": 13
9177                        },
9178                    ],
9179            });
9180            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9181
9182            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9183            match join {
9184                Ok(Err(e)) => {
9185                    let msg = e.to_string();
9186                    assert!(
9187                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9188                        "Expected error msg to contain server error, got: {msg}"
9189                    );
9190                }
9191                Ok(Ok(_)) => panic!("Expected error"),
9192                Err(_) => panic!("Task panicked"),
9193            }
9194        });
9195    }
9196
9197    #[test]
9198    fn order_list_place_oco_request_timeout() {
9199        TOKIO_SHARED_RT.block_on(async {
9200            let (ws_api, _conn, mut rx) = setup().await;
9201            let client = TradeApiClient::new(ws_api.clone());
9202
9203            let handle = spawn(async move {
9204                let params = OrderListPlaceOcoParams::builder(
9205                    "BNBUSDT".to_string(),
9206                    OrderListPlaceOcoSideEnum::Buy,
9207                    dec!(1.0),
9208                    OrderListPlaceOcoAboveTypeEnum::StopLossLimit,
9209                    OrderListPlaceOcoBelowTypeEnum::StopLoss,
9210                )
9211                .build()
9212                .unwrap();
9213                client.order_list_place_oco(params).await
9214            });
9215
9216            let sent = timeout(Duration::from_secs(1), rx.recv())
9217                .await
9218                .expect("send should occur")
9219                .expect("channel closed");
9220            let Message::Text(text) = sent else {
9221                panic!("expected Message Text")
9222            };
9223
9224            let _: Value = serde_json::from_str(&text).unwrap();
9225
9226            let result = handle.await.expect("task completed");
9227            match result {
9228                Err(e) => {
9229                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9230                        assert!(matches!(inner, WebsocketError::Timeout));
9231                    } else {
9232                        panic!("Unexpected error type: {:?}", e);
9233                    }
9234                }
9235                Ok(_) => panic!("Expected timeout error"),
9236            }
9237        });
9238    }
9239
9240    #[test]
9241    fn order_list_place_opo_success() {
9242        TOKIO_SHARED_RT.block_on(async {
9243            let (ws_api, conn, mut rx) = setup().await;
9244            let client = TradeApiClient::new(ws_api.clone());
9245
9246            let handle = spawn(async move {
9247                let params = OrderListPlaceOpoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpoWorkingTypeEnum::Limit,OrderListPlaceOpoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOpoPendingTypeEnum::Limit,OrderListPlaceOpoPendingSideEnum::Buy,).build().unwrap();
9248                client.order_list_place_opo(params).await
9249            });
9250
9251            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9252            let Message::Text(text) = sent else { panic!() };
9253            let v: Value = serde_json::from_str(&text).unwrap();
9254            let id = v["id"].as_str().unwrap();
9255            assert_eq!(v["method"], "/orderList.place.opo".trim_start_matches('/'));
9256
9257            let mut resp_json: Value = serde_json::from_str(r#"{"id":"1762941318128","status":200,"result":{"orderListId":2,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"OiOgqvRagBefpzdM5gjYX3","transactionTime":1762941318142,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":3,"clientOrderId":"x7ISSjywZxFXOdzwsThNnd"},{"symbol":"BTCUSDT","orderId":2,"clientOrderId":"pUzhKBbc0ZVdMScIRAqitH"}],"orderReports":[{"symbol":"BTCUSDT","orderId":3,"orderListId":2,"clientOrderId":"x7ISSjywZxFXOdzwsThNnd","transactTime":1762941318142,"price":"0.00000000","executedQty":"0.00000000","origQuoteOrderQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"PENDING_NEW","timeInForce":"GTC","type":"MARKET","side":"SELL","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","orderId":2,"orderListId":2,"clientOrderId":"pUzhKBbc0ZVdMScIRAqitH","transactTime":1762941318142,"price":"101496.00000000","origQty":"0.00070000","executedQty":"0.00000000","origQuoteOrderQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1762941318142,"selfTradePreventionMode":"NONE"}]}}"#).unwrap();
9258            resp_json["id"] = id.into();
9259
9260            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9261            let expected_data: Box<models::OrderListPlaceOpoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9262            let empty_array = Value::Array(vec![]);
9263            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9264            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9265                match raw_rate_limits.as_array() {
9266                    Some(arr) if arr.is_empty() => None,
9267                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9268                    None => None,
9269                };
9270
9271            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9272
9273            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9274
9275
9276            let response_rate_limits = response.rate_limits.clone();
9277            let response_data = response.data().expect("deserialize data");
9278
9279            assert_eq!(response_rate_limits, expected_rate_limits);
9280            assert_eq!(response_data, expected_data);
9281        });
9282    }
9283
9284    #[test]
9285    fn order_list_place_opo_error_response() {
9286        TOKIO_SHARED_RT.block_on(async {
9287            let (ws_api, conn, mut rx) = setup().await;
9288            let client = TradeApiClient::new(ws_api.clone());
9289
9290            let handle = tokio::spawn(async move {
9291                let params = OrderListPlaceOpoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpoWorkingTypeEnum::Limit,OrderListPlaceOpoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOpoPendingTypeEnum::Limit,OrderListPlaceOpoPendingSideEnum::Buy,).build().unwrap();
9292                client.order_list_place_opo(params).await
9293            });
9294
9295            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9296            let Message::Text(text) = sent else { panic!() };
9297            let v: Value = serde_json::from_str(&text).unwrap();
9298            let id = v["id"].as_str().unwrap().to_string();
9299
9300            let resp_json = json!({
9301                "id": id,
9302                "status": 400,
9303                    "error": {
9304                        "code": -2010,
9305                        "msg": "Account has insufficient balance for requested action.",
9306                    },
9307                    "rateLimits": [
9308                        {
9309                            "rateLimitType": "ORDERS",
9310                            "interval": "SECOND",
9311                            "intervalNum": 10,
9312                            "limit": 50,
9313                            "count": 13
9314                        },
9315                    ],
9316            });
9317            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9318
9319            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9320            match join {
9321                Ok(Err(e)) => {
9322                    let msg = e.to_string();
9323                    assert!(
9324                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9325                        "Expected error msg to contain server error, got: {msg}"
9326                    );
9327                }
9328                Ok(Ok(_)) => panic!("Expected error"),
9329                Err(_) => panic!("Task panicked"),
9330            }
9331        });
9332    }
9333
9334    #[test]
9335    fn order_list_place_opo_request_timeout() {
9336        TOKIO_SHARED_RT.block_on(async {
9337            let (ws_api, _conn, mut rx) = setup().await;
9338            let client = TradeApiClient::new(ws_api.clone());
9339
9340            let handle = spawn(async move {
9341                let params = OrderListPlaceOpoParams::builder(
9342                    "BNBUSDT".to_string(),
9343                    OrderListPlaceOpoWorkingTypeEnum::Limit,
9344                    OrderListPlaceOpoWorkingSideEnum::Buy,
9345                    dec!(1.0),
9346                    dec!(1.0),
9347                    OrderListPlaceOpoPendingTypeEnum::Limit,
9348                    OrderListPlaceOpoPendingSideEnum::Buy,
9349                )
9350                .build()
9351                .unwrap();
9352                client.order_list_place_opo(params).await
9353            });
9354
9355            let sent = timeout(Duration::from_secs(1), rx.recv())
9356                .await
9357                .expect("send should occur")
9358                .expect("channel closed");
9359            let Message::Text(text) = sent else {
9360                panic!("expected Message Text")
9361            };
9362
9363            let _: Value = serde_json::from_str(&text).unwrap();
9364
9365            let result = handle.await.expect("task completed");
9366            match result {
9367                Err(e) => {
9368                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9369                        assert!(matches!(inner, WebsocketError::Timeout));
9370                    } else {
9371                        panic!("Unexpected error type: {:?}", e);
9372                    }
9373                }
9374                Ok(_) => panic!("Expected timeout error"),
9375            }
9376        });
9377    }
9378
9379    #[test]
9380    fn order_list_place_opoco_success() {
9381        TOKIO_SHARED_RT.block_on(async {
9382            let (ws_api, conn, mut rx) = setup().await;
9383            let client = TradeApiClient::new(ws_api.clone());
9384
9385            let handle = spawn(async move {
9386                let params = OrderListPlaceOpocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpocoWorkingTypeEnum::Limit,OrderListPlaceOpocoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOpocoPendingSideEnum::Buy,OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9387                client.order_list_place_opoco(params).await
9388            });
9389
9390            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9391            let Message::Text(text) = sent else { panic!() };
9392            let v: Value = serde_json::from_str(&text).unwrap();
9393            let id = v["id"].as_str().unwrap();
9394            assert_eq!(v["method"], "/orderList.place.opoco".trim_start_matches('/'));
9395
9396            let mut resp_json: Value = serde_json::from_str(r#"{"id":"1763000139090","status":200,"result":{"orderListId":1,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"TVbG6ymkYMXTj7tczbOsBf","transactionTime":1763000139104,"symbol":"BTCUSDT","orders":[{"symbol":"BTCUSDT","orderId":8,"clientOrderId":"i76cGJWN9J1FpADS56TtQZ"},{"symbol":"BTCUSDT","orderId":7,"clientOrderId":"kyIKnMLKQclE5FmyYgaMSo"},{"symbol":"BTCUSDT","orderId":6,"clientOrderId":"3czuJSeyjPwV9Xo28j1Dv3"}],"orderReports":[{"symbol":"BTCUSDT","orderId":8,"orderListId":1,"clientOrderId":"i76cGJWN9J1FpADS56TtQZ","transactTime":1763000139104,"price":"104261.00000000","executedQty":"0.00000000","origQuoteOrderQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"PENDING_NEW","timeInForce":"GTC","type":"LIMIT_MAKER","side":"SELL","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","orderId":7,"orderListId":1,"clientOrderId":"kyIKnMLKQclE5FmyYgaMSo","transactTime":1763000139104,"price":"101613.00000000","executedQty":"0.00000000","origQuoteOrderQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"PENDING_NEW","timeInForce":"IOC","type":"STOP_LOSS_LIMIT","side":"SELL","stopPrice":"10100.00000000","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"BTCUSDT","orderId":6,"orderListId":1,"clientOrderId":"3czuJSeyjPwV9Xo28j1Dv3","transactTime":1763000139104,"price":"102496.00000000","origQty":"0.00170000","executedQty":"0.00000000","origQuoteOrderQty":"0.00000000","cummulativeQuoteQty":"0.00000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1763000139104,"selfTradePreventionMode":"NONE"}]}}"#).unwrap();
9397            resp_json["id"] = id.into();
9398
9399            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9400            let expected_data: Box<models::OrderListPlaceOpocoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9401            let empty_array = Value::Array(vec![]);
9402            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9403            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9404                match raw_rate_limits.as_array() {
9405                    Some(arr) if arr.is_empty() => None,
9406                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9407                    None => None,
9408                };
9409
9410            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9411
9412            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9413
9414
9415            let response_rate_limits = response.rate_limits.clone();
9416            let response_data = response.data().expect("deserialize data");
9417
9418            assert_eq!(response_rate_limits, expected_rate_limits);
9419            assert_eq!(response_data, expected_data);
9420        });
9421    }
9422
9423    #[test]
9424    fn order_list_place_opoco_error_response() {
9425        TOKIO_SHARED_RT.block_on(async {
9426            let (ws_api, conn, mut rx) = setup().await;
9427            let client = TradeApiClient::new(ws_api.clone());
9428
9429            let handle = tokio::spawn(async move {
9430                let params = OrderListPlaceOpocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOpocoWorkingTypeEnum::Limit,OrderListPlaceOpocoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOpocoPendingSideEnum::Buy,OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9431                client.order_list_place_opoco(params).await
9432            });
9433
9434            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9435            let Message::Text(text) = sent else { panic!() };
9436            let v: Value = serde_json::from_str(&text).unwrap();
9437            let id = v["id"].as_str().unwrap().to_string();
9438
9439            let resp_json = json!({
9440                "id": id,
9441                "status": 400,
9442                    "error": {
9443                        "code": -2010,
9444                        "msg": "Account has insufficient balance for requested action.",
9445                    },
9446                    "rateLimits": [
9447                        {
9448                            "rateLimitType": "ORDERS",
9449                            "interval": "SECOND",
9450                            "intervalNum": 10,
9451                            "limit": 50,
9452                            "count": 13
9453                        },
9454                    ],
9455            });
9456            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9457
9458            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9459            match join {
9460                Ok(Err(e)) => {
9461                    let msg = e.to_string();
9462                    assert!(
9463                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9464                        "Expected error msg to contain server error, got: {msg}"
9465                    );
9466                }
9467                Ok(Ok(_)) => panic!("Expected error"),
9468                Err(_) => panic!("Task panicked"),
9469            }
9470        });
9471    }
9472
9473    #[test]
9474    fn order_list_place_opoco_request_timeout() {
9475        TOKIO_SHARED_RT.block_on(async {
9476            let (ws_api, _conn, mut rx) = setup().await;
9477            let client = TradeApiClient::new(ws_api.clone());
9478
9479            let handle = spawn(async move {
9480                let params = OrderListPlaceOpocoParams::builder(
9481                    "BNBUSDT".to_string(),
9482                    OrderListPlaceOpocoWorkingTypeEnum::Limit,
9483                    OrderListPlaceOpocoWorkingSideEnum::Buy,
9484                    dec!(1.0),
9485                    dec!(1.0),
9486                    OrderListPlaceOpocoPendingSideEnum::Buy,
9487                    OrderListPlaceOpocoPendingAboveTypeEnum::StopLossLimit,
9488                )
9489                .build()
9490                .unwrap();
9491                client.order_list_place_opoco(params).await
9492            });
9493
9494            let sent = timeout(Duration::from_secs(1), rx.recv())
9495                .await
9496                .expect("send should occur")
9497                .expect("channel closed");
9498            let Message::Text(text) = sent else {
9499                panic!("expected Message Text")
9500            };
9501
9502            let _: Value = serde_json::from_str(&text).unwrap();
9503
9504            let result = handle.await.expect("task completed");
9505            match result {
9506                Err(e) => {
9507                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9508                        assert!(matches!(inner, WebsocketError::Timeout));
9509                    } else {
9510                        panic!("Unexpected error type: {:?}", e);
9511                    }
9512                }
9513                Ok(_) => panic!("Expected timeout error"),
9514            }
9515        });
9516    }
9517
9518    #[test]
9519    fn order_list_place_oto_success() {
9520        TOKIO_SHARED_RT.block_on(async {
9521            let (ws_api, conn, mut rx) = setup().await;
9522            let client = TradeApiClient::new(ws_api.clone());
9523
9524            let handle = spawn(async move {
9525                let params = OrderListPlaceOtoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtoWorkingTypeEnum::Limit,OrderListPlaceOtoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOtoPendingTypeEnum::Limit,OrderListPlaceOtoPendingSideEnum::Buy,dec!(1.0),).build().unwrap();
9526                client.order_list_place_oto(params).await
9527            });
9528
9529            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9530            let Message::Text(text) = sent else { panic!() };
9531            let v: Value = serde_json::from_str(&text).unwrap();
9532            let id = v["id"].as_str().unwrap();
9533            assert_eq!(v["method"], "/orderList.place.oto".trim_start_matches('/'));
9534
9535            let mut resp_json: Value = serde_json::from_str(r#"{"id":"1712544395950","status":200,"result":{"orderListId":626,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"KA4EBjGnzvSwSCQsDdTrlf","transactionTime":1712544395981,"symbol":"1712544378871","orders":[{"symbol":"LTCBNB","orderId":14,"clientOrderId":"9MxJSE1TYkmyx5lbGLve7R"},{"symbol":"LTCBNB","orderId":13,"clientOrderId":"YiAUtM9yJjl1a2jXHSp9Ny"}],"orderReports":[{"symbol":"LTCBNB","orderId":14,"orderListId":626,"clientOrderId":"9MxJSE1TYkmyx5lbGLve7R","transactTime":1712544395981,"price":"0.000000","origQty":"1.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.000000","status":"PENDING_NEW","timeInForce":"GTC","type":"MARKET","side":"BUY","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"LTCBNB","orderId":13,"orderListId":626,"clientOrderId":"YiAUtM9yJjl1a2jXHSp9Ny","transactTime":1712544395981,"price":"1.000000","origQty":"1.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"SELL","workingTime":1712544395981,"selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"ORDERS","interval":"MINUTE","intervalNum":1,"limit":10000000,"count":10},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":1000,"count":38}]}"#).unwrap();
9536            resp_json["id"] = id.into();
9537
9538            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9539            let expected_data: Box<models::OrderListPlaceOtoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9540            let empty_array = Value::Array(vec![]);
9541            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9542            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9543                match raw_rate_limits.as_array() {
9544                    Some(arr) if arr.is_empty() => None,
9545                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9546                    None => None,
9547                };
9548
9549            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9550
9551            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9552
9553
9554            let response_rate_limits = response.rate_limits.clone();
9555            let response_data = response.data().expect("deserialize data");
9556
9557            assert_eq!(response_rate_limits, expected_rate_limits);
9558            assert_eq!(response_data, expected_data);
9559        });
9560    }
9561
9562    #[test]
9563    fn order_list_place_oto_error_response() {
9564        TOKIO_SHARED_RT.block_on(async {
9565            let (ws_api, conn, mut rx) = setup().await;
9566            let client = TradeApiClient::new(ws_api.clone());
9567
9568            let handle = tokio::spawn(async move {
9569                let params = OrderListPlaceOtoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtoWorkingTypeEnum::Limit,OrderListPlaceOtoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOtoPendingTypeEnum::Limit,OrderListPlaceOtoPendingSideEnum::Buy,dec!(1.0),).build().unwrap();
9570                client.order_list_place_oto(params).await
9571            });
9572
9573            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9574            let Message::Text(text) = sent else { panic!() };
9575            let v: Value = serde_json::from_str(&text).unwrap();
9576            let id = v["id"].as_str().unwrap().to_string();
9577
9578            let resp_json = json!({
9579                "id": id,
9580                "status": 400,
9581                    "error": {
9582                        "code": -2010,
9583                        "msg": "Account has insufficient balance for requested action.",
9584                    },
9585                    "rateLimits": [
9586                        {
9587                            "rateLimitType": "ORDERS",
9588                            "interval": "SECOND",
9589                            "intervalNum": 10,
9590                            "limit": 50,
9591                            "count": 13
9592                        },
9593                    ],
9594            });
9595            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9596
9597            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9598            match join {
9599                Ok(Err(e)) => {
9600                    let msg = e.to_string();
9601                    assert!(
9602                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9603                        "Expected error msg to contain server error, got: {msg}"
9604                    );
9605                }
9606                Ok(Ok(_)) => panic!("Expected error"),
9607                Err(_) => panic!("Task panicked"),
9608            }
9609        });
9610    }
9611
9612    #[test]
9613    fn order_list_place_oto_request_timeout() {
9614        TOKIO_SHARED_RT.block_on(async {
9615            let (ws_api, _conn, mut rx) = setup().await;
9616            let client = TradeApiClient::new(ws_api.clone());
9617
9618            let handle = spawn(async move {
9619                let params = OrderListPlaceOtoParams::builder(
9620                    "BNBUSDT".to_string(),
9621                    OrderListPlaceOtoWorkingTypeEnum::Limit,
9622                    OrderListPlaceOtoWorkingSideEnum::Buy,
9623                    dec!(1.0),
9624                    dec!(1.0),
9625                    OrderListPlaceOtoPendingTypeEnum::Limit,
9626                    OrderListPlaceOtoPendingSideEnum::Buy,
9627                    dec!(1.0),
9628                )
9629                .build()
9630                .unwrap();
9631                client.order_list_place_oto(params).await
9632            });
9633
9634            let sent = timeout(Duration::from_secs(1), rx.recv())
9635                .await
9636                .expect("send should occur")
9637                .expect("channel closed");
9638            let Message::Text(text) = sent else {
9639                panic!("expected Message Text")
9640            };
9641
9642            let _: Value = serde_json::from_str(&text).unwrap();
9643
9644            let result = handle.await.expect("task completed");
9645            match result {
9646                Err(e) => {
9647                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9648                        assert!(matches!(inner, WebsocketError::Timeout));
9649                    } else {
9650                        panic!("Unexpected error type: {:?}", e);
9651                    }
9652                }
9653                Ok(_) => panic!("Expected timeout error"),
9654            }
9655        });
9656    }
9657
9658    #[test]
9659    fn order_list_place_otoco_success() {
9660        TOKIO_SHARED_RT.block_on(async {
9661            let (ws_api, conn, mut rx) = setup().await;
9662            let client = TradeApiClient::new(ws_api.clone());
9663
9664            let handle = spawn(async move {
9665                let params = OrderListPlaceOtocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtocoWorkingTypeEnum::Limit,OrderListPlaceOtocoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOtocoPendingSideEnum::Buy,dec!(1.0),OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9666                client.order_list_place_otoco(params).await
9667            });
9668
9669            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9670            let Message::Text(text) = sent else { panic!() };
9671            let v: Value = serde_json::from_str(&text).unwrap();
9672            let id = v["id"].as_str().unwrap();
9673            assert_eq!(v["method"], "/orderList.place.otoco".trim_start_matches('/'));
9674
9675            let mut resp_json: Value = serde_json::from_str(r#"{"id":"1712544408508","status":200,"result":{"orderListId":629,"contingencyType":"OTO","listStatusType":"EXEC_STARTED","listOrderStatus":"EXECUTING","listClientOrderId":"GaeJHjZPasPItFj4x7Mqm6","transactionTime":1712544408537,"symbol":"1712544378871","orders":[{"symbol":"LTCBNB","orderId":25,"clientOrderId":"ilpIoShcFZ1ZGgSASKxMPt"},{"symbol":"LTCBNB","orderId":24,"clientOrderId":"YcCPKCDMQIjNvLtNswt82X"},{"symbol":"LTCBNB","orderId":23,"clientOrderId":"OVQOpKwfmPCfaBTD0n7e7H"}],"orderReports":[{"symbol":"LTCBNB","orderId":25,"orderListId":629,"clientOrderId":"ilpIoShcFZ1ZGgSASKxMPt","transactTime":1712544408537,"price":"5.000000","origQty":"5.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.000000","status":"PENDING_NEW","timeInForce":"GTC","type":"LIMIT_MAKER","side":"SELL","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"LTCBNB","orderId":24,"orderListId":629,"clientOrderId":"YcCPKCDMQIjNvLtNswt82X","transactTime":1712544408537,"price":"0.000000","origQty":"5.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.000000","status":"PENDING_NEW","timeInForce":"GTC","type":"STOP_LOSS","side":"SELL","stopPrice":"0.500000","workingTime":-1,"selfTradePreventionMode":"NONE"},{"symbol":"LTCBNB","orderId":23,"orderListId":629,"clientOrderId":"OVQOpKwfmPCfaBTD0n7e7H","transactTime":1712544408537,"price":"1.500000","origQty":"1.000000","executedQty":"0.000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"0.000000","status":"NEW","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1712544408537,"selfTradePreventionMode":"NONE"}]},"rateLimits":[{"rateLimitType":"ORDERS","interval":"MINUTE","intervalNum":1,"limit":10000000,"count":18},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":1000,"count":65}]}"#).unwrap();
9676            resp_json["id"] = id.into();
9677
9678            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9679            let expected_data: Box<models::OrderListPlaceOtocoResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9680            let empty_array = Value::Array(vec![]);
9681            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9682            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9683                match raw_rate_limits.as_array() {
9684                    Some(arr) if arr.is_empty() => None,
9685                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9686                    None => None,
9687                };
9688
9689            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9690
9691            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9692
9693
9694            let response_rate_limits = response.rate_limits.clone();
9695            let response_data = response.data().expect("deserialize data");
9696
9697            assert_eq!(response_rate_limits, expected_rate_limits);
9698            assert_eq!(response_data, expected_data);
9699        });
9700    }
9701
9702    #[test]
9703    fn order_list_place_otoco_error_response() {
9704        TOKIO_SHARED_RT.block_on(async {
9705            let (ws_api, conn, mut rx) = setup().await;
9706            let client = TradeApiClient::new(ws_api.clone());
9707
9708            let handle = tokio::spawn(async move {
9709                let params = OrderListPlaceOtocoParams::builder("BNBUSDT".to_string(),OrderListPlaceOtocoWorkingTypeEnum::Limit,OrderListPlaceOtocoWorkingSideEnum::Buy,dec!(1.0),dec!(1.0),OrderListPlaceOtocoPendingSideEnum::Buy,dec!(1.0),OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,).build().unwrap();
9710                client.order_list_place_otoco(params).await
9711            });
9712
9713            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9714            let Message::Text(text) = sent else { panic!() };
9715            let v: Value = serde_json::from_str(&text).unwrap();
9716            let id = v["id"].as_str().unwrap().to_string();
9717
9718            let resp_json = json!({
9719                "id": id,
9720                "status": 400,
9721                    "error": {
9722                        "code": -2010,
9723                        "msg": "Account has insufficient balance for requested action.",
9724                    },
9725                    "rateLimits": [
9726                        {
9727                            "rateLimitType": "ORDERS",
9728                            "interval": "SECOND",
9729                            "intervalNum": 10,
9730                            "limit": 50,
9731                            "count": 13
9732                        },
9733                    ],
9734            });
9735            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9736
9737            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9738            match join {
9739                Ok(Err(e)) => {
9740                    let msg = e.to_string();
9741                    assert!(
9742                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9743                        "Expected error msg to contain server error, got: {msg}"
9744                    );
9745                }
9746                Ok(Ok(_)) => panic!("Expected error"),
9747                Err(_) => panic!("Task panicked"),
9748            }
9749        });
9750    }
9751
9752    #[test]
9753    fn order_list_place_otoco_request_timeout() {
9754        TOKIO_SHARED_RT.block_on(async {
9755            let (ws_api, _conn, mut rx) = setup().await;
9756            let client = TradeApiClient::new(ws_api.clone());
9757
9758            let handle = spawn(async move {
9759                let params = OrderListPlaceOtocoParams::builder(
9760                    "BNBUSDT".to_string(),
9761                    OrderListPlaceOtocoWorkingTypeEnum::Limit,
9762                    OrderListPlaceOtocoWorkingSideEnum::Buy,
9763                    dec!(1.0),
9764                    dec!(1.0),
9765                    OrderListPlaceOtocoPendingSideEnum::Buy,
9766                    dec!(1.0),
9767                    OrderListPlaceOtocoPendingAboveTypeEnum::StopLossLimit,
9768                )
9769                .build()
9770                .unwrap();
9771                client.order_list_place_otoco(params).await
9772            });
9773
9774            let sent = timeout(Duration::from_secs(1), rx.recv())
9775                .await
9776                .expect("send should occur")
9777                .expect("channel closed");
9778            let Message::Text(text) = sent else {
9779                panic!("expected Message Text")
9780            };
9781
9782            let _: Value = serde_json::from_str(&text).unwrap();
9783
9784            let result = handle.await.expect("task completed");
9785            match result {
9786                Err(e) => {
9787                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9788                        assert!(matches!(inner, WebsocketError::Timeout));
9789                    } else {
9790                        panic!("Unexpected error type: {:?}", e);
9791                    }
9792                }
9793                Ok(_) => panic!("Expected timeout error"),
9794            }
9795        });
9796    }
9797
9798    #[test]
9799    fn order_place_success() {
9800        TOKIO_SHARED_RT.block_on(async {
9801            let (ws_api, conn, mut rx) = setup().await;
9802            let client = TradeApiClient::new(ws_api.clone());
9803
9804            let handle = spawn(async move {
9805                let params = OrderPlaceParams::builder("BNBUSDT".to_string(),OrderPlaceSideEnum::Buy,OrderPlaceTypeEnum::Market,).build().unwrap();
9806                client.order_place(params).await
9807            });
9808
9809            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9810            let Message::Text(text) = sent else { panic!() };
9811            let v: Value = serde_json::from_str(&text).unwrap();
9812            let id = v["id"].as_str().unwrap();
9813            assert_eq!(v["method"], "/order.place".trim_start_matches('/'));
9814
9815            let mut resp_json: Value = serde_json::from_str(r#"{"id":"56374a46-3061-486b-a311-99ee972eb648","status":200,"result":{"symbol":"BTCUSDT","orderId":12569099453,"orderListId":-1,"clientOrderId":"4d96324ff9d44481926157ec08158a40","transactTime":1660801715793,"price":"23416.10000000","origQty":"0.00847000","executedQty":"0.00847000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"198.33521500","status":"FILLED","timeInForce":"GTC","type":"LIMIT","side":"SELL","workingTime":1660801715793,"selfTradePreventionMode":"NONE","fills":[{"price":"23416.50000000","qty":"0.00212000","commission":"0.000000","commissionAsset":"BNB","tradeId":1650422482},{"price":"23416.10000000","qty":"0.00635000","commission":"0.000000","commissionAsset":"BNB","tradeId":1650422481},{"price":"23416.50000000","qty":"0.00212000","commission":"0.000000","commissionAsset":"BNB","tradeId":1650422482},{"price":"23416.10000000","qty":"0.00635000","commission":"0.000000","commissionAsset":"BNB","tradeId":1650422481}]},"rateLimits":[{"rateLimitType":"ORDERS","interval":"SECOND","intervalNum":10,"limit":50,"count":1},{"rateLimitType":"ORDERS","interval":"DAY","intervalNum":1,"limit":160000,"count":1},{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
9816            resp_json["id"] = id.into();
9817
9818            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9819            let expected_data: Box<models::OrderPlaceResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9820            let empty_array = Value::Array(vec![]);
9821            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9822            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9823                match raw_rate_limits.as_array() {
9824                    Some(arr) if arr.is_empty() => None,
9825                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9826                    None => None,
9827                };
9828
9829            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9830
9831            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9832
9833
9834            let response_rate_limits = response.rate_limits.clone();
9835            let response_data = response.data().expect("deserialize data");
9836
9837            assert_eq!(response_rate_limits, expected_rate_limits);
9838            assert_eq!(response_data, expected_data);
9839        });
9840    }
9841
9842    #[test]
9843    fn order_place_error_response() {
9844        TOKIO_SHARED_RT.block_on(async {
9845            let (ws_api, conn, mut rx) = setup().await;
9846            let client = TradeApiClient::new(ws_api.clone());
9847
9848            let handle = tokio::spawn(async move {
9849                let params = OrderPlaceParams::builder("BNBUSDT".to_string(),OrderPlaceSideEnum::Buy,OrderPlaceTypeEnum::Market,).build().unwrap();
9850                client.order_place(params).await
9851            });
9852
9853            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9854            let Message::Text(text) = sent else { panic!() };
9855            let v: Value = serde_json::from_str(&text).unwrap();
9856            let id = v["id"].as_str().unwrap().to_string();
9857
9858            let resp_json = json!({
9859                "id": id,
9860                "status": 400,
9861                    "error": {
9862                        "code": -2010,
9863                        "msg": "Account has insufficient balance for requested action.",
9864                    },
9865                    "rateLimits": [
9866                        {
9867                            "rateLimitType": "ORDERS",
9868                            "interval": "SECOND",
9869                            "intervalNum": 10,
9870                            "limit": 50,
9871                            "count": 13
9872                        },
9873                    ],
9874            });
9875            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9876
9877            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
9878            match join {
9879                Ok(Err(e)) => {
9880                    let msg = e.to_string();
9881                    assert!(
9882                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
9883                        "Expected error msg to contain server error, got: {msg}"
9884                    );
9885                }
9886                Ok(Ok(_)) => panic!("Expected error"),
9887                Err(_) => panic!("Task panicked"),
9888            }
9889        });
9890    }
9891
9892    #[test]
9893    fn order_place_request_timeout() {
9894        TOKIO_SHARED_RT.block_on(async {
9895            let (ws_api, _conn, mut rx) = setup().await;
9896            let client = TradeApiClient::new(ws_api.clone());
9897
9898            let handle = spawn(async move {
9899                let params = OrderPlaceParams::builder(
9900                    "BNBUSDT".to_string(),
9901                    OrderPlaceSideEnum::Buy,
9902                    OrderPlaceTypeEnum::Market,
9903                )
9904                .build()
9905                .unwrap();
9906                client.order_place(params).await
9907            });
9908
9909            let sent = timeout(Duration::from_secs(1), rx.recv())
9910                .await
9911                .expect("send should occur")
9912                .expect("channel closed");
9913            let Message::Text(text) = sent else {
9914                panic!("expected Message Text")
9915            };
9916
9917            let _: Value = serde_json::from_str(&text).unwrap();
9918
9919            let result = handle.await.expect("task completed");
9920            match result {
9921                Err(e) => {
9922                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
9923                        assert!(matches!(inner, WebsocketError::Timeout));
9924                    } else {
9925                        panic!("Unexpected error type: {:?}", e);
9926                    }
9927                }
9928                Ok(_) => panic!("Expected timeout error"),
9929            }
9930        });
9931    }
9932
9933    #[test]
9934    fn order_test_success() {
9935        TOKIO_SHARED_RT.block_on(async {
9936            let (ws_api, conn, mut rx) = setup().await;
9937            let client = TradeApiClient::new(ws_api.clone());
9938
9939            let handle = spawn(async move {
9940                let params = OrderTestParams::builder("BNBUSDT".to_string(),OrderTestSideEnum::Buy,OrderTestTypeEnum::Market,).build().unwrap();
9941                client.order_test(params).await
9942            });
9943
9944            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
9945            let Message::Text(text) = sent else { panic!() };
9946            let v: Value = serde_json::from_str(&text).unwrap();
9947            let id = v["id"].as_str().unwrap();
9948            assert_eq!(v["method"], "/order.test".trim_start_matches('/'));
9949
9950            let mut resp_json: Value = serde_json::from_str(r#"{"id":"6ffebe91-01d9-43ac-be99-57cf062e0e30","status":200,"result":{"standardCommissionForOrder":{"maker":"0.00000112","taker":"0.00000114"},"specialCommissionForOrder":{"maker":"0.05000000","taker":"0.06000000"},"taxCommissionForOrder":{"maker":"0.00000112","taker":"0.00000114"},"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB","discount":"0.25000000"}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
9951            resp_json["id"] = id.into();
9952
9953            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
9954            let expected_data: Box<models::OrderTestResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
9955            let empty_array = Value::Array(vec![]);
9956            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
9957            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
9958                match raw_rate_limits.as_array() {
9959                    Some(arr) if arr.is_empty() => None,
9960                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
9961                    None => None,
9962                };
9963
9964            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
9965
9966            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
9967
9968
9969            let response_rate_limits = response.rate_limits.clone();
9970            let response_data = response.data().expect("deserialize data");
9971
9972            assert_eq!(response_rate_limits, expected_rate_limits);
9973            assert_eq!(response_data, expected_data);
9974        });
9975    }
9976
9977    #[test]
9978    fn order_test_error_response() {
9979        TOKIO_SHARED_RT.block_on(async {
9980            let (ws_api, conn, mut rx) = setup().await;
9981            let client = TradeApiClient::new(ws_api.clone());
9982
9983            let handle = tokio::spawn(async move {
9984                let params = OrderTestParams::builder("BNBUSDT".to_string(),OrderTestSideEnum::Buy,OrderTestTypeEnum::Market,).build().unwrap();
9985                client.order_test(params).await
9986            });
9987
9988            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
9989            let Message::Text(text) = sent else { panic!() };
9990            let v: Value = serde_json::from_str(&text).unwrap();
9991            let id = v["id"].as_str().unwrap().to_string();
9992
9993            let resp_json = json!({
9994                "id": id,
9995                "status": 400,
9996                    "error": {
9997                        "code": -2010,
9998                        "msg": "Account has insufficient balance for requested action.",
9999                    },
10000                    "rateLimits": [
10001                        {
10002                            "rateLimitType": "ORDERS",
10003                            "interval": "SECOND",
10004                            "intervalNum": 10,
10005                            "limit": 50,
10006                            "count": 13
10007                        },
10008                    ],
10009            });
10010            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10011
10012            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
10013            match join {
10014                Ok(Err(e)) => {
10015                    let msg = e.to_string();
10016                    assert!(
10017                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
10018                        "Expected error msg to contain server error, got: {msg}"
10019                    );
10020                }
10021                Ok(Ok(_)) => panic!("Expected error"),
10022                Err(_) => panic!("Task panicked"),
10023            }
10024        });
10025    }
10026
10027    #[test]
10028    fn order_test_request_timeout() {
10029        TOKIO_SHARED_RT.block_on(async {
10030            let (ws_api, _conn, mut rx) = setup().await;
10031            let client = TradeApiClient::new(ws_api.clone());
10032
10033            let handle = spawn(async move {
10034                let params = OrderTestParams::builder(
10035                    "BNBUSDT".to_string(),
10036                    OrderTestSideEnum::Buy,
10037                    OrderTestTypeEnum::Market,
10038                )
10039                .build()
10040                .unwrap();
10041                client.order_test(params).await
10042            });
10043
10044            let sent = timeout(Duration::from_secs(1), rx.recv())
10045                .await
10046                .expect("send should occur")
10047                .expect("channel closed");
10048            let Message::Text(text) = sent else {
10049                panic!("expected Message Text")
10050            };
10051
10052            let _: Value = serde_json::from_str(&text).unwrap();
10053
10054            let result = handle.await.expect("task completed");
10055            match result {
10056                Err(e) => {
10057                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
10058                        assert!(matches!(inner, WebsocketError::Timeout));
10059                    } else {
10060                        panic!("Unexpected error type: {:?}", e);
10061                    }
10062                }
10063                Ok(_) => panic!("Expected timeout error"),
10064            }
10065        });
10066    }
10067
10068    #[test]
10069    fn sor_order_place_success() {
10070        TOKIO_SHARED_RT.block_on(async {
10071            let (ws_api, conn, mut rx) = setup().await;
10072            let client = TradeApiClient::new(ws_api.clone());
10073
10074            let handle = spawn(async move {
10075                let params = SorOrderPlaceParams::builder("BNBUSDT".to_string(),SorOrderPlaceSideEnum::Buy,SorOrderPlaceTypeEnum::Market,dec!(1.0),).build().unwrap();
10076                client.sor_order_place(params).await
10077            });
10078
10079            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
10080            let Message::Text(text) = sent else { panic!() };
10081            let v: Value = serde_json::from_str(&text).unwrap();
10082            let id = v["id"].as_str().unwrap();
10083            assert_eq!(v["method"], "/sor.order.place".trim_start_matches('/'));
10084
10085            let mut resp_json: Value = serde_json::from_str(r#"{"id":"3a4437e2-41a3-4c19-897c-9cadc5dce8b6","status":200,"result":[{"symbol":"BTCUSDT","orderId":2,"orderListId":-1,"clientOrderId":"sBI1KM6nNtOfj5tccZSKly","transactTime":1689149087774,"price":"31000.00000000","origQty":"0.50000000","executedQty":"0.50000000","origQuoteOrderQty":"0.000000","cummulativeQuoteQty":"14000.00000000","status":"FILLED","timeInForce":"GTC","type":"LIMIT","side":"BUY","workingTime":1689149087774,"fills":[{"matchType":"ONE_PARTY_TRADE_REPORT","price":"28000.00000000","qty":"0.50000000","commission":"0.00000000","commissionAsset":"BTC","tradeId":-1,"allocId":0}],"workingFloor":"SOR","selfTradePreventionMode":"NONE","usedSor":true}],"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
10086            resp_json["id"] = id.into();
10087
10088            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
10089            let expected_data: Vec<models::SorOrderPlaceResponseResultInner> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
10090            let empty_array = Value::Array(vec![]);
10091            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
10092            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
10093                match raw_rate_limits.as_array() {
10094                    Some(arr) if arr.is_empty() => None,
10095                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
10096                    None => None,
10097                };
10098
10099            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10100
10101            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
10102
10103
10104            let response_rate_limits = response.rate_limits.clone();
10105            let response_data = response.data().expect("deserialize data");
10106
10107            assert_eq!(response_rate_limits, expected_rate_limits);
10108            assert_eq!(response_data, expected_data);
10109        });
10110    }
10111
10112    #[test]
10113    fn sor_order_place_error_response() {
10114        TOKIO_SHARED_RT.block_on(async {
10115            let (ws_api, conn, mut rx) = setup().await;
10116            let client = TradeApiClient::new(ws_api.clone());
10117
10118            let handle = tokio::spawn(async move {
10119                let params = SorOrderPlaceParams::builder("BNBUSDT".to_string(),SorOrderPlaceSideEnum::Buy,SorOrderPlaceTypeEnum::Market,dec!(1.0),).build().unwrap();
10120                client.sor_order_place(params).await
10121            });
10122
10123            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
10124            let Message::Text(text) = sent else { panic!() };
10125            let v: Value = serde_json::from_str(&text).unwrap();
10126            let id = v["id"].as_str().unwrap().to_string();
10127
10128            let resp_json = json!({
10129                "id": id,
10130                "status": 400,
10131                    "error": {
10132                        "code": -2010,
10133                        "msg": "Account has insufficient balance for requested action.",
10134                    },
10135                    "rateLimits": [
10136                        {
10137                            "rateLimitType": "ORDERS",
10138                            "interval": "SECOND",
10139                            "intervalNum": 10,
10140                            "limit": 50,
10141                            "count": 13
10142                        },
10143                    ],
10144            });
10145            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10146
10147            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
10148            match join {
10149                Ok(Err(e)) => {
10150                    let msg = e.to_string();
10151                    assert!(
10152                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
10153                        "Expected error msg to contain server error, got: {msg}"
10154                    );
10155                }
10156                Ok(Ok(_)) => panic!("Expected error"),
10157                Err(_) => panic!("Task panicked"),
10158            }
10159        });
10160    }
10161
10162    #[test]
10163    fn sor_order_place_request_timeout() {
10164        TOKIO_SHARED_RT.block_on(async {
10165            let (ws_api, _conn, mut rx) = setup().await;
10166            let client = TradeApiClient::new(ws_api.clone());
10167
10168            let handle = spawn(async move {
10169                let params = SorOrderPlaceParams::builder(
10170                    "BNBUSDT".to_string(),
10171                    SorOrderPlaceSideEnum::Buy,
10172                    SorOrderPlaceTypeEnum::Market,
10173                    dec!(1.0),
10174                )
10175                .build()
10176                .unwrap();
10177                client.sor_order_place(params).await
10178            });
10179
10180            let sent = timeout(Duration::from_secs(1), rx.recv())
10181                .await
10182                .expect("send should occur")
10183                .expect("channel closed");
10184            let Message::Text(text) = sent else {
10185                panic!("expected Message Text")
10186            };
10187
10188            let _: Value = serde_json::from_str(&text).unwrap();
10189
10190            let result = handle.await.expect("task completed");
10191            match result {
10192                Err(e) => {
10193                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
10194                        assert!(matches!(inner, WebsocketError::Timeout));
10195                    } else {
10196                        panic!("Unexpected error type: {:?}", e);
10197                    }
10198                }
10199                Ok(_) => panic!("Expected timeout error"),
10200            }
10201        });
10202    }
10203
10204    #[test]
10205    fn sor_order_test_success() {
10206        TOKIO_SHARED_RT.block_on(async {
10207            let (ws_api, conn, mut rx) = setup().await;
10208            let client = TradeApiClient::new(ws_api.clone());
10209
10210            let handle = spawn(async move {
10211                let params = SorOrderTestParams::builder("BNBUSDT".to_string(),SorOrderTestSideEnum::Buy,SorOrderTestTypeEnum::Market,dec!(1.0),).build().unwrap();
10212                client.sor_order_test(params).await
10213            });
10214
10215            let sent = timeout(Duration::from_secs(1), rx.recv()).await.expect("send should occur").expect("channel closed");
10216            let Message::Text(text) = sent else { panic!() };
10217            let v: Value = serde_json::from_str(&text).unwrap();
10218            let id = v["id"].as_str().unwrap();
10219            assert_eq!(v["method"], "/sor.order.test".trim_start_matches('/'));
10220
10221            let mut resp_json: Value = serde_json::from_str(r#"{"id":"3a4437e2-41a3-4c19-897c-9cadc5dce8b6","status":200,"result":{"standardCommissionForOrder":{"maker":"0.00000112","taker":"0.00000114"},"taxCommissionForOrder":{"maker":"0.00000112","taker":"0.00000114"},"discount":{"enabledForAccount":true,"enabledForSymbol":true,"discountAsset":"BNB","discount":"0.25"}},"rateLimits":[{"rateLimitType":"REQUEST_WEIGHT","interval":"MINUTE","intervalNum":1,"limit":6000,"count":1}]}"#).unwrap();
10222            resp_json["id"] = id.into();
10223
10224            let raw_data = resp_json.get("result").or_else(|| resp_json.get("response")).expect("no response in JSON");
10225            let expected_data: Box<models::SorOrderTestResponseResult> = serde_json::from_value(raw_data.clone()).expect("should parse raw response");
10226            let empty_array = Value::Array(vec![]);
10227            let raw_rate_limits = resp_json.get("rateLimits").unwrap_or(&empty_array);
10228            let expected_rate_limits: Option<Vec<WebsocketApiRateLimit>> =
10229                match raw_rate_limits.as_array() {
10230                    Some(arr) if arr.is_empty() => None,
10231                    Some(_) => Some(serde_json::from_value(raw_rate_limits.clone()).expect("should parse rateLimits array")),
10232                    None => None,
10233                };
10234
10235            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10236
10237            let response = timeout(Duration::from_secs(1), handle).await.expect("task done").expect("no panic").expect("no error");
10238
10239
10240            let response_rate_limits = response.rate_limits.clone();
10241            let response_data = response.data().expect("deserialize data");
10242
10243            assert_eq!(response_rate_limits, expected_rate_limits);
10244            assert_eq!(response_data, expected_data);
10245        });
10246    }
10247
10248    #[test]
10249    fn sor_order_test_error_response() {
10250        TOKIO_SHARED_RT.block_on(async {
10251            let (ws_api, conn, mut rx) = setup().await;
10252            let client = TradeApiClient::new(ws_api.clone());
10253
10254            let handle = tokio::spawn(async move {
10255                let params = SorOrderTestParams::builder("BNBUSDT".to_string(),SorOrderTestSideEnum::Buy,SorOrderTestTypeEnum::Market,dec!(1.0),).build().unwrap();
10256                client.sor_order_test(params).await
10257            });
10258
10259            let sent = timeout(Duration::from_secs(1), rx.recv()).await.unwrap().unwrap();
10260            let Message::Text(text) = sent else { panic!() };
10261            let v: Value = serde_json::from_str(&text).unwrap();
10262            let id = v["id"].as_str().unwrap().to_string();
10263
10264            let resp_json = json!({
10265                "id": id,
10266                "status": 400,
10267                    "error": {
10268                        "code": -2010,
10269                        "msg": "Account has insufficient balance for requested action.",
10270                    },
10271                    "rateLimits": [
10272                        {
10273                            "rateLimitType": "ORDERS",
10274                            "interval": "SECOND",
10275                            "intervalNum": 10,
10276                            "limit": 50,
10277                            "count": 13
10278                        },
10279                    ],
10280            });
10281            WebsocketHandler::on_message(&*ws_api, resp_json.to_string(), conn.clone()).await;
10282
10283            let join = timeout(Duration::from_secs(1), handle).await.unwrap();
10284            match join {
10285                Ok(Err(e)) => {
10286                    let msg = e.to_string();
10287                    assert!(
10288                        msg.contains("Server‐side response error (code -2010): Account has insufficient balance for requested action."),
10289                        "Expected error msg to contain server error, got: {msg}"
10290                    );
10291                }
10292                Ok(Ok(_)) => panic!("Expected error"),
10293                Err(_) => panic!("Task panicked"),
10294            }
10295        });
10296    }
10297
10298    #[test]
10299    fn sor_order_test_request_timeout() {
10300        TOKIO_SHARED_RT.block_on(async {
10301            let (ws_api, _conn, mut rx) = setup().await;
10302            let client = TradeApiClient::new(ws_api.clone());
10303
10304            let handle = spawn(async move {
10305                let params = SorOrderTestParams::builder(
10306                    "BNBUSDT".to_string(),
10307                    SorOrderTestSideEnum::Buy,
10308                    SorOrderTestTypeEnum::Market,
10309                    dec!(1.0),
10310                )
10311                .build()
10312                .unwrap();
10313                client.sor_order_test(params).await
10314            });
10315
10316            let sent = timeout(Duration::from_secs(1), rx.recv())
10317                .await
10318                .expect("send should occur")
10319                .expect("channel closed");
10320            let Message::Text(text) = sent else {
10321                panic!("expected Message Text")
10322            };
10323
10324            let _: Value = serde_json::from_str(&text).unwrap();
10325
10326            let result = handle.await.expect("task completed");
10327            match result {
10328                Err(e) => {
10329                    if let Some(inner) = e.downcast_ref::<WebsocketError>() {
10330                        assert!(matches!(inner, WebsocketError::Timeout));
10331                    } else {
10332                        panic!("Unexpected error type: {:?}", e);
10333                    }
10334                }
10335                Ok(_) => panic!("Expected timeout error"),
10336            }
10337        });
10338    }
10339}