nautilus_bybit/common/
enums.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Enumerations that model Bybit string/int enums across HTTP and WebSocket payloads.
17
18use nautilus_model::enums::{AggressorSide, OrderSide};
19use serde::{Deserialize, Serialize};
20use serde_repr::{Deserialize_repr, Serialize_repr};
21use strum::{AsRefStr, Display, EnumIter, EnumString};
22
23/// Unified margin account status values.
24#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize_repr, Deserialize_repr)]
25#[repr(i32)]
26pub enum BybitUnifiedMarginStatus {
27    /// Classic account.
28    ClassicAccount = 1,
29    /// Unified trading account 1.0.
30    UnifiedTradingAccount10 = 3,
31    /// Unified trading account 1.0 pro.
32    UnifiedTradingAccount10Pro = 4,
33    /// Unified trading account 2.0.
34    UnifiedTradingAccount20 = 5,
35    /// Unified trading account 2.0 pro.
36    UnifiedTradingAccount20Pro = 6,
37}
38
39/// Margin mode used by Bybit when switching risk profiles.
40#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
41#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
42#[cfg_attr(
43    feature = "python",
44    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.bybit")
45)]
46pub enum BybitMarginMode {
47    IsolatedMargin,
48    RegularMargin,
49    PortfolioMargin,
50}
51
52/// Position mode as returned by the v5 API.
53#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize_repr, Deserialize_repr)]
54#[repr(i32)]
55#[cfg_attr(
56    feature = "python",
57    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.bybit")
58)]
59pub enum BybitPositionMode {
60    /// Merged single position mode.
61    MergedSingle = 0,
62    /// Dual-side hedged position mode.
63    BothSides = 3,
64}
65
66/// Position index values used for hedge mode payloads.
67#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize_repr, Deserialize_repr)]
68#[repr(i32)]
69pub enum BybitPositionIdx {
70    /// One-way mode position identifier.
71    OneWay = 0,
72    /// Buy side of a hedge-mode position.
73    BuyHedge = 1,
74    /// Sell side of a hedge-mode position.
75    SellHedge = 2,
76}
77
78/// Account type enumeration.
79#[derive(
80    Copy,
81    Clone,
82    Debug,
83    Display,
84    PartialEq,
85    Eq,
86    Hash,
87    AsRefStr,
88    EnumIter,
89    EnumString,
90    Serialize,
91    Deserialize,
92)]
93#[serde(rename_all = "UPPERCASE")]
94#[cfg_attr(
95    feature = "python",
96    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.bybit")
97)]
98pub enum BybitAccountType {
99    Unified,
100}
101
102/// Environments supported by the Bybit API stack.
103#[derive(
104    Copy,
105    Clone,
106    Debug,
107    Display,
108    PartialEq,
109    Eq,
110    Hash,
111    AsRefStr,
112    EnumIter,
113    EnumString,
114    Serialize,
115    Deserialize,
116)]
117#[serde(rename_all = "lowercase")]
118#[cfg_attr(
119    feature = "python",
120    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.bybit")
121)]
122pub enum BybitEnvironment {
123    /// Live trading environment.
124    Mainnet,
125    /// Demo (paper trading) environment.
126    Demo,
127    /// Testnet environment for spot/derivatives.
128    Testnet,
129}
130
131/// Product categories supported by the v5 API.
132#[derive(
133    Copy,
134    Clone,
135    Debug,
136    Display,
137    Default,
138    PartialEq,
139    Eq,
140    Hash,
141    AsRefStr,
142    EnumIter,
143    EnumString,
144    Serialize,
145    Deserialize,
146)]
147#[serde(rename_all = "lowercase")]
148#[cfg_attr(
149    feature = "python",
150    pyo3::pyclass(eq, eq_int, module = "nautilus_trader.core.nautilus_pyo3.bybit")
151)]
152pub enum BybitProductType {
153    #[default]
154    Spot,
155    Linear,
156    Inverse,
157    Option,
158}
159
160/// Spot margin trading enablement states.
161#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
162pub enum BybitMarginTrading {
163    #[serde(rename = "none")]
164    None,
165    #[serde(rename = "utaOnly")]
166    UtaOnly,
167    #[serde(rename = "both")]
168    Both,
169    #[serde(other)]
170    Other,
171}
172
173/// Innovation market flag for spot instruments.
174#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
175pub enum BybitInnovationFlag {
176    #[serde(rename = "0")]
177    Standard,
178    #[serde(rename = "1")]
179    Innovation,
180    #[serde(other)]
181    Other,
182}
183
184/// Instrument lifecycle status values.
185#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
186#[serde(rename_all = "PascalCase")]
187pub enum BybitInstrumentStatus {
188    Trading,
189    Settled,
190    Delivering,
191    ListedOnly,
192    PendingListing,
193    PreTrading,
194    Closed,
195    Suspended,
196    #[serde(other)]
197    Other,
198}
199
200impl BybitProductType {
201    /// Returns the canonical lowercase identifier used for REST/WS routes.
202    #[must_use]
203    pub const fn as_str(self) -> &'static str {
204        match self {
205            Self::Spot => "spot",
206            Self::Linear => "linear",
207            Self::Inverse => "inverse",
208            Self::Option => "option",
209        }
210    }
211
212    /// Returns the uppercase suffix used in instrument identifiers (e.g. `-LINEAR`).
213    #[must_use]
214    pub const fn suffix(self) -> &'static str {
215        match self {
216            Self::Spot => "-SPOT",
217            Self::Linear => "-LINEAR",
218            Self::Inverse => "-INVERSE",
219            Self::Option => "-OPTION",
220        }
221    }
222
223    /// Returns `true` if the product is a spot instrument.
224    #[must_use]
225    pub fn is_spot(self) -> bool {
226        matches!(self, Self::Spot)
227    }
228
229    /// Returns `true` if the product is a linear contract.
230    #[must_use]
231    pub fn is_linear(self) -> bool {
232        matches!(self, Self::Linear)
233    }
234
235    /// Returns `true` if the product is an inverse contract.
236    #[must_use]
237    pub fn is_inverse(self) -> bool {
238        matches!(self, Self::Inverse)
239    }
240
241    /// Returns `true` if the product is an option contract.
242    #[must_use]
243    pub fn is_option(self) -> bool {
244        matches!(self, Self::Option)
245    }
246}
247
248/// Contract type enumeration for linear and inverse derivatives.
249#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
250#[serde(rename_all = "PascalCase")]
251pub enum BybitContractType {
252    LinearPerpetual,
253    LinearFutures,
254    InversePerpetual,
255    InverseFutures,
256}
257
258/// Option flavour values.
259#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
260#[serde(rename_all = "PascalCase")]
261pub enum BybitOptionType {
262    Call,
263    Put,
264}
265
266/// Position side as represented in REST/WebSocket payloads.
267#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
268pub enum BybitPositionSide {
269    #[serde(rename = "")]
270    Flat,
271    #[serde(rename = "Buy")]
272    Buy,
273    #[serde(rename = "Sell")]
274    Sell,
275}
276
277/// WebSocket order request operations.
278#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
279pub enum BybitWsOrderRequestOp {
280    #[serde(rename = "order.create")]
281    Create,
282    #[serde(rename = "order.amend")]
283    Amend,
284    #[serde(rename = "order.cancel")]
285    Cancel,
286    #[serde(rename = "order.create-batch")]
287    CreateBatch,
288    #[serde(rename = "order.amend-batch")]
289    AmendBatch,
290    #[serde(rename = "order.cancel-batch")]
291    CancelBatch,
292}
293
294/// Available kline intervals.
295#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
296pub enum BybitKlineInterval {
297    #[serde(rename = "1")]
298    Minute1,
299    #[serde(rename = "3")]
300    Minute3,
301    #[serde(rename = "5")]
302    Minute5,
303    #[serde(rename = "15")]
304    Minute15,
305    #[serde(rename = "30")]
306    Minute30,
307    #[serde(rename = "60")]
308    Hour1,
309    #[serde(rename = "120")]
310    Hour2,
311    #[serde(rename = "240")]
312    Hour4,
313    #[serde(rename = "360")]
314    Hour6,
315    #[serde(rename = "720")]
316    Hour12,
317    #[serde(rename = "D")]
318    Day1,
319    #[serde(rename = "W")]
320    Week1,
321    #[serde(rename = "M")]
322    Month1,
323}
324
325/// Order status values returned by Bybit.
326#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
327pub enum BybitOrderStatus {
328    #[serde(rename = "Created")]
329    Created,
330    #[serde(rename = "New")]
331    New,
332    #[serde(rename = "Rejected")]
333    Rejected,
334    #[serde(rename = "PartiallyFilled")]
335    PartiallyFilled,
336    #[serde(rename = "PartiallyFilledCanceled")]
337    PartiallyFilledCanceled,
338    #[serde(rename = "Filled")]
339    Filled,
340    #[serde(rename = "Cancelled")]
341    Canceled,
342    #[serde(rename = "Untriggered")]
343    Untriggered,
344    #[serde(rename = "Triggered")]
345    Triggered,
346    #[serde(rename = "Deactivated")]
347    Deactivated,
348}
349
350/// Order side enumeration.
351#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
352pub enum BybitOrderSide {
353    #[serde(rename = "")]
354    Unknown,
355    #[serde(rename = "Buy")]
356    Buy,
357    #[serde(rename = "Sell")]
358    Sell,
359}
360
361impl From<BybitOrderSide> for AggressorSide {
362    fn from(value: BybitOrderSide) -> Self {
363        match value {
364            BybitOrderSide::Buy => Self::Buyer,
365            BybitOrderSide::Sell => Self::Seller,
366            BybitOrderSide::Unknown => Self::NoAggressor,
367        }
368    }
369}
370
371impl From<BybitOrderSide> for OrderSide {
372    fn from(value: BybitOrderSide) -> Self {
373        match value {
374            BybitOrderSide::Buy => Self::Buy,
375            BybitOrderSide::Sell => Self::Sell,
376            BybitOrderSide::Unknown => Self::NoOrderSide,
377        }
378    }
379}
380
381/// Order cancel reason values as returned by Bybit.
382#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
383#[serde(rename_all = "PascalCase")]
384pub enum BybitCancelType {
385    CancelByUser,
386    CancelByReduceOnly,
387    CancelByPrepareLackOfMargin,
388    CancelByPrepareOrderFilter,
389    CancelByPrepareOrderMarginCheckFailed,
390    CancelByPrepareOrderCommission,
391    CancelByPrepareOrderRms,
392    CancelByPrepareOrderOther,
393    CancelByRiskLimit,
394    CancelOnDisconnect,
395    CancelByStopOrdersExceeded,
396    CancelByPzMarketClose,
397    CancelByMarginCheckFailed,
398    CancelByPzTakeover,
399    CancelByAdmin,
400    CancelByTpSlTsClear,
401    CancelByAmendNotModified,
402    CancelByPzCancel,
403    CancelByCrossSelfMatch,
404    CancelBySelfMatchPrevention,
405    #[serde(other)]
406    Other,
407}
408
409/// Order creation origin values.
410#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
411#[serde(rename_all = "PascalCase")]
412pub enum BybitCreateType {
413    CreateByUser,
414    CreateByClosing,
415    CreateByTakeProfit,
416    CreateByStopLoss,
417    CreateByTrailingStop,
418    CreateByStopOrder,
419    CreateByPartialTakeProfit,
420    CreateByPartialStopLoss,
421    CreateByAdl,
422    CreateByLiquidate,
423    CreateByTakeover,
424    CreateByTpsl,
425    #[serde(other)]
426    Other,
427}
428
429/// Venue order type enumeration.
430#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
431pub enum BybitOrderType {
432    #[serde(rename = "Market")]
433    Market,
434    #[serde(rename = "Limit")]
435    Limit,
436    #[serde(rename = "UNKNOWN")]
437    Unknown,
438}
439
440/// Stop order type classification.
441#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
442pub enum BybitStopOrderType {
443    #[serde(rename = "")]
444    None,
445    #[serde(rename = "UNKNOWN")]
446    Unknown,
447    #[serde(rename = "TakeProfit")]
448    TakeProfit,
449    #[serde(rename = "StopLoss")]
450    StopLoss,
451    #[serde(rename = "TrailingStop")]
452    TrailingStop,
453    #[serde(rename = "Stop")]
454    Stop,
455    #[serde(rename = "PartialTakeProfit")]
456    PartialTakeProfit,
457    #[serde(rename = "PartialStopLoss")]
458    PartialStopLoss,
459    #[serde(rename = "tpslOrder")]
460    TpslOrder,
461    #[serde(rename = "OcoOrder")]
462    OcoOrder,
463    #[serde(rename = "MmRateClose")]
464    MmRateClose,
465    #[serde(rename = "BidirectionalTpslOrder")]
466    BidirectionalTpslOrder,
467}
468
469/// Trigger type configuration.
470#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
471pub enum BybitTriggerType {
472    #[serde(rename = "")]
473    None,
474    #[serde(rename = "LastPrice")]
475    LastPrice,
476    #[serde(rename = "IndexPrice")]
477    IndexPrice,
478    #[serde(rename = "MarkPrice")]
479    MarkPrice,
480}
481
482/// Trigger direction integers used by the API.
483#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize_repr, Deserialize_repr)]
484#[repr(i32)]
485pub enum BybitTriggerDirection {
486    None = 0,
487    RisesTo = 1,
488    FallsTo = 2,
489}
490
491/// Take-profit/stop-loss mode for derivatives orders.
492#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
493#[serde(rename_all = "PascalCase")]
494pub enum BybitTpSlMode {
495    Full,
496    Partial,
497    #[serde(other)]
498    Unknown,
499}
500
501/// Time-in-force enumeration.
502#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
503pub enum BybitTimeInForce {
504    #[serde(rename = "GTC")]
505    Gtc,
506    #[serde(rename = "IOC")]
507    Ioc,
508    #[serde(rename = "FOK")]
509    Fok,
510    #[serde(rename = "PostOnly")]
511    PostOnly,
512}
513
514/// Execution type values used in execution reports.
515#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
516pub enum BybitExecType {
517    #[serde(rename = "Trade")]
518    Trade,
519    #[serde(rename = "AdlTrade")]
520    AdlTrade,
521    #[serde(rename = "Funding")]
522    Funding,
523    #[serde(rename = "BustTrade")]
524    BustTrade,
525    #[serde(rename = "Delivery")]
526    Delivery,
527    #[serde(rename = "Settle")]
528    Settle,
529    #[serde(rename = "BlockTrade")]
530    BlockTrade,
531    #[serde(rename = "MovePosition")]
532    MovePosition,
533    #[serde(rename = "UNKNOWN")]
534    Unknown,
535}
536
537/// Transaction types for wallet funding records.
538#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
539pub enum BybitTransactionType {
540    #[serde(rename = "TRANSFER_IN")]
541    TransferIn,
542    #[serde(rename = "TRANSFER_OUT")]
543    TransferOut,
544    #[serde(rename = "TRADE")]
545    Trade,
546    #[serde(rename = "SETTLEMENT")]
547    Settlement,
548    #[serde(rename = "DELIVERY")]
549    Delivery,
550    #[serde(rename = "LIQUIDATION")]
551    Liquidation,
552    #[serde(rename = "AIRDRP")]
553    Airdrop,
554}
555
556/// Endpoint classifications used by the Bybit API.
557#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
558#[serde(rename_all = "UPPERCASE")]
559pub enum BybitEndpointType {
560    None,
561    Asset,
562    Market,
563    Account,
564    Trade,
565    Position,
566    User,
567}