Skip to main content

bybit/models/
order.rs

1use crate::prelude::*;
2
3/// Represents a single order with detailed attributes.
4///
5/// This struct provides comprehensive details about an order, including its execution
6/// status, prices, quantities, and fees. In perpetual futures trading on Bybit, this
7/// struct is used to track the lifecycle of an order, from placement to execution or
8/// cancellation. Perpetual futures are financial derivatives that allow leveraged
9/// trading without an expiration date, balanced by funding rates. Bots use this struct
10/// to monitor order progress, calculate profitability, manage positions, and handle
11/// risk. Fields like `avg_price`, `cum_exec_fee`, and `take_profit` are critical for
12/// performance analysis and risk management in volatile markets.
13#[derive(Serialize, Deserialize, Clone, Debug)]
14#[serde(rename_all = "camelCase")]
15pub struct Order {
16    /// The unique identifier of the order provided by Bybit.
17    ///
18    /// This is a system-generated ID assigned when the order is created. In perpetual
19    /// futures, `order_id` is essential for tracking orders across API requests (e.g.,
20
21    /// amending, canceling, or querying status). Bots must store and reference this ID
22    /// to manage orders accurately, especially in high-frequency trading where multiple
23    /// orders are active. Losing track of `order_id` can lead to orphaned orders or
24    /// mismanaged positions, impacting strategy execution.
25    pub order_id: String,
26
27    /// The user-defined identifier of the order.
28    ///
29    /// A custom ID set by the trader to track the order. In perpetual futures, where
30    /// bots may manage numerous orders, `order_link_id` provides a way to correlate
31    /// orders with specific strategies or logic. Bots should use unique, descriptive
32    /// IDs to avoid confusion and ensure robust order tracking. If not set, it’s an
33    /// empty string, but bots should always assign a value for traceability.
34    pub order_link_id: String,
35
36    /// The identifier for block trades (optional).
37    ///
38    /// Represents the ID of a block trade, which is a large order executed off the
39    /// public order book, typically for institutional traders. In perpetual futures,
40
41    /// this field is usually `None` for retail bots, as block trades are less common.
42    /// For bots handling large orders, this field helps track such trades, ensuring
43    /// compliance with Bybit’s reporting requirements. Bots should log this for
44    /// auditing if applicable.
45    #[serde(
46        deserialize_with = "empty_string_as_none",
47        skip_serializing_if = "is_empty_or_none"
48    )]
49    pub block_trade_id: Option<String>,
50
51    /// The trading pair symbol, e.g., "BTCUSDT".
52    ///
53    /// Identifies the asset pair of the order (e.g., BTCUSDT for Bitcoin against USDT).
54    /// In perpetual futures, symbols are typically USDT-margined (Linear category).
55    /// Bots must validate that the symbol is supported by Bybit and align order
56    /// parameters (e.g., price, quantity) with the symbol’s contract specifications
57    /// (e.g., tick size, minimum quantity). This field is critical for correlating
58    /// orders with market data and ensuring strategy consistency.
59    pub symbol: String,
60
61    /// The price of the order.
62    ///
63    /// For limit orders, this is the specified price at which the order is placed; for
64    /// market orders, it’s the executed price. In perpetual futures, price must adhere
65    /// to the symbol’s tick size (e.g., $0.5 for BTCUSDT). Bots should use this field
66    /// to verify execution against market conditions and calculate profitability. For
67    /// limit orders, setting prices too far from the market may prevent execution,
68
69    /// while market orders risk slippage in volatile markets.
70    #[serde(with = "string_to_float")]
71    pub price: f64,
72
73    /// The quantity of the order.
74    ///
75    /// Represents the size of the order in the base asset (e.g., BTC for BTCUSDT).
76    /// In perpetual futures, quantity must comply with Bybit’s minimum and maximum
77    /// limits, which vary by symbol. Bots should validate this against account balance,
78
79    /// margin requirements, and symbol constraints to avoid rejections. Over-sizing
80    /// quantities can increase liquidation risk, especially with leverage, so bots
81    /// must carefully manage this field.
82    #[serde(with = "string_to_float")]
83    pub qty: f64,
84
85    /// The side of the order (Buy or Sell).
86    ///
87    /// Indicates whether the order is to buy (long) or sell (short). In perpetual
88    /// futures, Buy orders open long positions or close short ones, while Sell orders
89    /// open short positions or close long ones. Bots must align this with their market
90    /// outlook and position management strategy. Incorrect sides can lead to unintended
91    /// exposure, so bots should include validation logic to prevent errors.
92    pub side: Side,
93
94    /// Indicates if leverage was used (empty string for false).
95    ///
96    /// A non-empty string (e.g., "1") indicates the order used leverage, common in
97    /// perpetual futures to amplify position sizes. Leverage increases potential
98    /// returns but also liquidation risk if prices move adversely. Bots should check
99    /// this field to confirm margin usage and monitor account health, ensuring
100    /// sufficient collateral to avoid forced liquidations. For non-leveraged orders,
101
102    /// this is an empty string.
103    #[serde(skip_serializing_if = "String::is_empty")]
104    pub is_leverage: String,
105
106    /// The position index (0 for one-way, 1 or 2 for hedge mode).
107    ///
108    /// Specifies the position mode: 0 for one-way mode (single position per symbol),
109
110    /// 1 for long, or 2 for short in hedge mode (allowing simultaneous long and short
111    /// positions). In perpetual futures, bots must ensure this matches the account’s
112    /// position mode to avoid order rejections. Mismanaging `position_idx` can lead to
113    /// unintended position netting or increased margin requirements, disrupting
114    /// strategy execution.
115    pub position_idx: i32,
116
117    /// The current status of the order (e.g., "New", "Filled", "Cancelled").
118    ///
119    /// Indicates the order’s lifecycle stage, such as "New" (pending), "PartiallyFilled",
120
121    /// "Filled", or "Cancelled". In perpetual futures, bots should monitor this to track
122    /// execution progress and handle edge cases (e.g., partial fills or cancellations).
123    /// For example, a "PartiallyFilled" status requires bots to adjust position sizes
124    /// and risk calculations. This field is critical for state management and strategy
125    /// adaptation.
126    pub order_status: String,
127
128    /// The reason for cancellation (if applicable).
129    ///
130    /// Specifies why an order was canceled, such as "CancelByUser" or "Timeout". In
131    /// perpetual futures, understanding cancellation reasons helps bots diagnose issues
132    /// (e.g., market conditions preventing execution) and refine strategies. Bots
133    /// should log this field for auditing and use it to trigger fallback logic, such
134    /// as resubmitting orders with adjusted parameters.
135    pub cancel_type: String,
136
137    /// The reason for order rejection (if applicable).
138    ///
139    /// Explains why an order was rejected by Bybit, such as "InsufficientBalance" or
140    /// "InvalidPrice". In perpetual futures, rejections can occur due to margin
141    /// constraints, invalid parameters, or market limits. Bots must handle this field
142    /// to diagnose and resolve issues, implementing error-handling logic to adjust
143    /// order parameters (e.g., reducing quantity) or retrying after funding the account.
144    pub reject_reason: String,
145
146    /// The average execution price (optional).
147    ///
148    /// The weighted average price of executed portions for partially or fully filled
149    /// orders. In perpetual futures, bots use this to calculate realized profitability
150    /// and compare against market prices. For example, a lower `avg_price` than
151    /// expected for a Buy order indicates slippage. If `None`, the order has not been
152    /// filled. Bots should monitor this to assess execution quality and optimize order
153    /// types (e.g., preferring limit orders to reduce slippage).
154    #[serde(with = "string_to_float_optional")]
155    pub avg_price: Option<f64>,
156
157    /// The remaining quantity to be executed.
158    ///
159    /// Indicates the unfilled portion of the order’s quantity. In perpetual futures,
160
161    /// bots should monitor this to determine if an order is partially filled and adjust
162    /// position sizing or risk calculations. A non-zero `leaves_qty` for a limit order
163    /// may indicate the price is too far from the market, prompting bots to amend the
164    /// order or cancel and resubmit at a better price.
165    #[serde(with = "string_to_float")]
166    pub leaves_qty: f64,
167
168    /// The remaining value to be executed.
169    ///
170    /// The monetary value of the unfilled portion (typically `leaves_qty` multiplied
171    /// by the order price). In perpetual futures, bots can use this to assess exposure
172    /// and margin requirements for pending orders. This field helps quantify the
173    /// potential impact of unfilled orders on account health, especially in leveraged
174    /// trading scenarios.
175    #[serde(with = "string_to_float")]
176    pub leaves_value: f64,
177
178    /// The cumulative executed quantity.
179    ///
180    /// The total quantity filled so far. In perpetual futures, bots should use this
181    /// to track order progress and update position sizes. For example, if
182    /// `cum_exec_qty` is less than `qty`, the order is partially filled, requiring
183    /// bots to manage the open position and any remaining risk. This field is critical
184    /// for accurate position tracking and strategy execution.
185    #[serde(with = "string_to_float")]
186    pub cum_exec_qty: f64,
187
188    /// The cumulative executed value.
189    ///
190    /// The total monetary value of filled portions (typically `cum_exec_qty` multiplied
191    /// by the execution prices). In perpetual futures, bots use this to calculate the
192    /// cost basis of a position and assess profitability. This field helps bots
193    /// determine the financial impact of executed trades, especially for leveraged
194    /// positions where margin requirements are dynamic.
195    #[serde(with = "string_to_float")]
196    pub cum_exec_value: f64,
197
198    /// The cumulative execution fees.
199    ///
200    /// The total fees incurred for executed portions of the order. In perpetual
201    /// futures, fees vary based on order type: maker orders (e.g., PostOnly limit
202    /// orders) typically have lower or negative fees, while taker orders (e.g., market
203    /// orders) have higher fees. Bots should monitor this closely, as fees impact
204    /// profitability, especially in high-frequency trading. Optimizing for maker orders
205    /// can reduce costs, and bots should log this field for performance analysis.
206    #[serde(with = "string_to_float")]
207    pub cum_exec_fee: f64,
208
209    /// The time-in-force policy of the order.
210    ///
211    /// Specifies how long the order was active, such as "GTC" (Good Till Canceled),
212
213    /// "IOC" (Immediate or Cancel), "FOK" (Fill or Kill), or "PostOnly". In perpetual
214    /// futures, TIF affects execution strategy and fees. For example, PostOnly orders
215    /// optimize for maker fees but may not execute in fast markets. Bots should verify
216    /// this field to ensure the order’s behavior aligns with the strategy and adjust
217    /// TIF for future orders if needed.
218    pub time_in_force: String,
219
220    /// The type of order (Limit or Market).
221    ///
222    /// Indicates whether the order was a limit order (executed at a specified price)
223    /// or a market order (executed at the best available price). In perpetual futures,
224
225    /// limit orders offer price control but risk non-execution, while market orders
226    /// ensure execution but may incur slippage and higher fees. Bots should use this
227    /// field to confirm order type and assess execution performance, optimizing for
228    /// cost or speed based on strategy goals.
229    pub order_type: OrderType,
230
231    /// The type of stop order (optional, e.g., "StopLoss").
232    ///
233    /// Specifies if the order was a conditional stop order, such as "StopLoss" or
234    /// "TakeProfit". In perpetual futures, stop orders are critical for risk
235    /// management, automatically closing positions at predefined levels. If `None`,
236
237    /// the order is not a stop order. Bots should use this field to identify risk
238    /// management orders and ensure they align with the strategy’s exit conditions.
239    #[serde(
240        deserialize_with = "empty_string_as_none",
241        skip_serializing_if = "is_empty_or_none"
242    )]
243    pub stop_order_type: Option<String>,
244
245    /// The implied volatility for options orders (optional).
246    ///
247    /// Represents the expected volatility for options orders, not applicable to
248    /// perpetual futures. In Bybit’s API, this field is relevant only for options
249    /// trading, where volatility affects pricing. Bots trading perpetual futures can
250    /// ignore this field, but those expanding to options must source accurate
251    /// volatility data to interpret this correctly.
252    #[serde(
253        deserialize_with = "empty_string_as_none",
254        skip_serializing_if = "is_empty_or_none"
255    )]
256    pub order_iv: Option<String>,
257
258    /// The trigger price for conditional orders (optional).
259    ///
260    /// The price at which a conditional order (e.g., stop-loss or take-profit)
261    /// activates. In perpetual futures, trigger prices are essential for risk
262    /// management, defining exit points for profitable or losing positions. If `None`,
263
264    /// the order is not conditional. Bots should verify this field to ensure risk
265    /// management settings are correct and adjust trigger prices based on market
266    /// volatility and strategy goals.
267    #[serde(with = "string_to_float_optional")]
268    pub trigger_price: Option<f64>,
269
270    /// The take-profit price (optional).
271    ///
272    /// The price at which the position is closed to lock in profits. In perpetual
273    /// futures, take-profit (TP) is critical for securing gains in volatile markets.
274    /// If `None`, no TP is set. Bots should use this field to confirm TP settings and
275    /// calculate realized profits, ensuring the price is realistic given market
276    /// conditions and symbol tick size constraints.
277    #[serde(with = "string_to_float_optional")]
278    pub take_profit: Option<f64>,
279
280    /// The stop-loss price (optional).
281    ///
282    /// The price at which the position is closed to limit losses. In perpetual
283    /// futures, stop-loss (SL) is essential to prevent significant drawdowns,
284
285    /// especially with leverage. If `None`, no SL is set. Bots should use this field
286    /// to confirm SL settings and manage risk, setting SL prices based on risk
287    /// tolerance and volatility to avoid premature exits or excessive losses.
288    #[serde(with = "string_to_float_optional")]
289    pub stop_loss: Option<f64>,
290
291    /// The price type for triggering take-profit.
292    ///
293    /// Specifies the price metric used for TP triggering, such as "LastPrice",
294
295    /// "IndexPrice", or "MarkPrice". In perpetual futures, choosing a reliable metric
296    /// like "MarkPrice" (less susceptible to manipulation) ensures consistent
297    /// execution. Bots should verify this field to ensure TP triggers as intended,
298
299    /// especially in volatile markets where price discrepancies can occur.
300    pub tp_trigger_by: String,
301
302    /// The price type for triggering stop-loss.
303    ///
304    /// Specifies the price metric used for SL triggering, similar to `tp_trigger_by`.
305    /// Bots should select a stable metric (e.g., "MarkPrice") to protect against
306    /// manipulation-driven triggers in perpetual futures. This field ensures SL
307    /// activates reliably, safeguarding positions from adverse price movements.
308    pub sl_trigger_by: String,
309
310    /// The direction of the trigger price (0, 1, or 2).
311    ///
312    /// Indicates whether the trigger activates when the price rises (1) or falls (2);
313    /// 0 indicates no direction (non-conditional orders). In perpetual futures, this
314    /// field is critical for conditional orders like stop-loss or take-profit. For
315    /// example, a stop-loss for a long position typically has `trigger_direction` set
316    /// to 2 (falling price). Bots must validate this to ensure risk management logic
317    /// aligns with market expectations.
318    pub trigger_direction: i32,
319
320    /// The price type for triggering conditional orders (optional).
321    ///
322    /// Specifies the price metric for triggering conditional orders (e.g.,
323
324    /// "LastPrice", "MarkPrice"). If `None`, the order is not conditional. In
325    /// perpetual futures, bots should choose a reliable metric to ensure consistent
326    /// execution, especially for high-frequency strategies where timing is critical.
327    #[serde(
328        deserialize_with = "empty_string_as_none",
329        skip_serializing_if = "is_empty_or_none"
330    )]
331    pub trigger_by: Option<String>,
332
333    /// The market price when the order was created (optional).
334    ///
335    /// The reference market price at the time of order placement, typically the last
336    /// traded price. In perpetual futures, bots can use this to compare against
337    /// execution prices (`avg_price`) and assess slippage or market movement since
338    /// order creation. If `None`, no reference price was recorded. This field helps
339    /// bots evaluate order timing and market conditions.
340    #[serde(with = "string_to_float_optional")]
341    pub last_price_on_created: Option<f64>,
342
343    /// Indicates if the order reduces an existing position.
344    ///
345    /// When `true`, the order only closes an existing position, preventing unintended
346    /// increases in exposure. In perpetual futures, `reduce_only` is critical for
347    /// position management, ensuring bots exit positions without opening opposing
348    /// ones. Bots should set and verify this field when closing positions to avoid
349    /// margin issues or unexpected leverage.
350    pub reduce_only: bool,
351
352    /// Indicates if the order closes the position when triggered.
353    ///
354    /// When `true`, the order closes the position upon triggering, typically used for
355    /// stop-loss or take-profit orders. In perpetual futures, this ensures automatic
356    /// position closure at predefined levels, aiding risk management. Bots should
357    /// verify this field for risk-limiting orders to prevent unintended position
358    /// retention.
359    pub close_on_trigger: bool,
360
361    /// The type of self-match prevention.
362    ///
363    /// Specifies the self-match prevention (SMP) mechanism to prevent a trader’s own
364    /// orders from matching against each other, which could manipulate market
365    /// perception. In perpetual futures, this is relevant for large or institutional
366    /// bots to comply with exchange rules. Retail bots typically see an empty string
367    /// unless SMP is configured. Bots should log this for compliance auditing.
368    pub smp_type: String,
369
370    /// The self-match prevention group identifier.
371    ///
372    /// Groups orders for SMP purposes, assigning them to a specific SMP group. In
373    /// perpetual futures, this is relevant for advanced bots managing large order
374    /// books. Retail bots can usually ignore this unless participating in SMP
375    /// mechanisms. Bots should use this to ensure compliance with Bybit’s trading
376    /// rules.
377    pub smp_group: i32,
378
379    /// The identifier of the matched SMP order (optional).
380    ///
381    /// Indicates if an order was affected by SMP, identifying the matched order. In
382    /// perpetual futures, this is typically `None` for retail bots but relevant for
383    /// institutional traders. Bots should log this for auditing and compliance,
384
385    /// ensuring SMP rules are followed to avoid penalties.
386    #[serde(
387        deserialize_with = "empty_string_as_none",
388        skip_serializing_if = "is_empty_or_none"
389    )]
390    pub smp_order_id: Option<String>,
391
392    /// The take-profit/stop-loss mode (e.g., "Full", "Partial").
393    ///
394    /// Specifies whether TP/SL applies to the entire position ("Full") or a portion
395    /// ("Partial"). In perpetual futures, "Full" ensures complete position closure at
396    /// TP/SL levels, simplifying risk management, while "Partial" suits complex exit
397    /// strategies like scaling out. Bots should verify this field to confirm exit
398    /// strategy alignment and adjust TP/SL settings accordingly.
399    #[serde(skip_serializing_if = "String::is_empty")]
400    pub tpsl_mode: String,
401
402    /// The limit price for take-profit orders (optional).
403    ///
404    /// The exact price for a limit-based take-profit order. In perpetual futures,
405
406    /// this allows precise profit-taking but risks non-execution if the market doesn’t
407    /// reach the price. If `None`, the TP is not limit-based. Bots should set this
408    /// based on market depth and volatility to balance execution likelihood and
409    /// profitability, ensuring compliance with tick size constraints.
410    #[serde(with = "string_to_float_optional")]
411    pub tp_limit_price: Option<f64>,
412
413    /// The limit price for stop-loss orders (optional).
414    ///
415    /// The exact price for a limit-based stop-loss order. Similar to `tp_limit_price`,
416
417    /// bots must balance precision with execution risk, ensuring the price is
418    /// achievable in volatile perpetual futures markets to protect against losses. If
419    /// `None`, the SL is not limit-based. Bots should validate this against market
420    /// conditions to ensure effective risk management.
421    #[serde(with = "string_to_float_optional")]
422    pub sl_limit_price: Option<f64>,
423
424    /// The placement type of the order (optional).
425    ///
426    /// Indicates how the order was placed, such as via API, web, or mobile app. In
427    /// perpetual futures, this is typically `None` for API-based orders but may be
428    /// used for auditing or tracking order sources. Bots should log this for
429    /// traceability, especially in multi-platform trading environments.
430    #[serde(
431        deserialize_with = "empty_string_as_none",
432        skip_serializing_if = "is_empty_or_none"
433    )]
434    pub place_type: Option<String>,
435
436    /// The timestamp when the order was created (in milliseconds).
437    ///
438    /// The time the order was placed, in Unix epoch milliseconds. In perpetual
439    /// futures, bots use this to track order age and correlate with market events.
440    /// For example, comparing `created_time` with `updated_time` helps assess order
441    /// execution latency. Bots should log this for auditing and performance analysis.
442    #[serde(with = "string_to_u64")]
443    pub created_time: u64,
444
445    /// The timestamp when the order was last updated (in milliseconds).
446    ///
447    /// The time of the most recent update to the order (e.g., partial fill,
448
449    /// cancellation), in Unix epoch milliseconds. In perpetual futures, bots use this
450    /// to monitor order progress and detect changes in status or execution. Comparing
451    /// `updated_time` with `created_time` helps evaluate market responsiveness and
452    /// strategy timing. Bots should use this for real-time state management.
453    #[serde(with = "string_to_u64")]
454    pub updated_time: u64,
455}