bybit_async/models/
mod.rs

1use crate::parser::string_or;
2use crate::parser::string_or_decimal;
3use crate::parser::string_or_decimal_opt;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6
7pub mod market;
8pub mod order;
9
10#[derive(Copy, Clone, Debug)]
11pub enum Product {
12    Spot,
13    UsdMFutures,
14    CoinMFutures,
15    EuropeanOptions,
16}
17
18#[derive(Serialize, Deserialize, Default, Clone)]
19#[serde(rename_all = "camelCase")]
20pub struct ServerTime {
21    pub server_time: u64,
22}
23
24#[derive(Serialize, Deserialize, Clone, Debug)]
25pub enum Side {
26    Buy,
27    Sell,
28}
29
30impl Default for Side {
31    fn default() -> Self {
32        Self::Buy
33    }
34}
35
36#[derive(Serialize, Deserialize, Clone, Debug)]
37pub enum TimeInForce {
38    GTC,
39    IOC,
40    FOK,
41    PostOnly,
42}
43
44impl Default for TimeInForce {
45    fn default() -> Self {
46        Self::GTC
47    }
48}
49
50#[derive(Serialize, Deserialize, Clone, Debug)]
51#[allow(non_camel_case_types)]
52pub enum OrderType {
53    Market,
54    Limit,
55    TakeProfit,
56    StopLoss,
57    TrailingStop,
58    Stop,
59    PartialTakeProfit,
60    PartialStopLoss,
61    tpslOrder,
62    OcoOrder,
63    MmRateClose,
64    BidirectionalTpslOrder,
65}
66
67impl Default for OrderType {
68    fn default() -> Self {
69        OrderType::Market
70    }
71}
72
73// {
74//       "filterType": "LOT_SIZE",
75//       "minQty": "0.00100000",
76//       "maxQty": "100000.00000000",
77//       "stepSize": "0.00100000"
78//     }
79#[derive(Debug, Serialize, Deserialize, Clone)]
80#[serde(tag = "filterType", rename_all = "SCREAMING_SNAKE_CASE")]
81pub enum Filter {
82    #[serde(rename = "PRICE_FILTER")]
83    #[serde(rename_all = "camelCase")]
84    PriceFilter {
85        #[serde(with = "string_or_decimal")]
86        min_price: Decimal,
87        #[serde(with = "string_or_decimal")]
88        max_price: Decimal,
89        #[serde(with = "string_or_decimal")]
90        tick_size: Decimal,
91    },
92    #[serde(rename = "PERCENT_PRICE")]
93    #[serde(rename_all = "camelCase")]
94    PercentPrice {
95        #[serde(with = "string_or_decimal")]
96        multiplier_up: Decimal,
97        #[serde(with = "string_or_decimal")]
98        multiplier_down: Decimal,
99        avg_price_mins: Option<f64>,
100    },
101    #[serde(rename = "PERCENT_PRICE_BY_SIDE")]
102    #[serde(rename_all = "camelCase")]
103    PercentPriceBySide {
104        #[serde(with = "string_or_decimal")]
105        bid_multiplier_up: Decimal,
106        #[serde(with = "string_or_decimal")]
107        bid_multiplier_down: Decimal,
108        #[serde(with = "string_or_decimal")]
109        ask_multiplier_up: Decimal,
110        #[serde(with = "string_or_decimal")]
111        ask_multiplier_down: Decimal,
112        avg_price_mins: Option<f64>,
113    },
114    #[serde(rename = "LOT_SIZE")]
115    #[serde(rename_all = "camelCase")]
116    LotSize {
117        #[serde(with = "string_or_decimal")]
118        min_qty: Decimal,
119        #[serde(with = "string_or_decimal")]
120        max_qty: Decimal,
121        #[serde(with = "string_or_decimal")]
122        step_size: Decimal,
123    },
124    #[serde(rename = "MIN_NOTIONAL")]
125    #[serde(rename_all = "camelCase")]
126    MinNotional {
127        #[serde(default, with = "string_or_decimal_opt")]
128        notional: Option<Decimal>,
129        #[serde(default, with = "string_or_decimal_opt")]
130        min_notional: Option<Decimal>,
131        apply_to_market: Option<bool>,
132        avg_price_mins: Option<f64>,
133    },
134    #[serde(rename = "NOTIONAL")]
135    #[serde(rename_all = "camelCase")]
136    Notional {
137        #[serde(default, with = "string_or_decimal_opt")]
138        notional: Option<Decimal>,
139        #[serde(default, with = "string_or_decimal_opt")]
140        min_notional: Option<Decimal>,
141        apply_to_market: Option<bool>,
142        avg_price_mins: Option<f64>,
143    },
144    #[serde(rename = "ICEBERG_PARTS")]
145    #[serde(rename_all = "camelCase")]
146    IcebergParts { limit: Option<u16> },
147    #[serde(rename = "MAX_NUM_ORDERS")]
148    #[serde(rename_all = "camelCase")]
149    MaxNumOrders { max_num_orders: Option<u16> },
150    #[serde(rename = "MAX_NUM_ALGO_ORDERS")]
151    #[serde(rename_all = "camelCase")]
152    MaxNumAlgoOrders { max_num_algo_orders: Option<u16> },
153    #[serde(rename = "MAX_NUM_ICEBERG_ORDERS")]
154    #[serde(rename_all = "camelCase")]
155    MaxNumIcebergOrders { max_num_iceberg_orders: u16 },
156    #[serde(rename = "MAX_POSITION")]
157    #[serde(rename_all = "camelCase")]
158    MaxPosition { max_position: String },
159    #[serde(rename = "MARKET_LOT_SIZE")]
160    #[serde(rename_all = "camelCase")]
161    MarketLotSize {
162        #[serde(with = "string_or_decimal")]
163        min_qty: Decimal,
164        #[serde(with = "string_or_decimal")]
165        max_qty: Decimal,
166        #[serde(with = "string_or_decimal")]
167        step_size: Decimal,
168    },
169    #[serde(rename = "TRAILING_DELTA")]
170    #[serde(rename_all = "camelCase")]
171    TrailingData {
172        min_trailing_above_delta: Option<u16>,
173        max_trailing_above_delta: Option<u16>,
174        min_trailing_below_delta: Option<u16>,
175        max_trailing_below_delta: Option<u16>,
176    },
177}
178
179#[derive(Serialize, Deserialize, Clone, Debug)]
180pub enum OrderStatus {
181    New,
182    PartiallyFilled,
183    Filled,
184    Cancelled,
185    PendingCancel,
186    Rejected,
187    Expired,
188}
189
190#[derive(Serialize, Deserialize, Clone, Debug)]
191#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
192pub enum ExecutionType {
193    /// The order has been accepted into the engine.
194    New,
195    /// The order has been canceled by the user.
196    Canceled,
197    /// Liquidation Execution (Futures only)
198    Calculated,
199    /// (currently unused)
200    Replaced,
201    /// The order has been rejected and was not processed (This message appears only with Cancel Replace Orders wherein the new order placement is rejected but the request to cancel request succeeds.)
202    Rejected,
203    /// Part of the order or all of the order's quantity has filled.
204    Trade,
205    /// The order was canceled according to the order type's rules (e.g. LIMIT FOK orders with no fill, LIMIT IOC or MARKET orders that partially fill) or by the exchange, (e.g. orders canceled during liquidation, orders canceled during maintenance).
206    Expired,
207    /// The order has expired due to STP trigger.
208    TradePrevention,
209}
210
211// {
212//       "rateLimitType": "ORDERS",
213//       "interval": "DAY",
214//       "limit": 100000
215//     }
216#[derive(Debug, Serialize, Deserialize, Clone)]
217#[serde(rename_all = "camelCase")]
218pub struct RateLimit {
219    pub rate_limit_type: RateLimitType,
220    pub interval: Interval,
221    pub limit: u64,
222}
223
224#[derive(Debug, Serialize, Deserialize, Clone)]
225#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
226pub enum RateLimitType {
227    Orders,
228    RequestWeight,
229}
230
231#[derive(Debug, Serialize, Deserialize, Clone)]
232#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
233pub enum Interval {
234    Second,
235    Minute,
236    Day,
237}
238
239#[derive(Deserialize, Serialize, Debug, Default, Clone)]
240#[serde(rename_all = "camelCase")]
241pub struct AssetInformation {
242    asset: String,
243    margin_available: bool,
244    auto_asset_exchange: String,
245}
246
247#[derive(Deserialize, Serialize, Debug, Clone)]
248#[serde(rename_all = "lowercase")]
249pub enum OrderBookType {
250    Snapshot,
251    Delta,
252}
253#[derive(Debug, Serialize, Deserialize, Clone)]
254#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
255pub enum AccountType {
256    Spot,
257}
258
259#[derive(Debug, Serialize, Deserialize, Clone)]
260#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
261pub enum Permission {
262    Spot,
263}
264
265#[derive(Debug, Serialize, Deserialize, Clone)]
266#[serde(rename_all = "camelCase")]
267pub struct AccountInformation {
268    pub maker_commission: f32,
269    pub taker_commission: f32,
270    pub buyer_commission: f32,
271    pub seller_commission: f32,
272    pub can_trade: bool,
273    pub can_withdraw: bool,
274    pub can_deposit: bool,
275    pub brokered: bool,
276    pub require_self_trade_prevention: bool,
277    pub update_time: u64,
278    pub account_type: AccountType,
279    pub permissions: Vec<Permission>,
280    pub balances: Vec<Balance>,
281}
282
283#[derive(Debug, Serialize, Deserialize, Clone)]
284#[serde(rename_all = "camelCase")]
285pub struct Balance {
286    pub asset: String,
287    #[serde(with = "string_or_decimal")]
288    pub free: Decimal,
289    #[serde(with = "string_or_decimal")]
290    pub locked: Decimal,
291}
292
293#[derive(Debug, Serialize, Deserialize, Clone)]
294pub struct Bids {
295    #[serde(with = "string_or_decimal")]
296    pub price: Decimal,
297    #[serde(with = "string_or_decimal")]
298    pub qty: Decimal,
299
300    // Never serialized.
301    #[serde(skip_serializing, rename = "ignore")]
302    _ignore: Vec<String>,
303}
304
305#[derive(Debug, Serialize, Deserialize, Clone)]
306pub struct Asks {
307    #[serde(with = "string_or_decimal")]
308    pub price: Decimal,
309    #[serde(with = "string_or_decimal")]
310    pub qty: Decimal,
311
312    // Never serialized.
313    #[serde(skip_serializing, rename = "ignore")]
314    _ignore: Vec<String>,
315}
316
317#[derive(Debug, Serialize, Deserialize, Clone)]
318#[serde(rename_all = "camelCase")]
319pub struct UserDataStream {
320    pub listen_key: String,
321}
322
323#[derive(Debug, Serialize, Deserialize, Clone)]
324pub struct Success {}
325
326#[derive(Debug, Serialize, Deserialize, Clone)]
327#[serde(rename_all = "camelCase")]
328#[serde(untagged)]
329pub enum Prices {
330    AllPrices(Vec<SymbolPrice>),
331}
332
333#[derive(Debug, Serialize, Deserialize, Clone)]
334pub struct SymbolPrice {
335    pub symbol: String,
336    #[serde(with = "string_or_decimal")]
337    pub price: Decimal,
338}
339
340#[derive(Debug, Serialize, Deserialize, Clone)]
341#[serde(rename_all = "camelCase")]
342#[serde(untagged)]
343pub enum BookTickers {
344    AllBookTickers(Vec<Ticker>),
345}
346
347#[derive(Debug, Clone)]
348pub enum KlineSummaries {
349    AllKlineSummaries(Vec<KlineSummary>),
350}
351
352#[derive(Debug, Serialize, Deserialize, Clone)]
353#[serde(rename_all = "camelCase")]
354pub struct Ticker {
355    pub symbol: String,
356    #[serde(with = "string_or_decimal")]
357    pub bid_price: Decimal,
358    #[serde(with = "string_or_decimal")]
359    pub bid_qty: Decimal,
360    #[serde(with = "string_or_decimal")]
361    pub ask_price: Decimal,
362    #[serde(with = "string_or_decimal")]
363    pub ask_qty: Decimal,
364}
365
366#[derive(Debug, Serialize, Deserialize, Clone)]
367#[serde(rename_all = "camelCase")]
368pub struct TradeHistory {
369    pub symbol: String,
370    pub id: u64,
371    pub order_id: u64,
372    #[serde(with = "string_or_decimal")]
373    pub price: Decimal,
374    #[serde(with = "string_or_decimal")]
375    pub qty: Decimal,
376    #[serde(with = "string_or_decimal")]
377    pub commission: Decimal,
378    pub commission_asset: String,
379    pub time: u64,
380    pub is_buyer: bool,
381    pub is_maker: bool,
382    pub is_best_match: bool,
383}
384
385#[derive(Debug, Serialize, Deserialize, Clone)]
386#[serde(rename_all = "camelCase")]
387pub struct PriceStats {
388    pub symbol: String,
389    #[serde(with = "string_or_decimal")]
390    pub price_change: Decimal,
391    #[serde(with = "string_or_decimal")]
392    pub price_change_percent: Decimal,
393    #[serde(with = "string_or_decimal")]
394    pub weighted_avg_price: Decimal,
395    #[serde(with = "string_or_decimal")]
396    pub prev_close_price: Decimal,
397    #[serde(with = "string_or_decimal")]
398    pub last_price: Decimal,
399    #[serde(with = "string_or_decimal")]
400    pub bid_price: Decimal,
401    #[serde(with = "string_or_decimal")]
402    pub ask_price: Decimal,
403    #[serde(with = "string_or_decimal")]
404    pub open_price: Decimal,
405    #[serde(with = "string_or_decimal")]
406    pub high_price: Decimal,
407    #[serde(with = "string_or_decimal")]
408    pub low_price: Decimal,
409    #[serde(with = "string_or_decimal")]
410    pub volume: Decimal,
411    pub open_time: u64,
412    pub close_time: u64,
413    pub first_id: i64, // For dummy symbol "123456", it is -1
414    pub last_id: i64,  // Same as above
415    pub count: u64,
416}
417
418#[derive(Debug, Clone)]
419pub struct KlineSummary {
420    pub open_time: i64,
421
422    pub open: Decimal,
423
424    pub high: Decimal,
425
426    pub low: Decimal,
427
428    pub close: Decimal,
429
430    pub volume: Decimal,
431
432    pub close_time: i64,
433
434    pub quote_asset_volume: Decimal,
435
436    pub number_of_trades: i64,
437
438    pub taker_buy_base_asset_volume: Decimal,
439
440    pub taker_buy_quote_asset_volume: Decimal,
441}
442
443#[derive(Debug, Serialize, Deserialize, Clone)]
444#[serde(rename_all = "camelCase")]
445pub struct Kline {
446    #[serde(rename = "t")]
447    pub start_time: i64,
448    #[serde(rename = "T")]
449    pub end_time: i64,
450    #[serde(rename = "s")]
451    pub symbol: String,
452    #[serde(rename = "i")]
453    pub interval: String,
454    #[serde(rename = "f")]
455    pub first_trade_id: i32,
456    #[serde(rename = "L")]
457    pub last_trade_id: i32,
458    #[serde(rename = "o")]
459    pub open: String,
460    #[serde(rename = "c")]
461    pub close: String,
462    #[serde(rename = "h")]
463    pub high: String,
464    #[serde(rename = "l")]
465    pub low: String,
466    #[serde(rename = "v")]
467    pub volume: String,
468    #[serde(rename = "n")]
469    pub number_of_trades: i32,
470    #[serde(rename = "x")]
471    pub is_final_bar: bool,
472    #[serde(rename = "q")]
473    pub quote_volume: String,
474    #[serde(rename = "V")]
475    pub active_buy_volume: String,
476    #[serde(rename = "Q")]
477    pub active_volume_buy_quote: String,
478    #[serde(skip_serializing, rename = "B")]
479    pub ignore_me: String,
480}
481
482// {
483//     "symbol": "ETHBTC",
484//     "status": "TRADING",
485//     "baseAsset": "ETH",
486//     "baseAssetPrecision": 8,
487//     "quoteAsset": "BTC",
488//     "quotePrecision": 8,
489//     "orderTypes": ["LIMIT", "MARKET"],
490//     "icebergAllowed": false,
491//     "filters": [{
492//       "filterType": "PRICE_FILTER",
493//       "minPrice": "0.00000100",
494//       "maxPrice": "100000.00000000",
495//       "tickSize": "0.00000100"
496//     }, {
497//       "filterType": "LOT_SIZE",
498//       "minQty": "0.00100000",
499//       "maxQty": "100000.00000000",
500//       "stepSize": "0.00100000"
501//     }, {
502//       "filterType": "MIN_NOTIONAL",
503//       "minNotional": "0.00100000"
504//     }]
505//   }
506#[derive(Debug, Serialize, Deserialize, Clone)]
507#[serde(tag = "filterType", rename_all = "SCREAMING_SNAKE_CASE")]
508pub enum ExchangeFilter {
509    ExchangeMaxNumOrders { limit: u64 },
510    ExchangeMaxAlgoOrders { limit: u64 },
511}
512
513#[derive(Debug, Serialize, Deserialize, Clone)]
514#[serde(rename_all = "camelCase")]
515pub struct OrderBook {
516    pub last_update_id: u64,
517    pub bids: Vec<Bids>,
518    pub asks: Vec<Asks>,
519}
520
521#[derive(Serialize, Deserialize, Clone, Debug)]
522#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
523pub enum NewOrderResponseType {
524    Ack,
525    Result,
526}
527
528#[derive(Serialize, Deserialize, Clone, Debug)]
529#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
530pub enum OrderExecType {
531    New,
532}
533
534#[derive(Serialize, Deserialize, Clone, Debug)]
535#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
536pub enum OrderRejectReason {
537    None,
538}
539
540#[derive(Debug, Serialize, Deserialize, Clone)]
541#[serde(rename_all = "camelCase")]
542pub struct Asset {
543    pub asset: String,
544    #[serde(with = "string_or_decimal")]
545    pub wallet_balance: Decimal,
546    #[serde(with = "string_or_decimal")]
547    pub unrealized_profit: Decimal,
548    #[serde(with = "string_or_decimal")]
549    pub margin_balance: Decimal,
550    #[serde(with = "string_or_decimal")]
551    pub maint_margin: Decimal,
552    #[serde(with = "string_or_decimal")]
553    pub initial_margin: Decimal,
554    #[serde(with = "string_or_decimal")]
555    pub position_initial_margin: Decimal,
556    #[serde(with = "string_or_decimal")]
557    pub open_order_initial_margin: Decimal,
558    #[serde(with = "string_or_decimal")]
559    pub max_withdraw_amount: Decimal,
560    #[serde(with = "string_or_decimal")]
561    pub cross_wallet_balance: Decimal,
562    #[serde(with = "string_or_decimal")]
563    pub cross_un_pnl: Decimal,
564    #[serde(with = "string_or_decimal")]
565    pub available_balance: Decimal,
566    #[serde(with = "string_or")]
567    pub margin_available: bool,
568    pub update_time: u64,
569}
570
571#[derive(Debug, Serialize, Deserialize, Clone)]
572#[serde(rename_all = "camelCase")]
573pub struct Position {
574    pub symbol: String,
575    #[serde(with = "string_or_decimal")]
576    pub initial_margin: Decimal,
577    #[serde(with = "string_or_decimal")]
578    pub maint_margin: Decimal,
579    #[serde(with = "string_or_decimal")]
580    pub unrealized_profit: Decimal,
581    #[serde(with = "string_or_decimal")]
582    pub position_initial_margin: Decimal,
583    #[serde(with = "string_or_decimal")]
584    pub open_order_initial_margin: Decimal,
585    pub leverage: String,
586    #[serde(with = "string_or")]
587    pub isolated: bool,
588    #[serde(with = "string_or_decimal")]
589    pub entry_price: Decimal,
590    #[serde(with = "string_or_decimal")]
591    pub max_notional: Decimal,
592    pub position_side: String,
593    #[serde(with = "string_or_decimal", rename = "positionAmt")]
594    pub position_amount: Decimal,
595    #[serde(with = "string_or_decimal")]
596    pub notional: Decimal,
597    #[serde(with = "string_or_decimal")]
598    pub isolated_wallet: Decimal,
599    pub update_time: u64,
600    #[serde(with = "string_or_decimal")]
601    pub bid_notional: Decimal,
602    #[serde(with = "string_or_decimal")]
603    pub ask_notional: Decimal,
604}
605
606#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
607#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
608pub enum PositionSide {
609    Both,
610    Long,
611    Short,
612}
613
614#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
615#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
616pub enum WorkingType {
617    MarkPrice,
618    ContractPrice,
619}