Skip to main content

bybit/
enums.rs

1//! Enums Definitions
2//!
3//! Ref: <https://bybit-exchange.github.io/docs/v5/enum>
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_repr::*;
7use std::fmt;
8
9/// Language of announcements (`locale`).
10#[derive(Debug, Deserialize, Serialize)]
11pub enum Locale {
12    /// German.
13    #[serde(rename = "de-DE")]
14    DeDe,
15    /// English (US).
16    #[serde(rename = "en-US")]
17    EnUs,
18    /// Spanish (Argentina).
19    #[serde(rename = "es-AR")]
20    EsAr,
21    /// Spanish (Spain).
22    #[serde(rename = "es-ES")]
23    EsEs,
24    /// Spanish (Mexico).
25    #[serde(rename = "es-MX")]
26    EsMx,
27    /// French.
28    #[serde(rename = "fr-FR")]
29    FrFr,
30    /// Kazakh.
31    #[serde(rename = "kk-KZ")]
32    KkKz,
33    /// Indonesian.
34    #[serde(rename = "id-ID")]
35    IdId,
36    /// Ukrainian.
37    #[serde(rename = "uk-UA")]
38    UkUa,
39    /// Japanese.
40    #[serde(rename = "ja-JP")]
41    JaJp,
42    /// Russian.
43    #[serde(rename = "ru-RU")]
44    RuRu,
45    /// Thai.
46    #[serde(rename = "th-TH")]
47    ThTh,
48    /// Portuguese (Brazil).
49    #[serde(rename = "pt-BR")]
50    PtBr,
51    /// Turkish.
52    #[serde(rename = "tr-TR")]
53    TrTr,
54    /// Vietnamese.
55    #[serde(rename = "vi-VN")]
56    ViVn,
57    /// Chinese (Traditional).
58    #[serde(rename = "zh-TW")]
59    ZhTw,
60    /// Arabic.
61    #[serde(rename = "ar-SA")]
62    ArSa,
63    /// Hindi.
64    #[serde(rename = "hi-IN")]
65    HiIn,
66    /// Filipino.
67    #[serde(rename = "fil-PH")]
68    FilPh,
69}
70
71/// Announcement category (`announcementType`).
72#[derive(Debug, Deserialize, Serialize)]
73pub enum AnnouncementType {
74    /// New crypto listings.
75    #[serde(rename = "new_crypto")]
76    NewCrypto,
77    /// Latest Bybit news.
78    #[serde(rename = "latest_bybit_news")]
79    LatestBybitNews,
80    /// Delistings.
81    #[serde(rename = "delistings")]
82    Delistings,
83    /// Latest activities and campaigns.
84    #[serde(rename = "latest_activities")]
85    LatestActivities,
86    /// Product updates.
87    #[serde(rename = "product_updates")]
88    ProductUpdates,
89    /// Maintenance updates.
90    #[serde(rename = "maintenance_updates")]
91    MaintenanceUpdates,
92    /// New fiat listings.
93    #[serde(rename = "new_fiat_listings")]
94    NewFiatListings,
95    /// Other announcements.
96    #[serde(rename = "other")]
97    Other,
98}
99
100/// Unified Account: spot | linear | inverse | option
101/// Classic Account: linear | inverse | spot
102#[derive(PartialEq, Eq, Hash, Debug, Deserialize, Serialize, Clone, Copy)]
103#[serde(rename_all = "lowercase")]
104pub enum Category {
105    /// Inverse contract, including Inverse perp, Inverse futures.
106    Inverse,
107    /// USDT perpetual, and USDC contract, including USDC perp, USDC futures.
108    Linear,
109    /// Options.
110    Option,
111    /// Spot.
112    Spot,
113}
114
115impl fmt::Display for Category {
116    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117        let value = match self {
118            Self::Inverse => "inverse",
119            Self::Linear => "linear",
120            Self::Option => "option",
121            Self::Spot => "spot",
122        };
123        write!(f, "{value}")
124    }
125}
126
127/// Order status (`orderStatus`).
128#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
129pub enum OrderStatus {
130    // open status
131    /// order has been placed successfully
132    New,
133    /// Partially filled; the rest is still open.
134    PartiallyFilled,
135    /// Conditional orders are created
136    Untriggered,
137    // closed status
138    /// Rejected (a closed status).
139    Rejected,
140    /// Only spot has this order status
141    PartiallyFilledCanceled,
142    /// Fully filled (a closed status).
143    Filled,
144    /// In derivatives, orders with this status may have an executed qty
145    Cancelled,
146    /// instantaneous state for conditional orders from Untriggered to New
147    Triggered,
148    /// UTA: Spot tp/sl order, conditional order, OCO order are cancelled before they are triggered
149    Deactivated,
150}
151
152impl OrderStatus {
153    /// The order is still active (`New`, `PartiallyFilled` or `Untriggered`).
154    pub fn is_open(&self) -> bool {
155        matches!(self, Self::New | Self::PartiallyFilled | Self::Untriggered)
156    }
157    /// The order reached a final status.
158    pub fn is_closed(&self) -> bool {
159        matches!(
160            self,
161            Self::Rejected
162                | Self::PartiallyFilledCanceled
163                | Self::Filled
164                | Self::Cancelled
165                | Self::Triggered
166                | Self::Deactivated
167        )
168    }
169}
170
171/// How long an order stays active (`timeInForce`).
172#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
173pub enum TimeInForce {
174    /// GoodTillCancel
175    GTC,
176    /// ImmediateOrCancel
177    IOC,
178    /// FillOrKill
179    FOK,
180    /// Maker only: the order is cancelled if it would execute immediately.
181    PostOnly,
182    /// features:
183    /// Exclusive Matching: Only match non-algorithmic users; no execution against orders from Open API.
184    /// Post-Only Mechanism: Act as maker orders, adding liquidity
185    /// Lower Priority: Execute after non-RPI orders at the same price level.
186    /// Limited Access: Initially for select market makers across multiple pairs.
187    /// Order Book Updates: Excluded from API but displayed on the GUI.
188    RPI,
189}
190
191/// What created the order (`createType`).
192#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
193pub enum CreateType {
194    /// Placed by the user.
195    CreateByUser,
196    /// Spread order
197    CreateByFutureSpread,
198    /// Closing order placed by Bybit (admin).
199    CreateByAdminClosing,
200    /// USDC Futures delivery; position closed as a result of the delisting of a contract. This is recorded as a trade but not an order.
201    CreateBySettle,
202    /// Futures conditional order
203    CreateByStopOrder,
204    /// Futures take profit order
205    CreateByTakeProfit,
206    /// Futures partial take profit order
207    CreateByPartialTakeProfit,
208    /// Futures stop loss order
209    CreateByStopLoss,
210    /// Futures partial stop loss order
211    CreateByPartialStopLoss,
212    /// Futures trailing stop order
213    CreateByTrailingStop,
214    /// Laddered liquidation to reduce the required maintenance margin
215    CreateByLiq,
216    /// If the position is still subject to liquidation (i.e., does not meet the required maintenance margin level), the position shall be taken over by the liquidation engine and closed at the bankruptcy price.
217    #[serde(rename = "CreateByTakeOver_PassThrough")]
218    CreateByTakeOverPassThrough,
219    /// Auto-Deleveraging(ADL)
220    #[serde(rename = "CreateByAdl_PassThrough")]
221    CreateByAdlPassThrough,
222    /// Order placed via Paradigm
223    #[serde(rename = "CreateByBlock_PassThrough")]
224    CreateByBlockPassThrough,
225    /// Order created by move position
226    #[serde(rename = "CreateByBlockTradeMovePosition_PassThrough")]
227    CreateByBlockTradeMovePositionPassThrough,
228    /// The close order placed via web or app position area - web/app
229    CreateByClosing,
230    /// Order created via grid bot - web/app
231    CreateByFGridBot,
232    /// Order closed via grid bot - web/app
233    CloseByFGridBot,
234    /// Order created by TWAP - web/app
235    CreateByTWAP,
236    /// Order created by TV webhook - web/app
237    CreateByTVSignal,
238    /// Order created by Mm rate close function - web/app
239    CreateByMmRateClose,
240    /// Order created by Martingale bot - web/app
241    CreateByMartingaleBot,
242    /// Order closed by Martingale bot - web/app
243    CloseByMartingaleBot,
244    /// Order created by Ice berg strategy - web/app
245    CreateByIceBerg,
246    /// Order created by arbitrage - web/app
247    CreateByArbitrage,
248    /// Option dynamic delta hedge order - web/app
249    CreateByDdh,
250}
251
252/// Kind of execution (`execType`).
253#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
254pub enum ExecType {
255    /// A regular trade.
256    Trade,
257    /// Auto-Deleveraging
258    AdlTrade,
259    /// Funding fee
260    Funding,
261    /// Takeover liquidation
262    BustTrade,
263    /// USDC futures delivery; Position closed by contract delisted
264    Delivery,
265    /// Inverse futures settlement; Position closed due to delisting
266    Settle,
267    /// A block trade.
268    BlockTrade,
269    /// A position moved between accounts.
270    MovePosition,
271    /// Spread leg execution
272    FutureSpread,
273    /// May be returned by a classic account. Cannot query by this type
274    UNKNOWN,
275}
276
277/// Order type (`orderType`).
278#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
279pub enum OrderType {
280    /// Market order.
281    Market,
282    /// Limit order.
283    Limit,
284    /// is not a valid request parameter value. Is only used in some responses. Mainly, it is used when execType is Funding.
285    UNKNOWN,
286}
287
288/// Type of a conditional or TP/SL order (`stopOrderType`).
289#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
290pub enum StopOrderType {
291    /// Take profit for the whole position.
292    TakeProfit,
293    /// Stop loss for the whole position.
294    StopLoss,
295    /// Trailing stop.
296    TrailingStop,
297    /// Conditional order triggered by price.
298    Stop,
299    /// Take profit for part of the position.
300    PartialTakeProfit,
301    /// Stop loss for part of the position.
302    PartialStopLoss,
303    /// spot TP/SL order
304    #[serde(rename = "tpslOrder")]
305    TpslOrder,
306    /// spot Oco order
307    OcoOrder,
308    /// On web or app can set MMR to close position
309    MmRateClose,
310    /// Spot bidirectional tpsl order
311    BidirectionalTpslOrder,
312    /// Not a conditional order, or an unknown value.
313    UNKNOWN,
314}
315
316/// Direction of the last price change (`tickDirection`).
317#[derive(Debug, PartialEq, Deserialize, Clone, Copy)]
318pub enum TickDirection {
319    /// price rise
320    PlusTick,
321    /// trade occurs at the same price as the previous trade, which occurred at a price higher than that for the trade preceding it
322    ZeroPlusTick,
323    /// price drop
324    MinusTick,
325    /// trade occurs at the same price as the previous trade, which occurred at a price lower than that for the trade preceding it
326    ZeroMinusTick,
327}
328
329/// Kline interval (`interval`).
330#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
331pub enum Interval {
332    /// 1 minute.
333    #[serde(rename = "1")]
334    Minute1,
335    /// 3 minutes.
336    #[serde(rename = "3")]
337    Minute3,
338    /// 5 minutes.
339    #[serde(rename = "5")]
340    Minute5,
341    /// 15 minutes.
342    #[serde(rename = "15")]
343    Minute15,
344    /// 30 minutes.
345    #[serde(rename = "30")]
346    Minute30,
347    /// 1 hour.
348    #[serde(rename = "60")]
349    Hour1,
350    /// 2 hours.
351    #[serde(rename = "120")]
352    Hour2,
353    /// 4 hours.
354    #[serde(rename = "240")]
355    Hour4,
356    /// 6 hours.
357    #[serde(rename = "360")]
358    Hour6,
359    /// 12 hours.
360    #[serde(rename = "720")]
361    Hour12,
362    /// 1 day.
363    #[serde(rename = "D")]
364    Day1,
365    /// 1 week.
366    #[serde(rename = "W")]
367    Week1,
368    /// 1 month.
369    #[serde(rename = "M")]
370    Month1,
371}
372
373impl fmt::Display for Interval {
374    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
375        let value = match self {
376            Self::Minute1 => "1",
377            Self::Minute3 => "3",
378            Self::Minute5 => "5",
379            Self::Minute15 => "15",
380            Self::Minute30 => "30",
381            Self::Hour1 => "60",
382            Self::Hour2 => "120",
383            Self::Hour4 => "240",
384            Self::Hour6 => "360",
385            Self::Hour12 => "720",
386            Self::Day1 => "D",
387            Self::Week1 => "W",
388            Self::Month1 => "M",
389        };
390        write!(f, "{value}")
391    }
392}
393
394/// Interval of open interest data (`intervalTime`).
395#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
396pub enum IntervalTime {
397    /// 5 minutes.
398    #[serde(rename = "5min")]
399    Minute5,
400    /// 15 minutes.
401    #[serde(rename = "15min")]
402    Minute15,
403    /// 30 minutes.
404    #[serde(rename = "30min")]
405    Minute30,
406    /// 1 hour.
407    #[serde(rename = "1h")]
408    Hour1,
409    /// 4 hours.
410    #[serde(rename = "4h")]
411    Hour4,
412    /// 1 day.
413    #[serde(rename = "1d")]
414    Day1,
415}
416
417/// Position index: one-way mode or a side of hedge mode (`positionIdx`).
418#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Eq, Hash, Clone, Copy)]
419#[repr(u8)]
420pub enum PositionIdx {
421    /// 0:one-way mode position
422    OneWay = 0,
423    /// 1:Buy side of hedge-mode position
424    Buy = 1,
425    /// 2:Sell side of hedge-mode position
426    Sell = 2,
427}
428
429/// Position mode of a symbol or settle coin (`mode`).
430#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
431#[repr(u8)]
432pub enum PositionMode {
433    /// 0: Merged Single (one-way)
434    OneWay = 0,
435    /// 3: Both Sides (hedge)
436    Hedge = 3,
437}
438
439/// Position status (`positionStatus`).
440#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
441pub enum PositionStatus {
442    /// Normal.
443    Normal,
444    /// in the liquidation progress
445    Liq,
446    /// in the auto-deleverage progress
447    Adl,
448}
449
450/// Why an order was rejected or cancelled by the matching engine (`rejectReason`).
451#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
452pub enum RejectReason {
453    /// No error.
454    #[serde(rename = "EC_NoError")]
455    EcNoError,
456    /// Other reason.
457    #[serde(rename = "EC_Others")]
458    EcOthers,
459    /// Unknown message type.
460    #[serde(rename = "EC_UnknownMessageType")]
461    EcUnknownMessageType,
462    /// Missing client order id.
463    #[serde(rename = "EC_MissingClOrdID")]
464    EcMissingClOrdId,
465    /// Missing original client order id.
466    #[serde(rename = "EC_MissingOrigClOrdID")]
467    EcMissingOrigClOrdId,
468    /// Client order id and original client order id are the same.
469    #[serde(rename = "EC_ClOrdIDOrigClOrdIDAreTheSame")]
470    EcClOrdIdorigClOrdIdareTheSame,
471    /// Duplicated client order id.
472    #[serde(rename = "EC_DuplicatedClOrdID")]
473    EcDuplicatedClOrdId,
474    /// Original client order id does not exist.
475    #[serde(rename = "EC_OrigClOrdIDDoesNotExist")]
476    EcOrigClOrdIddoesNotExist,
477    /// Too late to cancel.
478    #[serde(rename = "EC_TooLateToCancel")]
479    EcTooLateToCancel,
480    /// Unknown order type.
481    #[serde(rename = "EC_UnknownOrderType")]
482    EcUnknownOrderType,
483    /// Unknown side.
484    #[serde(rename = "EC_UnknownSide")]
485    EcUnknownSide,
486    /// Unknown time in force.
487    #[serde(rename = "EC_UnknownTimeInForce")]
488    EcUnknownTimeInForce,
489    /// Wrongly routed.
490    #[serde(rename = "EC_WronglyRouted")]
491    EcWronglyRouted,
492    /// A market order has a non-zero price.
493    #[serde(rename = "EC_MarketOrderPriceIsNotZero")]
494    EcMarketOrderPriceIsNotZero,
495    /// Invalid limit price.
496    #[serde(rename = "EC_LimitOrderInvalidPrice")]
497    EcLimitOrderInvalidPrice,
498    /// Not enough quantity to fill.
499    #[serde(rename = "EC_NoEnoughQtyToFill")]
500    EcNoEnoughQtyToFill,
501    /// No maker could be found to fill the order.
502    #[serde(rename = "EC_NoImmediateQtyToFill")]
503    EcNoImmediateQtyToFill,
504    /// Cancelled by request.
505    #[serde(rename = "EC_PerCancelRequest")]
506    EcPerCancelRequest,
507    /// A market order cannot be post-only.
508    #[serde(rename = "EC_MarketOrderCannotBePostOnly")]
509    EcMarketOrderCannotBePostOnly,
510    /// The post-only order would have executed as a taker.
511    #[serde(rename = "EC_PostOnlyWillTakeLiquidity")]
512    EcPostOnlyWillTakeLiquidity,
513    /// Cancelled by a replace (amend).
514    #[serde(rename = "EC_CancelReplaceOrder")]
515    EcCancelReplaceOrder,
516    /// The symbol status does not allow it.
517    #[serde(rename = "EC_InvalidSymbolStatus")]
518    EcInvalidSymbolStatus,
519    /// Cancelled because it could not be filled completely (FOK).
520    #[serde(rename = "EC_CancelForNoFullFill")]
521    EcCancelForNoFullFill,
522    /// Cancelled by self-match prevention.
523    #[serde(rename = "EC_BySelfMatch")]
524    EcBySelfMatch,
525    /// used for pre-market order operation, e.g., during 2nd phase of call auction, cancel order is not allowed, when the cancel request is failed to be rejected by trading server, the request will be rejected by matching box finally
526    #[serde(rename = "EC_InCallAuctionStatus")]
527    EcInCallAuctionStatus,
528    /// Quantity cannot be zero.
529    #[serde(rename = "EC_QtyCannotBeZero")]
530    EcQtyCannotBeZero,
531    /// Market orders do not support this time in force.
532    #[serde(rename = "EC_MarketOrderNoSupportTIF")]
533    EcMarketOrderNoSupportTif,
534    /// Maximum number of trades reached.
535    #[serde(rename = "EC_ReachMaxTradeNum")]
536    EcReachMaxTradeNum,
537    /// Invalid price precision.
538    #[serde(rename = "EC_InvalidPriceScale")]
539    EcInvalidPriceScale,
540    /// Invalid bit index.
541    #[serde(rename = "EC_BitIndexInvalid")]
542    EcBitIndexInvalid,
543    /// Stopped by self-match prevention.
544    #[serde(rename = "EC_StopBySelfMatch")]
545    EcStopBySelfMatch,
546    /// Invalid self-match prevention type.
547    #[serde(rename = "EC_InvalidSmpType")]
548    EcInvalidSmpType,
549    /// Cancelled by market maker protection.
550    #[serde(rename = "EC_CancelByMMP")]
551    EcCancelByMmp,
552    /// Invalid user type.
553    #[serde(rename = "EC_InvalidUserType")]
554    EcInvalidUserType,
555    /// Invalid mirror order id.
556    #[serde(rename = "EC_InvalidMirrorOid")]
557    EcInvalidMirrorOid,
558    /// Invalid mirror user id.
559    #[serde(rename = "EC_InvalidMirrorUid")]
560    EcInvalidMirrorUid,
561    /// Invalid quantity.
562    #[serde(rename = "EC_EcInvalidQty")]
563    EcEcInvalidQty,
564    /// Invalid amount.
565    #[serde(rename = "EC_InvalidAmount")]
566    EcInvalidAmount,
567    /// Cancelled while loading the order.
568    #[serde(rename = "EC_LoadOrderCancel")]
569    EcLoadOrderCancel,
570    /// Market orders in quote quantity do not support sell.
571    #[serde(rename = "EC_MarketQuoteNoSuppSell")]
572    EcMarketQuoteNoSuppSell,
573    /// Out-of-order order id.
574    #[serde(rename = "EC_DisorderOrderID")]
575    EcDisorderOrderId,
576    /// Invalid base value.
577    #[serde(rename = "EC_InvalidBaseValue")]
578    EcInvalidBaseValue,
579    /// The loaded order can match.
580    #[serde(rename = "EC_LoadOrderCanMatch")]
581    EcLoadOrderCanMatch,
582    /// Security status check failed.
583    #[serde(rename = "EC_SecurityStatusFail")]
584    EcSecurityStatusFail,
585    /// Risk price limit reached.
586    #[serde(rename = "EC_ReachRiskPriceLimit")]
587    EcReachRiskPriceLimit,
588    /// The order does not exist.
589    #[serde(rename = "EC_OrderNotExist")]
590    EcOrderNotExist,
591    /// Cancelled because its remaining value is zero.
592    #[serde(rename = "EC_CancelByOrderValueZero")]
593    EcCancelByOrderValueZero,
594    /// Cancelled because the order it matched with has a remaining value of zero.
595    #[serde(rename = "EC_CancelByMatchValueZero")]
596    EcCancelByMatchValueZero,
597    /// Market price limit reached.
598    #[serde(rename = "EC_ReachMarketPriceLimit")]
599    EcReachMarketPriceLimit,
600}
601
602/// Account type (`accountType`).
603#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone, Copy)]
604pub enum AccountType {
605    /// Inverse Derivatives Account | Derivatives Account
606    CONTRACT,
607    /// Unified Trading Account
608    UNIFIED,
609    /// Funding Account
610    FUND,
611    /// Spot Account
612    SPOT,
613}
614
615impl AccountType {
616    /// Account type used by UTA 2.0 accounts.
617    pub fn is_uta_2(&self) -> bool {
618        matches!(self, Self::UNIFIED | Self::FUND)
619    }
620    /// Account type used by UTA 1.0 accounts.
621    pub fn is_uta_1(&self) -> bool {
622        matches!(self, Self::CONTRACT | Self::UNIFIED | Self::FUND)
623    }
624    /// Account type used by classic accounts.
625    pub fn is_classic(&self) -> bool {
626        matches!(self, Self::SPOT | Self::CONTRACT | Self::FUND)
627    }
628}
629
630/// Status of a transfer (`transferStatus`).
631#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
632pub enum TransferStatus {
633    /// Completed.
634    SUCCESS,
635    /// In progress.
636    PENDING,
637    /// Failed.
638    FAILED,
639}
640
641/// Status of a deposit (`depositStatus`).
642#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
643pub enum DepositStatus {
644    /// Unknown.
645    #[serde(rename = "0")]
646    Unknown,
647    /// Waiting for confirmations.
648    #[serde(rename = "1")]
649    ToBeConfirmed,
650    /// Processing.
651    #[serde(rename = "2")]
652    Processing,
653    /// (finalised status of a success deposit)
654    #[serde(rename = "3")]
655    Success,
656    /// Failed.
657    #[serde(rename = "4")]
658    DepositFailed,
659    /// Pending to be credited to the funding pool.
660    #[serde(rename = "10011")]
661    PendingToBeCreditedToFundingPool,
662    /// Credited to the funding pool.
663    #[serde(rename = "10012")]
664    CreditedToFundingPoolSuccessfully,
665}
666
667/// Status of a withdrawal (`withdrawStatus`).
668#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
669pub enum WithdrawStatus {
670    /// Under security check.
671    SecurityCheck,
672    /// Pending.
673    Pending,
674    /// Completed.
675    #[serde(rename = "success")]
676    Success,
677    /// Cancelled by the user.
678    CancelByUser,
679    /// Rejected.
680    Reject,
681    /// Failed.
682    Fail,
683    /// Confirmed on the blockchain.
684    BlockchainConfirmed,
685    /// More information is required.
686    MoreInformationRequired,
687    /// a rare status
688    Unknown,
689}
690
691/// Price used to trigger a conditional order or TP/SL (`triggerBy`).
692#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
693pub enum TriggerBy {
694    /// Last traded price.
695    LastPrice,
696    /// Index price.
697    IndexPrice,
698    /// Mark price.
699    MarkPrice,
700    /// Not set, or an unknown value.
701    UNKNOWN,
702}
703
704/// Why an order was cancelled (`cancelType`).
705#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
706pub enum CancelType {
707    /// Cancelled by the user.
708    CancelByUser,
709    /// cancelled by reduceOnly
710    CancelByReduceOnly,
711    /// cancelled in order to attempt liquidation prevention by freeing up margin
712    CancelByPrepareLiq,
713    /// cancelled in order to attempt liquidation prevention by freeing up margin
714    CancelAllBeforeLiq,
715    /// cancelled due to ADL
716    CancelByPrepareAdl,
717    /// cancelled due to ADL
718    CancelAllBeforeAdl,
719    /// Cancelled by Bybit (admin).
720    CancelByAdmin,
721    /// cancelled due to delisting contract
722    CancelBySettle,
723    /// TP/SL order cancelled when the position is cleared
724    CancelByTpSlTsClear,
725    /// cancelled by SMP
726    CancelBySmp,
727    /// cancelled by DCP triggering
728    CancelByDCP,
729    /// Spread trading: the order price of a single leg order is outside the limit price range.
730    CancelByRebalance,
731
732    // Options:
733    /// Cancelled because the account cannot afford the order cost.
734    CancelByCannotAffordOrderCost,
735    /// Cancelled because portfolio margin trial maintenance margin exceeded equity.
736    CancelByPmTrialMmOverEquity,
737    /// Cancelled because the account is blocked.
738    CancelByAccountBlocking,
739    /// Cancelled by delivery.
740    CancelByDelivery,
741    /// Cancelled by market maker protection.
742    CancelByMmpTriggered,
743    /// Cancelled by cross self-match.
744    CancelByCrossSelfMuch,
745    /// Cancelled because the cross reached the maximum number of trades.
746    CancelByCrossReachMaxTradeNum,
747
748    /// Not documented
749    UNKNOWN,
750}
751
752/// Period of option historical volatility, days (`period`).
753#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
754pub enum OptionPeriod {
755    /// 7 days.
756    #[serde(rename = "7")]
757    Day7,
758    /// 14 days.
759    #[serde(rename = "14")]
760    Day14,
761    /// 21 days.
762    #[serde(rename = "21")]
763    Day21,
764    /// 30 days.
765    #[serde(rename = "30")]
766    Day30,
767    /// 60 days.
768    #[serde(rename = "60")]
769    Day60,
770    /// 90 days.
771    #[serde(rename = "90")]
772    Day90,
773    /// 180 days.
774    #[serde(rename = "180")]
775    Day180,
776    /// 270 days.
777    #[serde(rename = "270")]
778    Day270,
779}
780
781/// Data recording period of long/short ratio data (`period`).
782#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
783pub enum DataRecordingPeriod {
784    /// 5 minutes.
785    #[serde(rename = "5min")]
786    Minute5,
787    /// 15 minutes.
788    #[serde(rename = "15min")]
789    Minute15,
790    /// 30 minutes.
791    #[serde(rename = "30min")]
792    Minute30,
793    /// 1 hour.
794    #[serde(rename = "1h")]
795    Hour1,
796    /// 4 hours.
797    #[serde(rename = "4h")]
798    Hour4,
799    /// 4 days.
800    #[serde(rename = "4d")]
801    Day4,
802}
803
804/// Contract type of a derivatives instrument (`contractType`).
805#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
806pub enum ContractType {
807    /// Inverse perpetual.
808    InversePerpetual,
809    /// Linear (USDT/USDC) perpetual.
810    LinearPerpetual,
811    /// USDT/USDC Futures
812    LinearFutures,
813    /// Inverse futures.
814    InverseFutures,
815}
816
817/// Trading status of an instrument (`status`).
818#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
819pub enum Status {
820    /// Pre-market (pre-launch) contract.
821    PreLaunch,
822    /// Trading.
823    Trading,
824    /// Being delivered (futures and options).
825    Delivering,
826    /// Closed.
827    Closed,
828}
829
830/// Whether a spot pair supports margin trading (`marginTrading`).
831#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
832#[serde(rename_all = "camelCase")]
833pub enum MarginTrading {
834    /// Regardless of normal account or UTA account, this trading pair does not support margin trading
835    None,
836    /// For both normal account and UTA account, this trading pair supports margin trading
837    Both,
838    /// Only for UTA account,this trading pair supports margin trading
839    UtaOnly,
840    /// Only for normal account, this trading pair supports margin trading
841    NormalSpotOnly,
842}
843
844/// Whether a symbol supports copy trading (`copyTrading`).
845#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
846#[serde(rename_all = "camelCase")]
847pub enum CopyTrading {
848    /// Regardless of normal account or UTA account, this trading pair does not support copy trading
849    None,
850    /// For both normal account and UTA account, this trading pair supports copy trading
851    Both,
852    /// Only for UTA account,this trading pair supports copy trading
853    UtaOnly,
854    /// Only for normal account, this trading pair supports copy trading
855    NormalOnly,
856}
857
858/// Type of a transaction log entry (`type`).
859#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
860#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
861pub enum Type {
862    /// Assets that transferred into Unified | (inverse) derivatives wallet
863    TransferIn,
864    /// Assets that transferred out from Unified | (inverse) derivatives wallet
865    TransferOut,
866    /// Trade.
867    Trade,
868    /// USDT Perp funding settlement, and USDC Perp funding settlement + USDC 8-hour session settlement
869    /// USDT / Inverse Perp funding settlement
870    Settlement,
871    /// USDC Futures, Option delivery
872    Delivery,
873    /// Inverse Futures delivery
874    Liquidation,
875    /// Auto-Deleveraging
876    ADL,
877    /// Airdrop.
878    Airdrop,
879    /// Bonus claimed
880    Bonus,
881    /// Bonus expired
882    BonusRecollect,
883    /// Trading fee refunded
884    FeeRefund,
885    /// Interest occurred due to borrowing
886    Interest,
887    /// Currency convert, and the liquidation for borrowing asset(UTA loan)
888    CurrencyBuy,
889    /// Currency convert, and the liquidation for borrowing asset(UTA loan)
890    CurrencySell,
891    /// Amount borrowed by an institutional loan.
892    BorrowedAmountInsLoan,
893    /// Principal repayment of an institutional loan.
894    PrincipleRepaymentInsLoan,
895    /// Interest repayment of an institutional loan.
896    InterestRepaymentInsLoan,
897    /// the liquidation for borrowing asset(INS loan)
898    AutoSoldCollateralInsLoan,
899    /// the liquidation for borrowing asset(INS loan)
900    AutoBuyLiabilityInsLoan,
901    /// Automatic principal repayment of an institutional loan.
902    AutoPrincipleRepaymentInsLoan,
903    /// Automatic interest repayment of an institutional loan.
904    AutoInterestRepaymentInsLoan,
905    /// Transfer In when in the liquidation of OTC loan
906    TransferInInsLoan,
907    /// Transfer Out when in the liquidation of OTC loan
908    TransferOutInsLoan,
909    /// One-click repayment currency sell
910    SpotRepaymentSell,
911    /// One-click repayment currency buy
912    SpotRepaymentBuy,
913    /// Spot leverage token subscription
914    TokensSubscription,
915    /// Spot leverage token redemption
916    TokensRedemption,
917    /// Asset auto deducted by system (roll back)
918    AutoDeduction,
919    /// Byfi flexible stake subscription
920    FlexibleStakingSubscription,
921    /// Byfi flexible stake redemption
922    FlexibleStakingRedemption,
923    /// Byfi fixed stake subscription
924    FixedStakingSubscription,
925    /// Transfer out for pre-market trading.
926    PremarketTransferOut,
927    /// Pre-market delivery: new coins sold.
928    PremarketDeliverySellNewCoin,
929    /// Pre-market delivery: new coins bought.
930    PremarketDeliveryBuyNewCoin,
931    /// Pre-market delivery: pledge paid to the seller.
932    PremarketDeliveryPledgePaySeller,
933    /// Pre-market delivery: pledge returned.
934    PremarketDeliveryPledgeBack,
935    /// Pre-market rollback: pledge returned.
936    PremarketRollbackPledgeBack,
937    /// Pre-market rollback: pledge penalty paid to the buyer.
938    PremarketRollbackPledgePenaltyToBuyer,
939    /// fireblocks business
940    CustodyNetworkFee,
941    /// fireblocks business
942    CustodySettleFee,
943    /// fireblocks / copper business
944    CustodyLock,
945    /// fireblocks business
946    CustodyUnlock,
947    /// fireblocks business
948    CustodyUnlockRefund,
949    /// crypto loan
950    LoansBorrowFunds,
951    /// crypto loan repayment
952    LoansPledgeAsset,
953    /// Bonus transferred in.
954    BonusTransferIn,
955    /// Bonus transferred out.
956    BonusTransferOut,
957    /// Transfer in for PEF.
958    PefTransferIn,
959    /// Transfer out for PEF.
960    PefTransferOut,
961    /// PEF profit share.
962    PefProfitShare,
963    /// Any type not covered by the other variants.
964    #[serde(rename = "Others")]
965    Others,
966}
967
968impl Type {
969    /// Transaction type that appears in the unified account log.
970    pub fn is_uta(&self) -> bool {
971        matches!(
972            self,
973            Self::TransferIn
974                | Self::TransferOut
975                | Self::Trade
976                | Self::Settlement
977                | Self::Delivery
978                | Self::Liquidation
979                | Self::ADL
980                | Self::Airdrop
981                | Self::Bonus
982                | Self::BonusRecollect
983                | Self::FeeRefund
984                | Self::Interest
985                | Self::CurrencyBuy
986                | Self::CurrencySell
987                | Self::BorrowedAmountInsLoan
988                | Self::PrincipleRepaymentInsLoan
989                | Self::InterestRepaymentInsLoan
990                | Self::AutoSoldCollateralInsLoan
991                | Self::AutoBuyLiabilityInsLoan
992                | Self::AutoPrincipleRepaymentInsLoan
993                | Self::AutoInterestRepaymentInsLoan
994                | Self::TransferInInsLoan
995                | Self::TransferOutInsLoan
996                | Self::SpotRepaymentSell
997                | Self::SpotRepaymentBuy
998                | Self::TokensSubscription
999                | Self::TokensRedemption
1000                | Self::AutoDeduction
1001                | Self::FlexibleStakingSubscription
1002                | Self::FlexibleStakingRedemption
1003                | Self::FixedStakingSubscription
1004                | Self::PremarketTransferOut
1005                | Self::PremarketDeliverySellNewCoin
1006                | Self::PremarketDeliveryBuyNewCoin
1007                | Self::PremarketDeliveryPledgePaySeller
1008                | Self::PremarketDeliveryPledgeBack
1009                | Self::PremarketRollbackPledgeBack
1010                | Self::PremarketRollbackPledgePenaltyToBuyer
1011                | Self::CustodyNetworkFee
1012                | Self::CustodySettleFee
1013                | Self::CustodyLock
1014                | Self::CustodyUnlock
1015                | Self::CustodyUnlockRefund
1016                | Self::LoansBorrowFunds
1017                | Self::LoansPledgeAsset
1018                | Self::BonusTransferIn
1019                | Self::BonusTransferOut
1020                | Self::PefTransferIn
1021                | Self::PefTransferOut
1022                | Self::PefProfitShare
1023        )
1024    }
1025    /// Transaction type that appears in the contract (classic) account log.
1026    pub fn is_contract(&self) -> bool {
1027        matches!(
1028            self,
1029            Self::TransferIn
1030                | Self::TransferOut
1031                | Self::Trade
1032                | Self::Settlement
1033                | Self::Delivery
1034                | Self::Liquidation
1035                | Self::ADL
1036                | Self::Airdrop
1037                | Self::Bonus
1038                | Self::BonusRecollect
1039                | Self::FeeRefund
1040                | Self::CurrencyBuy
1041                | Self::CurrencySell
1042                | Self::AutoDeduction
1043                | Self::Others
1044        )
1045    }
1046}
1047
1048/// Account mode (`unifiedMarginStatus`).
1049#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1050#[repr(u8)]
1051pub enum UnifiedMarginStatus {
1052    /// Classic account.
1053    ClassicAccount = 1,
1054    /// 1.0
1055    UnifiedTradingAccount1 = 3,
1056    /// 1.0 (pro version)
1057    UnifiedTradingAccount1Pro = 4,
1058    /// 2.0
1059    UnifiedTradingAccount2 = 5,
1060    /// 2.0 (pro version)
1061    UnifiedTradingAccount2Pro = 6,
1062}
1063
1064/// Margin mode of a unified account (`marginMode`).
1065#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1066#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1067pub enum MarginMode {
1068    /// Isolated margin.
1069    IsolatedMargin,
1070    /// Regular (cross) margin.
1071    RegularMargin,
1072    /// Portfolio margin.
1073    PortfolioMargin,
1074}
1075
1076/// Whether Spot Margin Trade (UTA) is turned on for the account.
1077#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1078pub enum SpotMarginMode {
1079    /// Spot margin trading off.
1080    #[serde(rename = "0")]
1081    Disabled,
1082    /// Spot margin trading on.
1083    #[serde(rename = "1")]
1084    Enabled,
1085}
1086
1087/// Whether spot hedging is on (`spotHedgingStatus`).
1088#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1089#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1090pub enum SpotHedgingStatus {
1091    /// On.
1092    On,
1093    /// Off.
1094    Off,
1095}
1096
1097/// Status of a leveraged token (`ltStatus`).
1098#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1099pub enum LtStatus {
1100    /// LT can be purchased and redeemed
1101    #[serde(rename = "1")]
1102    CanBePurchasedAndRedeemed,
1103    /// LT can be purchased, but not redeemed
1104    #[serde(rename = "2")]
1105    CanBePurchasedButNotRedeemed,
1106    /// LT can be redeemed, but not purchased
1107    #[serde(rename = "3")]
1108    CanBeRedeemedButNotPurchased,
1109    /// LT cannot be purchased nor redeemed
1110    #[serde(rename = "4")]
1111    CannotBePurchasedNorRedeemed,
1112    /// Adjusting position
1113    #[serde(rename = "5")]
1114    AdjustingPosition,
1115}
1116
1117/// Status of a leveraged token purchase or redemption order.
1118#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1119pub enum LtOrderStatus {
1120    /// Completed.
1121    #[serde(rename = "1")]
1122    Completed,
1123    /// In progress.
1124    #[serde(rename = "2")]
1125    InProgress,
1126    /// Failed.
1127    #[serde(rename = "3")]
1128    Failed,
1129}
1130
1131/// Whether a leveraged token order record is a purchase or a redemption.
1132#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1133#[repr(u8)]
1134pub enum LtOrderType {
1135    /// Purchase.
1136    Purchase = 1,
1137    /// Redemption.
1138    Redemption = 2,
1139}
1140
1141/// Account type of a convert (`accountType`).
1142#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1143pub enum ConvertAccountType {
1144    /// Unified Trading Account
1145    #[serde(rename = "eb_convert_uta")]
1146    Uta,
1147    /// Funding Account
1148    #[serde(rename = "eb_convert_funding")]
1149    Funding,
1150    /// Inverse Derivatives Account (no USDT in this wallet))
1151    #[serde(rename = "eb_convert_inverse")]
1152    Inverse,
1153    /// Spot Account
1154    #[serde(rename = "eb_convert_spot")]
1155    Spot,
1156    /// Derivatives Account (contain USDT in this wallet)
1157    #[serde(rename = "eb_convert_contract")]
1158    Contract,
1159}
1160
1161/// VIP or PRO level of the account (`vipLevel`).
1162#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1163pub enum VipLevel {
1164    /// No VIP level.
1165    #[serde(rename = "No VIP")]
1166    NoVIP,
1167    /// VIP level 1.
1168    #[serde(rename = "VIP-1")]
1169    VIP1,
1170    /// VIP level 2.
1171    #[serde(rename = "VIP-2")]
1172    VIP2,
1173    /// VIP level 3.
1174    #[serde(rename = "VIP-3")]
1175    VIP3,
1176    /// VIP level 4.
1177    #[serde(rename = "VIP-4")]
1178    VIP4,
1179    /// VIP level 5.
1180    #[serde(rename = "VIP-5")]
1181    VIP5,
1182    /// VIP Supreme.
1183    #[serde(rename = "VIP-Supreme")]
1184    VIPSupreme,
1185    /// PRO level 1.
1186    #[serde(rename = "PRO-1")]
1187    PRO1,
1188    /// PRO level 2.
1189    #[serde(rename = "PRO-2")]
1190    PRO2,
1191    /// PRO level 3.
1192    #[serde(rename = "PRO-3")]
1193    PRO3,
1194    /// PRO level 4.
1195    #[serde(rename = "PRO-4")]
1196    PRO4,
1197    /// PRO level 5.
1198    #[serde(rename = "PRO-5")]
1199    PRO5,
1200}
1201
1202/// Auto-deleveraging rank, 0 (lowest priority) to 5 (`adlRankIndicator`).
1203#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1204#[repr(u8)]
1205pub enum AdlRankIndicator {
1206    /// default value of empty position
1207    Zero = 0,
1208    /// Rank 1.
1209    One = 1,
1210    /// Rank 2.
1211    Two = 2,
1212    /// Rank 3.
1213    Three = 3,
1214    /// Rank 4.
1215    Four = 4,
1216    /// Rank 5.
1217    Five = 5,
1218}
1219
1220/// Self-match prevention type (`smpType`).
1221#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1222pub enum SmpType {
1223    /// default
1224    None,
1225    /// Cancel the maker order.
1226    CancelMaker,
1227    /// Cancel the taker order.
1228    CancelTaker,
1229    /// Cancel both orders.
1230    CancelBoth,
1231}
1232
1233/// Type of an extra fee (`feeType`), charged only on some regional sites.
1234#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1235#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1236pub enum ExtraFeeType {
1237    /// Unknown.
1238    Unknown,
1239    /// Government tax. Only for Indonesian site
1240    Tax,
1241    /// Indonesian foreign exchange tax. Only for Indonesian site
1242    Cfx,
1243    /// EU withholding tax. Only for EU site
1244    Wht,
1245    /// Indian GST tax. Only for kyc=Indian users
1246    Gst,
1247    /// ARE VAT tax. Only for kyc=ARE users
1248    Vat,
1249}
1250
1251/// Subtype of an extra fee (`subFeeType`).
1252#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1253#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1254pub enum ExtraSubFeeType {
1255    /// Unknown.
1256    Unknown,
1257    /// Tax fee, fiat currency to digital currency. Only for Indonesian site
1258    TaxPnn,
1259    /// Tax fee, digital currency to fiat currency. Only for Indonesian site
1260    TaxPph,
1261    /// CFX fee, fiat currency to digital currency. Only for Indonesian site
1262    CfxFiee,
1263    /// EU site withholding tax. Only for EU site
1264    AutWithholdingTax,
1265    /// Indian GST tax. Only for kyc=Indian users
1266    IndGst,
1267    /// ARE VAT tax. Only for kyc=ARE users
1268    AreVat,
1269}
1270
1271/// State of a system maintenance (`state`).
1272#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1273#[serde(rename_all = "lowercase")]
1274pub enum State {
1275    /// Scheduled.
1276    Scheduled,
1277    /// In progress.
1278    Ongoing,
1279    /// Completed.
1280    Completed,
1281    /// Cancelled.
1282    Canceled,
1283}
1284
1285/// Service affected by a maintenance (`serviceTypes`).
1286#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1287#[repr(u8)]
1288pub enum ServiceTypes {
1289    /// Trading service
1290    TradingService = 1,
1291    /// Trading service via http request
1292    TradingServiceViaHttpRequest = 2,
1293    /// Trading service via websocket
1294    TradingServiceViaWebsocket = 3,
1295    /// Private websocket stream
1296    PrivateWebsocketStream = 4,
1297    /// Market data service
1298    MarketDataService = 5,
1299}
1300
1301/// Product affected by a maintenance (`product`).
1302#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1303#[repr(u8)]
1304pub enum Product {
1305    /// Futures.
1306    Futures = 1,
1307    /// Spot.
1308    Spot = 2,
1309    /// Option.
1310    Option = 3,
1311    /// Spread.
1312    Spread = 4,
1313}
1314
1315/// Product of Disconnection Cancellation Protection (`product`).
1316#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1317#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1318pub enum DCPProduct {
1319    /// Spot.
1320    Spot,
1321    /// Derivatives.
1322    Derivatives,
1323    /// Options.
1324    Option,
1325}
1326
1327/// Outcome of an Upgrade to Unified Account (Pro) request.
1328#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1329#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1330pub enum UnifiedUpdateStatus {
1331    /// The upgrade failed.
1332    Fail,
1333    /// The upgrade is in progress.
1334    Process,
1335    /// The upgrade succeeded.
1336    Success,
1337}
1338
1339/// Kind of system maintenance (`maintainType`).
1340#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1341#[repr(u8)]
1342pub enum MaintainType {
1343    /// Planned maintenance.
1344    PlannedMaintenance = 1,
1345    /// Temporary maintenance.
1346    TemporaryMaintenance = 2,
1347    /// Incident.
1348    Incident = 3,
1349}
1350
1351/// Environment affected by a maintenance (`env`).
1352#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1353#[repr(u8)]
1354pub enum Env {
1355    /// Production.
1356    Product = 1,
1357    /// Production demo service.
1358    ProductDemoService = 2,
1359}
1360
1361/// TP/SL mode (`tpslMode`).
1362#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1363pub enum TpslMode {
1364    /// TP/SL for the whole position.
1365    Full,
1366    /// TP/SL for part of the position.
1367    Partial,
1368    /// Not set, or an unknown value.
1369    UNKNOWN,
1370}
1371
1372/// Which leg triggered a spot OCO order (`ocoTriggerBy`).
1373#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1374pub enum OcoTriggerBy {
1375    /// Not triggered, or an unknown value.
1376    #[serde(rename = "OcoTriggerByUnknown")]
1377    Unknown,
1378    /// Triggered by the take profit.
1379    #[serde(rename = "OcoTriggerByTp")]
1380    Tp,
1381    /// Triggered by the stop loss.
1382    #[serde(rename = "OcoTriggerByBySl")]
1383    BySl,
1384}
1385
1386/// Direction the price must move to trigger a conditional order (`triggerDirection`).
1387#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1388#[repr(u8)]
1389pub enum TriggerDirection {
1390    /// Not a conditional order.
1391    UNKNOWN = 0,
1392    /// Triggered when the price rises to the trigger price.
1393    Rise = 1,
1394    /// Triggered when the price falls to the trigger price.
1395    Fall = 2,
1396}
1397
1398/// Auction phase of a pre-market contract (`curAuctionPhase`).
1399#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1400pub enum CurAuctionPhase {
1401    /// Pre-market trading is not started
1402    NotStarted,
1403    /// Pre-market trading is finished
1404    /// After the auction, if the pre-market contract fails to enter continues trading phase, it will be delisted and phase="Finished"
1405    /// After the continuous trading, if the pre-market contract fails to be converted to official contract, it will be delisted and phase="Finished"
1406    Finished,
1407    /// Auction phase of pre-market trading
1408    /// only timeInForce=GTC, orderType=Limit order is allowed to submit
1409    /// TP/SL are not supported; Conditional orders are not supported
1410    /// cannot modify the order at this stage
1411    /// order price range: [preOpenPrice x 0.5, maxPrice]
1412    CallAuction,
1413    /// Auction no cancel phase of pre-market trading
1414    /// only timeInForce=GTC, orderType=Limit order is allowed to submit
1415    /// TP/SL are not supported; Conditional orders are not supported
1416    /// cannot modify and cancel the order at this stage
1417    /// order price range: Buy [lastPrice x 0.5, markPrice x 1.1], Sell [markPrice x 0.9, maxPrice]
1418    CallAuctionNoCancel,
1419    /// cross matching phase
1420    /// cannot create, modify and cancel the order at this stage
1421    /// Candle data is released from this stage
1422    CrossMatching,
1423    /// Continuous trading phase
1424    /// There is no restriction to create, amend, cancel orders
1425    /// orderbook, public trade data is released from this stage
1426    ContinuousTrading,
1427}
1428
1429/// How an option order is placed (`placeType`).
1430#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1431pub enum PlaceType {
1432    /// Default.
1433    #[serde(rename = "option")]
1434    Option,
1435    /// By implied volatility.
1436    #[serde(rename = "iv")]
1437    Iv,
1438    /// By price.
1439    #[serde(rename = "price")]
1440    Price,
1441}
1442
1443/// Option type.
1444#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Hash, Clone, Copy)]
1445pub enum OptionType {
1446    /// Call option.
1447    Call,
1448    /// Put option.
1449    Put,
1450}
1451
1452/// Order or trade side (`side`).
1453#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1454pub enum Side {
1455    /// Buy.
1456    Buy,
1457    /// Sell.
1458    Sell,
1459}
1460impl Side {
1461    /// The opposite side.
1462    pub fn reverse(&self) -> Self {
1463        match self {
1464            Side::Buy => Self::Sell,
1465            Side::Sell => Self::Buy,
1466        }
1467    }
1468}
1469
1470/// Coin of a spot pair in which a fee is charged (see [`spot_fee_currency`]).
1471#[derive(Debug, PartialEq, Clone, Copy)]
1472pub enum Pair {
1473    // example of BTCUSDT
1474    /// Base coin, e.g. BTC of BTCUSDT.
1475    Base, // BTC
1476    /// Quote coin, e.g. USDT of BTCUSDT.
1477    Quote, // USDT
1478}
1479
1480/// Unit of the slippage tolerance of a market order (`slippageToleranceType`).
1481#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
1482pub enum SlippageToleranceType {
1483    /// Number of ticks.
1484    TickSize,
1485    /// Percentage.
1486    Percent,
1487    /// default
1488    UNKNOWN,
1489}
1490
1491/// Margin mode of a classic account position (`tradeMode`).
1492#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy)]
1493#[repr(u8)]
1494pub enum TradeMode {
1495    /// Cross margin.
1496    CrossMargin = 0,
1497    /// Isolated margin.
1498    IsolatedMargin = 1,
1499}
1500
1501/// A WebSocket topic; serialized as Bybit expects, e.g. `tickers.BTCUSDT` or `order.linear`.
1502#[derive(Debug, Clone, PartialEq)]
1503pub enum Topic {
1504    /// Order book of a symbol (`orderbook.{depth}.{symbol}`).
1505    Orderbook {
1506        /// Symbol, e.g. `BTCUSDT`.
1507        symbol: String,
1508        /// Depth.
1509        depth: DepthLevel,
1510    },
1511    /// Public trades of a symbol (`publicTrade.{symbol}`).
1512    Trade(String),
1513    /// Ticker of a symbol (`tickers.{symbol}`).
1514    Ticker(String),
1515    /// Klines of a symbol (`kline.{interval}.{symbol}`).
1516    Kline {
1517        /// Symbol, e.g. `BTCUSDT`.
1518        symbol: String,
1519        /// Kline interval.
1520        interval: Interval,
1521    },
1522    /// All liquidations of a symbol (`allLiquidation.{symbol}`).
1523    AllLiquidation(String),
1524    /// Positions of a category (`position.{category}`).
1525    Position(Category),
1526    /// Positions of all categories (`position`).
1527    PositionAllCategory,
1528    /// Executions of a category (`execution.{category}`).
1529    Execution(Category),
1530    /// Executions of all categories (`execution`).
1531    ExecutionAllCategory,
1532    /// Fast executions of a category (`execution.fast.{category}`).
1533    FastExecution(Category),
1534    /// Fast executions of all categories (`execution.fast`).
1535    FastExecutionAllCategory,
1536    /// Orders of a category (`order.{category}`).
1537    Order(Category),
1538    /// Orders of all categories (`order`).
1539    OrderAllCategory,
1540    /// Wallet balance (`wallet`).
1541    Wallet,
1542    /// option only.
1543    Greek,
1544    /// Disconnection Cancellation Protection status (`dcp.{function}`).
1545    Dcp(DcpFunction),
1546}
1547
1548impl fmt::Display for Topic {
1549    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1550        let value = match self {
1551            Self::Orderbook { symbol, depth } => format!("orderbook.{depth}.{symbol}"),
1552            Self::Trade(symbol) => format!("publicTrade.{symbol}"),
1553            Self::Ticker(symbol) => format!("tickers.{symbol}"),
1554            Self::Kline { symbol, interval } => format!("kline.{interval}.{symbol}"),
1555            Self::AllLiquidation(symbol) => format!("allLiquidation.{symbol}"),
1556            Self::Position(category) => format!("position.{category}"),
1557            Self::PositionAllCategory => "position".to_string(),
1558            Self::Execution(category) => format!("execution.{category}"),
1559            Self::ExecutionAllCategory => "execution".to_string(),
1560            Self::FastExecution(category) => format!("execution.fast.{category}"),
1561            Self::FastExecutionAllCategory => "execution.fast".to_string(),
1562            Self::Order(category) => format!("order.{category}"),
1563            Self::OrderAllCategory => "order".to_string(),
1564            Self::Wallet => "wallet".to_string(),
1565            Self::Greek => "greek".to_string(),
1566            Self::Dcp(function) => format!("dcp.{function}"),
1567        };
1568        write!(f, "{value}")
1569    }
1570}
1571
1572impl Serialize for Topic {
1573    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1574    where
1575        S: Serializer,
1576    {
1577        serializer.collect_str(self)
1578    }
1579}
1580
1581impl<'de> Deserialize<'de> for Topic {
1582    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1583    where
1584        D: Deserializer<'de>,
1585    {
1586        let s: std::borrow::Cow<'de, str> = Deserialize::deserialize(deserializer)?;
1587        let s = s.as_ref();
1588        if let Some((kind, args)) = s.split_once('.') {
1589            match kind {
1590                "orderbook" => {
1591                    if let Some((depth, symbol)) = args.split_once('.') {
1592                        let depth =
1593                            serde_json::from_str(&format!("\"{depth}\"")).map_err(|err| {
1594                                serde::de::Error::custom(format!(
1595                                    "DepthLevel: {depth}, error: {err}"
1596                                ))
1597                            })?;
1598                        Ok(Self::Orderbook {
1599                            depth,
1600                            symbol: symbol.to_owned(),
1601                        })
1602                    } else {
1603                        Err(serde::de::Error::custom("invalid stream format"))
1604                    }
1605                }
1606                "publicTrade" => Ok(Self::Trade(args.to_owned())),
1607                "tickers" => Ok(Self::Ticker(args.to_owned())),
1608                "kline" => {
1609                    if let Some((interval, symbol)) = args.split_once('.') {
1610                        let interval = serde_json::from_str(&format!("\"{interval}\""))
1611                            .map_err(|err| serde::de::Error::custom(format!("Interval: {err}")))?;
1612                        Ok(Self::Kline {
1613                            symbol: symbol.to_owned(),
1614                            interval,
1615                        })
1616                    } else {
1617                        Err(serde::de::Error::custom("invalid stream format"))
1618                    }
1619                }
1620                "allLiquidation" => Ok(Self::AllLiquidation(args.to_owned())),
1621                "position" => {
1622                    let category = serde_json::from_str(&format!("\"{args}\""))
1623                        .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1624                    Ok(Self::Position(category))
1625                }
1626                "execution" => {
1627                    if args == "fast" {
1628                        Ok(Self::FastExecutionAllCategory)
1629                    } else if let Some((fast, category)) = args.split_once('.') {
1630                        let category = serde_json::from_str(&format!("\"{category}\""))
1631                            .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1632                        if fast == "fast" {
1633                            Ok(Self::FastExecution(category))
1634                        } else {
1635                            Ok(Self::Execution(category))
1636                        }
1637                    } else {
1638                        let category = serde_json::from_str(&format!("\"{args}\""))
1639                            .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1640                        Ok(Self::Execution(category))
1641                    }
1642                }
1643                "order" => {
1644                    let category = serde_json::from_str(&format!("\"{args}\""))
1645                        .map_err(|err| serde::de::Error::custom(format!("category: {err}")))?;
1646                    Ok(Self::Order(category))
1647                }
1648                "dcp" => {
1649                    let function = serde_json::from_str(&format!("\"{args}\""))
1650                        .map_err(|err| serde::de::Error::custom(format!("DcpFunction: {err}")))?;
1651                    Ok(Self::Dcp(function))
1652                }
1653                _ => Err(serde::de::Error::custom("invalid stream format")),
1654            }
1655        } else {
1656            match s {
1657                "position" => Ok(Self::PositionAllCategory),
1658                "execution" => Ok(Self::ExecutionAllCategory),
1659                "order" => Ok(Self::OrderAllCategory),
1660                "wallet" => Ok(Self::Wallet),
1661                "greek" => Ok(Self::Greek),
1662                _ => {
1663                    let msg = String::from("invalid stream format");
1664                    Err(serde::de::Error::custom(msg))
1665                }
1666            }
1667        }
1668    }
1669}
1670
1671/// Product of a DCP topic (`dcp.{function}`).
1672#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
1673#[serde(rename_all = "lowercase")]
1674pub enum DcpFunction {
1675    /// Futures.
1676    Future,
1677    /// Options.
1678    Option,
1679    /// Spot.
1680    Spot,
1681}
1682
1683impl fmt::Display for DcpFunction {
1684    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1685        let value = match self {
1686            Self::Future => "future",
1687            Self::Option => "option",
1688            Self::Spot => "spot",
1689        };
1690        write!(f, "{value}")
1691    }
1692}
1693
1694/// Depth of the order book stream (`orderbook.{depth}.{symbol}`).
1695#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
1696pub enum DepthLevel {
1697    /// 1 levels.
1698    #[serde(rename = "1")]
1699    Level1,
1700    /// 25 levels.
1701    #[serde(rename = "25")]
1702    Level25,
1703    /// 50 levels.
1704    #[serde(rename = "50")]
1705    Level50,
1706    /// 100 levels.
1707    #[serde(rename = "100")]
1708    Level100,
1709    /// 200 levels.
1710    #[serde(rename = "200")]
1711    Level200,
1712    /// Perpetuals and futures only.
1713    #[serde(rename = "500")]
1714    Level500,
1715    /// Spot only.
1716    #[serde(rename = "1000")]
1717    Level1000,
1718}
1719
1720impl fmt::Display for DepthLevel {
1721    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1722        let value = match self {
1723            Self::Level1 => "1",
1724            Self::Level25 => "25",
1725            Self::Level50 => "50",
1726            Self::Level100 => "100",
1727            Self::Level200 => "200",
1728            Self::Level500 => "500",
1729            Self::Level1000 => "1000",
1730        };
1731        write!(f, "{value}")
1732    }
1733}
1734
1735/// Coin in which the fee of a spot trade is charged: normally the coin
1736/// received; with a negative maker fee rate (rebate), a maker receives the
1737/// rebate in the coin paid.
1738pub fn spot_fee_currency(side: Side, is_maker_order: bool, maker_fee_rate: f64) -> Pair {
1739    if maker_fee_rate >= 0.0 {
1740        match side {
1741            Side::Buy => Pair::Base,
1742            Side::Sell => Pair::Quote,
1743        }
1744    } else if is_maker_order {
1745        match side {
1746            Side::Buy => Pair::Quote,
1747            Side::Sell => Pair::Base,
1748        }
1749    } else {
1750        match side {
1751            Side::Buy => Pair::Base,
1752            Side::Sell => Pair::Quote,
1753        }
1754    }
1755}
1756
1757#[cfg(test)]
1758mod tests {
1759    use crate::serde::deserialize_json;
1760
1761    use super::*;
1762
1763    #[test]
1764    fn serialize_category() {
1765        let cases = [
1766            (Category::Inverse, r#""inverse""#),
1767            (Category::Linear, r#""linear""#),
1768            (Category::Option, r#""option""#),
1769            (Category::Spot, r#""spot""#),
1770        ];
1771        cases.iter().for_each(|(category, expected)| {
1772            let json = serde_json::to_string(category).unwrap();
1773            assert_eq!(json, *expected);
1774        });
1775    }
1776
1777    #[test]
1778    fn deserialize_category() {
1779        let cases = [
1780            (r#""inverse""#, Category::Inverse),
1781            (r#""linear""#, Category::Linear),
1782            (r#""option""#, Category::Option),
1783            (r#""spot""#, Category::Spot),
1784        ];
1785        cases.iter().for_each(|(json, expected)| {
1786            let message: Category = deserialize_json(json).unwrap();
1787            assert_eq!(message, *expected);
1788        });
1789    }
1790
1791    #[test]
1792    fn serialize_interval() {
1793        let cases = vec![
1794            (Interval::Minute1, r#""1""#),
1795            (Interval::Minute3, r#""3""#),
1796            (Interval::Minute5, r#""5""#),
1797            (Interval::Minute15, r#""15""#),
1798            (Interval::Minute30, r#""30""#),
1799            (Interval::Hour1, r#""60""#),
1800            (Interval::Hour2, r#""120""#),
1801            (Interval::Hour4, r#""240""#),
1802            (Interval::Hour6, r#""360""#),
1803            (Interval::Hour12, r#""720""#),
1804            (Interval::Day1, r#""D""#),
1805            (Interval::Week1, r#""W""#),
1806            (Interval::Month1, r#""M""#),
1807        ];
1808        cases.iter().for_each(|(category, expected)| {
1809            let json = serde_json::to_string(category).unwrap();
1810            assert_eq!(json, *expected);
1811        });
1812    }
1813
1814    #[test]
1815    fn deserialize_interval() {
1816        let cases = vec![
1817            (r#""1""#, Interval::Minute1),
1818            (r#""3""#, Interval::Minute3),
1819            (r#""5""#, Interval::Minute5),
1820            (r#""15""#, Interval::Minute15),
1821            (r#""30""#, Interval::Minute30),
1822            (r#""60""#, Interval::Hour1),
1823            (r#""120""#, Interval::Hour2),
1824            (r#""240""#, Interval::Hour4),
1825            (r#""360""#, Interval::Hour6),
1826            (r#""720""#, Interval::Hour12),
1827            (r#""D""#, Interval::Day1),
1828            (r#""W""#, Interval::Week1),
1829            (r#""M""#, Interval::Month1),
1830        ];
1831        cases.iter().for_each(|(json, expected)| {
1832            let message: Interval = deserialize_json(json).unwrap();
1833            assert_eq!(message, *expected);
1834        });
1835    }
1836
1837    #[test]
1838    fn deserialize_topic_with_escaped_characters() {
1839        let topic: Topic = serde_json::from_str(r#""tickers.BTC\u0055SDT""#).unwrap();
1840
1841        assert_eq!(topic, Topic::Ticker(String::from("BTCUSDT")));
1842    }
1843
1844    #[test]
1845    fn serialize_topic() {
1846        let symbol = String::from("BTCUSDT");
1847        let cases = vec![
1848            (
1849                Topic::Orderbook {
1850                    symbol: symbol.clone(),
1851                    depth: DepthLevel::Level1,
1852                },
1853                r#""orderbook.1.BTCUSDT""#,
1854            ),
1855            (Topic::Trade(symbol.clone()), r#""publicTrade.BTCUSDT""#),
1856            (Topic::Ticker(symbol.clone()), r#""tickers.BTCUSDT""#),
1857            (
1858                Topic::Kline {
1859                    symbol: symbol.clone(),
1860                    interval: Interval::Minute1,
1861                },
1862                r#""kline.1.BTCUSDT""#,
1863            ),
1864            (
1865                Topic::AllLiquidation(symbol.clone()),
1866                r#""allLiquidation.BTCUSDT""#,
1867            ),
1868            (Topic::Position(Category::Linear), r#""position.linear""#),
1869            (Topic::PositionAllCategory, r#""position""#),
1870            (Topic::Execution(Category::Linear), r#""execution.linear""#),
1871            (Topic::ExecutionAllCategory, r#""execution""#),
1872            (
1873                Topic::FastExecution(Category::Linear),
1874                r#""execution.fast.linear""#,
1875            ),
1876            (Topic::FastExecutionAllCategory, r#""execution.fast""#),
1877            (Topic::Order(Category::Linear), r#""order.linear""#),
1878            (Topic::OrderAllCategory, r#""order""#),
1879            (Topic::Wallet, r#""wallet""#),
1880            (Topic::Greek, r#""greek""#),
1881            (Topic::Dcp(DcpFunction::Future), r#""dcp.future""#),
1882        ];
1883        cases.iter().for_each(|(category, expected)| {
1884            let json = serde_json::to_string(category).unwrap();
1885            assert_eq!(*expected, json);
1886        });
1887    }
1888
1889    #[test]
1890    fn deserialize_topic() {
1891        let symbol = String::from("BTCUSDT");
1892        let cases = vec![
1893            (
1894                r#""orderbook.1.BTCUSDT""#,
1895                Topic::Orderbook {
1896                    symbol: symbol.clone(),
1897                    depth: DepthLevel::Level1,
1898                },
1899            ),
1900            (r#""publicTrade.BTCUSDT""#, Topic::Trade(symbol.clone())),
1901            (r#""tickers.BTCUSDT""#, Topic::Ticker(symbol.clone())),
1902            (
1903                r#""kline.1.BTCUSDT""#,
1904                Topic::Kline {
1905                    symbol: symbol.clone(),
1906                    interval: Interval::Minute1,
1907                },
1908            ),
1909            (
1910                r#""allLiquidation.BTCUSDT""#,
1911                Topic::AllLiquidation(symbol.clone()),
1912            ),
1913            (r#""position.linear""#, Topic::Position(Category::Linear)),
1914            (r#""position""#, Topic::PositionAllCategory),
1915            (r#""execution.linear""#, Topic::Execution(Category::Linear)),
1916            (r#""execution""#, Topic::ExecutionAllCategory),
1917            (
1918                r#""execution.fast.linear""#,
1919                Topic::FastExecution(Category::Linear),
1920            ),
1921            (r#""execution.fast""#, Topic::FastExecutionAllCategory),
1922            (r#""order.linear""#, Topic::Order(Category::Linear)),
1923            (r#""order""#, Topic::OrderAllCategory),
1924            (r#""wallet""#, Topic::Wallet),
1925            (r#""greek""#, Topic::Greek),
1926            (r#""dcp.future""#, Topic::Dcp(DcpFunction::Future)),
1927        ];
1928        cases.iter().for_each(|(json, expected)| {
1929            let message = deserialize_json(json).unwrap();
1930            assert_eq!(*expected, message);
1931        });
1932    }
1933}