Skip to main content

bybit_api/api/
market.rs

1//! Market data API endpoints.
2
3use crate::client::BybitClient;
4use crate::error::Result;
5use crate::models::*;
6
7impl BybitClient {
8    /// Get server time.
9    ///
10    /// # Example
11    /// ```rust,no_run
12    /// # use bybit_api::BybitClient;
13    /// # async fn example() -> bybit_api::Result<()> {
14    /// let client = BybitClient::testnet("key", "secret")?;
15    /// let time = client.get_server_time().await?;
16    /// println!("Server time: {}", time.time_second);
17    /// # Ok(())
18    /// # }
19    /// ```
20    pub async fn get_server_time(&self) -> Result<ServerTime> {
21        self.get_public("/v5/market/time", &[]).await
22    }
23
24    /// Get instruments info.
25    ///
26    /// # Arguments
27    /// * `category` - Product category
28    /// * `symbol` - Optional symbol filter
29    ///
30    /// # Example
31    /// ```rust,no_run
32    /// # use bybit_api::{BybitClient, Category};
33    /// # async fn example() -> bybit_api::Result<()> {
34    /// let client = BybitClient::testnet("key", "secret")?;
35    /// let info = client.get_instruments_info(Category::Linear, Some("BTCUSDT")).await?;
36    /// # Ok(())
37    /// # }
38    /// ```
39    pub async fn get_instruments_info(
40        &self,
41        category: Category,
42        symbol: Option<&str>,
43    ) -> Result<InstrumentsInfo> {
44        let mut params = vec![("category", category.to_string())];
45
46        let symbol_str;
47        if let Some(s) = symbol {
48            symbol_str = s.to_string();
49            params.push(("symbol", symbol_str.clone()));
50        }
51
52        let params_ref: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
53
54        self.get_public("/v5/market/instruments-info", &params_ref)
55            .await
56    }
57
58    /// Get orderbook.
59    ///
60    /// # Arguments
61    /// * `category` - Product category
62    /// * `symbol` - Symbol name
63    /// * `limit` - Optional depth limit (1-500, default 25)
64    pub async fn get_orderbook(
65        &self,
66        category: Category,
67        symbol: &str,
68        limit: Option<u32>,
69    ) -> Result<Orderbook> {
70        let cat_str = category.to_string();
71        let limit_str = limit.unwrap_or(25).to_string();
72
73        let params = vec![
74            ("category", cat_str.as_str()),
75            ("symbol", symbol),
76            ("limit", limit_str.as_str()),
77        ];
78
79        self.get_public("/v5/market/orderbook", &params).await
80    }
81
82    /// Get tickers.
83    ///
84    /// # Arguments
85    /// * `category` - Product category
86    /// * `symbol` - Optional symbol filter (returns all if None)
87    pub async fn get_tickers(&self, category: Category, symbol: Option<&str>) -> Result<Tickers> {
88        let cat_str = category.to_string();
89        let mut params = vec![("category", cat_str.as_str())];
90
91        if let Some(s) = symbol {
92            params.push(("symbol", s));
93        }
94
95        self.get_public("/v5/market/tickers", &params).await
96    }
97
98    /// Get klines (candlestick data).
99    ///
100    /// # Arguments
101    /// * `category` - Product category
102    /// * `symbol` - Symbol name
103    /// * `interval` - Kline interval
104    /// * `limit` - Optional limit (1-1000, default 200)
105    pub async fn get_klines(
106        &self,
107        category: Category,
108        symbol: &str,
109        interval: Interval,
110        limit: Option<u32>,
111    ) -> Result<Klines> {
112        let cat_str = category.to_string();
113        let interval_str = interval.to_string();
114        let limit_str = limit.unwrap_or(200).to_string();
115
116        let params = vec![
117            ("category", cat_str.as_str()),
118            ("symbol", symbol),
119            ("interval", interval_str.as_str()),
120            ("limit", limit_str.as_str()),
121        ];
122
123        self.get_public("/v5/market/kline", &params).await
124    }
125
126    /// Get funding rate history.
127    ///
128    /// # Arguments
129    /// * `category` - Product category (linear or inverse)
130    /// * `symbol` - Symbol name
131    /// * `limit` - Optional limit (default 200)
132    pub async fn get_funding_history(
133        &self,
134        category: Category,
135        symbol: &str,
136        limit: Option<u32>,
137    ) -> Result<FundingHistory> {
138        let cat_str = category.to_string();
139        let limit_str = limit.unwrap_or(200).to_string();
140
141        let params = vec![
142            ("category", cat_str.as_str()),
143            ("symbol", symbol),
144            ("limit", limit_str.as_str()),
145        ];
146
147        self.get_public("/v5/market/funding/history", &params).await
148    }
149
150    /// Get recent trades.
151    ///
152    /// # Arguments
153    /// * `category` - Product category
154    /// * `symbol` - Symbol name
155    /// * `limit` - Optional limit (1-1000, default 500)
156    pub async fn get_recent_trades(
157        &self,
158        category: Category,
159        symbol: &str,
160        limit: Option<u32>,
161    ) -> Result<RecentTrades> {
162        let cat_str = category.to_string();
163        let limit_str = limit.unwrap_or(500).to_string();
164
165        let params = vec![
166            ("category", cat_str.as_str()),
167            ("symbol", symbol),
168            ("limit", limit_str.as_str()),
169        ];
170
171        self.get_public("/v5/market/recent-trade", &params).await
172    }
173
174    /// Get open interest.
175    ///
176    /// # Arguments
177    /// * `category` - Product category (linear or inverse)
178    /// * `symbol` - Symbol name
179    /// * `interval_time` - Interval (5min, 15min, 30min, 1h, 4h, 1d)
180    /// * `limit` - Optional limit (default 50)
181    pub async fn get_open_interest(
182        &self,
183        category: Category,
184        symbol: &str,
185        interval_time: &str,
186        limit: Option<u32>,
187    ) -> Result<OpenInterest> {
188        let cat_str = category.to_string();
189        let limit_str = limit.unwrap_or(50).to_string();
190
191        let params = vec![
192            ("category", cat_str.as_str()),
193            ("symbol", symbol),
194            ("intervalTime", interval_time),
195            ("limit", limit_str.as_str()),
196        ];
197
198        self.get_public("/v5/market/open-interest", &params).await
199    }
200
201    /// Get risk limit info.
202    ///
203    /// # Arguments
204    /// * `category` - Product category (linear or inverse)
205    /// * `symbol` - Optional symbol filter
206    pub async fn get_risk_limit(
207        &self,
208        category: Category,
209        symbol: Option<&str>,
210    ) -> Result<RiskLimits> {
211        let cat_str = category.to_string();
212        let mut params = vec![("category", cat_str.as_str())];
213
214        if let Some(s) = symbol {
215            params.push(("symbol", s));
216        }
217
218        self.get_public("/v5/market/risk-limit", &params).await
219    }
220
221    /// Get mark price kline.
222    pub async fn get_mark_price_kline(
223        &self,
224        category: Category,
225        symbol: &str,
226        interval: Interval,
227        limit: Option<u32>,
228    ) -> Result<Klines> {
229        let cat_str = category.to_string();
230        let interval_str = interval.to_string();
231        let limit_str = limit.unwrap_or(200).to_string();
232
233        let params = vec![
234            ("category", cat_str.as_str()),
235            ("symbol", symbol),
236            ("interval", interval_str.as_str()),
237            ("limit", limit_str.as_str()),
238        ];
239
240        self.get_public("/v5/market/mark-price-kline", &params)
241            .await
242    }
243
244    /// Get index price kline.
245    pub async fn get_index_price_kline(
246        &self,
247        category: Category,
248        symbol: &str,
249        interval: Interval,
250        limit: Option<u32>,
251    ) -> Result<Klines> {
252        let cat_str = category.to_string();
253        let interval_str = interval.to_string();
254        let limit_str = limit.unwrap_or(200).to_string();
255
256        let params = vec![
257            ("category", cat_str.as_str()),
258            ("symbol", symbol),
259            ("interval", interval_str.as_str()),
260            ("limit", limit_str.as_str()),
261        ];
262
263        self.get_public("/v5/market/index-price-kline", &params)
264            .await
265    }
266
267    /// Get premium index price kline.
268    pub async fn get_premium_index_price_kline(
269        &self,
270        category: Category,
271        symbol: &str,
272        interval: Interval,
273        limit: Option<u32>,
274    ) -> Result<Klines> {
275        let cat_str = category.to_string();
276        let interval_str = interval.to_string();
277        let limit_str = limit.unwrap_or(200).to_string();
278
279        let params = vec![
280            ("category", cat_str.as_str()),
281            ("symbol", symbol),
282            ("interval", interval_str.as_str()),
283            ("limit", limit_str.as_str()),
284        ];
285
286        self.get_public("/v5/market/premium-index-price-kline", &params)
287            .await
288    }
289
290    pub async fn get_adl_alert(&self, symbol: Option<&str>) -> Result<GetAdlAlertResponse> {
291        let mut params: Vec<(&str, &str)> = vec![];
292        if let Some(s) = symbol {
293            params.push(("symbol", s));
294        }
295        self.get_public("/v5/market/adlAlert", &params).await
296    }
297
298    pub async fn get_delivery_price(
299        &self,
300        category: Category,
301        symbol: Option<&str>,
302        base_coin: Option<&str>,
303        settle_coin: Option<&str>,
304        limit: Option<u32>,
305        cursor: Option<&str>,
306    ) -> Result<GetDeliveryPriceResponse> {
307        let cat_str = category.to_string();
308        let limit_str = limit.map(|v| v.to_string());
309        let mut params: Vec<(&str, &str)> = vec![("category", cat_str.as_str())];
310        if let Some(s) = symbol {
311            params.push(("symbol", s));
312        }
313        if let Some(s) = base_coin {
314            params.push(("baseCoin", s));
315        }
316        if let Some(s) = settle_coin {
317            params.push(("settleCoin", s));
318        }
319        if let Some(ref s) = limit_str {
320            params.push(("limit", s.as_str()));
321        }
322        if let Some(s) = cursor {
323            params.push(("cursor", s));
324        }
325        self.get_public("/v5/market/delivery-price", &params).await
326    }
327
328    pub async fn get_historical_volatility(
329        &self,
330        category: Category,
331        base_coin: Option<&str>,
332        quote_coin: Option<&str>,
333        period: Option<u32>,
334        start_time: Option<u64>,
335        end_time: Option<u64>,
336    ) -> Result<GetHistoricalVolatilityResponse> {
337        let cat_str = category.to_string();
338        let period_str = period.map(|v| v.to_string());
339        let start_time_str = start_time.map(|v| v.to_string());
340        let end_time_str = end_time.map(|v| v.to_string());
341        let mut params: Vec<(&str, &str)> = vec![("category", cat_str.as_str())];
342        if let Some(s) = base_coin {
343            params.push(("baseCoin", s));
344        }
345        if let Some(s) = quote_coin {
346            params.push(("quoteCoin", s));
347        }
348        if let Some(ref s) = period_str {
349            params.push(("period", s.as_str()));
350        }
351        if let Some(ref s) = start_time_str {
352            params.push(("startTime", s.as_str()));
353        }
354        if let Some(ref s) = end_time_str {
355            params.push(("endTime", s.as_str()));
356        }
357        self.get_public("/v5/market/historical-volatility", &params)
358            .await
359    }
360
361    pub async fn get_index_price_components(
362        &self,
363        index_name: &str,
364    ) -> Result<GetIndexPriceComponentsResponse> {
365        let params: Vec<(&str, &str)> = vec![("indexName", index_name)];
366        self.get_public("/v5/market/index-price-components", &params)
367            .await
368    }
369
370    pub async fn get_insurance_pool(&self, coin: Option<&str>) -> Result<GetInsurancePoolResponse> {
371        let mut params: Vec<(&str, &str)> = vec![];
372        if let Some(s) = coin {
373            params.push(("coin", s));
374        }
375        self.get_public("/v5/market/insurance", &params).await
376    }
377
378    #[allow(clippy::too_many_arguments)] // TODO(api-ergonomics): convert positional args to a typed `*Params` struct
379    pub async fn get_long_short_ratio(
380        &self,
381        category: Category,
382        symbol: &str,
383        period: &str,
384        start_time: Option<&str>,
385        end_time: Option<&str>,
386        limit: Option<u32>,
387        cursor: Option<&str>,
388    ) -> Result<GetLongShortRatioResponse> {
389        let cat_str = category.to_string();
390        let limit_str = limit.map(|v| v.to_string());
391        let mut params: Vec<(&str, &str)> = vec![
392            ("category", cat_str.as_str()),
393            ("symbol", symbol),
394            ("period", period),
395        ];
396        if let Some(s) = start_time {
397            params.push(("startTime", s));
398        }
399        if let Some(s) = end_time {
400            params.push(("endTime", s));
401        }
402        if let Some(ref s) = limit_str {
403            params.push(("limit", s.as_str()));
404        }
405        if let Some(s) = cursor {
406            params.push(("cursor", s));
407        }
408        self.get_public("/v5/market/account-ratio", &params).await
409    }
410
411    pub async fn get_new_delivery_price(
412        &self,
413        category: Category,
414        base_coin: &str,
415        settle_coin: Option<&str>,
416    ) -> Result<GetNewDeliveryPriceResponse> {
417        let cat_str = category.to_string();
418        let mut params: Vec<(&str, &str)> =
419            vec![("category", cat_str.as_str()), ("baseCoin", base_coin)];
420        if let Some(s) = settle_coin {
421            params.push(("settleCoin", s));
422        }
423        self.get_public("/v5/market/new-delivery-price", &params)
424            .await
425    }
426
427    pub async fn get_order_price_limit(
428        &self,
429        category: Option<Category>,
430        symbol: &str,
431    ) -> Result<GetOrderPriceLimitResponse> {
432        let cat_str = category.map(|c| c.to_string());
433        let mut params: Vec<(&str, &str)> = vec![("symbol", symbol)];
434        if let Some(ref s) = cat_str {
435            params.push(("category", s.as_str()));
436        }
437        self.get_public("/v5/market/price-limit", &params).await
438    }
439
440    pub async fn get_rpi_orderbook(
441        &self,
442        category: Option<Category>,
443        symbol: &str,
444        limit: u32,
445    ) -> Result<GetRpiOrderbookResponse> {
446        let cat_str = category.map(|c| c.to_string());
447        let limit_str = limit.to_string();
448        let mut params: Vec<(&str, &str)> = vec![("symbol", symbol), ("limit", limit_str.as_str())];
449        if let Some(ref s) = cat_str {
450            params.push(("category", s.as_str()));
451        }
452        self.get_public("/v5/market/rpi_orderbook", &params).await
453    }
454}