Skip to main content

bybit_api/models/
trade.rs

1//! Trade models for orders.
2
3use crate::error::{BybitError, Result};
4use crate::models::common::*;
5use rust_decimal::Decimal;
6use serde::{Deserialize, Serialize};
7
8/// Place order request parameters.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct PlaceOrderParams {
12    /// Product category
13    pub category: Category,
14    /// Symbol name
15    pub symbol: String,
16    /// Order side
17    pub side: Side,
18    /// Order type
19    pub order_type: OrderType,
20    /// Order quantity
21    pub qty: String,
22    /// Order price (required for limit orders)
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub price: Option<String>,
25    /// Time in force
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub time_in_force: Option<TimeInForce>,
28    /// Position index (for hedge mode)
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub position_idx: Option<i32>,
31    /// User-defined order ID
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub order_link_id: Option<String>,
34    /// Take profit price
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub take_profit: Option<String>,
37    /// Stop loss price
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub stop_loss: Option<String>,
40    /// Reduce only flag
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub reduce_only: Option<bool>,
43    /// Close on trigger
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub close_on_trigger: Option<bool>,
46    /// Trigger price
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub trigger_price: Option<String>,
49    /// Trigger price type
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub trigger_by: Option<TriggerBy>,
52}
53
54impl PlaceOrderParams {
55    /// Create a new market order.
56    pub fn market(category: Category, symbol: &str, side: Side, qty: &str) -> Self {
57        Self {
58            category,
59            symbol: symbol.to_string(),
60            side,
61            order_type: OrderType::Market,
62            qty: qty.to_string(),
63            price: None,
64            time_in_force: None,
65            position_idx: None,
66            order_link_id: None,
67            take_profit: None,
68            stop_loss: None,
69            reduce_only: None,
70            close_on_trigger: None,
71            trigger_price: None,
72            trigger_by: None,
73        }
74    }
75
76    /// Create a new limit order.
77    pub fn limit(category: Category, symbol: &str, side: Side, qty: &str, price: &str) -> Self {
78        Self {
79            category,
80            symbol: symbol.to_string(),
81            side,
82            order_type: OrderType::Limit,
83            qty: qty.to_string(),
84            price: Some(price.to_string()),
85            time_in_force: Some(TimeInForce::GTC),
86            position_idx: None,
87            order_link_id: None,
88            take_profit: None,
89            stop_loss: None,
90            reduce_only: None,
91            close_on_trigger: None,
92            trigger_price: None,
93            trigger_by: None,
94        }
95    }
96
97    /// Set position index (for hedge mode).
98    pub fn with_position_idx(mut self, idx: i32) -> Self {
99        self.position_idx = Some(idx);
100        self
101    }
102
103    /// Set user-defined order ID.
104    pub fn with_order_link_id(mut self, id: &str) -> Self {
105        self.order_link_id = Some(id.to_string());
106        self
107    }
108
109    /// Set take profit price.
110    pub fn with_take_profit(mut self, price: &str) -> Self {
111        self.take_profit = Some(price.to_string());
112        self
113    }
114
115    /// Set stop loss price.
116    pub fn with_stop_loss(mut self, price: &str) -> Self {
117        self.stop_loss = Some(price.to_string());
118        self
119    }
120
121    /// Set reduce only flag.
122    pub fn with_reduce_only(mut self, reduce_only: bool) -> Self {
123        self.reduce_only = Some(reduce_only);
124        self
125    }
126
127    /// Validate parameters before sending.
128    pub fn validate(&self) -> Result<()> {
129        if self.symbol.is_empty() {
130            return Err(BybitError::InvalidParam("symbol cannot be empty".into()));
131        }
132
133        if self.qty.is_empty() {
134            return Err(BybitError::InvalidParam("qty cannot be empty".into()));
135        }
136
137        // Parse and validate qty is positive
138        let qty: Decimal = self
139            .qty
140            .parse()
141            .map_err(|_| BybitError::InvalidParam("qty must be a valid number".into()))?;
142        if qty <= Decimal::ZERO {
143            return Err(BybitError::InvalidParam("qty must be positive".into()));
144        }
145
146        // Limit orders require price
147        if self.order_type == OrderType::Limit {
148            match &self.price {
149                None => {
150                    return Err(BybitError::InvalidParam(
151                        "price is required for limit orders".into(),
152                    ))
153                }
154                Some(p) => {
155                    let price: Decimal = p.parse().map_err(|_| {
156                        BybitError::InvalidParam("price must be a valid number".into())
157                    })?;
158                    if price <= Decimal::ZERO {
159                        return Err(BybitError::InvalidParam("price must be positive".into()));
160                    }
161                }
162            }
163        }
164
165        Ok(())
166    }
167}
168
169/// Amend order request parameters.
170#[derive(Debug, Clone, Serialize, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub struct AmendOrderParams {
173    /// Product category
174    pub category: Category,
175    /// Symbol name
176    pub symbol: String,
177    /// Order ID (either order_id or order_link_id required)
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub order_id: Option<String>,
180    /// User-defined order ID
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub order_link_id: Option<String>,
183    /// New order quantity
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub qty: Option<String>,
186    /// New order price
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub price: Option<String>,
189    /// New take profit price
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub take_profit: Option<String>,
192    /// New stop loss price
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub stop_loss: Option<String>,
195}
196
197impl AmendOrderParams {
198    /// Create amend params by order ID.
199    pub fn by_order_id(category: Category, symbol: &str, order_id: &str) -> Self {
200        Self {
201            category,
202            symbol: symbol.to_string(),
203            order_id: Some(order_id.to_string()),
204            order_link_id: None,
205            qty: None,
206            price: None,
207            take_profit: None,
208            stop_loss: None,
209        }
210    }
211
212    /// Create amend params by order link ID.
213    pub fn by_order_link_id(category: Category, symbol: &str, order_link_id: &str) -> Self {
214        Self {
215            category,
216            symbol: symbol.to_string(),
217            order_id: None,
218            order_link_id: Some(order_link_id.to_string()),
219            qty: None,
220            price: None,
221            take_profit: None,
222            stop_loss: None,
223        }
224    }
225
226    /// Set new price.
227    pub fn with_price(mut self, price: &str) -> Self {
228        self.price = Some(price.to_string());
229        self
230    }
231
232    /// Set new quantity.
233    pub fn with_qty(mut self, qty: &str) -> Self {
234        self.qty = Some(qty.to_string());
235        self
236    }
237}
238
239/// Cancel order request parameters.
240#[derive(Debug, Clone, Serialize, Deserialize)]
241#[serde(rename_all = "camelCase")]
242pub struct CancelOrderParams {
243    /// Product category
244    pub category: Category,
245    /// Symbol name
246    pub symbol: String,
247    /// Order ID
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub order_id: Option<String>,
250    /// User-defined order ID
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub order_link_id: Option<String>,
253}
254
255impl CancelOrderParams {
256    /// Create cancel params by order ID.
257    pub fn by_order_id(category: Category, symbol: &str, order_id: &str) -> Self {
258        Self {
259            category,
260            symbol: symbol.to_string(),
261            order_id: Some(order_id.to_string()),
262            order_link_id: None,
263        }
264    }
265
266    /// Create cancel params by order link ID.
267    pub fn by_order_link_id(category: Category, symbol: &str, order_link_id: &str) -> Self {
268        Self {
269            category,
270            symbol: symbol.to_string(),
271            order_id: None,
272            order_link_id: Some(order_link_id.to_string()),
273        }
274    }
275}
276
277/// Cancel all orders request parameters.
278#[derive(Debug, Clone, Serialize, Deserialize)]
279#[serde(rename_all = "camelCase")]
280pub struct CancelAllOrdersParams {
281    /// Product category
282    pub category: Category,
283    /// Symbol name (optional, cancel all if not specified)
284    #[serde(skip_serializing_if = "Option::is_none")]
285    pub symbol: Option<String>,
286    /// Base coin
287    #[serde(skip_serializing_if = "Option::is_none")]
288    pub base_coin: Option<String>,
289    /// Settle coin
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub settle_coin: Option<String>,
292}
293
294/// Order response.
295#[derive(Debug, Clone, Serialize, Deserialize)]
296#[serde(rename_all = "camelCase")]
297pub struct OrderResponse {
298    /// Order ID
299    pub order_id: String,
300    /// User-defined order ID
301    #[serde(default)]
302    pub order_link_id: String,
303}
304
305/// Orders list response.
306#[derive(Debug, Clone, Serialize, Deserialize)]
307#[serde(rename_all = "camelCase")]
308pub struct OrdersList {
309    /// Category
310    pub category: String,
311    /// List of orders
312    pub list: Vec<OrderInfo>,
313    /// Next page cursor
314    #[serde(default)]
315    pub next_page_cursor: String,
316}
317
318/// Order info.
319#[derive(Debug, Clone, Serialize, Deserialize)]
320#[serde(rename_all = "camelCase")]
321pub struct OrderInfo {
322    /// Order ID
323    pub order_id: String,
324    /// User-defined order ID
325    #[serde(default)]
326    pub order_link_id: String,
327    /// Symbol
328    pub symbol: String,
329    /// Side
330    pub side: String,
331    /// Order type
332    pub order_type: String,
333    /// Price
334    #[serde(default)]
335    pub price: String,
336    /// Quantity
337    pub qty: String,
338    /// Time in force
339    #[serde(default)]
340    pub time_in_force: String,
341    /// Order status
342    pub order_status: String,
343    /// Cumulative executed qty
344    #[serde(default)]
345    pub cum_exec_qty: String,
346    /// Cumulative executed value
347    #[serde(default)]
348    pub cum_exec_value: String,
349    /// Average price
350    #[serde(default)]
351    pub avg_price: String,
352    /// Created time
353    pub created_time: String,
354    /// Updated time
355    pub updated_time: String,
356    /// Take profit price
357    #[serde(default)]
358    pub take_profit: String,
359    /// Stop loss price
360    #[serde(default)]
361    pub stop_loss: String,
362    /// Position index
363    #[serde(default)]
364    pub position_idx: i32,
365    /// Reduce only
366    #[serde(default)]
367    pub reduce_only: bool,
368}
369
370/// Batch order request.
371#[derive(Debug, Clone, Serialize, Deserialize)]
372#[serde(rename_all = "camelCase")]
373pub struct BatchOrderRequest {
374    /// Product category
375    pub category: Category,
376    /// List of orders
377    pub request: Vec<PlaceOrderParams>,
378}
379
380/// Batch order response.
381#[derive(Debug, Clone, Serialize, Deserialize)]
382#[serde(rename_all = "camelCase")]
383pub struct BatchOrderResponse {
384    /// List of results
385    pub list: Vec<BatchOrderResult>,
386}
387
388/// Single batch order result.
389#[derive(Debug, Clone, Serialize, Deserialize)]
390#[serde(rename_all = "camelCase")]
391pub struct BatchOrderResult {
392    /// Category
393    pub category: String,
394    /// Symbol
395    pub symbol: String,
396    /// Order ID
397    #[serde(default)]
398    pub order_id: String,
399    /// User-defined order ID
400    #[serde(default)]
401    pub order_link_id: String,
402    /// Create type
403    #[serde(default)]
404    pub create_type: String,
405}
406
407/// Cancel all orders response.
408#[derive(Debug, Clone, Serialize, Deserialize)]
409#[serde(rename_all = "camelCase")]
410pub struct CancelAllResponse {
411    /// List of cancelled orders
412    pub list: Vec<CancelledOrder>,
413}
414
415/// Cancelled order info.
416#[derive(Debug, Clone, Serialize, Deserialize)]
417#[serde(rename_all = "camelCase")]
418pub struct CancelledOrder {
419    /// Order ID
420    pub order_id: String,
421    /// User-defined order ID
422    #[serde(default)]
423    pub order_link_id: String,
424}
425
426pub type DcpSetTimewindowResponse = serde_json::Value;
427
428#[derive(Debug, Clone, Serialize, Deserialize)]
429#[serde(rename_all = "camelCase")]
430pub struct DcpSetTimewindowParams {
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub product: Option<String>,
433    pub time_window: i32,
434}
435
436pub type SetDcpResponse = serde_json::Value;
437
438#[derive(Debug, Clone, Serialize, Deserialize)]
439#[serde(rename_all = "camelCase")]
440pub struct SetDcpParams {
441    #[serde(skip_serializing_if = "Option::is_none")]
442    pub product: Option<String>,
443    pub time_window: i32,
444}
445
446pub type PreCheckOrderResponse = serde_json::Value;
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
449#[serde(rename_all = "camelCase")]
450pub struct PreCheckOrderParams {
451    pub category: String,
452    pub symbol: String,
453    pub side: String,
454    pub order_type: String,
455    pub qty: String,
456    #[serde(skip_serializing_if = "Option::is_none")]
457    pub price: Option<String>,
458    #[serde(skip_serializing_if = "Option::is_none")]
459    pub is_leverage: Option<i32>,
460    #[serde(skip_serializing_if = "Option::is_none")]
461    pub time_in_force: Option<String>,
462    #[serde(skip_serializing_if = "Option::is_none")]
463    pub position_idx: Option<i32>,
464    #[serde(skip_serializing_if = "Option::is_none")]
465    pub order_link_id: Option<String>,
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub take_profit: Option<String>,
468    #[serde(skip_serializing_if = "Option::is_none")]
469    pub stop_loss: Option<String>,
470    #[serde(skip_serializing_if = "Option::is_none")]
471    pub tp_trigger_by: Option<String>,
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub sl_trigger_by: Option<String>,
474    #[serde(skip_serializing_if = "Option::is_none")]
475    pub reduce_only: Option<bool>,
476    #[serde(skip_serializing_if = "Option::is_none")]
477    pub tpsl_mode: Option<String>,
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub tp_limit_price: Option<String>,
480    #[serde(skip_serializing_if = "Option::is_none")]
481    pub sl_limit_price: Option<String>,
482    #[serde(skip_serializing_if = "Option::is_none")]
483    pub tp_order_type: Option<String>,
484    #[serde(skip_serializing_if = "Option::is_none")]
485    pub sl_order_type: Option<String>,
486    #[serde(skip_serializing_if = "Option::is_none")]
487    pub order_iv: Option<String>,
488}
489
490pub type GetSpotBorrowQuotaResponse = SpotBorrowQuotaResult;
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
493#[serde(rename_all = "camelCase")]
494pub struct SpotBorrowQuotaResult {
495    #[serde(skip_serializing_if = "Option::is_none")]
496    pub symbol: Option<String>,
497    #[serde(skip_serializing_if = "Option::is_none")]
498    pub side: Option<String>,
499    #[serde(skip_serializing_if = "Option::is_none")]
500    pub max_trade_qty: Option<String>,
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub max_trade_amount: Option<String>,
503    #[serde(skip_serializing_if = "Option::is_none")]
504    pub spot_max_trade_qty: Option<String>,
505    #[serde(skip_serializing_if = "Option::is_none")]
506    pub spot_max_trade_amount: Option<String>,
507    #[serde(skip_serializing_if = "Option::is_none")]
508    pub borrow_coin: Option<String>,
509}
510
511pub type AmendOrderResponse = AmendOrderResult;
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
514#[serde(rename_all = "camelCase")]
515pub struct AmendOrderResult {
516    #[serde(skip_serializing_if = "Option::is_none")]
517    pub order_id: Option<String>,
518    #[serde(skip_serializing_if = "Option::is_none")]
519    pub order_link_id: Option<String>,
520}
521
522#[derive(Debug, Clone, Serialize, Deserialize)]
523#[serde(rename_all = "camelCase")]
524pub struct BatchAmendOrdersRequest {
525    pub category: String,
526    pub request: Vec<BatchAmendOrderItem>,
527}
528
529#[derive(Debug, Clone, Serialize, Deserialize)]
530#[serde(rename_all = "camelCase")]
531pub struct BatchAmendOrderItem {
532    pub symbol: String,
533    #[serde(skip_serializing_if = "Option::is_none")]
534    pub order_id: Option<String>,
535    #[serde(skip_serializing_if = "Option::is_none")]
536    pub order_link_id: Option<String>,
537    #[serde(skip_serializing_if = "Option::is_none")]
538    pub qty: Option<String>,
539    #[serde(skip_serializing_if = "Option::is_none")]
540    pub price: Option<String>,
541    #[serde(skip_serializing_if = "Option::is_none")]
542    pub order_iv: Option<String>,
543    #[serde(skip_serializing_if = "Option::is_none")]
544    pub trigger_price: Option<String>,
545    #[serde(skip_serializing_if = "Option::is_none")]
546    pub tpsl_mode: Option<String>,
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub take_profit: Option<String>,
549    #[serde(skip_serializing_if = "Option::is_none")]
550    pub stop_loss: Option<String>,
551    #[serde(skip_serializing_if = "Option::is_none")]
552    pub tp_trigger_by: Option<String>,
553    #[serde(skip_serializing_if = "Option::is_none")]
554    pub sl_trigger_by: Option<String>,
555    #[serde(skip_serializing_if = "Option::is_none")]
556    pub trigger_by: Option<String>,
557    #[serde(skip_serializing_if = "Option::is_none")]
558    pub tp_limit_price: Option<String>,
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub sl_limit_price: Option<String>,
561}
562
563pub type BatchAmendOrdersResponse = serde_json::Value;
564
565#[derive(Debug, Clone, Serialize, Deserialize)]
566#[serde(rename_all = "camelCase")]
567pub struct BatchCancelOrdersRequest {
568    pub category: String,
569    pub request: Vec<BatchCancelOrderItem>,
570}
571
572#[derive(Debug, Clone, Serialize, Deserialize)]
573#[serde(rename_all = "camelCase")]
574pub struct BatchCancelOrderItem {
575    pub symbol: String,
576    #[serde(skip_serializing_if = "Option::is_none")]
577    pub order_id: Option<String>,
578    #[serde(skip_serializing_if = "Option::is_none")]
579    pub order_link_id: Option<String>,
580}
581
582pub type BatchCancelOrdersResponse = serde_json::Value;
583
584#[derive(Debug, Clone, Serialize, Deserialize)]
585#[serde(rename_all = "camelCase")]
586pub struct BatchCreateOrdersRequest {
587    pub category: String,
588    pub request: Vec<BatchOrderItem>,
589}
590
591#[derive(Debug, Clone, Serialize, Deserialize)]
592#[serde(rename_all = "camelCase")]
593pub struct BatchOrderItem {
594    pub symbol: String,
595    pub side: String,
596    pub order_type: String,
597    pub qty: String,
598    #[serde(skip_serializing_if = "Option::is_none")]
599    pub price: Option<String>,
600    #[serde(skip_serializing_if = "Option::is_none")]
601    pub is_leverage: Option<i32>,
602    #[serde(skip_serializing_if = "Option::is_none")]
603    pub market_unit: Option<String>,
604    #[serde(skip_serializing_if = "Option::is_none")]
605    pub time_in_force: Option<String>,
606    #[serde(skip_serializing_if = "Option::is_none")]
607    pub trigger_direction: Option<i32>,
608    #[serde(skip_serializing_if = "Option::is_none")]
609    pub order_filter: Option<String>,
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub trigger_price: Option<String>,
612    #[serde(skip_serializing_if = "Option::is_none")]
613    pub trigger_by: Option<String>,
614    #[serde(skip_serializing_if = "Option::is_none")]
615    pub order_iv: Option<String>,
616    #[serde(skip_serializing_if = "Option::is_none")]
617    pub position_idx: Option<i32>,
618    #[serde(skip_serializing_if = "Option::is_none")]
619    pub order_link_id: Option<String>,
620    #[serde(skip_serializing_if = "Option::is_none")]
621    pub take_profit: Option<String>,
622    #[serde(skip_serializing_if = "Option::is_none")]
623    pub stop_loss: Option<String>,
624    #[serde(skip_serializing_if = "Option::is_none")]
625    pub tp_trigger_by: Option<String>,
626    #[serde(skip_serializing_if = "Option::is_none")]
627    pub sl_trigger_by: Option<String>,
628    #[serde(skip_serializing_if = "Option::is_none")]
629    pub tpsl_mode: Option<String>,
630    #[serde(skip_serializing_if = "Option::is_none")]
631    pub tp_order_type: Option<String>,
632    #[serde(skip_serializing_if = "Option::is_none")]
633    pub sl_order_type: Option<String>,
634    #[serde(skip_serializing_if = "Option::is_none")]
635    pub tp_limit_price: Option<String>,
636    #[serde(skip_serializing_if = "Option::is_none")]
637    pub sl_limit_price: Option<String>,
638    #[serde(skip_serializing_if = "Option::is_none")]
639    pub reduce_only: Option<bool>,
640    #[serde(skip_serializing_if = "Option::is_none")]
641    pub close_on_trigger: Option<bool>,
642    #[serde(skip_serializing_if = "Option::is_none")]
643    pub smp_type: Option<String>,
644    #[serde(skip_serializing_if = "Option::is_none")]
645    pub mmp: Option<bool>,
646}
647
648pub type BatchCreateOrdersResponse = serde_json::Value;
649
650pub type CancelAllOrdersResponse = serde_json::Value;
651
652#[derive(Debug, Clone, Serialize, Deserialize)]
653#[serde(rename_all = "camelCase")]
654pub struct CancelAllOrdersRequest {
655    pub category: String,
656    #[serde(skip_serializing_if = "Option::is_none")]
657    pub symbol: Option<String>,
658    #[serde(skip_serializing_if = "Option::is_none")]
659    pub base_coin: Option<String>,
660    #[serde(skip_serializing_if = "Option::is_none")]
661    pub settle_coin: Option<String>,
662    #[serde(skip_serializing_if = "Option::is_none")]
663    pub order_filter: Option<String>,
664    #[serde(skip_serializing_if = "Option::is_none")]
665    pub stop_order_type: Option<String>,
666}
667
668#[derive(Debug, Clone, Serialize, Deserialize)]
669#[serde(rename_all = "camelCase")]
670pub struct CancelOrderRequest {
671    pub category: String,
672    pub symbol: String,
673    #[serde(skip_serializing_if = "Option::is_none")]
674    pub order_id: Option<String>,
675    #[serde(skip_serializing_if = "Option::is_none")]
676    pub order_link_id: Option<String>,
677    #[serde(skip_serializing_if = "Option::is_none")]
678    pub order_filter: Option<String>,
679}
680
681pub type CancelOrderResponse = serde_json::Value;
682
683#[derive(Debug, Clone, Serialize, Deserialize)]
684#[serde(rename_all = "camelCase")]
685pub struct CreateOrderRequest {
686    pub category: String,
687    pub symbol: String,
688    #[serde(skip_serializing_if = "Option::is_none")]
689    pub is_leverage: Option<i32>,
690    pub side: String,
691    pub order_type: String,
692    pub qty: String,
693    #[serde(skip_serializing_if = "Option::is_none")]
694    pub market_unit: Option<String>,
695    #[serde(skip_serializing_if = "Option::is_none")]
696    pub slippage_tolerance_type: Option<String>,
697    #[serde(skip_serializing_if = "Option::is_none")]
698    pub slippage_tolerance: Option<String>,
699    #[serde(skip_serializing_if = "Option::is_none")]
700    pub price: Option<String>,
701    #[serde(skip_serializing_if = "Option::is_none")]
702    pub trigger_direction: Option<i32>,
703    #[serde(skip_serializing_if = "Option::is_none")]
704    pub order_filter: Option<String>,
705    #[serde(skip_serializing_if = "Option::is_none")]
706    pub trigger_price: Option<String>,
707    #[serde(skip_serializing_if = "Option::is_none")]
708    pub trigger_by: Option<String>,
709    #[serde(skip_serializing_if = "Option::is_none")]
710    pub order_iv: Option<String>,
711    #[serde(skip_serializing_if = "Option::is_none")]
712    pub time_in_force: Option<String>,
713    #[serde(skip_serializing_if = "Option::is_none")]
714    pub position_idx: Option<i32>,
715    #[serde(skip_serializing_if = "Option::is_none")]
716    pub order_link_id: Option<String>,
717    #[serde(skip_serializing_if = "Option::is_none")]
718    pub take_profit: Option<String>,
719    #[serde(skip_serializing_if = "Option::is_none")]
720    pub stop_loss: Option<String>,
721    #[serde(skip_serializing_if = "Option::is_none")]
722    pub tp_trigger_by: Option<String>,
723    #[serde(skip_serializing_if = "Option::is_none")]
724    pub sl_trigger_by: Option<String>,
725    #[serde(skip_serializing_if = "Option::is_none")]
726    pub reduce_only: Option<bool>,
727    #[serde(skip_serializing_if = "Option::is_none")]
728    pub close_on_trigger: Option<bool>,
729    #[serde(skip_serializing_if = "Option::is_none")]
730    pub smp_type: Option<String>,
731    #[serde(skip_serializing_if = "Option::is_none")]
732    pub mmp: Option<bool>,
733    #[serde(skip_serializing_if = "Option::is_none")]
734    pub tpsl_mode: Option<String>,
735    #[serde(skip_serializing_if = "Option::is_none")]
736    pub tp_limit_price: Option<String>,
737    #[serde(skip_serializing_if = "Option::is_none")]
738    pub sl_limit_price: Option<String>,
739    #[serde(skip_serializing_if = "Option::is_none")]
740    pub tp_order_type: Option<String>,
741    #[serde(skip_serializing_if = "Option::is_none")]
742    pub sl_order_type: Option<String>,
743    #[serde(skip_serializing_if = "Option::is_none")]
744    pub bbo_side_type: Option<String>,
745    #[serde(skip_serializing_if = "Option::is_none")]
746    pub bbo_level: Option<String>,
747    #[serde(skip_serializing_if = "Option::is_none")]
748    pub rpi_taker_access: Option<bool>,
749}
750
751pub type CreateOrderResponse = serde_json::Value;
752
753pub type GetOpenOrdersResponse = serde_json::Value;
754
755#[derive(Debug, Clone, Serialize, Deserialize)]
756#[serde(rename_all = "camelCase")]
757pub struct OrderDetail {
758    #[serde(skip_serializing_if = "Option::is_none")]
759    pub order_id: Option<String>,
760    #[serde(skip_serializing_if = "Option::is_none")]
761    pub order_link_id: Option<String>,
762    #[serde(skip_serializing_if = "Option::is_none")]
763    pub parent_order_link_id: Option<String>,
764    #[serde(skip_serializing_if = "Option::is_none")]
765    pub block_trade_id: Option<String>,
766    #[serde(skip_serializing_if = "Option::is_none")]
767    pub symbol: Option<String>,
768    #[serde(skip_serializing_if = "Option::is_none")]
769    pub price: Option<String>,
770    #[serde(skip_serializing_if = "Option::is_none")]
771    pub qty: Option<String>,
772    #[serde(skip_serializing_if = "Option::is_none")]
773    pub side: Option<String>,
774    #[serde(skip_serializing_if = "Option::is_none")]
775    pub is_leverage: Option<String>,
776    #[serde(skip_serializing_if = "Option::is_none")]
777    pub position_idx: Option<i32>,
778    #[serde(skip_serializing_if = "Option::is_none")]
779    pub order_status: Option<String>,
780    #[serde(skip_serializing_if = "Option::is_none")]
781    pub cancel_type: Option<String>,
782    #[serde(skip_serializing_if = "Option::is_none")]
783    pub reject_reason: Option<String>,
784    #[serde(skip_serializing_if = "Option::is_none")]
785    pub avg_price: Option<String>,
786    #[serde(skip_serializing_if = "Option::is_none")]
787    pub leaves_qty: Option<String>,
788    #[serde(skip_serializing_if = "Option::is_none")]
789    pub leaves_value: Option<String>,
790    #[serde(skip_serializing_if = "Option::is_none")]
791    pub cum_exec_qty: Option<String>,
792    #[serde(skip_serializing_if = "Option::is_none")]
793    pub cum_exec_value: Option<String>,
794    #[serde(skip_serializing_if = "Option::is_none")]
795    pub cum_exec_fee: Option<String>,
796    #[serde(skip_serializing_if = "Option::is_none")]
797    pub time_in_force: Option<String>,
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub order_type: Option<String>,
800    #[serde(skip_serializing_if = "Option::is_none")]
801    pub stop_order_type: Option<String>,
802    #[serde(skip_serializing_if = "Option::is_none")]
803    pub order_iv: Option<String>,
804    #[serde(skip_serializing_if = "Option::is_none")]
805    pub market_unit: Option<String>,
806    #[serde(skip_serializing_if = "Option::is_none")]
807    pub trigger_price: Option<String>,
808    #[serde(skip_serializing_if = "Option::is_none")]
809    pub take_profit: Option<String>,
810    #[serde(skip_serializing_if = "Option::is_none")]
811    pub stop_loss: Option<String>,
812    #[serde(skip_serializing_if = "Option::is_none")]
813    pub tpsl_mode: Option<String>,
814    #[serde(skip_serializing_if = "Option::is_none")]
815    pub tp_limit_price: Option<String>,
816    #[serde(skip_serializing_if = "Option::is_none")]
817    pub sl_limit_price: Option<String>,
818    #[serde(skip_serializing_if = "Option::is_none")]
819    pub tp_trigger_by: Option<String>,
820    #[serde(skip_serializing_if = "Option::is_none")]
821    pub sl_trigger_by: Option<String>,
822    #[serde(skip_serializing_if = "Option::is_none")]
823    pub trigger_direction: Option<i32>,
824    #[serde(skip_serializing_if = "Option::is_none")]
825    pub trigger_by: Option<String>,
826    #[serde(skip_serializing_if = "Option::is_none")]
827    pub last_price_on_created: Option<String>,
828    #[serde(skip_serializing_if = "Option::is_none")]
829    pub reduce_only: Option<bool>,
830    #[serde(skip_serializing_if = "Option::is_none")]
831    pub close_on_trigger: Option<bool>,
832    #[serde(skip_serializing_if = "Option::is_none")]
833    pub place_type: Option<String>,
834    #[serde(skip_serializing_if = "Option::is_none")]
835    pub smp_type: Option<String>,
836    #[serde(skip_serializing_if = "Option::is_none")]
837    pub smp_group: Option<i32>,
838    #[serde(skip_serializing_if = "Option::is_none")]
839    pub smp_order_id: Option<String>,
840    #[serde(skip_serializing_if = "Option::is_none")]
841    pub create_type: Option<String>,
842    #[serde(skip_serializing_if = "Option::is_none")]
843    pub oco_trigger_by: Option<String>,
844    #[serde(skip_serializing_if = "Option::is_none")]
845    pub base_price: Option<String>,
846    // FIXME(typed-field): falls back to `serde_json::Value` because the Bybit
847    // spec did not provide a matching inner type at generation time. Replace
848    // with a typed struct in a follow-up PR after consulting the V5 docs.
849    #[serde(skip_serializing_if = "Option::is_none")]
850    pub cum_fee_detail: Option<serde_json::Value>,
851    #[serde(skip_serializing_if = "Option::is_none")]
852    pub created_time: Option<String>,
853    #[serde(skip_serializing_if = "Option::is_none")]
854    pub updated_time: Option<String>,
855}
856
857pub type GetOrderHistoryResponse = serde_json::Value;
858
859#[derive(Debug, Clone, Serialize, Deserialize)]
860#[serde(rename_all = "camelCase")]
861pub struct OrderHistoryDetail {
862    #[serde(skip_serializing_if = "Option::is_none")]
863    pub order_id: Option<String>,
864    #[serde(skip_serializing_if = "Option::is_none")]
865    pub order_link_id: Option<String>,
866    #[serde(skip_serializing_if = "Option::is_none")]
867    pub parent_order_link_id: Option<String>,
868    #[serde(skip_serializing_if = "Option::is_none")]
869    pub block_trade_id: Option<String>,
870    #[serde(skip_serializing_if = "Option::is_none")]
871    pub symbol: Option<String>,
872    #[serde(skip_serializing_if = "Option::is_none")]
873    pub is_leverage: Option<String>,
874    #[serde(skip_serializing_if = "Option::is_none")]
875    pub position_idx: Option<i32>,
876    #[serde(skip_serializing_if = "Option::is_none")]
877    pub price: Option<String>,
878    #[serde(skip_serializing_if = "Option::is_none")]
879    pub qty: Option<String>,
880    #[serde(skip_serializing_if = "Option::is_none")]
881    pub side: Option<String>,
882    #[serde(skip_serializing_if = "Option::is_none")]
883    pub order_status: Option<String>,
884    #[serde(skip_serializing_if = "Option::is_none")]
885    pub create_type: Option<String>,
886    #[serde(skip_serializing_if = "Option::is_none")]
887    pub cancel_type: Option<String>,
888    #[serde(skip_serializing_if = "Option::is_none")]
889    pub reject_reason: Option<String>,
890    #[serde(skip_serializing_if = "Option::is_none")]
891    pub avg_price: Option<String>,
892    #[serde(skip_serializing_if = "Option::is_none")]
893    pub cum_exec_qty: Option<String>,
894    #[serde(skip_serializing_if = "Option::is_none")]
895    pub cum_exec_value: Option<String>,
896    #[serde(skip_serializing_if = "Option::is_none")]
897    pub cum_exec_fee: Option<String>,
898    #[serde(skip_serializing_if = "Option::is_none")]
899    pub leaves_qty: Option<String>,
900    #[serde(skip_serializing_if = "Option::is_none")]
901    pub leaves_value: Option<String>,
902    #[serde(skip_serializing_if = "Option::is_none")]
903    pub order_type: Option<String>,
904    #[serde(skip_serializing_if = "Option::is_none")]
905    pub stop_order_type: Option<String>,
906    #[serde(skip_serializing_if = "Option::is_none")]
907    pub order_iv: Option<String>,
908    #[serde(skip_serializing_if = "Option::is_none")]
909    pub market_unit: Option<String>,
910    #[serde(skip_serializing_if = "Option::is_none")]
911    pub time_in_force: Option<String>,
912    #[serde(skip_serializing_if = "Option::is_none")]
913    pub trigger_price: Option<String>,
914    #[serde(skip_serializing_if = "Option::is_none")]
915    pub take_profit: Option<String>,
916    #[serde(skip_serializing_if = "Option::is_none")]
917    pub stop_loss: Option<String>,
918    #[serde(skip_serializing_if = "Option::is_none")]
919    pub tpsl_mode: Option<String>,
920    #[serde(skip_serializing_if = "Option::is_none")]
921    pub tp_limit_price: Option<String>,
922    #[serde(skip_serializing_if = "Option::is_none")]
923    pub sl_limit_price: Option<String>,
924    #[serde(skip_serializing_if = "Option::is_none")]
925    pub tp_trigger_by: Option<String>,
926    #[serde(skip_serializing_if = "Option::is_none")]
927    pub sl_trigger_by: Option<String>,
928    #[serde(skip_serializing_if = "Option::is_none")]
929    pub trigger_direction: Option<i32>,
930    #[serde(skip_serializing_if = "Option::is_none")]
931    pub trigger_by: Option<String>,
932    #[serde(skip_serializing_if = "Option::is_none")]
933    pub last_price_on_created: Option<String>,
934    #[serde(skip_serializing_if = "Option::is_none")]
935    pub reduce_only: Option<bool>,
936    #[serde(skip_serializing_if = "Option::is_none")]
937    pub close_on_trigger: Option<bool>,
938    #[serde(skip_serializing_if = "Option::is_none")]
939    pub place_type: Option<String>,
940    #[serde(skip_serializing_if = "Option::is_none")]
941    pub smp_type: Option<String>,
942    #[serde(skip_serializing_if = "Option::is_none")]
943    pub smp_group: Option<i32>,
944    #[serde(skip_serializing_if = "Option::is_none")]
945    pub smp_order_id: Option<String>,
946    #[serde(skip_serializing_if = "Option::is_none")]
947    pub rpi_taker_access: Option<bool>,
948    #[serde(skip_serializing_if = "Option::is_none")]
949    pub rpi_matched_qty: Option<String>,
950    #[serde(skip_serializing_if = "Option::is_none")]
951    pub oco_trigger_by: Option<String>,
952    #[serde(skip_serializing_if = "Option::is_none")]
953    pub base_price: Option<String>,
954    #[serde(skip_serializing_if = "Option::is_none")]
955    pub slippage_tolerance_type: Option<String>,
956    #[serde(skip_serializing_if = "Option::is_none")]
957    pub slippage_tolerance: Option<String>,
958    // FIXME(typed-field): falls back to `serde_json::Value` because the Bybit
959    // spec did not provide a matching inner type at generation time. Replace
960    // with a typed struct in a follow-up PR after consulting the V5 docs.
961    #[serde(skip_serializing_if = "Option::is_none")]
962    pub cum_fee_detail: Option<serde_json::Value>,
963    #[serde(skip_serializing_if = "Option::is_none")]
964    pub extra_fees: Option<String>,
965    #[serde(skip_serializing_if = "Option::is_none")]
966    pub created_time: Option<String>,
967    #[serde(skip_serializing_if = "Option::is_none")]
968    pub updated_time: Option<String>,
969}
970
971#[derive(Debug, Clone, Serialize, Deserialize)]
972#[serde(rename_all = "camelCase")]
973pub struct TradeExecutionDetail {
974    #[serde(skip_serializing_if = "Option::is_none")]
975    pub symbol: Option<String>,
976    #[serde(skip_serializing_if = "Option::is_none")]
977    pub order_id: Option<String>,
978    #[serde(skip_serializing_if = "Option::is_none")]
979    pub order_link_id: Option<String>,
980    #[serde(skip_serializing_if = "Option::is_none")]
981    pub side: Option<String>,
982    #[serde(skip_serializing_if = "Option::is_none")]
983    pub order_price: Option<String>,
984    #[serde(skip_serializing_if = "Option::is_none")]
985    pub order_qty: Option<String>,
986    #[serde(skip_serializing_if = "Option::is_none")]
987    pub leaves_qty: Option<String>,
988    #[serde(skip_serializing_if = "Option::is_none")]
989    pub create_type: Option<String>,
990    #[serde(skip_serializing_if = "Option::is_none")]
991    pub order_type: Option<String>,
992    #[serde(skip_serializing_if = "Option::is_none")]
993    pub stop_order_type: Option<String>,
994    #[serde(skip_serializing_if = "Option::is_none")]
995    pub exec_fee: Option<String>,
996    #[serde(skip_serializing_if = "Option::is_none")]
997    pub exec_fee_v2: Option<String>,
998    #[serde(skip_serializing_if = "Option::is_none")]
999    pub exec_id: Option<String>,
1000    #[serde(skip_serializing_if = "Option::is_none")]
1001    pub exec_price: Option<String>,
1002    #[serde(skip_serializing_if = "Option::is_none")]
1003    pub exec_qty: Option<String>,
1004    #[serde(skip_serializing_if = "Option::is_none")]
1005    pub exec_type: Option<String>,
1006    #[serde(skip_serializing_if = "Option::is_none")]
1007    pub exec_value: Option<String>,
1008    #[serde(skip_serializing_if = "Option::is_none")]
1009    pub exec_time: Option<String>,
1010    #[serde(skip_serializing_if = "Option::is_none")]
1011    pub fee_currency: Option<String>,
1012    #[serde(skip_serializing_if = "Option::is_none")]
1013    pub is_maker: Option<bool>,
1014    #[serde(skip_serializing_if = "Option::is_none")]
1015    pub fee_rate: Option<String>,
1016    #[serde(skip_serializing_if = "Option::is_none")]
1017    pub trade_iv: Option<String>,
1018    #[serde(skip_serializing_if = "Option::is_none")]
1019    pub mark_iv: Option<String>,
1020    #[serde(skip_serializing_if = "Option::is_none")]
1021    pub mark_price: Option<String>,
1022    #[serde(skip_serializing_if = "Option::is_none")]
1023    pub index_price: Option<String>,
1024    #[serde(skip_serializing_if = "Option::is_none")]
1025    pub underlying_price: Option<String>,
1026    #[serde(skip_serializing_if = "Option::is_none")]
1027    pub block_trade_id: Option<String>,
1028    #[serde(skip_serializing_if = "Option::is_none")]
1029    pub closed_size: Option<String>,
1030    #[serde(skip_serializing_if = "Option::is_none")]
1031    pub seq: Option<i64>,
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub extra_fees: Option<String>,
1034}
1035
1036#[derive(Debug, Clone, Serialize, Deserialize)]
1037#[serde(rename_all = "camelCase")]
1038pub struct PreCheckOrderResult {
1039    #[serde(skip_serializing_if = "Option::is_none")]
1040    pub order_id: Option<String>,
1041    #[serde(skip_serializing_if = "Option::is_none")]
1042    pub order_link_id: Option<String>,
1043    #[serde(skip_serializing_if = "Option::is_none")]
1044    pub pre_imr_e4: Option<i64>,
1045    #[serde(skip_serializing_if = "Option::is_none")]
1046    pub pre_mmr_e4: Option<i64>,
1047    #[serde(skip_serializing_if = "Option::is_none")]
1048    pub post_imr_e4: Option<i64>,
1049    #[serde(skip_serializing_if = "Option::is_none")]
1050    pub post_mmr_e4: Option<i64>,
1051}