Skip to main content

bybit/http/
market.rs

1use rust_decimal::{Decimal, serde::str_option::deserialize as option_decimal};
2use serde::{Deserialize, Serialize};
3use serde_aux::prelude::{
4    deserialize_number_from_string as number,
5    deserialize_option_number_from_string as option_number,
6};
7
8use crate::{
9    ContractType, CopyTrading, CurAuctionPhase, Side, Status, Timestamp,
10    enums::{Category, Interval},
11    serde::{empty_string_as_none, string_to_bool},
12};
13
14#[derive(Debug, Serialize)]
15pub struct GetKLinesParams {
16    pub category: Category,
17    pub symbol: String,
18    pub interval: Interval,
19    pub start: Option<Timestamp>,
20    pub end: Option<Timestamp>,
21    pub limit: Option<u64>,
22}
23
24#[derive(Debug, Deserialize, PartialEq)]
25#[serde(tag = "category")]
26pub enum KLine {
27    #[serde(rename = "inverse")]
28    Inverse { symbol: String, list: Vec<KLineRow> },
29    #[serde(rename = "linear")]
30    Linear { symbol: String, list: Vec<KLineRow> },
31    #[serde(rename = "option")]
32    Option { symbol: String, list: Vec<KLineRow> },
33    #[serde(rename = "spot")]
34    Spot { symbol: String, list: Vec<KLineRow> },
35}
36
37#[derive(Debug, Deserialize, PartialEq)]
38pub struct KLineRow {
39    /// Start time of the candle (ms)
40    #[serde(rename = "startTime", deserialize_with = "number")]
41    pub start_time: Timestamp,
42    /// Open price
43    #[serde(rename = "openPrice")]
44    pub open_price: Decimal,
45    /// Highest price
46    #[serde(rename = "highPrice")]
47    pub high_price: Decimal,
48    /// Lowest price
49    #[serde(rename = "lowPrice")]
50    pub low_price: Decimal,
51    /// Close price. Is the last traded price when the candle is not closed
52    #[serde(rename = "closePrice")]
53    pub close_price: Decimal,
54    /// Trade volume. Unit of contract: pieces of contract. Unit of spot: quantity of coins
55    #[serde(rename = "volume")]
56    pub volume: Decimal,
57    /// Turnover. Unit of figure: quantity of quota coin
58    #[serde(rename = "turnover")]
59    pub turnover: Decimal,
60}
61
62#[derive(Debug, Serialize)]
63pub struct GetTickersParams {
64    pub category: Category,
65    pub symbol: Option<String>,
66    pub base_coin: Option<String>,
67    pub exp_date: Option<String>,
68}
69
70#[derive(Debug, Deserialize, PartialEq)]
71#[serde(tag = "category")]
72pub enum Ticker {
73    #[serde(rename = "inverse")]
74    Inverse { list: Vec<LinearInverseTicker> },
75    #[serde(rename = "linear")]
76    Linear { list: Vec<LinearInverseTicker> },
77    #[serde(rename = "option")]
78    Option { list: Vec<OptionTicker> },
79    #[serde(rename = "spot")]
80    Spot { list: Vec<SpotTicker> },
81}
82
83#[derive(Debug, Deserialize, PartialEq)]
84#[serde(rename_all = "camelCase")]
85pub struct LinearInverseTicker {
86    /// Symbol name
87    pub symbol: String,
88    /// Last price
89    pub last_price: Decimal,
90    /// Mark price
91    pub mark_price: Decimal,
92    /// Index price
93    pub index_price: Decimal,
94    /// Market price 24 hours ago
95    pub prev_price24h: Decimal,
96    /// Percentage change of market price in the last 24 hours
97    pub price24h_pcnt: Decimal,
98    /// The highest price in the last 24 hours
99    pub high_price24h: Decimal,
100    /// The lowest price in the last 24 hours
101    pub low_price24h: Decimal,
102    /// Market price an hour ago
103    pub prev_price1h: Decimal,
104    /// Open interest size
105    pub open_interest: Decimal,
106    /// Open interest value
107    pub open_interest_value: Decimal,
108    /// Turnover for 24h
109    pub turnover24h: Decimal,
110    /// Volume for 24h
111    pub volume24h: Decimal,
112    /// Funding rate
113    #[serde(default, deserialize_with = "option_decimal")]
114    pub funding_rate: Option<Decimal>,
115    /// Next funding timestamp (ms)
116    #[serde(deserialize_with = "number")]
117    pub next_funding_time: Timestamp,
118    /// Predicated delivery price. It has value when 30 min before delivery
119    #[serde(default, deserialize_with = "option_decimal")]
120    pub predicted_delivery_price: Option<Decimal>,
121    /// Basis rate. Unique field for inverse futures & USDC futures
122    #[serde(default, deserialize_with = "option_decimal")]
123    pub basis_rate: Option<Decimal>,
124    /// Basis. Unique field for inverse futures & USDC futures
125    #[serde(default, deserialize_with = "option_decimal")]
126    pub basis: Option<Decimal>,
127    /// Delivery fee rate. Unique field for inverse futures & USDC futures
128    #[serde(default, deserialize_with = "option_decimal")]
129    pub delivery_fee_rate: Option<Decimal>,
130    /// Delivery date time (UTC+0). Unique field for inverse futures & USDC futures
131    #[serde(deserialize_with = "option_number")]
132    pub delivery_time: Option<Timestamp>,
133    /// Best bid price
134    pub bid1_price: Decimal,
135    /// Best bid size
136    pub bid1_size: Decimal,
137    /// Best ask price
138    pub ask1_price: Decimal,
139    /// Best ask size
140    pub ask1_size: Decimal,
141    /// Estimated pre-market contract open price. The value is meaningless when entering continuous trading phase.
142    #[serde(default, deserialize_with = "option_decimal")]
143    pub pre_open_price: Option<Decimal>,
144    /// Estimated pre-market contract open qty. The value is meaningless when entering continuous trading phase.
145    #[serde(default, deserialize_with = "option_decimal")]
146    pub pre_qty: Option<Decimal>,
147    /// Enum: NotStarted, Finished, CallAuction, CallAuctionNoCancel, CrossMatching, ContinuousTrading.
148    #[serde(default, deserialize_with = "empty_string_as_none")]
149    pub cur_pre_listing_phase: Option<CurAuctionPhase>,
150}
151
152#[derive(Debug, Deserialize, PartialEq)]
153#[serde(rename_all = "camelCase")]
154pub struct OptionTicker {
155    /// Symbol name
156    pub symbol: String,
157    /// Best bid price
158    pub bid1_price: Decimal,
159    /// Best bid size
160    pub bid1_size: Decimal,
161    /// Best bid iv
162    pub bid1_iv: Decimal,
163    /// Best ask price
164    pub ask1_price: Decimal,
165    /// Best ask size
166    pub ask1_size: Decimal,
167    /// Best ask iv
168    pub ask1_iv: Decimal,
169    /// Last price
170    pub last_price: Decimal,
171    /// The highest price in the last 24 hours
172    pub high_price24h: Decimal,
173    /// The lowest price in the last 24 hours
174    pub low_price24h: Decimal,
175    /// Mark price
176    pub mark_price: Decimal,
177    /// Index price
178    pub index_price: Decimal,
179    /// Mark price iv
180    pub mark_iv: Decimal,
181    /// Underlying price
182    pub underlying_price: Decimal,
183    /// Open interest size
184    pub open_interest: Decimal,
185    /// Turnover for 24h
186    pub turnover24h: Decimal,
187    /// Volume for 24h
188    pub volume24h: Decimal,
189    /// Total volume
190    pub total_volume: Decimal,
191    /// Total turnover
192    pub total_turnover: Decimal,
193    /// Delta
194    pub delta: Decimal,
195    /// Gamma
196    pub gamma: Decimal,
197    /// Vega
198    pub vega: Decimal,
199    /// Theta
200    pub theta: Decimal,
201    /// Predicated delivery price. It has value when 30 min before delivery
202    pub predicted_delivery_price: Decimal,
203    /// The change in the last 24 hours
204    pub change24h: Decimal,
205}
206
207#[derive(Debug, Deserialize, PartialEq)]
208#[serde(rename_all = "camelCase")]
209pub struct SpotTicker {
210    /// Symbol name
211    pub symbol: String,
212    /// Best bid price
213    pub bid1_price: Decimal,
214    /// Best bid size
215    pub bid1_size: Decimal,
216    /// Best ask price
217    pub ask1_price: Decimal,
218    /// Best ask size
219    pub ask1_size: Decimal,
220    /// Last price
221    pub last_price: Decimal,
222    /// Market price 24 hours ago
223    pub prev_price24h: Decimal,
224    /// Percentage change of market price in the last 24 hours
225    pub price24h_pcnt: Decimal,
226    /// The highest price in the last 24 hours
227    pub high_price24h: Decimal,
228    /// The lowest price in the last 24 hours
229    pub low_price24h: Decimal,
230    /// Turnover for 24h
231    pub turnover24h: Decimal,
232    /// Volume for 24h
233    pub volume24h: Decimal,
234    /// USD index price
235    /// - used to calculate USD value of the assets in Unified account
236    /// - non-collateral margin coin returns ""
237    /// - Only those trading pairs like "XXX/USDT" or "XXX/USDC" have the value
238    #[serde(default, deserialize_with = "option_decimal")]
239    pub usd_index_price: Option<Decimal>,
240}
241
242#[derive(Debug, Serialize)]
243#[serde(rename_all = "camelCase")]
244pub struct GetTradesParams {
245    pub category: Category,
246    /// required for spot/linear/inverse
247    /// optional for option
248    pub symbol: Option<String>,
249    /// Apply to option only
250    /// If the field is not passed, return BTC data by default
251    pub base_coin: Option<String>,
252    /// optionType false string Option type. Call or Put. Apply to option only
253    pub option_type: Option<u64>,
254    /// spot: [1,60], default: 60
255    /// others: [1,1000], default: 500
256    pub limit: Option<u64>,
257}
258
259#[derive(Debug, Deserialize, PartialEq)]
260#[serde(tag = "category")]
261pub enum Trade {
262    #[serde(rename = "inverse")]
263    Inverse { list: Vec<InverseLinearSpotTrade> },
264    #[serde(rename = "linear")]
265    Linear { list: Vec<InverseLinearSpotTrade> },
266    #[serde(rename = "option")]
267    Option { list: Vec<OptionTrade> },
268    #[serde(rename = "spot")]
269    Spot { list: Vec<InverseLinearSpotTrade> },
270}
271
272#[derive(Debug, Deserialize, PartialEq)]
273#[serde(rename_all = "camelCase")]
274pub struct InverseLinearSpotTrade {
275    /// Execution ID
276    pub exec_id: String,
277    /// Symbol name
278    pub symbol: String,
279    /// Trade price
280    pub price: Decimal,
281    /// Trade size
282    pub size: Decimal,
283    /// Side of taker Buy, Sell
284    pub side: Side,
285    /// Trade time (ms)
286    #[serde(deserialize_with = "number")]
287    pub time: Timestamp,
288    /// boolean Whether the trade is block trade
289    pub is_block_trade: bool,
290    /// Whether the trade is RPI trade
291    #[serde(rename = "isRPITrade")]
292    pub is_rpi_trade: bool,
293}
294
295#[derive(Debug, Deserialize, PartialEq)]
296#[serde(rename_all = "camelCase")]
297pub struct OptionTrade {
298    /// Execution ID
299    pub exec_id: String,
300    /// Symbol name
301    pub symbol: String,
302    /// Trade price
303    pub price: Decimal,
304    /// Trade size
305    pub size: Decimal,
306    /// Side of taker Buy, Sell
307    pub side: Side,
308    /// Trade time (ms)
309    #[serde(deserialize_with = "number")]
310    pub time: Timestamp,
311    /// boolean Whether the trade is block trade
312    pub is_block_trade: bool,
313    /// Whether the trade is RPI trade
314    #[serde(rename = "isRPITrade")]
315    pub is_rpi_trade: bool,
316    /// Mark price
317    #[serde(rename = "mP")]
318    pub mark_price: Decimal,
319    /// Index price
320    #[serde(rename = "iP")]
321    pub index_price: Decimal,
322    /// Mark iv
323    #[serde(rename = "mIv")]
324    pub mark_iv: Decimal,
325    /// iv
326    #[serde(rename = "iv")]
327    pub iv: Decimal,
328}
329
330#[derive(Debug, Deserialize, PartialEq)]
331#[serde(rename_all = "camelCase")]
332pub struct ServerTime {
333    /// Bybit server timestamp (sec)
334    #[serde(deserialize_with = "number")]
335    pub time_second: u64,
336    /// Bybit server timestamp (nano)
337    #[serde(deserialize_with = "number")]
338    pub time_nano: u64,
339}
340
341#[derive(Debug, Serialize)]
342pub struct GetInstrumentsInfoParams {
343    pub category: Category,
344    pub symbol: Option<String>,
345    pub status: Option<Status>,
346    pub base_coin: Option<String>,
347    pub limit: Option<i64>,
348    pub cursor: Option<String>,
349}
350
351#[derive(Debug, Deserialize, PartialEq)]
352#[serde(tag = "category")]
353pub enum InstrumentsInfo {
354    #[serde(rename = "inverse", rename_all = "camelCase")]
355    Inverse {
356        next_page_cursor: String,
357        list: Vec<InverseLinearInstrumentsInfo>,
358    },
359    #[serde(rename = "linear", rename_all = "camelCase")]
360    Linear {
361        next_page_cursor: String,
362        list: Vec<InverseLinearInstrumentsInfo>,
363    },
364    #[serde(rename = "option", rename_all = "camelCase")]
365    Option {
366        next_page_cursor: String,
367        list: Vec<OptionInstrumentsInfo>,
368    },
369    #[serde(rename = "spot", rename_all = "camelCase")]
370    Spot {
371        #[serde(default, deserialize_with = "empty_string_as_none")]
372        next_page_cursor: Option<String>,
373        list: Vec<SpotInstrumentsInfo>,
374    },
375}
376
377#[derive(Debug, Deserialize, PartialEq)]
378#[serde(rename_all = "camelCase")]
379pub struct InverseLinearInstrumentsInfo {
380    pub symbol: String,
381    pub contract_type: ContractType,
382    pub status: Status,
383    pub base_coin: String,
384    pub quote_coin: String,
385    #[serde(deserialize_with = "number")]
386    pub launch_time: Timestamp,
387    #[serde(deserialize_with = "number")]
388    pub delivery_time: Timestamp,
389    #[serde(deserialize_with = "option_decimal")]
390    pub delivery_fee_rate: Option<Decimal>,
391    #[serde(deserialize_with = "number")]
392    pub price_scale: i64,
393    pub leverage_filter: LeverageFilter,
394    pub price_filter: PriceFilter,
395    pub lot_size_filter: LotSizeFilter,
396    pub unified_margin_trade: bool,
397    pub funding_interval: i64,
398    pub settle_coin: String,
399    pub copy_trading: CopyTrading,
400    pub upper_funding_rate: Decimal,
401    pub lower_funding_rate: Decimal,
402    pub risk_parameters: RiskParameters,
403    pub is_pre_listing: bool,
404    pub pre_listing_info: Option<PreListingInfo>,
405}
406
407#[derive(Debug, Deserialize, PartialEq)]
408#[serde(rename_all = "camelCase")]
409pub struct OptionInstrumentsInfo {
410    pub symbol: String,
411    pub contract_type: ContractType,
412    pub status: Status,
413    pub base_coin: String,
414    pub quote_coin: String,
415    #[serde(deserialize_with = "number")]
416    pub launch_time: i64,
417    #[serde(deserialize_with = "number")]
418    pub delivery_time: i64,
419    #[serde(deserialize_with = "option_decimal")]
420    pub delivery_fee_rate: Option<Decimal>,
421    #[serde(deserialize_with = "number")]
422    pub price_scale: i64,
423    pub leverage_filter: LeverageFilter,
424    pub price_filter: PriceFilter,
425    pub lot_size_filter: LotSizeFilter,
426    pub unified_margin_trade: bool,
427    pub funding_interval: i64,
428    pub settle_coin: String,
429    pub copy_trading: CopyTrading,
430    pub upper_funding_rate: Decimal,
431    pub lower_funding_rate: Decimal,
432    pub risk_parameters: RiskParameters,
433    pub is_pre_listing: bool,
434    pub pre_listing_info: Option<PreListingInfo>,
435}
436
437#[derive(Debug, Deserialize, PartialEq)]
438#[serde(rename_all = "camelCase")]
439pub struct SpotInstrumentsInfo {
440    /// Symbol name
441    pub symbol: String,
442    /// Base coin
443    pub base_coin: String,
444    /// Quote coin
445    pub quote_coin: String,
446    /// Whether or not this is an innovation zone token. 0: false, 1: true
447    #[serde(deserialize_with = "string_to_bool")]
448    pub innovation: bool,
449    /// Instrument status
450    pub status: Status,
451    /// Margin trade symbol or not
452    /// This is to identify if the symbol support margin trading under different account modes
453    /// You may find some symbols not supporting margin buy or margin sell, so you need to go to Collateral Info (UTA) to check if that coin is borrowable
454    pub margin_trading: String,
455    /// Whether or not it has an special treatment label. 0: false, 1: true
456    #[serde(deserialize_with = "string_to_bool")]
457    pub st_tag: bool,
458    /// Size attributes
459    pub lot_size_filter: SpotLotSizeFilter,
460    /// Price attributes
461    pub price_filter: SpotPriceFilter,
462    /// Risk parameters for limit order price, refer to announcement
463    pub risk_parameters: RiskParameters,
464}
465
466#[derive(Debug, Deserialize, PartialEq)]
467#[serde(rename_all = "camelCase")]
468pub struct LeverageFilter {
469    pub min_leverage: Decimal,
470    pub max_leverage: Decimal,
471    pub leverage_step: Decimal,
472}
473
474#[derive(Debug, Deserialize, PartialEq)]
475#[serde(rename_all = "camelCase")]
476pub struct PriceFilter {
477    pub min_price: Decimal,
478    pub max_price: Decimal,
479    pub tick_size: Decimal,
480}
481
482#[derive(Debug, Deserialize, PartialEq)]
483#[serde(rename_all = "camelCase")]
484pub struct SpotPriceFilter {
485    /// The step to increase/reduce order price
486    pub tick_size: Decimal,
487}
488
489#[derive(Debug, Deserialize, PartialEq)]
490#[serde(rename_all = "camelCase")]
491pub struct LotSizeFilter {
492    pub min_notional_value: Decimal,
493    pub max_order_qty: Decimal,
494    pub max_mkt_order_qty: Decimal,
495    pub min_order_qty: Decimal,
496    pub qty_step: Decimal,
497    pub post_only_max_order_qty: Decimal,
498}
499
500#[derive(Debug, Deserialize, PartialEq)]
501#[serde(rename_all = "camelCase")]
502pub struct SpotLotSizeFilter {
503    /// The precision of base coin
504    pub base_precision: Decimal,
505    /// The precision of quote coin
506    pub quote_precision: Decimal,
507    /// Minimum order quantity
508    pub min_order_qty: Decimal,
509    /// Maximum order quantity
510    pub max_order_qty: Decimal,
511    /// Minimum order amount
512    pub min_order_amt: Decimal,
513    /// Maximum order amount
514    pub max_order_amt: Decimal,
515}
516
517#[derive(Debug, Deserialize, PartialEq)]
518#[serde(rename_all = "camelCase")]
519pub struct RiskParameters {
520    pub price_limit_ratio_x: Decimal,
521    pub price_limit_ratio_y: Decimal,
522}
523
524#[derive(Debug, Deserialize, PartialEq)]
525#[serde(rename_all = "camelCase")]
526pub struct PreListingInfo {
527    pub cur_auction_phase: CurAuctionPhase,
528    pub phases: Vec<Phase>,
529    pub auction_fee_info: AuctionFeeInfo,
530}
531
532#[derive(Debug, Deserialize, PartialEq)]
533#[serde(rename_all = "camelCase")]
534pub struct Phase {
535    pub phase: CurAuctionPhase,
536    #[serde(deserialize_with = "option_number")]
537    pub start_time: Option<Timestamp>,
538    #[serde(deserialize_with = "option_number")]
539    pub end_time: Option<Timestamp>,
540}
541
542#[derive(Debug, Deserialize, PartialEq)]
543#[serde(rename_all = "camelCase")]
544pub struct AuctionFeeInfo {
545    pub auction_fee_rate: Decimal,
546    pub taker_fee_rate: Decimal,
547    pub maker_fee_rate: Decimal,
548}