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}