bybit/
model.rs

1#![allow(unused_imports)]
2use crate::errors::BybitError;
3use serde::{Deserialize, Serialize};
4use serde_json::{from_value, Value};
5use std::{borrow::Cow, collections::BTreeMap};
6use thiserror::Error;
7
8#[derive(Serialize, Default, Deserialize, Clone, Debug)]
9pub struct Empty {}
10
11/// ----------------------------------------
12///  RESPONSE STRUCTS FOR MARKET REQUESTS
13/// ----------------------------------------
14
15#[derive(Serialize, Deserialize, Clone, Debug)]
16#[serde(rename_all = "camelCase")]
17pub struct ServerTimeResponse {
18    #[serde(rename = "retCode")]
19    pub ret_code: i16,
20    #[serde(rename = "retMsg")]
21    pub ret_msg: String,
22    pub result: ServerTime,
23    #[serde(rename = "retExtInfo")]
24    pub ret_ext_info: Empty,
25    pub time: u64,
26}
27
28#[derive(Serialize, Deserialize, Clone, Debug)]
29#[serde(rename_all = "camelCase")]
30pub struct ServerTime {
31    #[serde(with = "string_to_u64")]
32    pub time_second: u64,
33    #[serde(with = "string_to_u64")]
34    pub time_nano: u64,
35}
36
37#[derive(Clone, Default)]
38pub struct KlineRequest<'a> {
39    pub category: Option<Category>,
40    pub symbol: Cow<'a, str>,
41    pub interval: Cow<'a, str>,
42    pub start: Option<Cow<'a, str>>,
43    pub end: Option<Cow<'a, str>>,
44    pub limit: Option<u64>,
45}
46
47impl<'a> KlineRequest<'a> {
48    pub fn default() -> KlineRequest<'a> {
49        KlineRequest::new(None, "BTCUSDT", "", None, None, None)
50    }
51    pub fn new(
52        category: Option<Category>,
53        symbol: &'a str,
54        interval: &'a str,
55        start: Option<&'a str>,
56        end: Option<&'a str>,
57        limit: Option<u64>,
58    ) -> KlineRequest<'a> {
59        KlineRequest {
60            category: category,
61            symbol: Cow::Borrowed(symbol),
62            interval: Cow::Borrowed(interval),
63            start: start.map(|s| Cow::Borrowed(s)),
64            end: end.map(|s| Cow::Borrowed(s)),
65            limit,
66        }
67    }
68}
69#[derive(Serialize, Deserialize, Clone, Debug)]
70#[serde(rename_all = "camelCase")]
71pub struct KlineResponse {
72    #[serde(rename = "retCode")]
73    pub ret_code: i16,
74    #[serde(rename = "retMsg")]
75    pub ret_msg: String,
76    pub result: KlineSummary,
77    #[serde(rename = "retExtInfo")]
78    pub ret_ext_info: Empty,
79    pub time: u64,
80}
81
82#[derive(Serialize, Deserialize, Clone, Debug)]
83#[serde(rename_all = "camelCase")]
84pub struct KlineSummary {
85    pub symbol: String,
86    pub category: String,
87    pub list: Vec<Kline>,
88}
89
90#[derive(Serialize, Deserialize, Clone, Debug)]
91#[serde(rename_all = "camelCase")]
92pub struct Kline {
93    #[serde(with = "string_to_u64")]
94    pub start_time: u64,
95    pub open_price: String,
96    pub high_price: String,
97    pub low_price: String,
98    pub close_price: String,
99    pub volume: String,
100    pub quote_asset_volume: String,
101}
102
103#[derive(Serialize, Deserialize, Clone, Debug)]
104#[serde(rename_all = "camelCase")]
105pub struct MarkPriceKlineResponse {
106    #[serde(rename = "retCode")]
107    pub ret_code: i16,
108    #[serde(rename = "retMsg")]
109    pub ret_msg: String,
110    pub result: MarkPriceKlineSummary,
111    #[serde(rename = "retExtInfo")]
112    pub ret_ext_info: Empty,
113    pub time: u64,
114}
115
116#[derive(Serialize, Deserialize, Clone, Debug)]
117#[serde(rename_all = "camelCase")]
118pub struct MarkPriceKlineSummary {
119    pub symbol: String,
120    pub category: String,
121    pub list: Vec<MarkPriceKline>,
122}
123
124#[derive(Serialize, Deserialize, Clone, Debug)]
125#[serde(rename_all = "camelCase")]
126pub struct MarkPriceKline {
127    #[serde(with = "string_to_u64")]
128    pub start_time: u64,
129    pub open_price: String,
130    pub high_price: String,
131    pub low_price: String,
132    pub close_price: String,
133}
134
135#[derive(Serialize, Deserialize, Clone, Debug)]
136#[serde(rename_all = "camelCase")]
137pub struct IndexPriceKlineResponse {
138    #[serde(rename = "retCode")]
139    pub ret_code: i16,
140    #[serde(rename = "retMsg")]
141    pub ret_msg: String,
142    pub result: IndexPriceKlineSummary,
143    #[serde(rename = "retExtInfo")]
144    pub ret_ext_info: Empty,
145    pub time: u64,
146}
147
148#[derive(Serialize, Deserialize, Clone, Debug)]
149#[serde(rename_all = "camelCase")]
150pub struct IndexPriceKlineSummary {
151    pub symbol: String,
152    pub category: String,
153    pub list: Vec<IndexPriceKline>,
154}
155
156#[derive(Serialize, Deserialize, Clone, Debug)]
157#[serde(rename_all = "camelCase")]
158pub struct IndexPriceKline {
159    #[serde(with = "string_to_u64")]
160    pub start_time: u64,
161    pub open_price: String,
162    pub high_price: String,
163    pub low_price: String,
164    pub close_price: String,
165}
166
167#[derive(Serialize, Deserialize, Clone, Debug)]
168#[serde(rename_all = "camelCase")]
169pub struct PremiumIndexPriceKlineResponse {
170    #[serde(rename = "retCode")]
171    pub ret_code: i16,
172    #[serde(rename = "retMsg")]
173    pub ret_msg: String,
174    pub result: PremiumIndexPriceKlineSummary,
175    #[serde(rename = "retExtInfo")]
176    pub ret_ext_info: Empty,
177    pub time: u64,
178}
179
180#[derive(Serialize, Deserialize, Clone, Debug)]
181#[serde(rename_all = "camelCase")]
182pub struct PremiumIndexPriceKlineSummary {
183    pub symbol: String,
184    pub category: String,
185    pub list: Vec<PremiumIndexPriceKline>,
186}
187
188#[derive(Serialize, Deserialize, Clone, Debug)]
189#[serde(rename_all = "camelCase")]
190pub struct PremiumIndexPriceKline {
191    #[serde(with = "string_to_u64")]
192    pub start_time: u64,
193    pub open_price: String,
194    pub high_price: String,
195    pub low_price: String,
196    pub close_price: String,
197}
198
199#[derive(Clone, Default)]
200pub struct InstrumentRequest<'a> {
201    pub category: Category,
202    pub symbol: Option<Cow<'a, str>>,
203    pub status: Option<bool>,
204    pub base_coin: Option<Cow<'a, str>>,
205    pub limit: Option<u64>,
206}
207impl<'a> InstrumentRequest<'a> {
208    pub fn default() -> InstrumentRequest<'a> {
209        InstrumentRequest::new(Category::Linear, Some("BTCUSDT"), None, None, None)
210    }
211    pub fn new(
212        category: Category,
213        symbol: Option<&'a str>,
214        status: Option<bool>,
215        base_coin: Option<&'a str>,
216        limit: Option<u64>,
217    ) -> InstrumentRequest<'a> {
218        InstrumentRequest {
219            category: category,
220            symbol: symbol.map(|s| Cow::Borrowed(s)),
221            status: status,
222            base_coin: base_coin.map(|s| Cow::Borrowed(s)),
223            limit,
224        }
225    }
226}
227
228#[derive(Serialize, Deserialize, Clone, Debug)]
229#[serde(rename_all = "camelCase")]
230pub struct FuturesInstrumentsInfoResponse {
231    #[serde(rename = "retCode")]
232    pub ret_code: i16,
233    #[serde(rename = "retMsg")]
234    pub ret_msg: String,
235    pub result: FuturesInstrumentsInfo,
236    #[serde(rename = "retExtInfo")]
237    pub ret_ext_info: Empty,
238    pub time: u64,
239}
240
241#[derive(Serialize, Deserialize, Clone, Debug)]
242#[serde(rename_all = "camelCase")]
243pub struct FuturesInstrumentsInfo {
244    pub category: String,
245    pub list: Vec<FuturesInstrument>,
246    #[serde(rename = "nextPageCursor", skip_serializing_if = "String::is_empty")]
247    pub next_page_cursor: String,
248}
249
250#[derive(Serialize, Deserialize, Clone, Debug)]
251#[serde(rename_all = "camelCase")]
252pub struct FuturesInstrument {
253    pub symbol: String,
254    #[serde(rename = "contractType")]
255    pub contract_type: String,
256    pub status: String,
257    #[serde(rename = "baseCoin")]
258    pub base_coin: String,
259    #[serde(rename = "quoteCoin")]
260    pub quote_coin: String,
261    #[serde(rename = "launchTime", with = "string_to_u64")]
262    pub launch_time: u64,
263    #[serde(rename = "deliveryTime", skip_serializing_if = "String::is_empty")]
264    pub delivery_time: String,
265    #[serde(rename = "deliveryFeeRate")]
266    pub delivery_fee_rate: String,
267    #[serde(rename = "priceScale")]
268    pub price_scale: String,
269    #[serde(rename = "leverageFilter")]
270    pub leverage_filter: LeverageFilter,
271    #[serde(rename = "priceFilter")]
272    pub price_filter: PriceFilter,
273    #[serde(rename = "lotSizeFilter")]
274    pub lot_size_filter: LotSizeFilter,
275    #[serde(rename = "unifiedMarginTrade")]
276    pub unified_margin_trade: bool,
277    #[serde(rename = "fundingInterval")]
278    pub funding_interval: u64,
279    #[serde(rename = "settleCoin")]
280    pub settle_coin: String,
281    #[serde(rename = "copyTrading")]
282    pub copy_trading: String,
283    #[serde(rename = "upperFundingRate")]
284    pub upper_funding_rate: String,
285    #[serde(rename = "lowerFundingRate")]
286    pub lower_funding_rate: String,
287    // #[serde(rename = "isPreListing" )]
288    // pub is_pre_listing: bool,
289    // #[serde(rename = "preListingInfo")]
290    // pub pre_listing_info: PreListingInfo,
291}
292
293#[derive(Serialize, Deserialize, Clone, Debug)]
294#[serde(rename_all = "camelCase")]
295pub struct SpotInstrumentsInfoResponse {
296    #[serde(rename = "retCode")]
297    pub ret_code: i16,
298    #[serde(rename = "retMsg")]
299    pub ret_msg: String,
300    pub result: SpotInstrumentsInfo,
301    #[serde(rename = "retExtInfo")]
302    pub ret_ext_info: Empty,
303    pub time: u64,
304}
305
306#[derive(Serialize, Deserialize, Clone, Debug)]
307#[serde(rename_all = "camelCase")]
308pub struct SpotInstrumentsInfo {
309    pub category: String,
310    pub list: Vec<SpotInstrument>,
311    #[serde(rename = "nextPageCursor", skip_serializing_if = "String::is_empty")]
312    pub next_page_cursor: String,
313}
314#[derive(Serialize, Deserialize, Clone, Debug)]
315#[serde(rename_all = "camelCase")]
316pub struct SpotInstrument {
317    pub symbol: String,
318    #[serde(rename = "baseCoin")]
319    pub base_coin: String,
320    #[serde(rename = "quoteCoin")]
321    pub quote_coin: String,
322    pub innovation: String,
323    pub status: String,
324    #[serde(rename = "marginTrading")]
325    pub margin_trading: String,
326    #[serde(rename = "lotSizeFilter")]
327    pub lot_size_filter: LotSizeFilter,
328    #[serde(rename = "priceFilter")]
329    pub price_filter: PriceFilter,
330    #[serde(rename = "riskParameters")]
331    pub risk_parameters: RiskParameters,
332}
333
334#[derive(Serialize, Deserialize, Clone, Debug)]
335#[serde(rename_all = "camelCase")]
336pub struct OptionsInstrument {
337    pub symbol: String,
338    pub status: String,
339    #[serde(rename = "baseCoin")]
340    pub base_coin: String,
341    #[serde(rename = "quoteCoin")]
342    pub quote_coin: String,
343    #[serde(rename = "settleCoin")]
344    pub settle_coin: String,
345    #[serde(rename = "optionType")]
346    pub option_type: String,
347    #[serde(rename = "launchTime", with = "string_to_u64")]
348    pub launch_time: u64,
349    #[serde(rename = "deliveryTime", with = "string_to_u64")]
350    pub delivery_time: u64,
351    #[serde(rename = "deliveryFeeRate")]
352    pub delivery_fee_rate: String,
353    #[serde(rename = "priceFilter")]
354    pub price_filter: PriceFilter,
355    #[serde(rename = "lotSizeFilter")]
356    pub lot_size_filter: LotSizeFilter,
357}
358
359#[derive(Serialize, Deserialize, Clone, Debug)]
360#[serde(rename_all = "camelCase")]
361pub struct PreListingInfo {
362    pub cur_auction_phase: String,
363    pub phases: Vec<PreListingPhase>,
364    pub auction_fee_info: AuctionFeeInfo,
365}
366
367#[derive(Serialize, Deserialize, Clone, Debug)]
368#[serde(rename_all = "camelCase")]
369pub struct PreListingPhase {
370    pub phase: String,
371    #[serde(rename = "startTime", with = "string_to_u64")]
372    pub start_time: u64,
373    #[serde(rename = "endTime", with = "string_to_u64")]
374    pub end_time: u64,
375}
376
377#[derive(Serialize, Deserialize, Clone, Debug)]
378#[serde(rename_all = "camelCase")]
379pub struct AuctionFeeInfo {
380    pub auction_fee_rate: String,
381    pub taker_fee_rate: String,
382    pub maker_fee_rate: String,
383}
384
385#[derive(Debug, Serialize, Deserialize, Clone)]
386#[serde(rename_all = "camelCase")]
387pub struct RiskParameters {
388    #[serde(rename = "limitParameter")]
389    pub limit_parameter: String,
390    #[serde(rename = "marketParameter")]
391    pub market_parameter: String,
392}
393
394#[derive(Debug, Serialize, Deserialize, Clone)]
395#[serde(rename_all = "camelCase")]
396pub struct LeverageFilter {
397    #[serde(rename = "minLeverage")]
398    pub min_leverage: String,
399    #[serde(rename = "maxLeverage")]
400    pub max_leverage: String,
401    #[serde(rename = "leverageStep")]
402    pub leverage_step: String,
403}
404
405#[derive(Debug, Serialize, Deserialize, Clone)]
406#[serde(rename_all = "camelCase")]
407pub struct PriceFilter {
408    #[serde(rename = "minPrice")]
409    pub min_price: Option<String>,
410    #[serde(rename = "maxPrice")]
411    pub max_price: Option<String>,
412    #[serde(rename = "tickSize", with = "string_to_float")]
413    pub tick_size: f64,
414}
415
416#[derive(Debug, Serialize, Deserialize, Clone)]
417#[serde(rename_all = "camelCase")]
418pub struct LotSizeFilter {
419    #[serde(rename = "basePrecision", skip_serializing_if = "Option::is_none", default)]
420    pub base_precision: Option<String>,
421    #[serde(rename = "quotePrecision", skip_serializing_if = "Option::is_none")]
422    pub quote_precision: Option<String>,
423    #[serde(rename = "maxMktOrderQty", skip_serializing_if = "Option::is_none")]
424    pub max_mkt_order_qty: Option<String>,
425    #[serde(rename = "minOrderQty", with = "string_to_float")]
426    pub min_order_qty: f64,
427    #[serde(rename = "maxOrderQty", with = "string_to_float")]
428    pub max_order_qty: f64,
429    #[serde(rename = "minOrderAmt", skip_serializing_if = "Option::is_none")]
430    pub min_order_amt: Option<String>,
431    #[serde(rename = "maxOrderAmt", skip_serializing_if = "Option::is_none")]
432    pub max_order_amt: Option<String>,
433    #[serde(rename = "qtyStep", skip_serializing_if = "Option::is_none")]
434    pub qty_step: Option<String>,
435    #[serde(
436        rename = "postOnlyMaxOrderQty",
437        skip_serializing_if = "Option::is_none"
438    )]
439    pub post_only_max_order_qty: Option<String>,
440    #[serde(rename = "minNotionalValue", skip_serializing_if = "Option::is_none")]
441    pub min_notional_value: Option<String>,
442}
443
444#[derive(Clone, Default)]
445pub struct OrderbookRequest<'a> {
446    pub symbol: Cow<'a, str>,
447    pub category: Category,
448    pub limit: Option<u64>,
449}
450
451impl<'a> OrderbookRequest<'a> {
452    pub fn default() -> OrderbookRequest<'a> {
453        OrderbookRequest::new("BTCUSDT", Category::Linear, None)
454    }
455
456    pub fn new(symbol: &'a str, category: Category, limit: Option<u64>) -> OrderbookRequest<'a> {
457        OrderbookRequest {
458            symbol: Cow::Borrowed(symbol),
459            category,
460            limit,
461        }
462    }
463}
464#[derive(Serialize, Deserialize, Clone, Debug)]
465#[serde(rename_all = "camelCase")]
466pub struct OrderBookResponse {
467    #[serde(rename = "retCode")]
468    pub ret_code: i16,
469    #[serde(rename = "retMsg")]
470    pub ret_msg: String,
471    pub result: OrderBook,
472    #[serde(rename = "retExtInfo")]
473    pub ret_ext_info: Empty,
474    pub time: u64,
475}
476
477#[derive(Serialize, Deserialize, Clone, Debug)]
478#[serde(rename_all = "camelCase")]
479pub struct OrderBook {
480    #[serde(rename = "s")]
481    pub symbol: String,
482    #[serde(rename = "a")]
483    pub asks: Vec<Ask>,
484    #[serde(rename = "b")]
485    pub bids: Vec<Bid>,
486    #[serde(rename = "ts")]
487    pub timestamp: u64,
488    #[serde(rename = "u")]
489    pub update_id: u64,
490}
491
492#[derive(Serialize, Deserialize, Clone, Debug)]
493#[serde(rename_all = "camelCase")]
494pub struct Ask {
495    #[serde(with = "string_to_float")]
496    pub price: f64,
497    #[serde(with = "string_to_float")]
498    pub qty: f64,
499}
500
501#[derive(Serialize, Deserialize, Clone, Debug)]
502#[serde(rename_all = "camelCase")]
503pub struct Bid {
504    #[serde(with = "string_to_float")]
505    pub price: f64,
506    #[serde(with = "string_to_float")]
507    pub qty: f64,
508}
509
510impl Bid {
511    pub fn new(price: f64, qty: f64) -> Bid {
512        Bid { price, qty }
513    }
514}
515impl Ask {
516    pub fn new(price: f64, qty: f64) -> Ask {
517        Ask { price, qty }
518    }
519}
520
521#[derive(Serialize, Deserialize, Clone, Debug)]
522#[serde(rename_all = "camelCase")]
523pub struct FuturesTickersResponse {
524    #[serde(rename = "retCode")]
525    pub ret_code: i16,
526    #[serde(rename = "retMsg")]
527    pub ret_msg: String,
528    pub result: FuturesTickers,
529    #[serde(rename = "retExtInfo")]
530    pub ret_ext_info: Empty,
531    pub time: u64,
532}
533#[derive(Serialize, Deserialize, Clone, Debug)]
534#[serde(rename_all = "camelCase")]
535pub struct SpotTickersResponse {
536    #[serde(rename = "retCode")]
537    pub ret_code: i16,
538    #[serde(rename = "retMsg")]
539    pub ret_msg: String,
540    pub result: SpotTickers,
541    #[serde(rename = "retExtInfo")]
542    pub ret_ext_info: Empty,
543    pub time: u64,
544}
545
546#[derive(Serialize, Deserialize, Clone, Debug)]
547#[serde(rename_all = "camelCase")]
548pub struct FuturesTickers {
549    pub category: String,
550    pub list: Vec<FuturesTicker>,
551}
552
553#[derive(Serialize, Deserialize, Clone, Debug)]
554#[serde(rename_all = "camelCase")]
555pub struct SpotTickers {
556    pub category: String,
557    pub list: Vec<SpotTicker>,
558}
559
560#[derive(Serialize, Deserialize, Clone, Debug)]
561#[serde(rename_all = "camelCase")]
562pub struct FuturesTicker {
563    pub symbol: String,
564    #[serde(with = "string_to_float")]
565    pub last_price: f64,
566    #[serde(with = "string_to_float")]
567    pub index_price: f64,
568    #[serde(with = "string_to_float")]
569    pub mark_price: f64,
570    #[serde(rename = "prevPrice24h", with = "string_to_float")]
571    pub prev_price_24h: f64,
572    #[serde(rename = "price24hPcnt", with = "string_to_float")]
573    pub daily_change_percentage: f64,
574    #[serde(rename = "highPrice24h", with = "string_to_float")]
575    pub high_24h: f64,
576    #[serde(rename = "lowPrice24h", with = "string_to_float")]
577    pub low_24h: f64,
578    #[serde(rename = "prevPrice1h", with = "string_to_float")]
579    pub prev_price_1h: f64,
580    #[serde(with = "string_to_float")]
581    pub open_interest: f64,
582    #[serde(with = "string_to_float")]
583    pub open_interest_value: f64,
584    #[serde(rename = "turnover24h")]
585    pub turnover_24h: String,
586    #[serde(rename = "volume24h")]
587    pub volume_24h: String,
588    pub funding_rate: String,
589    #[serde(rename = "nextFundingTime", with = "string_to_u64")]
590    pub next_funding_time: u64,
591    #[serde(skip_serializing_if = "String::is_empty")]
592    pub predicted_delivery_price: String,
593    #[serde(skip_serializing_if = "String::is_empty")]
594    pub basis_rate: String,
595    pub delivery_fee_rate: String,
596    #[serde(rename = "deliveryTime", with = "string_to_u64")]
597    pub delivery_time: u64,
598    #[serde(rename = "ask1Size", with = "string_to_float")]
599    pub ask_size: f64,
600    #[serde(rename = "bid1Price", with = "string_to_float")]
601    pub bid_price: f64,
602    #[serde(rename = "ask1Price", with = "string_to_float")]
603    pub ask_price: f64,
604    #[serde(rename = "bid1Size", with = "string_to_float")]
605    pub bid_size: f64,
606    #[serde(skip_serializing_if = "String::is_empty")]
607    pub basis: String,
608}
609
610#[derive(Serialize, Deserialize, Clone, Debug)]
611#[serde(rename_all = "camelCase")]
612pub struct SpotTicker {
613    pub symbol: String,
614    #[serde(rename = "bid1Price", with = "string_to_float")]
615    pub bid_price: f64,
616    #[serde(rename = "bid1Size", with = "string_to_float")]
617    pub bid_size: f64,
618    #[serde(rename = "ask1Price", with = "string_to_float")]
619    pub ask_price: f64,
620    #[serde(rename = "ask1Size", with = "string_to_float")]
621    pub ask_size: f64,
622    #[serde(with = "string_to_float")]
623    pub last_price: f64,
624    #[serde(rename = "prevPrice24h", with = "string_to_float")]
625    pub prev_price_24h: f64,
626    #[serde(rename = "price24hPcnt", with = "string_to_float")]
627    pub daily_change_percentage: f64,
628    #[serde(rename = "highPrice24h", with = "string_to_float")]
629    pub high_24h: f64,
630    #[serde(rename = "lowPrice24h", with = "string_to_float")]
631    pub low_24h: f64,
632    #[serde(rename = "turnover24h")]
633    pub turnover_24h: String,
634    #[serde(rename = "volume24h")]
635    pub volume_24h: String,
636    #[serde(rename = "usdIndexPrice")]
637    pub usd_index_price: String,
638}
639
640#[derive(Clone, Default)]
641pub struct FundingHistoryRequest<'a> {
642    pub category: Category,
643    pub symbol: Cow<'a, str>,
644    pub start_time: Option<Cow<'a, str>>,
645    pub end_time: Option<Cow<'a, str>>,
646    pub limit: Option<u64>,
647}
648impl<'a> FundingHistoryRequest<'a> {
649    pub fn default() -> FundingHistoryRequest<'a> {
650        FundingHistoryRequest::new(Category::Linear, "BTCUSDT", None, None, None)
651    }
652    pub fn new(
653        category: Category,
654        symbol: &'a str,
655        start_time: Option<&'a str>,
656        end_time: Option<&'a str>,
657        limit: Option<u64>,
658    ) -> FundingHistoryRequest<'a> {
659        FundingHistoryRequest {
660            category,
661            symbol: Cow::Borrowed(symbol),
662            start_time: start_time.map(|s| Cow::Borrowed(s)),
663            end_time: end_time.map(|s| Cow::Borrowed(s)),
664            limit,
665        }
666    }
667}
668
669#[derive(Serialize, Deserialize, Clone, Debug)]
670#[serde(rename_all = "camelCase")]
671pub struct FundingRateResponse {
672    #[serde(rename = "retCode")]
673    pub ret_code: i16,
674    #[serde(rename = "retMsg")]
675    pub ret_msg: String,
676    pub result: FundingRateSummary,
677    #[serde(rename = "retExtInfo")]
678    pub ret_ext_info: Empty,
679    pub time: u64,
680}
681
682#[derive(Serialize, Deserialize, Clone, Debug)]
683#[serde(rename_all = "camelCase")]
684pub struct FundingRateSummary {
685    pub category: String,
686    pub list: Vec<FundingRate>,
687}
688
689#[derive(Serialize, Deserialize, Clone, Debug)]
690#[serde(rename_all = "camelCase")]
691pub struct FundingRate {
692    pub symbol: String,
693    #[serde(rename = "fundingRate", with = "string_to_float")]
694    pub funding_rate: f64,
695    #[serde(rename = "fundingRateTimestamp", with = "string_to_u64")]
696    pub funding_rate_timestamp: u64,
697}
698
699#[derive(Clone, Default)]
700pub struct RecentTradesRequest<'a> {
701    pub category: Category,
702    pub symbol: Option<Cow<'a, str>>,
703    pub base_coin: Option<Cow<'a, str>>,
704    pub limit: Option<u64>,
705}
706impl<'a> RecentTradesRequest<'a> {
707    pub fn default() -> RecentTradesRequest<'a> {
708        RecentTradesRequest::new(Category::Linear, Some("BTCUSDT"), None, None)
709    }
710    pub fn new(
711        category: Category,
712        symbol: Option<&'a str>,
713        base_coin: Option<&'a str>,
714        limit: Option<u64>,
715    ) -> RecentTradesRequest<'a> {
716        RecentTradesRequest {
717            category,
718            symbol: symbol.map(|s| Cow::Borrowed(s)),
719            base_coin: base_coin.map(|s| Cow::Borrowed(s)),
720            limit,
721        }
722    }
723}
724
725#[derive(Serialize, Deserialize, Clone, Debug)]
726#[serde(rename_all = "camelCase")]
727pub struct RecentTradesResponse {
728    #[serde(rename = "retCode")]
729    pub ret_code: i16,
730    #[serde(rename = "retMsg")]
731    pub ret_msg: String,
732    pub result: RecentTrades,
733    #[serde(rename = "retExtInfo")]
734    pub ret_ext_info: Empty,
735    pub time: u64,
736}
737
738#[derive(Serialize, Deserialize, Clone, Debug)]
739#[serde(rename_all = "camelCase")]
740pub struct RecentTrades {
741    pub category: String,
742    pub list: Vec<RecentTrade>,
743}
744
745#[derive(Serialize, Deserialize, Clone, Debug)]
746#[serde(rename_all = "camelCase")]
747pub struct RecentTrade {
748    #[serde(rename = "execId")]
749    pub exec_id: String,
750    pub symbol: String,
751    #[serde(with = "string_to_float")]
752    pub price: f64,
753    #[serde(rename = "size", with = "string_to_float")]
754    pub qty: f64,
755    pub side: String,
756    #[serde(rename = "time")]
757    pub timestamp: String,
758    #[serde(rename = "isBlockTrade")]
759    pub is_block_trade: bool,
760}
761
762#[derive(Clone, Default)]
763pub struct OpenInterestRequest<'a> {
764    pub category: Category,
765    pub symbol: Cow<'a, str>,
766    pub interval: Cow<'a, str>,
767    pub start: Option<Cow<'a, str>>,
768    pub end: Option<Cow<'a, str>>,
769    pub limit: Option<u64>,
770}
771
772impl<'a> OpenInterestRequest<'a> {
773    pub fn default() -> OpenInterestRequest<'a> {
774        OpenInterestRequest::new(Category::Linear, "BTCUSDT", "4h", None, None, None)
775    }
776    pub fn new(
777        category: Category,
778        symbol: &'a str,
779        interval: &'a str,
780        start: Option<&'a str>,
781        end: Option<&'a str>,
782        limit: Option<u64>,
783    ) -> OpenInterestRequest<'a> {
784        OpenInterestRequest {
785            category,
786            symbol: Cow::Borrowed(symbol),
787            interval: Cow::Borrowed(interval),
788            start: start.map(|s| Cow::Borrowed(s)),
789            end: end.map(|s| Cow::Borrowed(s)),
790            limit,
791        }
792    }
793}
794#[derive(Serialize, Deserialize, Clone, Debug)]
795#[serde(rename_all = "camelCase")]
796pub struct OpeninterestResponse {
797    #[serde(rename = "retCode")]
798    pub ret_code: i16,
799    #[serde(rename = "retMsg")]
800    pub ret_msg: String,
801    pub result: OpenInterestSummary,
802    #[serde(rename = "retExtInfo")]
803    pub ret_ext_info: Empty,
804    pub time: u64,
805}
806
807#[derive(Serialize, Deserialize, Clone, Debug)]
808#[serde(rename_all = "camelCase")]
809pub struct OpenInterestSummary {
810    pub symbol: String,
811    pub category: String,
812    pub list: Vec<OpenInterest>,
813    #[serde(rename = "nextPageCursor", skip_serializing_if = "String::is_empty")]
814    pub next_page_cursor: String,
815}
816
817#[derive(Serialize, Deserialize, Clone, Debug)]
818#[serde(rename_all = "camelCase")]
819pub struct OpenInterest {
820    #[serde(rename = "openInterest", with = "string_to_float")]
821    pub open_interest: f64,
822    #[serde(with = "string_to_u64")]
823    pub timestamp: u64,
824}
825
826#[derive(Clone, Default)]
827pub struct HistoricalVolatilityRequest<'a> {
828    pub base_coin: Option<Cow<'a, str>>,
829    pub period: Option<Cow<'a, str>>,
830    pub start: Option<Cow<'a, str>>,
831    pub end: Option<Cow<'a, str>>,
832}
833
834impl<'a> HistoricalVolatilityRequest<'a> {
835    pub fn default() -> HistoricalVolatilityRequest<'a> {
836        HistoricalVolatilityRequest::new(Some("BTC"), None, None, None)
837    }
838    pub fn new(
839        base_coin: Option<&'a str>,
840        period: Option<&'a str>,
841        start: Option<&'a str>,
842        end: Option<&'a str>,
843    ) -> HistoricalVolatilityRequest<'a> {
844        HistoricalVolatilityRequest {
845            base_coin: base_coin.map(|s| Cow::Borrowed(s)),
846            period: period.map(|s| Cow::Borrowed(s)),
847            start: start.map(|s| Cow::Borrowed(s)),
848            end: end.map(|s| Cow::Borrowed(s)),
849        }
850    }
851}
852
853#[derive(Serialize, Deserialize, Clone, Debug)]
854#[serde(rename_all = "camelCase")]
855pub struct HistoricalVolatilityResponse {
856    #[serde(rename = "retCode")]
857    pub ret_code: i16,
858    #[serde(rename = "retMsg")]
859    pub ret_msg: String,
860    pub category: String,
861    #[serde(rename = "result")]
862    pub result: Vec<HistoricalVolatility>,
863}
864
865#[derive(Serialize, Deserialize, Clone, Debug)]
866#[serde(rename_all = "camelCase")]
867pub struct HistoricalVolatility {
868    pub period: u64,
869    #[serde(with = "string_to_float")]
870    pub value: f64,
871    #[serde(rename = "time", with = "string_to_u64")]
872    pub timestamp: u64,
873}
874
875#[derive(Serialize, Deserialize, Clone, Debug)]
876#[serde(rename_all = "camelCase")]
877pub struct InsuranceResponse {
878    #[serde(rename = "retCode")]
879    pub ret_code: i16,
880    #[serde(rename = "retMsg")]
881    pub ret_msg: String,
882    pub result: InsuranceSummary,
883    #[serde(rename = "retExtInfo")]
884    pub ret_ext_info: Empty,
885    pub time: u64,
886}
887
888#[derive(Serialize, Deserialize, Clone, Debug)]
889#[serde(rename_all = "camelCase")]
890pub struct InsuranceSummary {
891    #[serde(rename = "updatedTime", with = "string_to_u64")]
892    pub updated_time: u64,
893    pub list: Vec<Insurance>,
894}
895
896#[derive(Serialize, Deserialize, Clone, Debug)]
897#[serde(rename_all = "camelCase")]
898pub struct Insurance {
899    pub coin: String,
900    #[serde(with = "string_to_float")]
901    pub balance: f64,
902    pub value: String,
903}
904
905#[derive(Clone, Default)]
906pub struct RiskLimitRequest<'a> {
907    pub category: Category,
908    pub symbol: Option<Cow<'a, str>>,
909}
910
911impl<'a> RiskLimitRequest<'a> {
912    pub fn default() -> RiskLimitRequest<'a> {
913        RiskLimitRequest::new(Category::Linear, None)
914    }
915    pub fn new(category: Category, symbol: Option<&'a str>) -> RiskLimitRequest<'a> {
916        RiskLimitRequest {
917            category,
918            symbol: symbol.map(|s| Cow::Borrowed(s)),
919        }
920    }
921}
922
923#[derive(Serialize, Deserialize, Clone, Debug)]
924pub struct RiskLimitResponse {
925    #[serde(rename = "retCode")]
926    pub ret_code: i16,
927    #[serde(rename = "retMsg")]
928    pub ret_msg: String,
929    pub result: RiskLimitSummary,
930    #[serde(rename = "retExtInfo")]
931    pub ret_ext_info: Empty,
932    pub time: u64,
933}
934
935#[derive(Serialize, Deserialize, Clone, Debug)]
936pub struct RiskLimitSummary {
937    pub category: String,
938    pub list: Vec<RiskLimit>,
939}
940
941#[derive(Serialize, Deserialize, Clone, Debug)]
942pub struct RiskLimit {
943    pub id: u64,
944    pub symbol: String,
945    #[serde(rename = "riskLimitValue", with = "string_to_float")]
946    pub risk_limit_value: f64,
947    #[serde(rename = "maintenanceMargin", with = "string_to_float")]
948    pub maintainence_margin: f64,
949    #[serde(rename = "initialMargin", with = "string_to_float")]
950    pub initial_margin: f64,
951    #[serde(rename = "isLowestRisk")]
952    pub is_lowest_risk: u8,
953    #[serde(rename = "maxLeverage")]
954    pub max_leverage: String,
955}
956
957#[derive(Serialize, Deserialize, Clone, Debug)]
958#[serde(rename_all = "camelCase")]
959pub struct DeliveryPriceResponse {
960    pub ret_code: i16,
961    pub ret_msg: String,
962    pub result: DeliveryPriceSummary,
963    pub ret_ext_info: Empty,
964    pub time: u64,
965}
966
967#[derive(Serialize, Deserialize, Clone, Debug)]
968#[serde(rename_all = "camelCase")]
969pub struct DeliveryPriceSummary {
970    pub category: String,
971    #[serde(rename = "nextPageCursor", skip_serializing_if = "Option::is_none")]
972    pub next_page_cursor: Option<String>,
973    pub list: Vec<DeliveryPrice>,
974}
975
976#[derive(Serialize, Deserialize, Clone, Debug)]
977#[serde(rename_all = "camelCase")]
978pub struct DeliveryPrice {
979    pub symbol: String,
980    pub delivery_price: String,
981    #[serde(with = "string_to_u64")]
982    pub delivery_time: u64,
983}
984
985#[derive(Serialize, Deserialize, Clone, Debug)]
986#[serde(rename_all = "camelCase")]
987pub struct LongShortRatioResponse {
988    #[serde(rename = "retCode")]
989    pub ret_code: i16,
990    #[serde(rename = "retMsg")]
991    pub ret_msg: String,
992    pub result: LongShortRatioSummary,
993    #[serde(rename = "retExtInfo")]
994    pub ret_ext_info: Empty,
995    pub time: u64,
996}
997
998#[derive(Serialize, Deserialize, Clone, Debug)]
999#[serde(rename_all = "camelCase")]
1000pub struct LongShortRatioSummary {
1001    pub list: Vec<LongShortRatio>,
1002}
1003
1004#[derive(Serialize, Deserialize, Clone, Debug)]
1005#[serde(rename_all = "camelCase")]
1006pub struct LongShortRatio {
1007    #[serde(rename = "symbol")]
1008    pub symbol: String,
1009    #[serde(rename = "buyRatio", with = "string_to_float")]
1010    pub buy_ratio: f64,
1011    #[serde(rename = "sellRatio", with = "string_to_float")]
1012    pub sell_ratio: f64,
1013    #[serde(rename = "timestamp", with = "string_to_u64")]
1014    pub timestamp: u64,
1015}
1016
1017/// --------------------------------------------------
1018///  REQUEST & RESPONSE STRUCTS FOR TRADE
1019/// --------------------------------------------------
1020#[derive(Clone, Copy, Default, Serialize)]
1021pub enum Category {
1022    Spot,
1023    #[default]
1024    Linear,
1025    Inverse,
1026    Option,
1027}
1028impl Category {
1029    pub fn as_str(&self) -> &str {
1030        match self {
1031            Category::Spot => "spot",
1032            Category::Linear => "linear",
1033            Category::Inverse => "inverse",
1034            Category::Option => "option",
1035        }
1036    }
1037}
1038
1039#[derive(Serialize, Deserialize, Clone, Debug, Default)]
1040pub enum Side {
1041    #[default]
1042    Buy,
1043    Sell,
1044}
1045
1046impl Side {
1047    pub fn as_str(&self) -> &str {
1048        match self {
1049            Side::Buy => "Buy",
1050            Side::Sell => "Sell",
1051        }
1052    }
1053}
1054
1055#[derive(Serialize, Deserialize, Clone, Debug, Default)]
1056pub enum OrderType {
1057    Limit,
1058    #[default]
1059    Market,
1060}
1061
1062impl OrderType {
1063    pub fn as_str(&self) -> &str {
1064        match self {
1065            OrderType::Limit => "Limit",
1066            OrderType::Market => "Market",
1067        }
1068    }
1069}
1070
1071#[derive(Serialize, Deserialize, Clone, Debug, Default)]
1072pub enum TimeInForce {
1073    #[default]
1074    GTC,
1075    IOC,
1076    FOK,
1077    PostOnly,
1078}
1079
1080impl TimeInForce {
1081    pub fn as_str(&self) -> &str {
1082        match self {
1083            TimeInForce::GTC => "GTC",
1084            TimeInForce::IOC => "IOC",
1085            TimeInForce::FOK => "FOK",
1086            TimeInForce::PostOnly => "PostOnly",
1087        }
1088    }
1089}
1090#[derive(Clone, Default, Serialize)]
1091pub struct OrderRequest<'a> {
1092    pub category: Category,                 // String
1093    pub symbol: Cow<'a, str>,               // String
1094    pub is_leverage: Option<bool>,          // Integer
1095    pub side: Side,                         // String
1096    pub order_type: OrderType,              // String
1097    pub qty: f64,                           // String
1098    pub market_unit: Option<f64>,           // String
1099    pub price: Option<f64>,                 // String
1100    pub trigger_direction: Option<bool>,    // String
1101    pub order_filter: Option<Cow<'a, str>>, // String
1102    pub trigger_price: Option<f64>,
1103    pub trigger_by: Option<Cow<'a, str>>,    // String
1104    pub order_iv: Option<f64>,               // String
1105    pub time_in_force: Option<Cow<'a, str>>, // String
1106    pub position_idx: Option<u8>,
1107    pub order_link_id: Option<Cow<'a, str>>,
1108    pub take_profit: Option<f64>,
1109    pub stop_loss: Option<f64>,
1110    pub tp_trigger_by: Option<Cow<'a, str>>,
1111    pub sl_trigger_by: Option<Cow<'a, str>>,
1112    pub reduce_only: Option<bool>,
1113    pub close_on_trigger: Option<bool>,
1114    pub smp_type: Option<Cow<'a, str>>,
1115    pub mmp: Option<bool>,
1116    pub tpsl_mode: Option<Cow<'a, str>>,
1117    pub tp_limit_price: Option<f64>,
1118    pub sl_limit_price: Option<f64>,
1119    pub tp_order_type: Option<Cow<'a, str>>,
1120    pub sl_order_type: Option<Cow<'a, str>>,
1121}
1122
1123impl<'a> OrderRequest<'a> {
1124    pub fn default() -> Self {
1125        Self {
1126            category: Category::Linear,
1127            symbol: Cow::Borrowed("BTCUSDT"),
1128            is_leverage: None,
1129            side: Side::default(),
1130            order_type: OrderType::Market,
1131            qty: 0.00,
1132            market_unit: None,
1133            price: None,
1134            trigger_direction: None,
1135            order_filter: None,
1136            trigger_price: None,
1137            trigger_by: None,
1138            order_iv: None,
1139            time_in_force: None,
1140            position_idx: None,
1141            order_link_id: None,
1142            take_profit: None,
1143            stop_loss: None,
1144            tp_trigger_by: None,
1145            sl_trigger_by: None,
1146            reduce_only: None,
1147            close_on_trigger: None,
1148            smp_type: None,
1149            mmp: None,
1150            tpsl_mode: None,
1151            tp_limit_price: None,
1152            sl_limit_price: None,
1153            tp_order_type: None,
1154            sl_order_type: None,
1155        }
1156    }
1157    pub fn custom(
1158        category: Category,
1159        symbol: &'a str,
1160        leverage: Option<bool>,
1161        side: Side,
1162        order_type: OrderType,
1163        qty: f64,
1164        market_unit: Option<f64>,
1165        price: Option<f64>,
1166        trigger_direction: Option<bool>,
1167        order_filter: Option<&'a str>,
1168        trigger_price: Option<f64>,
1169        trigger_by: Option<&'a str>,
1170        order_iv: Option<f64>,
1171        time_in_force: Option<&'a str>,
1172        position_idx: Option<u8>,
1173        order_link_id: Option<&'a str>,
1174        take_profit: Option<f64>,
1175        stop_loss: Option<f64>,
1176        tp_trigger_by: Option<&'a str>,
1177        sl_trigger_by: Option<&'a str>,
1178        reduce_only: Option<bool>,
1179        close_on_trigger: Option<bool>,
1180        smp_type: Option<&'a str>,
1181        mmp: Option<bool>,
1182        tpsl_mode: Option<&'a str>,
1183        tp_limit_price: Option<f64>,
1184        sl_limit_price: Option<f64>,
1185        tp_order_type: Option<&'a str>,
1186        sl_order_type: Option<&'a str>,
1187    ) -> Self {
1188        Self {
1189            category,
1190            symbol: Cow::Borrowed(symbol),
1191            is_leverage: leverage,
1192            side,
1193            order_type,
1194            qty,
1195            market_unit,
1196            price,
1197            trigger_direction,
1198            order_filter: order_filter.map(Cow::Borrowed),
1199            trigger_price,
1200            trigger_by: trigger_by.map(Cow::Borrowed),
1201            order_iv,
1202            time_in_force: time_in_force.map(Cow::Borrowed),
1203            position_idx,
1204            order_link_id: order_link_id.map(Cow::Borrowed),
1205            take_profit,
1206            stop_loss,
1207            tp_trigger_by: tp_trigger_by.map(Cow::Borrowed),
1208            sl_trigger_by: sl_trigger_by.map(Cow::Borrowed),
1209            reduce_only,
1210            close_on_trigger,
1211            smp_type: smp_type.map(Cow::Borrowed),
1212            mmp,
1213            tpsl_mode: tpsl_mode.map(Cow::Borrowed),
1214            tp_limit_price,
1215            sl_limit_price,
1216            tp_order_type: tp_order_type.map(Cow::Borrowed),
1217            sl_order_type: sl_order_type.map(Cow::Borrowed),
1218        }
1219    }
1220    pub fn spot_limit_with_market_tpsl(
1221        symbol: &'a str,
1222        side: Side,
1223        qty: f64,
1224        price: f64,
1225        tp: f64,
1226        sl: f64,
1227    ) -> Self {
1228        Self {
1229            category: Category::Spot,
1230            symbol: Cow::Borrowed(symbol),
1231            side,
1232            order_type: OrderType::Limit,
1233            qty,
1234            price: Some(price),
1235            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1236            take_profit: Some(tp),
1237            stop_loss: Some(sl),
1238            tp_order_type: Some(Cow::Borrowed("Market")),
1239            sl_order_type: Some(Cow::Borrowed("Market")),
1240            ..Self::default()
1241        }
1242    }
1243    pub fn spot_limit_with_limit_tpsl(
1244        symbol: &'a str,
1245        side: Side,
1246        qty: f64,
1247        price: f64,
1248        tp: f64,
1249        sl: f64,
1250    ) -> Self {
1251        Self {
1252            category: Category::Spot,
1253            symbol: Cow::Borrowed(symbol),
1254            side,
1255            order_type: OrderType::Limit,
1256            qty,
1257            price: Some(price),
1258            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1259            take_profit: Some(tp),
1260            stop_loss: Some(sl),
1261            tp_limit_price: Some(tp),
1262            sl_limit_price: Some(sl),
1263            tp_order_type: Some(Cow::Borrowed("Limit")),
1264            sl_order_type: Some(Cow::Borrowed("Limit")),
1265            ..Self::default()
1266        }
1267    }
1268    pub fn spot_postonly(symbol: &'a str, side: Side, qty: f64, price: f64) -> Self {
1269        Self {
1270            category: Category::Spot,
1271            symbol: Cow::Borrowed(symbol),
1272            side,
1273            order_type: OrderType::Limit,
1274            qty,
1275            price: Some(price),
1276            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1277            ..Self::default()
1278        }
1279    }
1280    pub fn spot_tpsl(
1281        symbol: &'a str,
1282        side: Side,
1283        price: f64,
1284        qty: f64,
1285        order_link_id: Option<&'a str>,
1286    ) -> Self {
1287        Self {
1288            category: Category::Spot,
1289            symbol: Cow::Borrowed(symbol),
1290            side,
1291            order_type: OrderType::Limit,
1292            qty,
1293            price: Some(price),
1294            time_in_force: Some(Cow::Borrowed(TimeInForce::GTC.as_str())),
1295            order_link_id: order_link_id.map(Cow::Borrowed),
1296            order_filter: Some(Cow::Borrowed("tpslOrder")),
1297            ..Self::default()
1298        }
1299    }
1300    pub fn spot_margin(symbol: &'a str, side: Side, qty: f64, price: f64) -> Self {
1301        Self {
1302            category: Category::Spot,
1303            symbol: Cow::Borrowed(symbol),
1304            side,
1305            order_type: OrderType::Market,
1306            qty,
1307            price: Some(price),
1308            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1309            is_leverage: Some(true),
1310            ..Self::default()
1311        }
1312    }
1313
1314    pub fn spot_market(symbol: &'a str, side: Side, qty: f64) -> Self {
1315        Self {
1316            category: Category::Spot,
1317            symbol: Cow::Borrowed(symbol),
1318            side,
1319            order_type: OrderType::Market,
1320            qty,
1321            time_in_force: Some(Cow::Borrowed(TimeInForce::IOC.as_str())),
1322            ..Self::default()
1323        }
1324    }
1325
1326    pub fn futures_limit_with_market_tpsl(
1327        symbol: &'a str,
1328        side: Side,
1329        qty: f64,
1330        price: f64,
1331        tp: f64,
1332        sl: f64,
1333    ) -> Self {
1334        Self {
1335            category: Category::Linear,
1336            symbol: Cow::Borrowed(symbol),
1337            side,
1338            order_type: OrderType::Limit,
1339            qty,
1340            price: Some(price),
1341            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1342            reduce_only: Some(false),
1343            take_profit: Some(tp),
1344            stop_loss: Some(sl),
1345            tpsl_mode: Some(Cow::Borrowed("Full")),
1346            tp_order_type: Some(Cow::Borrowed("Market")),
1347            sl_order_type: Some(Cow::Borrowed("Market")),
1348            ..Self::default()
1349        }
1350    }
1351
1352    pub fn futures_limit_with_limit_tpsl(
1353        symbol: &'a str,
1354        side: Side,
1355        qty: f64,
1356        price: f64,
1357        tp: f64,
1358        sl: f64,
1359    ) -> Self {
1360        Self {
1361            category: Category::Linear,
1362            symbol: Cow::Borrowed(symbol),
1363            side,
1364            order_type: OrderType::Limit,
1365            qty,
1366            price: Some(price),
1367            time_in_force: Some(Cow::Borrowed(TimeInForce::PostOnly.as_str())),
1368            reduce_only: Some(false),
1369            take_profit: Some(tp),
1370            stop_loss: Some(sl),
1371            tpsl_mode: Some(Cow::Borrowed("Partial")),
1372            tp_order_type: Some(Cow::Borrowed("Limit")),
1373            sl_order_type: Some(Cow::Borrowed("Limit")),
1374            tp_limit_price: Some(tp),
1375            sl_limit_price: Some(sl),
1376            ..Self::default()
1377        }
1378    }
1379
1380    pub fn futures_market(symbol: &'a str, side: Side, qty: f64) -> Self {
1381        Self {
1382            category: Category::Linear,
1383            symbol: Cow::Borrowed(symbol),
1384            side,
1385            order_type: OrderType::Market,
1386            qty,
1387            time_in_force: Some(Cow::Borrowed(TimeInForce::IOC.as_str())),
1388            reduce_only: Some(false),
1389            ..Self::default()
1390        }
1391    }
1392
1393    pub fn futures_close_limit(
1394        symbol: &'a str,
1395        side: Side,
1396        qty: f64,
1397        price: f64,
1398        order_link_id: &'a str,
1399    ) -> Self {
1400        Self {
1401            category: Category::Linear,
1402            symbol: Cow::Borrowed(symbol),
1403            side,
1404            order_type: OrderType::Limit,
1405            qty,
1406            price: Some(price),
1407            time_in_force: Some(Cow::Borrowed(TimeInForce::GTC.as_str())),
1408            order_link_id: Some(Cow::Borrowed(order_link_id)),
1409            reduce_only: Some(true),
1410            ..Self::default()
1411        }
1412    }
1413
1414    pub fn futures_market_close(symbol: &'a str, side: Side, qty: f64) -> Self {
1415        Self {
1416            category: Category::Linear,
1417            symbol: Cow::Borrowed(symbol),
1418            side,
1419            order_type: OrderType::Market,
1420            qty,
1421            time_in_force: Some(Cow::Borrowed(TimeInForce::IOC.as_str())),
1422            reduce_only: Some(true),
1423            ..Self::default()
1424        }
1425    }
1426}
1427#[derive(Serialize, Deserialize, Clone, Debug)]
1428#[serde(rename_all = "camelCase")]
1429pub struct AmendOrderResponse {
1430    pub ret_code: i16,
1431    pub ret_msg: String,
1432    pub result: OrderStatus,
1433    pub ret_ext_info: Empty,
1434    pub time: u64,
1435}
1436
1437#[derive(Clone, Default, Serialize)]
1438pub struct AmendOrderRequest<'a> {
1439    pub category: Category,   // String
1440    pub symbol: Cow<'a, str>, // String
1441    pub order_id: Option<Cow<'a, str>>,
1442    pub order_link_id: Option<Cow<'a, str>>,
1443    pub order_iv: Option<f64>, // String
1444    pub trigger_price: Option<f64>,
1445    pub qty: f64,           // String
1446    pub price: Option<f64>, // String
1447    pub tpsl_mode: Option<Cow<'a, str>>,
1448    pub take_profit: Option<f64>,
1449    pub stop_loss: Option<f64>,
1450    pub tp_trigger_by: Option<Cow<'a, str>>,
1451    pub sl_trigger_by: Option<Cow<'a, str>>,
1452    pub trigger_by: Option<Cow<'a, str>>, // String
1453    pub tp_limit_price: Option<f64>,
1454    pub sl_limit_price: Option<f64>,
1455}
1456
1457impl<'a> AmendOrderRequest<'a> {
1458    pub fn default() -> Self {
1459        Self {
1460            category: Category::Linear,
1461            symbol: Cow::Borrowed("BTCUSDT"),
1462            order_id: None,
1463            order_link_id: None,
1464            order_iv: None,
1465            trigger_price: None,
1466            qty: 0.00,
1467            price: None,
1468            tpsl_mode: None,
1469            take_profit: None,
1470            stop_loss: None,
1471            tp_trigger_by: None,
1472            sl_trigger_by: None,
1473            trigger_by: None,
1474            tp_limit_price: None,
1475            sl_limit_price: None,
1476        }
1477    }
1478    pub fn custom(
1479        category: Category,
1480        symbol: &'a str,
1481        order_id: Option<&'a str>,
1482        order_link_id: Option<&'a str>,
1483        order_iv: Option<f64>,
1484        trigger_price: Option<f64>,
1485        qty: f64,
1486        price: Option<f64>,
1487        tpsl_mode: Option<&'a str>,
1488        take_profit: Option<f64>,
1489        stop_loss: Option<f64>,
1490        tp_trigger_by: Option<&'a str>,
1491        sl_trigger_by: Option<&'a str>,
1492        trigger_by: Option<&'a str>,
1493        tp_limit_price: Option<f64>,
1494        sl_limit_price: Option<f64>,
1495    ) -> Self {
1496        Self {
1497            category,
1498            symbol: Cow::Borrowed(symbol),
1499            order_id: order_id.map(Cow::Borrowed),
1500            order_link_id: order_link_id.map(Cow::Borrowed),
1501            order_iv,
1502            trigger_price,
1503            qty,
1504            price,
1505            tpsl_mode: tpsl_mode.map(Cow::Borrowed),
1506            take_profit,
1507            stop_loss,
1508            tp_trigger_by: tp_trigger_by.map(Cow::Borrowed),
1509            sl_trigger_by: sl_trigger_by.map(Cow::Borrowed),
1510            trigger_by: trigger_by.map(Cow::Borrowed),
1511            tp_limit_price,
1512            sl_limit_price,
1513        }
1514    }
1515}
1516
1517#[derive(Clone, Serialize)]
1518pub struct CancelOrderRequest<'a> {
1519    pub category: Category,
1520    pub symbol: Cow<'a, str>,
1521    pub order_id: Option<Cow<'a, str>>,
1522    pub order_link_id: Option<Cow<'a, str>>,
1523    pub order_filter: Option<Cow<'a, str>>,
1524}
1525
1526#[derive(Debug, Serialize, Deserialize, Clone)]
1527#[serde(rename_all = "camelCase")]
1528pub struct CancelOrderResponse {
1529    pub ret_code: i16,
1530    pub ret_msg: String,
1531    pub result: OrderStatus,
1532    pub ret_ext_info: Empty,
1533    pub time: u64,
1534}
1535
1536#[derive(Clone, Default)]
1537pub struct OpenOrdersRequest<'a> {
1538    pub category: Category,
1539    pub symbol: Cow<'a, str>,
1540    pub base_coin: Option<Cow<'a, str>>,
1541    pub settle_coin: Option<Cow<'a, str>>,
1542    pub order_id: Option<Cow<'a, str>>,
1543    pub order_link_id: Option<Cow<'a, str>>,
1544    pub open_only: Option<usize>,
1545    pub order_filter: Option<Cow<'a, str>>,
1546    pub limit: Option<usize>,
1547}
1548
1549impl<'a> OpenOrdersRequest<'a> {
1550    pub fn default() -> Self {
1551        Self {
1552            category: Category::Linear,
1553            symbol: Cow::Borrowed("BTCUSDT"),
1554            base_coin: None,
1555            settle_coin: None,
1556            order_id: None,
1557            order_link_id: None,
1558            open_only: None,
1559            order_filter: None,
1560            limit: None,
1561        }
1562    }
1563
1564    pub fn custom(
1565        category: Category,
1566        symbol: &'a str,
1567        base_coin: Option<&'a str>,
1568        settle_coin: Option<&'a str>,
1569        order_id: Option<&'a str>,
1570        order_link_id: Option<&'a str>,
1571        open_only: usize,
1572        order_filter: Option<&'a str>,
1573        limit: Option<usize>,
1574    ) -> Self {
1575        Self {
1576            category,
1577            symbol: Cow::Borrowed(symbol),
1578            base_coin: base_coin.map(Cow::Borrowed),
1579            settle_coin: settle_coin.map(Cow::Borrowed),
1580            order_id: order_id.map(Cow::Borrowed),
1581            order_link_id: order_link_id.map(Cow::Borrowed),
1582            open_only: match open_only {
1583                0 | 1 | 2 => Some(open_only),
1584                _ => None,
1585            },
1586            order_filter: order_filter.map(Cow::Borrowed),
1587            limit,
1588        }
1589    }
1590}
1591
1592#[derive(Debug, Serialize, Deserialize, Clone)]
1593#[serde(rename_all = "camelCase")]
1594pub struct OpenOrdersResponse {
1595    pub ret_code: i16,
1596    pub ret_msg: String,
1597    pub result: OrderHistory,
1598    pub ret_ext_info: Empty,
1599    pub time: u64,
1600}
1601
1602#[derive(Serialize, Deserialize, Clone, Debug)]
1603#[serde(rename_all = "camelCase")]
1604pub struct OrderStatus {
1605    #[serde(rename = "orderId")]
1606    pub order_id: String,
1607    #[serde(rename = "orderLinkId")]
1608    pub order_link_id: String,
1609}
1610
1611#[derive(Serialize, Deserialize, Clone, Debug)]
1612#[serde(rename_all = "camelCase")]
1613pub struct OrderResponse {
1614    #[serde(rename = "retCode")]
1615    pub ret_code: i16,
1616    #[serde(rename = "retMsg")]
1617    pub ret_msg: String,
1618    pub result: OrderStatus,
1619    #[serde(rename = "retExtInfo")]
1620    pub ret_ext_info: Empty,
1621    pub time: u64,
1622}
1623
1624#[derive(Clone, Default)]
1625pub struct OrderHistoryRequest<'a> {
1626    pub category: Category,
1627    pub symbol: Option<Cow<'a, str>>,
1628    pub base_coin: Option<Cow<'a, str>>,
1629    pub settle_coin: Option<Cow<'a, str>>,
1630    pub order_id: Option<Cow<'a, str>>,
1631    pub order_link_id: Option<Cow<'a, str>>,
1632    pub order_filter: Option<Cow<'a, str>>,
1633    pub order_status: Option<Cow<'a, str>>,
1634    pub start_time: Option<Cow<'a, str>>,
1635    pub end_time: Option<Cow<'a, str>>,
1636    pub limit: Option<u64>,
1637}
1638
1639impl<'a> OrderHistoryRequest<'a> {
1640    pub fn default() -> Self {
1641        Self {
1642            category: Category::Linear,
1643            symbol: None,
1644            base_coin: None,
1645            settle_coin: None,
1646            order_id: None,
1647            order_link_id: None,
1648            order_filter: None,
1649            order_status: None,
1650            start_time: None,
1651            end_time: None,
1652            limit: None,
1653        }
1654    }
1655    pub fn new(
1656        category: Category,
1657        symbol: Option<&'a str>,
1658        base_coin: Option<&'a str>,
1659        settle_coin: Option<&'a str>,
1660        order_id: Option<&'a str>,
1661        order_link_id: Option<&'a str>,
1662        order_filter: Option<&'a str>,
1663        order_status: Option<&'a str>,
1664        start_time: Option<&'a str>,
1665        end_time: Option<&'a str>,
1666        limit: Option<u64>,
1667    ) -> Self {
1668        Self {
1669            category,
1670            symbol: symbol.map(Cow::Borrowed),
1671            base_coin: base_coin.map(Cow::Borrowed),
1672            settle_coin: settle_coin.map(Cow::Borrowed),
1673            order_id: order_id.map(Cow::Borrowed),
1674            order_link_id: order_link_id.map(Cow::Borrowed),
1675            order_filter: order_filter.map(Cow::Borrowed),
1676            order_status: order_status.map(Cow::Borrowed),
1677            start_time: start_time.map(Cow::Borrowed),
1678            end_time: end_time.map(Cow::Borrowed),
1679            limit,
1680        }
1681    }
1682}
1683
1684#[derive(Serialize, Deserialize, Clone, Debug)]
1685#[serde(rename_all = "camelCase")]
1686pub struct OrderHistoryResponse {
1687    #[serde(rename = "retCode")]
1688    pub ret_code: i16,
1689    #[serde(rename = "retMsg")]
1690    pub ret_msg: String,
1691    pub result: OrderHistory,
1692    #[serde(rename = "retExtInfo")]
1693    pub ret_ext_info: Empty,
1694    pub time: u64,
1695}
1696
1697#[derive(Serialize, Deserialize, Clone, Debug)]
1698#[serde(rename_all = "camelCase")]
1699pub struct OrderHistory {
1700    pub category: String,
1701    pub list: Vec<Orders>,
1702    #[serde(rename = "nextPageCursor", skip_serializing_if = "String::is_empty")]
1703    pub next_page_cursor: String,
1704}
1705
1706#[derive(Serialize, Deserialize, Clone, Debug)]
1707#[serde(rename_all = "camelCase")]
1708pub struct Orders {
1709    #[serde(rename = "orderId")]
1710    pub order_id: String,
1711    #[serde(rename = "orderLinkId")]
1712    pub order_link_id: String,
1713    #[serde(rename = "blockTradeId")]
1714    pub block_trade_id: String,
1715    pub symbol: String,
1716    #[serde(with = "string_to_float")]
1717    pub price: f64,
1718    #[serde(with = "string_to_float")]
1719    pub qty: f64,
1720    pub side: Side,
1721    #[serde(rename = "isLeverage", skip_serializing_if = "String::is_empty")]
1722    pub is_leverage: String,
1723    #[serde(rename = "positionIdx")]
1724    pub position_idx: i32,
1725    #[serde(rename = "orderStatus")]
1726    pub order_status: String,
1727    #[serde(rename = "cancelType")]
1728    pub cancel_type: String,
1729    #[serde(rename = "rejectReason")]
1730    pub reject_reason: String,
1731    #[serde(rename = "avgPrice", with = "string_to_float")]
1732    pub avg_price: f64,
1733    #[serde(rename = "leavesQty", with = "string_to_float")]
1734    pub leaves_qty: f64,
1735    #[serde(rename = "leavesValue", with = "string_to_float")]
1736    pub leaves_value: f64,
1737    #[serde(rename = "cumExecQty", with = "string_to_float")]
1738    pub cum_exec_qty: f64,
1739    #[serde(rename = "cumExecValue", with = "string_to_float")]
1740    pub cum_exec_value: f64,
1741    #[serde(rename = "cumExecFee", with = "string_to_float")]
1742    pub cum_exec_fee: f64,
1743    #[serde(rename = "timeInForce")]
1744    pub time_in_force: String,
1745    #[serde(rename = "orderType")]
1746    pub order_type: OrderType,
1747    #[serde(rename = "stopOrderType")]
1748    pub stop_order_type: String,
1749    #[serde(rename = "orderIv", skip_serializing_if = "String::is_empty")]
1750    pub order_iv: String,
1751    #[serde(rename = "triggerPrice", with = "string_to_float")]
1752    pub trigger_price: f64,
1753    #[serde(rename = "takeProfit", with = "string_to_float")]
1754    pub take_profit: f64,
1755    #[serde(rename = "stopLoss", with = "string_to_float")]
1756    pub stop_loss: f64,
1757    #[serde(rename = "tpTriggerBy")]
1758    pub tp_trigger_by: String,
1759    #[serde(rename = "slTriggerBy")]
1760    pub sl_trigger_by: String,
1761    #[serde(rename = "triggerDirection")]
1762    pub trigger_direction: i32,
1763    #[serde(rename = "triggerBy")]
1764    pub trigger_by: String,
1765    #[serde(rename = "lastPriceOnCreated", with = "string_to_float")]
1766    pub last_price_on_created: f64,
1767    #[serde(rename = "reduceOnly")]
1768    pub reduce_only: bool,
1769    #[serde(rename = "closeOnTrigger")]
1770    pub close_on_trigger: bool,
1771    #[serde(rename = "smpType")]
1772    pub smp_type: String,
1773    #[serde(rename = "smpGroup")]
1774    pub smp_group: i32,
1775    #[serde(rename = "smpOrderId", skip_serializing_if = "String::is_empty")]
1776    pub smp_order_id: String,
1777    #[serde(rename = "tpslMode", skip_serializing_if = "String::is_empty")]
1778    pub tpsl_mode: String,
1779    #[serde(rename = "tpLimitPrice", with = "string_to_float")]
1780    pub tp_limit_price: f64,
1781    #[serde(rename = "slLimitPrice", with = "string_to_float")]
1782    pub sl_limit_price: f64,
1783    #[serde(rename = "placeType", skip_serializing_if = "String::is_empty")]
1784    pub place_type: String,
1785    #[serde(with = "string_to_u64")]
1786    pub created_time: u64,
1787    #[serde(with = "string_to_u64")]
1788    pub updated_time: u64,
1789}
1790
1791#[derive(Clone, Default)]
1792pub struct CancelallRequest<'a> {
1793    pub category: Category,
1794    pub symbol: &'a str,
1795    pub base_coin: Option<&'a str>,
1796    pub settle_coin: Option<&'a str>,
1797    pub order_filter: Option<&'a str>,
1798    pub stop_order_type: Option<&'a str>,
1799}
1800
1801impl<'a> CancelallRequest<'a> {
1802    pub fn default() -> Self {
1803        Self {
1804            category: Category::Linear,
1805            symbol: "BTCUSDT",
1806            base_coin: None,
1807            settle_coin: None,
1808            order_filter: None,
1809            stop_order_type: None,
1810        }
1811    }
1812    pub fn new(
1813        category: Category,
1814        symbol: &'a str,
1815        base_coin: Option<&'a str>,
1816        settle_coin: Option<&'a str>,
1817        order_filter: Option<&'a str>,
1818        stop_order_type: Option<&'a str>,
1819    ) -> Self {
1820        Self {
1821            category,
1822            symbol,
1823            base_coin,
1824            settle_coin,
1825            order_filter,
1826            stop_order_type,
1827        }
1828    }
1829}
1830
1831#[derive(Serialize, Deserialize, Clone, Debug)]
1832#[serde(rename_all = "camelCase")]
1833pub struct CancelallResponse {
1834    #[serde(rename = "retCode")]
1835    pub ret_code: i16,
1836    #[serde(rename = "retMsg")]
1837    pub ret_msg: String,
1838    pub result: CancelledList,
1839    #[serde(rename = "retExtInfo")]
1840    pub ret_ext_info: Empty,
1841    pub time: u64,
1842}
1843
1844#[derive(Serialize, Deserialize, Clone, Debug)]
1845#[serde(rename_all = "camelCase")]
1846pub struct CancelledList {
1847    pub list: Vec<OrderStatus>,
1848}
1849
1850#[derive(Serialize, Deserialize, Clone, Debug)]
1851#[serde(rename_all = "camelCase")]
1852pub struct TradeHistoryResponse {
1853    pub ret_code: i16,
1854    pub ret_msg: String,
1855    pub result: TradeHistorySummary,
1856    pub ret_ext_info: Empty,
1857    pub time: u64,
1858}
1859
1860#[derive(Serialize, Deserialize, Clone, Debug)]
1861#[serde(rename_all = "camelCase")]
1862pub struct TradeHistorySummary {
1863    #[serde(rename = "nextPageCursor", skip_serializing_if = "String::is_empty")]
1864    pub next_page_cursor: String,
1865    pub category: String,
1866    pub list: Vec<TradeHistory>,
1867}
1868#[derive(Serialize, Deserialize, Clone, Debug)]
1869#[serde(rename_all = "camelCase")]
1870pub struct TradeHistory {
1871    pub symbol: String,
1872    #[serde(rename = "orderType")]
1873    pub order_type: String,
1874    #[serde(
1875        rename = "underlyingPrice",
1876        default,
1877        skip_serializing_if = "String::is_empty"
1878    )]
1879    pub underlying_price: String,
1880    #[serde(
1881        rename = "orderLinkId",
1882        default,
1883        skip_serializing_if = "String::is_empty"
1884    )]
1885    pub order_link_id: String,
1886    pub side: String,
1887    #[serde(
1888        rename = "indexPrice",
1889        default,
1890        skip_serializing_if = "String::is_empty"
1891    )]
1892    pub index_price: String,
1893    #[serde(rename = "orderId")]
1894    pub order_id: String,
1895    #[serde(rename = "stopOrderType")]
1896    pub stop_order_type: String,
1897    #[serde(rename = "leavesQty")]
1898    pub leaves_qty: String,
1899    #[serde(rename = "execTime")]
1900    pub exec_time: String,
1901    #[serde(
1902        rename = "feeCurrency",
1903        default,
1904        skip_serializing_if = "String::is_empty"
1905    )]
1906    pub fee_currency: String,
1907    #[serde(rename = "isMaker")]
1908    pub is_maker: bool,
1909    #[serde(rename = "execFee")]
1910    pub exec_fee: String,
1911    #[serde(rename = "feeRate")]
1912    pub fee_rate: String,
1913    #[serde(rename = "execId")]
1914    pub exec_id: String,
1915    #[serde(rename = "tradeIv", default, skip_serializing_if = "String::is_empty")]
1916    pub trade_iv: String,
1917    #[serde(
1918        rename = "blockTradeId",
1919        default,
1920        skip_serializing_if = "String::is_empty"
1921    )]
1922    pub block_trade_id: String,
1923    #[serde(rename = "markPrice")]
1924    pub mark_price: String,
1925    #[serde(rename = "execPrice")]
1926    pub exec_price: String,
1927    #[serde(rename = "markIv", default, skip_serializing_if = "String::is_empty")]
1928    pub mark_iv: String,
1929    #[serde(rename = "orderQty")]
1930    pub order_qty: String,
1931    #[serde(rename = "orderPrice")]
1932    pub order_price: String,
1933    #[serde(rename = "execValue")]
1934    pub exec_value: String,
1935    #[serde(rename = "execType")]
1936    pub exec_type: String,
1937    #[serde(rename = "execQty")]
1938    pub exec_qty: String,
1939    #[serde(
1940        rename = "closedSize",
1941        default,
1942        skip_serializing_if = "String::is_empty"
1943    )]
1944    pub closed_size: String,
1945    pub seq: u64,
1946}
1947
1948#[derive(Clone, Default)]
1949pub struct TradeHistoryRequest<'a> {
1950    pub category: Category,
1951    pub symbol: Option<Cow<'a, str>>,
1952    pub order_id: Option<Cow<'a, str>>,
1953    pub order_link_id: Option<Cow<'a, str>>,
1954    pub base_coin: Option<Cow<'a, str>>,
1955    pub start_time: Option<Cow<'a, str>>,
1956    pub end_time: Option<Cow<'a, str>>,
1957    pub exec_type: Option<Cow<'a, str>>,
1958    pub limit: Option<u64>,
1959}
1960
1961impl<'a> TradeHistoryRequest<'a> {
1962    pub fn default() -> TradeHistoryRequest<'a> {
1963        TradeHistoryRequest::new(
1964            Category::Linear,
1965            None,
1966            None,
1967            None,
1968            None,
1969            None,
1970            None,
1971            None,
1972            None,
1973        )
1974    }
1975    pub fn new(
1976        category: Category,
1977        symbol: Option<&'a str>,
1978        order_id: Option<&'a str>,
1979        order_link_id: Option<&'a str>,
1980        base_coin: Option<&'a str>,
1981        start_time: Option<&'a str>,
1982        end_time: Option<&'a str>,
1983        exec_type: Option<&'a str>,
1984        limit: Option<u64>,
1985    ) -> TradeHistoryRequest<'a> {
1986        TradeHistoryRequest {
1987            category,
1988            symbol: symbol.map(|s| Cow::Borrowed(s)),
1989            order_id: order_id.map(|s| Cow::Borrowed(s)),
1990            order_link_id: order_link_id.map(|s| Cow::Borrowed(s)),
1991            base_coin: base_coin.map(|s| Cow::Borrowed(s)),
1992            start_time: start_time.map(|s| Cow::Borrowed(s)),
1993            end_time: end_time.map(|s| Cow::Borrowed(s)),
1994            exec_type: exec_type.map(|s| Cow::Borrowed(s)),
1995            limit,
1996        }
1997    }
1998}
1999
2000#[derive(Clone, Default)]
2001pub struct BatchPlaceRequest<'a> {
2002    pub category: Category,
2003    pub requests: Vec<OrderRequest<'a>>,
2004}
2005impl<'a> BatchPlaceRequest<'a> {
2006    pub fn new(category: Category, requests: Vec<OrderRequest<'a>>) -> BatchPlaceRequest<'a> {
2007        BatchPlaceRequest { category, requests }
2008    }
2009}
2010#[derive(Serialize, Deserialize, Clone, Debug)]
2011#[serde(rename_all = "camelCase")]
2012pub struct BatchPlaceResponse {
2013    #[serde(rename = "retCode")]
2014    pub ret_code: i16,
2015    #[serde(rename = "retMsg")]
2016    pub ret_msg: String,
2017    pub result: BatchedOrderList,
2018    #[serde(rename = "retExtInfo")]
2019    pub ret_ext_info: OrderConfirmationList,
2020    pub time: u64,
2021}
2022
2023#[derive(Serialize, Deserialize, Clone, Debug)]
2024#[serde(rename_all = "camelCase")]
2025pub struct BatchedOrderList {
2026    pub list: Vec<BatchedOrder>,
2027}
2028
2029#[derive(Serialize, Deserialize, Clone, Debug)]
2030#[serde(rename_all = "camelCase")]
2031pub struct BatchedOrder {
2032    pub category: String,
2033    pub symbol: String,
2034    #[serde(rename = "orderId")]
2035    pub order_id: String,
2036    #[serde(rename = "orderLinkId")]
2037    pub order_link_id: String,
2038    #[serde(rename = "createAt")]
2039    pub create_at: String,
2040}
2041
2042#[derive(Serialize, Deserialize, Clone, Debug)]
2043#[serde(rename_all = "camelCase")]
2044pub struct OrderConfirmationList {
2045    pub list: Vec<OrderConfirmation>,
2046}
2047
2048#[derive(Serialize, Deserialize, Clone, Debug)]
2049#[serde(rename_all = "camelCase")]
2050pub struct OrderConfirmation {
2051    pub code: i16,
2052    pub msg: String,
2053}
2054
2055#[derive(Clone, Default)]
2056pub struct BatchAmendRequest<'a> {
2057    pub category: Category,
2058    pub requests: Vec<AmendOrderRequest<'a>>,
2059}
2060
2061impl<'a> BatchAmendRequest<'a> {
2062    pub fn new(category: Category, requests: Vec<AmendOrderRequest<'a>>) -> BatchAmendRequest<'a> {
2063        BatchAmendRequest { category, requests }
2064    }
2065}
2066
2067#[derive(Serialize, Deserialize, Clone, Debug)]
2068#[serde(rename_all = "camelCase")]
2069pub struct BatchAmendResponse {
2070    #[serde(rename = "retCode")]
2071    pub ret_code: i16,
2072    #[serde(rename = "retMsg")]
2073    pub ret_msg: String,
2074    pub result: AmendedOrderList,
2075    #[serde(rename = "retExtInfo")]
2076    pub ret_ext_info: OrderConfirmationList,
2077    pub time: u64,
2078}
2079
2080#[derive(Serialize, Deserialize, Clone, Debug)]
2081#[serde(rename_all = "camelCase")]
2082pub struct AmendedOrderList {
2083    pub list: Vec<AmendedOrder>,
2084}
2085
2086#[derive(Serialize, Deserialize, Clone, Debug)]
2087#[serde(rename_all = "camelCase")]
2088pub struct AmendedOrder {
2089    pub category: String,
2090    pub symbol: String,
2091    #[serde(rename = "orderId")]
2092    pub order_id: String,
2093    #[serde(rename = "orderLinkId")]
2094    pub order_link_id: String,
2095}
2096
2097#[derive(Clone, Default)]
2098pub struct BatchCancelRequest<'a> {
2099    pub category: Category,
2100    pub requests: Vec<CancelOrderRequest<'a>>,
2101}
2102
2103impl<'a> BatchCancelRequest<'a> {
2104    pub fn new(
2105        category: Category,
2106        requests: Vec<CancelOrderRequest<'a>>,
2107    ) -> BatchCancelRequest<'a> {
2108        BatchCancelRequest { category, requests }
2109    }
2110}
2111
2112#[derive(Serialize, Deserialize, Clone, Debug)]
2113#[serde(rename_all = "camelCase")]
2114pub struct BatchCancelResponse {
2115    #[serde(rename = "retCode")]
2116    pub ret_code: i16,
2117    #[serde(rename = "retMsg")]
2118    pub ret_msg: String,
2119    pub result: CanceledOrderList,
2120    #[serde(rename = "retExtInfo")]
2121    pub ret_ext_info: OrderConfirmationList,
2122    pub time: u64,
2123}
2124
2125#[derive(Serialize, Deserialize, Clone, Debug)]
2126#[serde(rename_all = "camelCase")]
2127pub struct CanceledOrderList {
2128    pub list: Vec<CanceledOrder>,
2129}
2130
2131#[derive(Serialize, Deserialize, Clone, Debug)]
2132#[serde(rename_all = "camelCase")]
2133pub struct CanceledOrder {
2134    pub category: String,
2135    pub symbol: String,
2136    #[serde(rename = "orderId")]
2137    pub order_id: String,
2138    #[serde(rename = "orderLinkId")]
2139    pub order_link_id: String,
2140}
2141
2142
2143#[derive(Clone)]
2144pub enum RequestType<'a> {
2145    Create(BatchPlaceRequest<'a>),
2146    Amend(BatchAmendRequest<'a>),
2147    Cancel(BatchCancelRequest<'a>),
2148}
2149
2150// ----------------------------------------------------------
2151// POSITION STRUCTS SECTION
2152// ------------------------------------------------------
2153
2154#[derive(Clone, Default)]
2155pub struct PositionRequest<'a> {
2156    pub category: Category,
2157    pub symbol: Option<Cow<'a, str>>,
2158    pub base_coin: Option<Cow<'a, str>>,
2159    pub settle_coin: Option<Cow<'a, str>>,
2160    pub limit: Option<usize>,
2161}
2162
2163impl<'a> PositionRequest<'a> {
2164    pub fn default() -> Self {
2165        Self::new(Category::Linear, None, None, None, None)
2166    }
2167    pub fn new(
2168        category: Category,
2169        symbol: Option<&'a str>,
2170        base_coin: Option<&'a str>,
2171        settle_coin: Option<&'a str>,
2172        limit: Option<usize>,
2173    ) -> Self {
2174        Self {
2175            category,
2176            symbol: symbol.map(Cow::Borrowed),
2177            base_coin: base_coin.map(Cow::Borrowed),
2178            settle_coin: settle_coin.map(Cow::Borrowed),
2179            limit,
2180        }
2181    }
2182}
2183
2184#[derive(Debug, Serialize, Deserialize, Clone)]
2185pub struct InfoResponse {
2186    pub ret_code: i32,
2187    pub ret_msg: String,
2188    pub result: InfoResult,
2189    pub ret_ext_info: Empty,
2190    pub time: u64,
2191}
2192
2193#[derive(Debug, Serialize, Deserialize, Clone)]
2194pub struct InfoResult {
2195    pub list: Vec<PositionInfo>,
2196    #[serde(rename = "nextPageCursor", skip_serializing_if = "Option::is_none")]
2197    pub next_page_cursor: Option<String>,
2198    pub category: String,
2199}
2200
2201#[derive(Debug, Serialize, Deserialize, Clone)]
2202#[serde(rename_all = "camelCase")]
2203pub struct PositionInfo {
2204    #[serde(rename = "positionIdx")]
2205    pub position_idx: i32,
2206    pub risk_id: i32,
2207    #[serde(rename = "riskLimitValue", with = "string_to_float")]
2208    pub risk_limit_value: f64,
2209    pub symbol: String,
2210    pub side: String,
2211    #[serde(with = "string_to_float")]
2212    pub size: f64,
2213    #[serde(with = "string_to_float")]
2214    pub avg_price: f64,
2215    #[serde(rename = "positionValue", with = "string_to_float")]
2216    pub position_value: f64,
2217    #[serde(rename = "tradeMode")]
2218    pub trade_mode: i32,
2219    #[serde(rename = "positionStatus")]
2220    pub position_status: String,
2221    #[serde(rename = "autoAddMargin")]
2222    pub auto_add_margin: i32,
2223    #[serde(rename = "adlRankIndicator")]
2224    pub adl_rank_indicator: i32,
2225    #[serde(with = "string_to_float")]
2226    pub leverage: f64,
2227    #[serde(rename = "positionBalance", with = "string_to_float")]
2228    pub position_balance: f64,
2229    #[serde(rename = "markPrice")]
2230    pub mark_price: String,
2231    #[serde(rename = "liqPrice")]
2232    pub liq_price: String,
2233    #[serde(rename = "bustPrice")]
2234    pub bust_price: String,
2235    #[serde(rename = "positionMM", with = "string_to_float")]
2236    pub position_mm: f64,
2237    #[serde(rename = "positionIM", with = "string_to_float")]
2238    pub position_im: f64,
2239    #[serde(rename = "tpslMode")]
2240    pub tpsl_mode: String,
2241    pub take_profit: String,
2242    pub stop_loss: String,
2243    pub trailing_stop: String,
2244    #[serde(rename = "unrealisedPnl", with = "string_to_float")]
2245    pub unrealised_pnl: f64,
2246    #[serde(rename = "cumRealisedPnl", with = "string_to_float")]
2247    pub cum_realised_pnl: f64,
2248    pub seq: u64,
2249    #[serde(rename = "isReduceOnly")]
2250    pub is_reduce_only: bool,
2251    #[serde(rename = "mmrSysUpdateTime")]
2252    pub mmr_sys_update_time: String,
2253    #[serde(rename = "leverageSysUpdatedTime")]
2254    pub leverage_sys_updated_time: String,
2255    #[serde(rename = "createdTime")]
2256    pub created_time: String,
2257    #[serde(rename = "updatedTime")]
2258    pub updated_time: String,
2259}
2260
2261#[derive(Clone, Default)]
2262pub struct LeverageRequest<'a> {
2263    pub category: Category,
2264    pub symbol: Cow<'a, str>,
2265    pub leverage: i8,
2266}
2267
2268impl<'a> LeverageRequest<'a> {
2269    pub fn new(category: Category, symbol: &'a str, leverage: i8) -> Self {
2270        Self {
2271            category,
2272            symbol: Cow::Borrowed(symbol),
2273            leverage,
2274        }
2275    }
2276    pub fn default() -> LeverageRequest<'a> {
2277        LeverageRequest::new(Category::Linear, "BTCUSDT", 10)
2278    }
2279}
2280
2281#[derive(Serialize, Deserialize, Clone, Debug)]
2282#[serde(rename_all = "camelCase")]
2283pub struct LeverageResponse {
2284    #[serde(rename = "retCode")]
2285    pub ret_code: i32,
2286    #[serde(rename = "retMsg")]
2287    pub ret_msg: String,
2288    pub result: Empty, // Assuming result is an empty struct as per provided JSON
2289    #[serde(rename = "retExtInfo")]
2290    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2291    pub time: u64,
2292}
2293
2294#[derive(Default, Clone)]
2295pub struct ChangeMarginRequest<'a> {
2296    pub category: Category,
2297    pub symbol: Cow<'a, str>,
2298    pub trade_mode: i8,
2299    pub leverage: i8,
2300}
2301
2302impl<'a> ChangeMarginRequest<'a> {
2303    pub fn new(category: Category, symbol: &'a str, trade_mode: i8, leverage: i8) -> Self {
2304        Self {
2305            category,
2306            symbol: Cow::Borrowed(symbol),
2307            trade_mode: match trade_mode {
2308                1 => 1,
2309                0 => 0,
2310                _ => 0,
2311            },
2312            leverage,
2313        }
2314    }
2315    pub fn default() -> ChangeMarginRequest<'a> {
2316        ChangeMarginRequest::new(Category::Linear, "BTCUSDT", 0, 10)
2317    }
2318}
2319
2320#[derive(Serialize, Deserialize, Clone, Debug)]
2321#[serde(rename_all = "camelCase")]
2322pub struct ChangeMarginResponse {
2323    #[serde(rename = "retCode")]
2324    pub ret_code: i32,
2325    #[serde(rename = "retMsg")]
2326    pub ret_msg: String,
2327    pub result: Empty, // Assuming result is an empty struct as per provided JSON
2328    #[serde(rename = "retExtInfo")]
2329    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2330    pub time: u64,
2331}
2332
2333#[derive(Clone, Default)]
2334pub struct MarginModeRequest<'a> {
2335    pub category: Category,
2336    pub mode: i8,
2337    pub symbol: Option<Cow<'a, str>>,
2338    pub coin: Option<Cow<'a, str>>,
2339}
2340
2341impl<'a> MarginModeRequest<'a> {
2342    pub fn new(
2343        category: Category,
2344        mode: i8,
2345        symbol: Option<&'a str>,
2346        coin: Option<&'a str>,
2347    ) -> Self {
2348        Self {
2349            category,
2350            mode,
2351            symbol: symbol.map(|s| Cow::Borrowed(s)),
2352            coin: coin.map(|s| Cow::Borrowed(s)),
2353        }
2354    }
2355    pub fn default() -> MarginModeRequest<'a> {
2356        MarginModeRequest::new(Category::Linear, 1, None, None)
2357    }
2358}
2359
2360#[derive(Serialize, Deserialize, Clone, Debug)]
2361#[serde(rename_all = "camelCase")]
2362pub struct MarginModeResponse {
2363    #[serde(rename = "retCode")]
2364    pub ret_code: i32,
2365    #[serde(rename = "retMsg")]
2366    pub ret_msg: String,
2367    pub result: Empty, // Assuming result is an empty struct as per provided JSON
2368    #[serde(rename = "retExtInfo")]
2369    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2370    pub time: u64,
2371}
2372
2373#[derive(Clone, Default)]
2374pub struct SetRiskLimit<'a> {
2375    pub category: Category,
2376    pub symbol: Cow<'a, str>,
2377    pub risk_id: i8,
2378    pub position_idx: Option<i32>,
2379}
2380
2381impl<'a> SetRiskLimit<'a> {
2382    pub fn new(
2383        category: Category,
2384        symbol: &'a str,
2385        risk_id: i8,
2386        position_idx: Option<i32>,
2387    ) -> Self {
2388        Self {
2389            category,
2390            symbol: Cow::Borrowed(symbol),
2391            risk_id,
2392            position_idx,
2393        }
2394    }
2395    pub fn default() -> SetRiskLimit<'a> {
2396        SetRiskLimit::new(Category::Linear, "BTCUSDT", 1, None)
2397    }
2398}
2399
2400#[derive(Serialize, Deserialize, Clone, Debug)]
2401#[serde(rename_all = "camelCase")]
2402pub struct SetRiskLimitResponse {
2403    #[serde(rename = "retCode")]
2404    pub ret_code: i32,
2405    #[serde(rename = "retMsg")]
2406    pub ret_msg: String,
2407    pub result: SetRiskLimitResult,
2408    #[serde(rename = "retExtInfo")]
2409    pub ret_ext_info: Empty, // Assuming retExtInfo is a JSON value as per provided JSON
2410    pub time: u64,
2411}
2412
2413#[derive(Serialize, Deserialize, Clone, Debug)]
2414pub struct SetRiskLimitResult {
2415    #[serde(rename = "riskId")]
2416    pub risk_id: i32,
2417    #[serde(rename = "riskLimitValue", with = "string_to_u64")]
2418    pub risk_limit_value: u64,
2419    pub category: String,
2420}
2421
2422#[derive(Clone, Default)]
2423pub struct TradingStopRequest<'a> {
2424    pub category: Category,
2425    pub symbol: Cow<'a, str>,
2426    pub take_profit: Option<f64>,
2427    pub stop_loss: Option<f64>,
2428    pub tp_trigger_by: Option<Cow<'a, str>>,
2429    pub sl_trigger_by: Option<Cow<'a, str>>,
2430    pub tpsl_mode: Option<Cow<'a, str>>,
2431    pub tp_order_type: Option<OrderType>,
2432    pub sl_order_type: Option<OrderType>,
2433    pub tp_size: Option<f64>,
2434    pub sl_size: Option<f64>,
2435    pub tp_limit_price: Option<f64>,
2436    pub sl_limit_price: Option<f64>,
2437    pub position_idx: i32,
2438}
2439
2440impl<'a> TradingStopRequest<'a> {
2441    pub fn new(
2442        category: Category,
2443        symbol: &'a str,
2444        take_profit: Option<f64>,
2445        stop_loss: Option<f64>,
2446        tp_trigger_by: Option<&'a str>,
2447        sl_trigger_by: Option<&'a str>,
2448        tpsl_mode: Option<&'a str>,
2449        tp_order_type: Option<OrderType>,
2450        sl_order_type: Option<OrderType>,
2451        tp_size: Option<f64>,
2452        sl_size: Option<f64>,
2453        tp_limit_price: Option<f64>,
2454        sl_limit_price: Option<f64>,
2455        position_idx: i32,
2456    ) -> Self {
2457        Self {
2458            category,
2459            symbol: Cow::Borrowed(symbol),
2460            take_profit,
2461            stop_loss,
2462            tp_trigger_by: tp_trigger_by.map(|s| Cow::Borrowed(s)),
2463            sl_trigger_by: sl_trigger_by.map(|s| Cow::Borrowed(s)),
2464            tpsl_mode: tpsl_mode.map(|s| Cow::Borrowed(s)),
2465            tp_order_type,
2466            sl_order_type,
2467            tp_size,
2468            sl_size,
2469            tp_limit_price,
2470            sl_limit_price,
2471            position_idx,
2472        }
2473    }
2474
2475    pub fn default() -> TradingStopRequest<'a> {
2476        TradingStopRequest::new(
2477            Category::Linear,
2478            "BTCUSDT",
2479            None,
2480            None,
2481            None,
2482            None,
2483            None,
2484            None,
2485            None,
2486            None,
2487            None,
2488            None,
2489            None,
2490            1,
2491        )
2492    }
2493}
2494
2495#[derive(Serialize, Deserialize, Clone, Debug)]
2496#[serde(rename_all = "camelCase")]
2497pub struct TradingStopResponse {
2498    #[serde(rename = "retCode")]
2499    pub ret_code: i32,
2500    #[serde(rename = "retMsg")]
2501    pub ret_msg: String,
2502    pub result: Empty, // Assuming result is an empty struct as per provided JSON
2503    #[serde(rename = "retExtInfo")]
2504    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2505    pub time: u64,
2506}
2507
2508#[derive(Clone, Default)]
2509pub struct AddMarginRequest<'a> {
2510    pub category: Category,
2511    pub symbol: Cow<'a, str>,
2512    pub auto_add: bool,
2513    pub position_idx: Option<i32>,
2514}
2515
2516impl<'a> AddMarginRequest<'a> {
2517    pub fn new(
2518        category: Category,
2519        symbol: &'a str,
2520        auto_add: bool,
2521        position_idx: Option<i32>,
2522    ) -> Self {
2523        Self {
2524            category,
2525            symbol: Cow::Borrowed(symbol),
2526            auto_add,
2527            position_idx,
2528        }
2529    }
2530    pub fn default() -> AddMarginRequest<'a> {
2531        AddMarginRequest::new(Category::Linear, "BTCUSDT", false, None)
2532    }
2533}
2534
2535#[derive(Serialize, Deserialize, Clone, Debug)]
2536#[serde(rename_all = "camelCase")]
2537pub struct AddMarginResponse {
2538    #[serde(rename = "retCode")]
2539    pub ret_code: i32,
2540    #[serde(rename = "retMsg")]
2541    pub ret_msg: String,
2542    pub result: Empty, // Assuming result is an empty struct as per provided JSON
2543    #[serde(rename = "retExtInfo")]
2544    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2545    pub time: u64,
2546}
2547
2548#[derive(Clone, Default)]
2549pub struct AddReduceMarginRequest<'a> {
2550    pub category: Category,
2551    pub symbol: Cow<'a, str>,
2552    pub margin: f64,
2553    pub position_idx: Option<i32>,
2554}
2555
2556impl<'a> AddReduceMarginRequest<'a> {
2557    pub fn new(
2558        category: Category,
2559        symbol: &'a str,
2560        margin: f64,
2561        position_idx: Option<i32>,
2562    ) -> Self {
2563        Self {
2564            category,
2565            symbol: Cow::Borrowed(symbol),
2566            margin,
2567            position_idx,
2568        }
2569    }
2570    pub fn default() -> AddReduceMarginRequest<'a> {
2571        AddReduceMarginRequest::new(Category::Linear, "BTCUSDT", 1.0, None)
2572    }
2573}
2574
2575#[derive(Serialize, Deserialize, Clone, Debug)]
2576#[serde(rename_all = "camelCase")]
2577pub struct AddReduceMarginResponse {
2578    #[serde(rename = "retCode")]
2579    pub ret_code: i32,
2580    #[serde(rename = "retMsg")]
2581    pub ret_msg: String,
2582    pub result: AddReduceMarginResult,
2583    #[serde(rename = "retExtInfo")]
2584    pub ret_ext_info: Empty, // Assuming retExtInfo is an empty struct as per provided JSON
2585    pub time: u64,
2586}
2587
2588#[derive(Serialize, Deserialize, Clone, Debug)]
2589#[serde(rename_all = "camelCase")]
2590pub struct AddReduceMarginResult {
2591    pub category: String,
2592    pub symbol: String,
2593    pub position_idx: i32,
2594    #[serde(rename = "riskId")]
2595    pub risk_id: i32,
2596    #[serde(rename = "riskLimitValue")]
2597    pub risk_limit_value: String,
2598    pub size: String,
2599    #[serde(rename = "positionValue")]
2600    pub position_value: String,
2601    #[serde(rename = "avgPrice")]
2602    pub avg_price: String,
2603    #[serde(rename = "liqPrice")]
2604    pub liq_price: String,
2605    #[serde(rename = "bustPrice")]
2606    pub bust_price: String,
2607    #[serde(rename = "markPrice")]
2608    pub mark_price: String,
2609    pub leverage: String,
2610    #[serde(rename = "autoAddMargin")]
2611    pub auto_add_margin: i32,
2612    #[serde(rename = "positionStatus")]
2613    pub position_status: String,
2614    #[serde(rename = "positionIM")]
2615    pub position_im: String,
2616    #[serde(rename = "positionMM")]
2617    pub position_mm: String,
2618    #[serde(rename = "unrealisedPnl")]
2619    pub unrealised_pnl: String,
2620    #[serde(rename = "cumRealisedPnl")]
2621    pub cum_realised_pnl: String,
2622    #[serde(rename = "stopLoss")]
2623    pub stop_loss: String,
2624    #[serde(rename = "takeProfit")]
2625    pub take_profit: String,
2626    #[serde(rename = "trailingStop")]
2627    pub trailing_stop: String,
2628    #[serde(rename = "createdTime")]
2629    pub created_time: String,
2630    #[serde(rename = "updatedTime")]
2631    pub updated_time: String,
2632}
2633
2634#[derive(Clone, Default)]
2635pub struct ClosedPnlRequest<'a> {
2636    pub category: Category,
2637    pub symbol: Option<Cow<'a, str>>,
2638    pub start_time: Option<Cow<'a, str>>,
2639    pub end_time: Option<Cow<'a, str>>,
2640    pub limit: Option<u64>,
2641}
2642
2643impl<'a> ClosedPnlRequest<'a> {
2644    pub fn new(
2645        category: Category,
2646        symbol: Option<&'a str>,
2647        start_time: Option<&'a str>,
2648        end_time: Option<&'a str>,
2649        limit: Option<u64>,
2650    ) -> Self {
2651        Self {
2652            category,
2653            symbol: symbol.map(|s| Cow::Borrowed(s)),
2654            start_time: start_time.map(|s| Cow::Borrowed(s)),
2655            end_time: end_time.map(|s| Cow::Borrowed(s)),
2656            limit,
2657        }
2658    }
2659    pub fn default() -> ClosedPnlRequest<'a> {
2660        ClosedPnlRequest::new(Category::Linear, None, None, None, None)
2661    }
2662}
2663
2664#[derive(Serialize, Deserialize, Clone, Debug)]
2665#[serde(rename_all = "camelCase")]
2666pub struct ClosedPnlResponse {
2667    pub ret_code: i32,
2668    pub ret_msg: String,
2669    pub result: ClosedPnlResult,
2670    pub ret_ext_info: Empty,
2671    pub time: u64,
2672}
2673
2674#[derive(Serialize, Deserialize, Clone, Debug)]
2675#[serde(rename_all = "camelCase")]
2676pub struct ClosedPnlResult {
2677    #[serde(skip_serializing_if = "Option::is_none")]
2678    pub next_page_cursor: Option<String>,
2679    pub category: String,
2680    pub list: Vec<ClosedPnlItem>,
2681}
2682
2683#[derive(Serialize, Deserialize, Clone, Debug)]
2684#[serde(rename_all = "camelCase")]
2685pub struct ClosedPnlItem {
2686    pub symbol: String,
2687    pub order_type: String,
2688    pub leverage: String,
2689    pub updated_time: String,
2690    pub side: String,
2691    pub order_id: String,
2692    #[serde(with = "string_to_float")]
2693    pub closed_pnl: f64,
2694    #[serde(rename = "avgEntryPrice", with = "string_to_float")]
2695    pub avg_entry_price: f64,
2696    pub qty: String,
2697    #[serde(with = "string_to_float")]
2698    pub cum_entry_value: f64,
2699    pub created_time: String,
2700    #[serde(with = "string_to_float")]
2701    pub order_price: f64,
2702    pub closed_size: String,
2703    #[serde(rename = "avgExitPrice", with = "string_to_float")]
2704    pub avg_exit_price: f64,
2705    pub exec_type: String,
2706    pub fill_count: String,
2707    #[serde(with = "string_to_float")]
2708    pub cum_exit_value: f64,
2709}
2710
2711#[derive(Clone, Default, Serialize)]
2712pub struct MovePositionRequest<'a> {
2713    pub from_uid: u64,
2714    pub to_uid: u64,
2715    pub list: Vec<PositionItem<'a>>,
2716}
2717
2718#[derive(Clone, Default, Serialize)]
2719pub struct PositionItem<'a> {
2720    pub category: Category,
2721    pub symbol: Cow<'a, str>,
2722    pub price: f64,
2723    pub side: Side,
2724    pub qty: f64,
2725}
2726
2727impl<'a> MovePositionRequest<'a> {
2728    pub fn new(from_uid: u64, to_uid: u64, list: Vec<PositionItem<'a>>) -> Self {
2729        Self {
2730            from_uid,
2731            to_uid,
2732            list,
2733        }
2734    }
2735    pub fn default() -> MovePositionRequest<'a> {
2736        MovePositionRequest::new(0, 0, vec![])
2737    }
2738}
2739impl<'a> PositionItem<'a> {
2740    pub fn new(category: Category, symbol: &'a str, price: f64, side: Side, qty: f64) -> Self {
2741        Self {
2742            category,
2743            symbol: Cow::Borrowed(symbol),
2744            price,
2745            side,
2746            qty,
2747        }
2748    }
2749    pub fn default() -> PositionItem<'a> {
2750        PositionItem::new(Category::Linear, "BTCUSDT", 0.0, Side::Buy, 0.0)
2751    }
2752}
2753
2754#[derive(Deserialize, Serialize, Clone, Debug)]
2755pub struct MovePositionResponse {
2756    pub ret_code: i32,
2757    pub ret_msg: String,
2758    pub result: MovePositionResult,
2759}
2760
2761#[derive(Deserialize, Serialize, Clone, Debug)]
2762pub struct MovePositionResult {
2763    pub block_trade_id: String,
2764    pub status: String,
2765    pub reject_party: String,
2766}
2767
2768#[derive(Serialize, Clone, Default)]
2769pub struct MoveHistoryRequest<'a> {
2770    pub category: Option<Category>,
2771    pub symbol: Option<Cow<'a, str>>,
2772    pub start_time: Option<Cow<'a, str>>,
2773    pub end_time: Option<Cow<'a, str>>,
2774    pub status: Option<Cow<'a, str>>,
2775    pub block_trade_id: Option<Cow<'a, str>>,
2776    pub limit: Option<Cow<'a, str>>,
2777}
2778
2779impl<'a> MoveHistoryRequest<'a> {
2780    pub fn new(
2781        category: Option<Category>,
2782        symbol: Option<&'a str>,
2783        start_time: Option<&'a str>,
2784        end_time: Option<&'a str>,
2785        status: Option<&'a str>,
2786        block_trade_id: Option<&'a str>,
2787        limit: Option<&'a str>,
2788    ) -> Self {
2789        Self {
2790            category,
2791            symbol: symbol.map(|s| Cow::Borrowed(s)),
2792            start_time: start_time.map(|s| Cow::Borrowed(s)),
2793            end_time: end_time.map(|s| Cow::Borrowed(s)),
2794            status: status.map(|s| Cow::Borrowed(s)),
2795            block_trade_id: block_trade_id.map(|s| Cow::Borrowed(s)),
2796            limit: limit.map(|s| Cow::Borrowed(s)),
2797        }
2798    }
2799    pub fn default() -> MoveHistoryRequest<'a> {
2800        MoveHistoryRequest::new(None, None, None, None, None, None, None)
2801    }
2802}
2803
2804#[derive(Serialize, Deserialize, Clone, Debug)]
2805#[serde(rename_all = "camelCase")]
2806pub struct MoveHistoryResponse {
2807    #[serde(rename = "retCode")]
2808    pub ret_code: i16,
2809    #[serde(rename = "retMsg")]
2810    pub ret_msg: String,
2811    pub result: MoveHistoryResult,
2812    #[serde(rename = "retExtInfo")]
2813    pub ret_ext_info: Empty,
2814    pub time: u64,
2815}
2816
2817#[derive(Serialize, Deserialize, Clone, Debug)]
2818#[serde(rename_all = "camelCase")]
2819pub struct MoveHistoryResult {
2820    pub list: Vec<MoveHistoryEntry>,
2821    #[serde(rename = "nextPageCursor")]
2822    pub next_page_cursor: String,
2823}
2824
2825#[derive(Serialize, Deserialize, Clone, Debug)]
2826#[serde(rename_all = "camelCase")]
2827pub struct MoveHistoryEntry {
2828    #[serde(rename = "blockTradeId")]
2829    pub block_trade_id: String,
2830    pub category: String,
2831    #[serde(rename = "orderId")]
2832    pub order_id: String,
2833    #[serde(rename = "userId")]
2834    pub user_id: u64,
2835    pub symbol: String,
2836    pub side: String,
2837    pub price: String,
2838    pub qty: String,
2839    #[serde(rename = "execFee")]
2840    pub exec_fee: String,
2841    pub status: String,
2842    #[serde(rename = "execId")]
2843    pub exec_id: String,
2844    #[serde(rename = "resultCode")]
2845    pub result_code: i16,
2846    #[serde(rename = "resultMessage")]
2847    pub result_message: String,
2848    #[serde(rename = "createdAt")]
2849    pub created_at: u64,
2850    #[serde(rename = "updatedAt")]
2851    pub updated_at: u64,
2852    #[serde(rename = "rejectParty")]
2853    pub reject_party: String,
2854}
2855
2856// = = = = = = = = =  ==  = = == = = == =  = = = = = = = = = = = = = = = =
2857//
2858//  ACCOUNT STRUCTS AND RESPONSES
2859//
2860// = = = = = = = = = = = = = = = = = = ==  = = = = ==  = = == = =  = = = =
2861
2862#[derive(Deserialize, Serialize, Clone, Debug)]
2863#[serde(rename_all = "camelCase")]
2864pub struct WalletResponse {
2865    #[serde(rename = "retCode")]
2866    pub ret_code: i32,
2867    #[serde(rename = "retMsg")]
2868    pub ret_msg: String,
2869    pub result: WalletList,
2870    #[serde(rename = "retExtInfo")]
2871    pub ret_ext_info: Empty,
2872    pub time: u64,
2873}
2874
2875#[derive(Deserialize, Serialize, Clone, Debug)]
2876pub struct WalletList {
2877    pub list: Vec<WalletData>,
2878}
2879
2880#[derive(Deserialize, Serialize, Clone, Debug)]
2881#[serde(rename_all = "camelCase")]
2882pub struct UTAResponse {
2883    #[serde(rename = "retCode")]
2884    pub ret_code: i32,
2885    #[serde(rename = "retMsg")]
2886    pub ret_msg: String,
2887    pub result: UTAUpdateStatus,
2888    #[serde(rename = "retExtInfo")]
2889    pub ret_ext_info: Empty,
2890    pub time: u64,
2891}
2892
2893#[derive(Deserialize, Serialize, Clone, Debug)]
2894#[serde(rename_all = "camelCase")]
2895pub struct UTAUpdateStatus {
2896    #[serde(rename = "unifiedUpdateStatus")]
2897    pub unified_update_status: String,
2898    #[serde(rename = "unifiedUpdateMsg")]
2899    pub unified_update_msg: UnifiedUpdateMsg,
2900}
2901
2902#[derive(Deserialize, Serialize, Clone, Debug)]
2903pub struct UnifiedUpdateMsg {
2904    pub msg: Vec<String>,
2905}
2906
2907#[derive(Clone, Debug, Default)]
2908pub struct BorrowHistoryRequest<'a> {
2909    pub coin: Option<Cow<'a, str>>,
2910    pub start_time: Option<Cow<'a, str>>,
2911    pub end_time: Option<Cow<'a, str>>,
2912    pub limit: Option<Cow<'a, str>>,
2913}
2914
2915impl<'a> BorrowHistoryRequest<'a> {
2916    pub fn new(
2917        coin: Option<&'a str>,
2918        start_time: Option<&'a str>,
2919        end_time: Option<&'a str>,
2920        limit: Option<&'a str>,
2921    ) -> Self {
2922        Self {
2923            coin: coin.map(|s| Cow::Borrowed(s)),
2924            start_time: start_time.map(|s| Cow::Borrowed(s)),
2925            end_time: end_time.map(|s| Cow::Borrowed(s)),
2926            limit: limit.map(|s| Cow::Borrowed(s)),
2927        }
2928    }
2929    pub fn default() -> BorrowHistoryRequest<'a> {
2930        BorrowHistoryRequest::new(None, None, None, None)
2931    }
2932}
2933
2934#[derive(Debug, Serialize, Deserialize, Clone)]
2935#[serde(rename_all = "camelCase")]
2936pub struct BorrowHistoryResponse {
2937    pub ret_code: i32,
2938    pub ret_msg: String,
2939    pub result: BorrowHistory,
2940    pub ret_ext_info: Empty,
2941    pub time: u64,
2942}
2943
2944#[derive(Debug, Serialize, Deserialize, Clone)]
2945#[serde(rename_all = "camelCase")]
2946pub struct BorrowHistory {
2947    pub next_page_cursor: String,
2948    pub rows: Vec<BorrowHistoryEntry>,
2949}
2950
2951#[derive(Debug, Serialize, Deserialize, Clone)]
2952#[serde(rename_all = "camelCase")]
2953pub struct BorrowHistoryEntry {
2954    #[serde(rename = "borrowAmount")]
2955    pub borrow_amount: String,
2956    #[serde(rename = "costExemption")]
2957    pub cost_exemption: String,
2958    #[serde(rename = "freeBorrowedAmount")]
2959    pub free_borrowed_amount: String,
2960    #[serde(rename = "createdTime")]
2961    pub created_time: u64,
2962    #[serde(rename = "InterestBearingBorrowSize")]
2963    pub interest_bearing_borrow_size: String,
2964    pub currency: String,
2965    #[serde(rename = "unrealisedLoss")]
2966    pub unrealised_loss: String,
2967    #[serde(rename = "hourlyBorrowRate")]
2968    pub hourly_borrow_rate: String,
2969    #[serde(rename = "borrowCost")]
2970    pub borrow_cost: String,
2971}
2972
2973#[derive(Debug, Serialize, Deserialize, Clone)]
2974#[serde(rename_all = "camelCase")]
2975pub struct RepayLiabilityResponse {
2976    pub ret_code: i32,
2977    pub ret_msg: String,
2978    pub result: LiabilityQty,
2979    pub ret_ext_info: Empty,
2980    pub time: u64,
2981}
2982
2983#[derive(Debug, Serialize, Deserialize, Clone)]
2984pub struct LiabilityQty {
2985    pub list: Vec<LiabilityQtyData>,
2986}
2987
2988#[derive(Debug, Serialize, Deserialize, Clone)]
2989#[serde(rename_all = "camelCase")]
2990pub struct LiabilityQtyData {
2991    pub coin: String,
2992    pub repayment_qty: String,
2993}
2994
2995#[derive(Debug, Serialize, Deserialize, Clone)]
2996#[serde(rename_all = "camelCase")]
2997pub struct SetCollateralCoinResponse {
2998    pub ret_code: i32,
2999    pub ret_msg: String,
3000    pub result: Empty,
3001    pub ret_ext_info: Empty,
3002    pub time: u64,
3003}
3004
3005#[derive(Debug, Serialize, Deserialize, Clone)]
3006#[serde(rename_all = "camelCase")]
3007pub struct BatchSetCollateralCoinResponse {
3008    pub ret_code: i32,
3009    pub ret_msg: String,
3010    pub result: SwitchList,
3011    pub ret_ext_info: Empty,
3012    pub time: u64,
3013}
3014
3015#[derive(Debug, Serialize, Deserialize, Clone)]
3016#[serde(rename_all = "camelCase")]
3017pub struct SwitchList {
3018    pub list: Vec<SwitchListData>,
3019}
3020
3021#[derive(Debug, Serialize, Deserialize, Clone)]
3022#[serde(rename_all = "camelCase")]
3023pub struct SwitchListData {
3024    pub coin: String,
3025    pub collateral_switch: String,
3026}
3027
3028#[derive(Debug, Serialize, Deserialize, Clone)]
3029#[serde(rename_all = "camelCase")]
3030pub struct CollateralInfoResponse {
3031    pub ret_code: i32,
3032    pub ret_msg: String,
3033    pub result: CollateralInfoList,
3034    pub ret_ext_info: Empty,
3035    pub time: u64,
3036}
3037
3038#[derive(Debug, Serialize, Deserialize, Clone)]
3039#[serde(rename_all = "camelCase")]
3040pub struct CollateralInfoList {
3041    pub list: Vec<CollateralInfo>,
3042}
3043
3044#[derive(Debug, Serialize, Deserialize, Clone)]
3045#[serde(rename_all = "camelCase")]
3046pub struct CollateralInfo {
3047    #[serde(rename = "availableToBorrow")]
3048    pub available_to_borrow: String,
3049    #[serde(rename = "freeBorrowingAmount")]
3050    pub free_borrowing_amount: String,
3051    #[serde(rename = "freeBorrowAmount")]
3052    pub free_borrow_amount: String,
3053    #[serde(rename = "maxBorrowingAmount")]
3054    pub max_borrowing_amount: String,
3055    #[serde(rename = "hourlyBorrowRate")]
3056    pub hourly_borrow_rate: String,
3057    #[serde(rename = "borrowUsageRate")]
3058    pub borrow_usage_rate: String,
3059    #[serde(rename = "collateralSwitch")]
3060    pub collateral_switch: bool,
3061    #[serde(rename = "borrowAmount")]
3062    pub borrow_amount: String,
3063    #[serde(rename = "borrowable")]
3064    pub borrowable: bool,
3065    pub currency: String,
3066    #[serde(rename = "marginCollateral")]
3067    pub margin_collateral: bool,
3068    #[serde(rename = "freeBorrowingLimit")]
3069    pub free_borrowing_limit: String,
3070    #[serde(rename = "collateralRatio")]
3071    pub collateral_ratio: String,
3072}
3073
3074#[derive(Debug, Serialize, Deserialize, Clone)]
3075#[serde(rename_all = "camelCase")]
3076pub struct FeeRateResponse {
3077    pub ret_code: i32,
3078    pub ret_msg: String,
3079    pub result: FeeRateList,
3080    pub ret_ext_info: Empty,
3081    pub time: u64,
3082}
3083
3084#[derive(Debug, Serialize, Deserialize, Clone)]
3085#[serde(rename_all = "camelCase")]
3086pub struct FeeRateList {
3087    pub list: Vec<FeeRate>,
3088}
3089
3090#[derive(Debug, Serialize, Deserialize, Clone)]
3091#[serde(rename_all = "camelCase")]
3092pub struct FeeRate {
3093    pub symbol: String,
3094    pub maker_fee_rate: String,
3095    pub taker_fee_rate: String,
3096}
3097
3098#[derive(Debug, Serialize, Deserialize, Clone)]
3099#[serde(rename_all = "camelCase")]
3100pub struct AccountInfoResponse {
3101    pub ret_code: i32,
3102    pub ret_msg: String,
3103    pub result: AccountInfo,
3104    #[serde(default)]
3105    pub ret_ext_info: Empty,
3106    #[serde(default)]
3107    pub time: Option<u64>,
3108}
3109
3110#[derive(Debug, Serialize, Deserialize, Clone)]
3111#[serde(rename_all = "camelCase")]
3112pub struct AccountInfo {
3113    pub margin_mode: String,
3114    pub updated_time: String,
3115    pub unified_margin_status: i8,
3116    pub dcp_status: String,
3117    pub time_window: i32,
3118    pub smp_group: i8,
3119    pub is_master_trader: bool,
3120    pub spot_hedging_status: String,
3121}
3122
3123#[derive(Clone, Default)]
3124pub struct TransactionLogRequest<'a> {
3125    pub account_type: Option<Cow<'a, str>>,
3126    pub category: Option<Category>,
3127    pub currency: Option<Cow<'a, str>>,
3128    pub base_coin: Option<Cow<'a, str>>,
3129    pub log_type: Option<Cow<'a, str>>,
3130    pub start_time: Option<Cow<'a, str>>,
3131    pub end_time: Option<Cow<'a, str>>,
3132    pub limit: Option<u32>,
3133}
3134
3135impl<'a> TransactionLogRequest<'a> {
3136    pub fn new(
3137        account_type: Option<&'a str>,
3138        category: Option<Category>,
3139        currency: Option<&'a str>,
3140        base_coin: Option<&'a str>,
3141        log_type: Option<&'a str>,
3142        start_time: Option<&'a str>,
3143        end_time: Option<&'a str>,
3144        limit: Option<u32>,
3145    ) -> Self {
3146        Self {
3147            account_type: account_type.map(|s| Cow::Borrowed(s)),
3148            category,
3149            currency: currency.map(|s| Cow::Borrowed(s)),
3150            base_coin: base_coin.map(|s| Cow::Borrowed(s)),
3151            log_type: log_type.map(|s| Cow::Borrowed(s)),
3152            start_time: start_time.map(|s| Cow::Borrowed(s)),
3153            end_time: end_time.map(|s| Cow::Borrowed(s)),
3154            limit,
3155        }
3156    }
3157    pub fn default() -> Self {
3158        Self::new(None, None, None, None, None, None, None, None)
3159    }
3160}
3161
3162#[derive(Debug, Serialize, Deserialize, Clone)]
3163#[serde(rename_all = "camelCase")]
3164pub struct TransactionLogEntry {
3165    pub id: String,
3166    pub symbol: String,
3167    pub side: String,
3168    pub funding: Option<String>,
3169    pub order_link_id: Option<String>,
3170    pub order_id: String,
3171    pub fee: String,
3172    pub change: String,
3173    pub cash_flow: String,
3174    pub transaction_time: String,
3175    pub type_field: String,
3176    #[serde(rename = "feeRate")]
3177    pub fee_rate: String,
3178    pub bonus_change: Option<String>,
3179    pub size: String,
3180    pub qty: String,
3181    pub cash_balance: String,
3182    pub currency: String,
3183    pub category: String,
3184    pub trade_price: String,
3185    pub trade_id: String,
3186}
3187
3188#[derive(Debug, Serialize, Deserialize, Clone)]
3189#[serde(rename_all = "camelCase")]
3190pub struct TransactionLogResult {
3191    pub next_page_cursor: String,
3192    pub list: Vec<TransactionLogEntry>,
3193}
3194
3195#[derive(Debug, Serialize, Deserialize, Clone)]
3196#[serde(rename_all = "camelCase")]
3197pub struct TransactionLogResponse {
3198    pub ret_code: i32,
3199    pub ret_msg: String,
3200    pub result: TransactionLogResult,
3201    pub ret_ext_info: Empty,
3202    pub time: u64,
3203}
3204
3205#[derive(Debug, Serialize, Deserialize, Clone)]
3206#[serde(rename_all = "camelCase")]
3207pub struct SmpResponse {
3208    pub ret_code: i32,
3209    pub ret_msg: String,
3210    pub result: SmpResult,
3211    pub ret_ext_info: Empty,
3212    pub time: u64,
3213}
3214
3215#[derive(Debug, Serialize, Deserialize, Clone)]
3216#[serde(rename_all = "camelCase")]
3217pub struct SmpResult {
3218    pub smp_group: u8,
3219}
3220
3221#[derive(Debug, Serialize, Deserialize, Clone)]
3222#[serde(rename_all = "camelCase")]
3223pub struct SetMarginModeResponse {
3224    pub ret_code: i32,
3225    pub ret_msg: String,
3226    pub result: MarginModeResult,
3227    pub ret_ext_info: Empty,
3228    pub time: u64,
3229}
3230
3231#[derive(Debug, Serialize, Deserialize, Clone)]
3232#[serde(rename_all = "camelCase")]
3233pub struct MarginModeResult {
3234    pub reason: Vec<ReasonObject>,
3235}
3236
3237#[derive(Debug, Serialize, Deserialize, Clone)]
3238#[serde(rename_all = "camelCase")]
3239pub struct ReasonObject {
3240    pub reason_code: String,
3241    pub reason_msg: String,
3242}
3243
3244#[derive(Debug, Serialize, Deserialize, Clone)]
3245#[serde(rename_all = "camelCase")]
3246pub struct SpotHedgingResponse {
3247    pub ret_code: i32,
3248    pub ret_msg: String,
3249}
3250
3251// = = = = = = = = = = = = ==  = == = =  =  = = = = ==
3252// HEADER STRUCT FOR TRADESTREM RESPONSE
3253// = = = = = = = = = = = = ==  = == = =  =  = = = = ==
3254
3255#[derive(Debug, Serialize, Deserialize, Clone)]
3256pub struct Header {
3257    #[serde(rename = "X-Bapi-Limit")]
3258    pub x_bapi_limit: String,
3259    #[serde(rename = "X-Bapi-Limit-Status")]
3260    pub x_bapi_limit_status: String,
3261    #[serde(rename = "X-Bapi-Limit-Reset-Timestamp")]
3262    pub x_bapi_limit_reset_timestamp: String,
3263    #[serde(rename = "Traceid")]
3264    pub traceid: String,
3265    #[serde(rename = "Timenow")]
3266    pub timenow: String,
3267}
3268
3269// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
3270//
3271// WEBSOCKET STRUCTS AND RESPONSES
3272//
3273// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
3274
3275#[derive(Clone, Debug, Default)]
3276pub struct Subscription<'a> {
3277    pub op: &'a str,
3278    pub args: Vec<&'a str>,
3279}
3280
3281impl<'a> Subscription<'a> {
3282    pub fn new(op: &'a str, args: Vec<&'a str>) -> Self {
3283        Self { op, args }
3284    }
3285    pub fn default() -> Subscription<'a> {
3286        Subscription::new("subscribe", vec![])
3287    }
3288}
3289
3290#[derive(Debug, Serialize, Deserialize, Clone)]
3291#[serde(untagged)]
3292pub enum WebsocketEvents {
3293    OrderBookEvent(OrderBookUpdate),
3294    TradeEvent(TradeUpdate),
3295    TickerEvent(WsTicker),
3296    LiquidationEvent(Liquidation),
3297    KlineEvent(WsKline),
3298    PositionEvent(PositionEvent),
3299    ExecutionEvent(Execution),
3300    OrderEvent(OrderEvent),
3301    Wallet(WalletEvent),
3302    TradeStream(TradeStreamEvent),
3303    FastExecEvent(FastExecution)
3304}
3305
3306#[derive(Debug, Serialize, Deserialize, Clone)]
3307#[serde(untagged)]
3308pub enum Tickers {
3309    Linear(LinearTickerData),
3310    Spot(SpotTickerData),
3311}
3312
3313#[derive(Debug, Serialize, Deserialize, Clone)]
3314#[serde(untagged)]
3315pub enum PongResponse {
3316    PublicPong(PongData),
3317    PrivatePong(PongData),
3318}
3319
3320#[derive(Debug, Serialize, Deserialize, Clone)]
3321pub struct PongData {
3322    #[serde(skip_serializing_if = "Option::is_none")]
3323    pub ret_code: Option<i32>,
3324    #[serde(skip_serializing_if = "Option::is_none")]
3325    pub success: Option<bool>,
3326    pub ret_msg: String,
3327    pub conn_id: String,
3328    #[serde(skip_serializing_if = "Option::is_none")]
3329    pub req_id: Option<String>,
3330    #[serde(skip_serializing_if = "Option::is_none")]
3331    pub args: Option<Vec<String>>,
3332    #[serde(skip_serializing_if = "Option::is_none")]
3333    pub data: Option<Vec<String>>,
3334    pub op: String,
3335}
3336
3337unsafe impl Send for PongData {}
3338unsafe impl Sync for PongData {}
3339
3340#[derive(Serialize, Deserialize, Debug, Clone)]
3341#[serde(rename_all = "camelCase")]
3342pub struct TradeStreamEvent {
3343    #[serde(skip_serializing_if = "Option::is_none")]
3344    pub req_id: Option<String>,
3345    pub ret_code: i32,
3346    pub ret_msg: String,
3347    pub op: String,
3348    pub data: OrderStatus,
3349    pub header: Header,
3350    pub conn_id: String,
3351}
3352
3353unsafe impl Send for TradeStreamEvent {}
3354unsafe impl Sync for TradeStreamEvent {}
3355
3356#[derive(Serialize, Deserialize, Debug, Clone)]
3357#[serde(rename_all = "camelCase")]
3358pub struct OrderBookUpdate {
3359    #[serde(rename = "topic")]
3360    pub topic: String,
3361    #[serde(rename = "type")]
3362    pub event_type: String,
3363    #[serde(rename = "ts")]
3364    pub timestamp: u64,
3365    pub data: WsOrderBook,
3366    pub cts: u64,
3367}
3368
3369unsafe impl Send for OrderBookUpdate {}
3370unsafe impl Sync for OrderBookUpdate {}
3371
3372#[derive(Serialize, Deserialize, Debug, Clone)]
3373#[serde(rename_all = "camelCase")]
3374pub struct WsOrderBook {
3375    #[serde(rename = "s")]
3376    pub symbol: String,
3377    #[serde(rename = "a")]
3378    pub asks: Vec<Ask>,
3379    #[serde(rename = "b")]
3380    pub bids: Vec<Bid>,
3381    #[serde(rename = "u")]
3382    pub update_id: u64,
3383    pub seq: u64,
3384}
3385
3386unsafe impl Send for WsOrderBook {}
3387unsafe impl Sync for WsOrderBook {}
3388
3389#[derive(Serialize, Deserialize, Debug, Clone)]
3390pub struct TradeUpdate {
3391    #[serde(rename = "topic")]
3392    pub topic: String,
3393    #[serde(rename = "type")]
3394    pub event_type: String,
3395    #[serde(rename = "ts")]
3396    pub timestamp: u64,
3397    pub data: Vec<WsTrade>,
3398}
3399
3400unsafe impl Send for TradeUpdate {}
3401unsafe impl Sync for TradeUpdate {}
3402
3403#[derive(Serialize, Deserialize, Debug, Clone)]
3404pub struct WsTrade {
3405    #[serde(rename = "T")]
3406    pub timestamp: u64,
3407    #[serde(rename = "s")]
3408    pub symbol: String,
3409    #[serde(rename = "S")]
3410    pub side: String,
3411    #[serde(rename = "v", with = "string_to_float")]
3412    pub volume: f64,
3413    #[serde(rename = "p", with = "string_to_float")]
3414    pub price: f64,
3415    #[serde(rename = "L")]
3416    pub tick_direction: String,
3417    #[serde(rename = "i")]
3418    pub id: String,
3419    #[serde(rename = "BT")]
3420    pub buyer_is_maker: bool,
3421}
3422
3423unsafe impl Send for WsTrade {}
3424unsafe impl Sync for WsTrade {}
3425
3426#[derive(Serialize, Deserialize, Debug, Clone)]
3427pub struct WsTicker {
3428    pub topic: String,
3429    #[serde(rename = "type")]
3430    pub event_type: String,
3431    pub data: Tickers,
3432    pub cs: u64,
3433    pub ts: u64,
3434}
3435
3436unsafe impl Send for WsTicker {}
3437unsafe impl Sync for WsTicker {}
3438
3439#[derive(Serialize, Deserialize, Debug, Clone)]
3440pub struct LinearTickerData {
3441    pub symbol: String,
3442    #[serde(rename = "tickDirection")]
3443    pub tick_direction: String,
3444    #[serde(rename = "price24hPcnt")]
3445    pub price_24h_pcnt: String,
3446    #[serde(rename = "lastPrice")]
3447    pub last_price: String,
3448    #[serde(rename = "prevPrice24h")]
3449    pub prev_price_24h: String,
3450    #[serde(rename = "highPrice24h")]
3451    pub high_price_24h: String,
3452    #[serde(rename = "lowPrice24h")]
3453    pub low_price_24h: String,
3454    #[serde(rename = "prevPrice1h")]
3455    pub prev_price_1h: String,
3456    #[serde(rename = "markPrice")]
3457    pub mark_price: String,
3458    #[serde(rename = "indexPrice")]
3459    pub index_price: String,
3460    #[serde(rename = "openInterest")]
3461    pub open_interest: String,
3462    #[serde(rename = "openInterestValue")]
3463    pub open_interest_value: String,
3464    #[serde(rename = "turnover24h")]
3465    pub turnover_24h: String,
3466    #[serde(rename = "volume24h")]
3467    pub volume_24h: String,
3468    #[serde(rename = "nextFundingTime")]
3469    pub next_funding_time: String,
3470    #[serde(rename = "fundingRate")]
3471    pub funding_rate: String,
3472    #[serde(rename = "bid1Price")]
3473    pub bid_price: String,
3474    #[serde(rename = "bid1Size")]
3475    pub bid_size: String,
3476    #[serde(rename = "ask1Price")]
3477    pub ask_price: String,
3478    #[serde(rename = "ask1Size")]
3479    pub ask_size: String,
3480}
3481
3482unsafe impl Send for LinearTickerData {}
3483unsafe impl Sync for LinearTickerData {}
3484
3485#[derive(Serialize, Deserialize, Debug, Clone)]
3486pub struct SpotTickerData {
3487    #[serde(rename = "symbol")]
3488    pub symbol: String,
3489    #[serde(rename = "lastPrice")]
3490    pub last_price: String,
3491    #[serde(rename = "highPrice24h")]
3492    pub high_price_24h: String,
3493    #[serde(rename = "lowPrice24h")]
3494    pub low_price_24h: String,
3495    #[serde(rename = "prevPrice24h")]
3496    pub prev_price_24h: String,
3497    #[serde(rename = "volume24h")]
3498    pub volume_24h: String,
3499    #[serde(rename = "turnover24h")]
3500    pub turnover_24h: String,
3501    #[serde(rename = "price24hPcnt")]
3502    pub price_24h_pcnt: String,
3503    #[serde(rename = "usdIndexPrice")]
3504    pub usd_index_price: String,
3505}
3506
3507unsafe impl Send for SpotTickerData {}
3508unsafe impl Sync for SpotTickerData {}
3509
3510#[derive(Serialize, Deserialize, Debug, Clone)]
3511pub struct Liquidation {
3512    #[serde(rename = "topic")]
3513    pub topic: String,
3514    #[serde(rename = "type")]
3515    pub event_type: String,
3516    #[serde(rename = "ts")]
3517    pub ts: u64,
3518    #[serde(rename = "data")]
3519    pub data: LiquidationData,
3520}
3521
3522unsafe impl Send for Liquidation {}
3523unsafe impl Sync for Liquidation {}
3524
3525#[derive(Serialize, Deserialize, Debug, Clone)]
3526pub struct LiquidationData {
3527    #[serde(rename = "updatedTime")]
3528    pub updated_time: u64,
3529    #[serde(rename = "symbol")]
3530    pub symbol: String,
3531    #[serde(rename = "side")]
3532    pub side: String,
3533    #[serde(with = "string_to_float")]
3534    pub size: f64,
3535    #[serde(with = "string_to_float")]
3536    pub price: f64,
3537}
3538
3539unsafe impl Send for LiquidationData {}
3540unsafe impl Sync for LiquidationData {}
3541
3542#[derive(Serialize, Deserialize, Debug, Clone)]
3543pub struct WsKline {
3544    pub topic: String,
3545    pub data: Vec<KlineData>,
3546    #[serde(rename = "ts")]
3547    pub timestamp: u64,
3548    #[serde(rename = "type")]
3549    pub event_type: String,
3550}
3551
3552unsafe impl Send for WsKline {}
3553unsafe impl Sync for WsKline {}
3554
3555#[derive(Serialize, Deserialize, Debug, Clone)]
3556pub struct KlineData {
3557    pub start: u64,
3558    pub end: u64,
3559    pub interval: String,
3560    pub open: String,
3561    pub close: String,
3562    pub high: String,
3563    pub low: String,
3564    pub volume: String,
3565    pub turnover: String,
3566    pub confirm: bool,
3567    pub timestamp: u64,
3568}
3569
3570unsafe impl Send for KlineData {}
3571unsafe impl Sync for KlineData {}
3572
3573#[derive(Serialize, Deserialize, Debug, Clone)]
3574pub struct PositionEvent {
3575    pub id: String,
3576    pub topic: String,
3577    #[serde(rename = "creationTime")]
3578    pub creation_time: u64,
3579    pub data: Vec<PositionData>,
3580}
3581
3582unsafe impl Send for PositionEvent {}
3583unsafe impl Sync for PositionEvent {}
3584
3585#[derive(Serialize, Deserialize, Debug, Clone)]
3586pub struct PositionData {
3587    #[serde(rename = "positionIdx")]
3588    pub position_idx: u8,
3589    #[serde(rename = "tradeMode")]
3590    pub trade_mode: u8,
3591    #[serde(rename = "riskId")]
3592    pub risk_id: u8,
3593    #[serde(rename = "riskLimitValue")]
3594    pub risk_limit_value: String,
3595    pub symbol: String,
3596    pub side: String,
3597    pub size: String,
3598    #[serde(rename = "entryPrice")]
3599    pub entry_price: String,
3600    pub leverage: String,
3601    #[serde(rename = "positionValue")]
3602    pub position_value: String,
3603    #[serde(rename = "positionBalance")]
3604    pub position_balance: String,
3605    #[serde(rename = "markPrice")]
3606    pub mark_price: String,
3607    #[serde(rename = "positionIM")]
3608    pub position_im: String,
3609    #[serde(rename = "positionMM")]
3610    pub position_mm: String,
3611    #[serde(rename = "takeProfit")]
3612    pub take_profit: String,
3613    #[serde(rename = "stopLoss")]
3614    pub stop_loss: String,
3615    #[serde(rename = "trailingStop")]
3616    pub trailing_stop: String,
3617    #[serde(rename = "unrealisedPnl")]
3618    pub unrealised_pnl: String,
3619    #[serde(rename = "cumRealisedPnl")]
3620    pub cum_realised_pnl: String,
3621    #[serde(rename = "createdTime")]
3622    pub created_time: String,
3623    #[serde(rename = "updatedTime")]
3624    pub updated_time: String,
3625    #[serde(rename = "tpslMode")]
3626    pub tpsl_mode: String,
3627    #[serde(rename = "liqPrice")]
3628    pub liq_price: String,
3629    #[serde(rename = "bustPrice")]
3630    pub bust_price: String,
3631    pub category: String,
3632    #[serde(rename = "positionStatus")]
3633    pub position_status: String,
3634    #[serde(rename = "adlRankIndicator")]
3635    pub adl_rank_indicator: u8,
3636    #[serde(rename = "autoAddMargin")]
3637    pub auto_add_margin: u8,
3638    #[serde(rename = "leverageSysUpdatedTime")]
3639    pub leverage_sys_updated_time: String,
3640    #[serde(rename = "mmrSysUpdatedTime")]
3641    pub mmr_sys_updated_time: String,
3642    pub seq: u64,
3643    #[serde(rename = "isReduceOnly")]
3644    pub is_reduce_only: bool,
3645}
3646
3647unsafe impl Send for PositionData {}
3648unsafe impl Sync for PositionData {}
3649
3650#[derive(Serialize, Deserialize, Debug, Clone)]
3651pub struct Execution {
3652    #[serde(rename = "id")]
3653    pub id: String,
3654    #[serde(rename = "topic")]
3655    pub topic: String,
3656    #[serde(rename = "creationTime")]
3657    pub creation_time: u64,
3658    #[serde(rename = "data")]
3659    pub data: Vec<ExecutionData>,
3660}
3661
3662unsafe impl Send for Execution {}
3663unsafe impl Sync for Execution {}
3664
3665#[derive(Serialize, Deserialize, Debug, Clone)]
3666pub struct ExecutionData {
3667    #[serde(rename = "category")]
3668    pub category: String,
3669    #[serde(rename = "symbol")]
3670    pub symbol: String,
3671    #[serde(rename = "execFee")]
3672    pub exec_fee: String,
3673    #[serde(rename = "execId")]
3674    pub exec_id: String,
3675    #[serde(rename = "execPrice")]
3676    pub exec_price: String,
3677    #[serde(rename = "execQty")]
3678    pub exec_qty: String,
3679    #[serde(rename = "execType")]
3680    pub exec_type: String,
3681    #[serde(rename = "execValue")]
3682    pub exec_value: String,
3683    #[serde(rename = "isMaker")]
3684    pub is_maker: bool,
3685    #[serde(rename = "feeRate")]
3686    pub fee_rate: String,
3687    #[serde(rename = "tradeIv")]
3688    pub trade_iv: String,
3689    #[serde(rename = "markIv")]
3690    pub mark_iv: String,
3691    #[serde(rename = "blockTradeId")]
3692    pub block_trade_id: String,
3693    #[serde(rename = "markPrice")]
3694    pub mark_price: String,
3695    #[serde(rename = "indexPrice")]
3696    pub index_price: String,
3697    #[serde(rename = "underlyingPrice")]
3698    pub underlying_price: String,
3699    #[serde(rename = "leavesQty")]
3700    pub leaves_qty: String,
3701    #[serde(rename = "orderId")]
3702    pub order_id: String,
3703    #[serde(rename = "orderLinkId")]
3704    pub order_link_id: String,
3705    #[serde(rename = "orderPrice")]
3706    pub order_price: String,
3707    #[serde(rename = "orderQty")]
3708    pub order_qty: String,
3709    #[serde(rename = "orderType")]
3710    pub order_type: String,
3711    #[serde(rename = "stopOrderType")]
3712    pub stop_order_type: String,
3713    #[serde(rename = "side")]
3714    pub side: String,
3715    #[serde(rename = "execTime")]
3716    pub exec_time: String,
3717    #[serde(rename = "isLeverage")]
3718    pub is_leverage: String,
3719    #[serde(rename = "closedSize")]
3720    pub closed_size: String,
3721    #[serde(rename = "seq")]
3722    pub seq: u64,
3723}
3724
3725unsafe impl Send for ExecutionData {}
3726unsafe impl Sync for ExecutionData {}
3727
3728
3729#[derive(Serialize, Deserialize, Debug, Clone)]
3730pub struct FastExecution {
3731    pub topic: String,
3732    #[serde(rename = "creationTime")]
3733    pub creation_time: u64,
3734    pub data:  Vec<FastExecData>
3735}
3736
3737unsafe impl Send for FastExecution {}
3738unsafe impl Sync for FastExecution {}
3739
3740#[derive(Serialize, Deserialize, Debug, Clone)]
3741pub struct FastExecData {
3742    pub category: String,
3743    pub symbol: String,
3744    #[serde(rename = "execId")]
3745    pub exec_id: String,
3746    #[serde(rename = "execPrice")]
3747    pub exec_price: String,
3748    #[serde(rename = "execQty")]
3749    pub exec_qty: String,
3750    #[serde(rename = "orderId")]
3751    pub order_id: String,
3752    #[serde(rename = "orderLinkId")]
3753    pub order_link_id: String,
3754    pub side: String,
3755    #[serde(rename = "execTime")]
3756    pub exec_time: String,
3757    pub seq: u64,
3758}
3759
3760unsafe impl Send for FastExecData {}
3761unsafe impl Sync for  FastExecData {}
3762
3763
3764#[derive(Serialize, Deserialize, Debug, Clone)]
3765pub struct OrderData {
3766    pub symbol: String,
3767    #[serde(rename = "orderId")]
3768    pub order_id: String,
3769    pub side: String,
3770    #[serde(rename = "orderType")]
3771    pub order_type: String,
3772    #[serde(rename = "cancelType")]
3773    pub cancel_type: String,
3774    pub price: String,
3775    pub qty: String,
3776    #[serde(rename = "orderIv")]
3777    pub order_iv: String,
3778    #[serde(rename = "timeInForce")]
3779    pub time_in_force: String,
3780    #[serde(rename = "orderStatus")]
3781    pub order_status: String,
3782    #[serde(rename = "orderLinkId")]
3783    pub order_link_id: String,
3784    #[serde(rename = "lastPriceOnCreated")]
3785    pub last_price_on_created: String,
3786    #[serde(rename = "reduceOnly")]
3787    pub reduce_only: bool,
3788    #[serde(rename = "leavesQty")]
3789    pub leaves_qty: String,
3790    #[serde(rename = "leavesValue")]
3791    pub leaves_value: String,
3792    #[serde(rename = "cumExecQty")]
3793    pub cum_exec_qty: String,
3794    #[serde(rename = "cumExecValue")]
3795    pub cum_exec_value: String,
3796    #[serde(rename = "avgPrice")]
3797    pub avg_price: String,
3798    #[serde(rename = "blockTradeId")]
3799    pub block_trade_id: String,
3800    #[serde(rename = "positionIdx")]
3801    pub position_idx: u8,
3802    #[serde(rename = "cumExecFee")]
3803    pub cum_exec_fee: String,
3804    #[serde(rename = "createdTime")]
3805    pub created_time: String,
3806    #[serde(rename = "updatedTime")]
3807    pub updated_time: String,
3808    #[serde(rename = "rejectReason")]
3809    pub reject_reason: String,
3810    #[serde(rename = "stopOrderType")]
3811    pub stop_order_type: String,
3812    #[serde(rename = "tpslMode")]
3813    pub tpsl_mode: String,
3814    #[serde(rename = "triggerPrice")]
3815    pub trigger_price: String,
3816    #[serde(rename = "takeProfit")]
3817    pub take_profit: String,
3818    #[serde(rename = "stopLoss")]
3819    pub stop_loss: String,
3820    #[serde(rename = "tpTriggerBy")]
3821    pub tp_trigger_by: String,
3822    #[serde(rename = "slTriggerBy")]
3823    pub sl_trigger_by: String,
3824    #[serde(rename = "tpLimitPrice")]
3825    pub tp_limit_price: String,
3826    #[serde(rename = "slLimitPrice")]
3827    pub sl_limit_price: String,
3828    #[serde(rename = "triggerDirection")]
3829    pub trigger_direction: u8,
3830    #[serde(rename = "triggerBy")]
3831    pub trigger_by: String,
3832    #[serde(rename = "closeOnTrigger")]
3833    pub close_on_trigger: bool,
3834    pub category: String,
3835    #[serde(rename = "placeType")]
3836    pub place_type: String,
3837    #[serde(rename = "smpType")]
3838    pub smp_type: String,
3839    #[serde(rename = "smpGroup")]
3840    pub smp_group: u8,
3841    #[serde(rename = "smpOrderId")]
3842    pub smp_order_id: String,
3843    #[serde(rename = "feeCurrency")]
3844    pub fee_currency: String,
3845}
3846
3847unsafe impl Send for OrderData {}
3848unsafe impl Sync for OrderData {}
3849
3850#[derive(Serialize, Deserialize, Debug, Clone)]
3851pub struct OrderEvent {
3852    pub id: String,
3853    pub topic: String,
3854    #[serde(rename = "creationTime")]
3855    pub creation_time: u64,
3856    pub data: Vec<OrderData>,
3857}
3858
3859unsafe impl Send for OrderEvent {}
3860unsafe impl Sync for OrderEvent {}
3861
3862#[derive(Serialize, Deserialize, Debug, Clone)]
3863pub struct WalletEvent {
3864    pub id: String,
3865    pub topic: String,
3866    #[serde(rename = "creationTime")]
3867    pub creation_time: u64,
3868    pub data: Vec<WalletData>,
3869}
3870unsafe impl Send for WalletEvent {}
3871unsafe impl Sync for WalletEvent {}
3872
3873#[derive(Serialize, Deserialize, Debug, Clone)]
3874pub struct WalletData {
3875    #[serde(rename = "accountIMRate")]
3876    pub account_im_rate: String,
3877    #[serde(rename = "accountMMRate")]
3878    pub account_mm_rate: String,
3879    #[serde(rename = "totalEquity")]
3880    pub total_equity: String,
3881    #[serde(rename = "totalWalletBalance")]
3882    pub total_wallet_balance: String,
3883    #[serde(rename = "totalMarginBalance")]
3884    pub total_margin_balance: String,
3885    #[serde(rename = "totalAvailableBalance")]
3886    pub total_available_balance: String,
3887    #[serde(rename = "totalPerpUPL")]
3888    pub total_perp_upl: String,
3889    #[serde(rename = "totalInitialMargin")]
3890    pub total_initial_margin: String,
3891    #[serde(rename = "totalMaintenanceMargin")]
3892    pub total_maintenance_margin: String,
3893    #[serde(rename = "coin")]
3894    pub coin: Vec<CoinData>,
3895    #[serde(rename = "accountLTV")]
3896    pub account_ltv: String,
3897    #[serde(rename = "accountType", skip_serializing_if = "Option::is_none")]
3898    pub account_type: Option<String>,
3899}
3900unsafe impl Send for WalletData {}
3901unsafe impl Sync for WalletData {}
3902#[derive(Serialize, Deserialize, Debug, Clone)]
3903pub struct CoinData {
3904    #[serde(rename = "coin")]
3905    pub coin: String,
3906    #[serde(rename = "equity")]
3907    pub equity: String,
3908    #[serde(rename = "usdValue")]
3909    pub usd_value: String,
3910    #[serde(rename = "walletBalance")]
3911    pub wallet_balance: String,
3912    #[serde(rename = "availableToWithdraw")]
3913    pub available_to_withdraw: String,
3914    #[serde(rename = "availableToBorrow")]
3915    pub available_to_borrow: String,
3916    #[serde(rename = "borrowAmount")]
3917    pub borrow_amount: String,
3918    #[serde(rename = "accruedInterest")]
3919    pub accrued_interest: String,
3920    #[serde(rename = "totalOrderIM")]
3921    pub total_order_im: String,
3922    #[serde(rename = "totalPositionIM")]
3923    pub total_position_im: String,
3924    #[serde(rename = "totalPositionMM")]
3925    pub total_position_mm: String,
3926    #[serde(rename = "unrealisedPnl")]
3927    pub unrealised_pnl: String,
3928    #[serde(rename = "cumRealisedPnl")]
3929    pub cum_realised_pnl: String,
3930    pub bonus: String,
3931    #[serde(rename = "collateralSwitch")]
3932    pub collateral_switch: bool,
3933    #[serde(rename = "marginCollateral")]
3934    pub margin_collateral: bool,
3935    #[serde(rename = "locked")]
3936    pub locked: String,
3937    #[serde(rename = "spotHedgingQty")]
3938    pub spot_hedging_qty: String,
3939}
3940
3941unsafe impl Send for CoinData {}
3942unsafe impl Sync for CoinData {}
3943
3944mod string_to_u64 {
3945    use std::default;
3946
3947    use serde::{self, Deserialize, Deserializer, Serializer};
3948
3949    // Serialize a u64 as a string.
3950    pub fn serialize<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
3951    where
3952        S: Serializer,
3953    {
3954        let s = value.to_string();
3955        serializer.serialize_str(&s)
3956    }
3957
3958    // Deserialize a string to a u64.
3959    pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
3960    where
3961        D: Deserializer<'de>,
3962    {
3963        let s = String::deserialize(deserializer)?;
3964        s.parse::<u64>().map_err(serde::de::Error::custom)
3965    }
3966}
3967
3968mod string_to_float {
3969    use serde::{self, Deserialize, Deserializer, Serializer};
3970
3971    // Serialize a u64 as a string.
3972    pub fn serialize<S>(value: &f64, serializer: S) -> Result<S::Ok, S::Error>
3973    where
3974        S: Serializer,
3975    {
3976        let s = value.to_string();
3977        serializer.serialize_str(&s)
3978    }
3979
3980    // Deserialize a string as an f64.
3981    pub fn deserialize<'de, D>(deserializer: D) -> Result<f64, D::Error>
3982    where
3983        D: Deserializer<'de>,
3984    {
3985        let s = String::deserialize(deserializer)?;
3986        s.parse::<f64>().map_err(serde::de::Error::custom)
3987    }
3988}