bybit/models/linear_ticker_data.rs
1use crate::prelude::*;
2
3/// Structure for linear perpetual futures ticker data.
4///
5/// Contains ticker metrics specific to linear perpetual futures, such as funding rates and open interest. Bots use this for real-time market analysis and risk management in USDT-margined contracts.
6
7#[derive(Deserialize, Serialize, Clone)]
8#[serde(rename_all = "camelCase")]
9#[serde(deny_unknown_fields)]
10pub struct LinearTickerData {
11 /// The trading pair symbol (e.g., "BTCUSDT").
12 ///
13 /// The ONLY required field for the ticker data. Bots use this to identify the market they are trading in.
14 ///
15 /// Identifies the perpetual futures contract for the ticker data. Bots use this to verify the correct market.
16 pub symbol: String,
17
18 /// The tick direction of the last price change.
19 ///
20 /// Indicates whether the last price change was an uptick or downtick (e.g., "PlusTick"). Bots use this to analyze short-term price momentum.
21 pub tick_direction: Option<String>,
22
23 /// The 24-hour price change percentage.
24 ///
25 /// The percentage change in price over the last 24 hours. Bots use this to assess market trends and volatility.
26 #[serde(default, with = "string_to_float_optional")]
27 pub price_24h_pcnt: Option<f64>,
28
29 /// The last traded price.
30 ///
31 /// The most recent price at which the contract was traded. Bots use this for real-time price tracking and technical analysis.
32 #[serde(default, with = "string_to_float_optional")]
33 pub last_price: Option<f64>,
34
35 /// The price 24 hours ago.
36 ///
37 /// The price of the contract 24 hours prior. Bots use this to calculate price changes and validate `price_24h_pcnt`.
38 #[serde(default, with = "string_to_float_optional")]
39 pub prev_price_24h: Option<f64>,
40
41 /// The highest price in the last 24 hours.
42 ///
43 /// The peak price reached in the last 24 hours. Bots use this to identify resistance levels and assess volatility.
44 #[serde(default, with = "string_to_float_optional")]
45 pub high_price_24h: Option<f64>,
46
47 /// The lowest price in the last 24 hours.
48 ///
49 /// The lowest price reached in the last 24 hours. Bots use this to identify support levels and assess volatility.
50 #[serde(default, with = "string_to_float_optional")]
51 pub low_price_24h: Option<f64>,
52
53 /// The price 1 hour ago.
54 ///
55 /// The price of the contract 1 hour prior. Bots use this to calculate short-term price changes and momentum.
56 #[serde(default, with = "string_to_float_optional")]
57 pub prev_price_1h: Option<f64>,
58
59 /// The open interest value in settlement currency.
60 ///
61 /// The monetary value of open interest (`open_interest` * `mark_price`). Bots use this to assess market exposure and leverage levels.
62 #[serde(default, with = "string_to_float_optional")]
63 pub open_interest_value: Option<f64>,
64
65 /// The 24-hour trading turnover.
66 ///
67 /// The total trading value in the last 24 hours, in settlement currency. Bots use this to assess market activity and liquidity.
68 #[serde(default, with = "string_to_float_optional")]
69 pub turnover_24h: Option<f64>,
70
71 /// The 24-hour trading volume.
72 ///
73 /// The total quantity of contracts traded in the last 24 hours. Bots use this to analyze market activity and trading intensity.
74 #[serde(default, with = "string_to_float_optional")]
75 pub volume_24h: Option<f64>,
76
77 /// The best bid price.
78 ///
79 /// The highest price at which someone is willing to buy. Bots use this to assess buy-side liquidity and calculate spreads.
80 #[serde(default, rename = "bid1Price", with = "string_to_float_optional")]
81 pub bid_price: Option<f64>,
82
83 /// The best bid size.
84 ///
85 /// The quantity available at the best bid price. Bots use this to evaluate buy-side liquidity and potential slippage.
86 #[serde(default, rename = "bid1Size", with = "string_to_float_optional")]
87 pub bid_size: Option<f64>,
88
89 /// The best ask price.
90 ///
91 /// The lowest price at which someone is willing to sell. Bots use this to assess sell-side liquidity and calculate spreads.
92 #[serde(default, rename = "ask1Price", with = "string_to_float_optional")]
93 pub ask_price: Option<f64>,
94
95 /// The best ask size.
96 ///
97 /// The quantity available at the best ask price. Bots use this to evaluate sell-side liquidity and potential slippage.
98 #[serde(default, rename = "ask1Size", with = "string_to_float_optional")]
99 pub ask_size: Option<f64>,
100
101 /// The pre-open price, set by Bybit for a trading pair before it enters
102 /// regular trading, often during phases like subscription, announcement,
103 /// or pre-trading for new pairs. This price guides early trading or
104 /// subscription activities.
105 #[serde(default, with = "string_to_float_optional")]
106 pub pre_open_price: Option<f64>,
107
108 /// The pre-open quantity, represents the indicative or reference price for
109 /// a trading pair during a pre-listing or pre-trading phase. This price is
110 /// typically set by the exchange to guide trading activity when the pair is
111 /// not yet fully open for unrestricted trading (e.g., during a subscription
112 /// or announcement phase for new pairs).
113 #[serde(default, with = "string_to_float_optional")]
114 pub pre_qty: Option<f64>,
115
116 /// Indicates the current stage of a trading pair in Bybit’s pre-listing
117 /// process. Pre-listing phases are used for new or upcoming trading pairs
118 /// that are not yet fully available for trading but may be in a preparatory
119 /// or promotional stage.
120 pub cur_pre_listing_phase: Option<String>,
121
122 /// The current funding rate.
123 ///
124 /// The funding rate applied to positions, as a decimal (e.g., 0.0001 for 0.01%). Bots use this to calculate funding costs or profits for long/short positions.
125 #[serde(default, with = "string_to_float_optional")]
126 pub funding_rate: Option<f64>,
127
128 /// The timestamp of the next funding event in milliseconds.
129 ///
130 /// Indicates when the next funding rate payment will occur. Bots use this to schedule funding fee calculations and position adjustments.
131 #[serde(default, with = "string_to_u64_optional")]
132 pub next_funding_time: Option<u64>,
133
134 /// The current index price.
135 ///
136 /// The index price, based on external spot markets, used for reference in perpetual futures. Bots use this to compare with mark price for funding rate calculations.
137 #[serde(default, with = "string_to_float_optional")]
138 pub index_price: Option<f64>,
139
140 /// The current mark price.
141 ///
142 /// The mark price used for P&L calculations in perpetual futures. Bots use this to calculate unrealized P&L and assess position health.
143 #[serde(default, with = "string_to_float_optional")]
144 pub mark_price: Option<f64>,
145
146 /// The open interest in contracts.
147 ///
148 /// The total number of open contracts in the market. Bots use this to gauge market participation and liquidity.
149 #[serde(default, with = "string_to_float_optional")]
150 pub open_interest: Option<f64>,
151}
152
153impl std::fmt::Debug for LinearTickerData {
154 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 let mut debug_struct = fmt.debug_struct("LinearTickerData");
156
157 debug_struct.field("symbol", &self.symbol);
158
159 if let Some(index_price) = &self.index_price {
160 debug_struct.field("index_price", index_price);
161 }
162 if let Some(tick_direction) = &self.tick_direction {
163 debug_struct.field("tick_direction", tick_direction);
164 }
165 if let Some(price_24h_pcnt) = &self.price_24h_pcnt {
166 debug_struct.field("price_24h_pcnt", price_24h_pcnt);
167 }
168 if let Some(last_price) = &self.last_price {
169 debug_struct.field("last_price", last_price);
170 }
171 if let Some(prev_price_24h) = &self.prev_price_24h {
172 debug_struct.field("prev_price_24h", prev_price_24h);
173 }
174 if let Some(high_price_24h) = &self.high_price_24h {
175 debug_struct.field("high_price_24h", high_price_24h);
176 }
177 if let Some(low_price_24h) = &self.low_price_24h {
178 debug_struct.field("low_price_24h", low_price_24h);
179 }
180 if let Some(prev_price_1h) = &self.prev_price_1h {
181 debug_struct.field("prev_price_1h", prev_price_1h);
182 }
183 if let Some(mark_price) = &self.mark_price {
184 debug_struct.field("mark_price", mark_price);
185 }
186 if let Some(open_interest) = &self.open_interest {
187 debug_struct.field("open_interest", open_interest);
188 }
189 if let Some(open_interest_value) = &self.open_interest_value {
190 debug_struct.field("open_interest_value", open_interest_value);
191 }
192 if let Some(turnover_24h) = &self.turnover_24h {
193 debug_struct.field("turnover_24h", turnover_24h);
194 }
195 if let Some(volume_24h) = &self.volume_24h {
196 debug_struct.field("volume_24h", volume_24h);
197 }
198 if let Some(next_funding_time) = &self.next_funding_time {
199 debug_struct.field("next_funding_time", next_funding_time);
200 }
201 if let Some(funding_rate) = &self.funding_rate {
202 debug_struct.field("funding_rate", funding_rate);
203 }
204 if let Some(bid_price) = &self.bid_price {
205 debug_struct.field("bid_price", bid_price);
206 }
207 if let Some(bid_size) = &self.bid_size {
208 debug_struct.field("bid_size", bid_size);
209 }
210 if let Some(ask_price) = &self.ask_price {
211 debug_struct.field("ask_price", ask_price);
212 }
213 if let Some(ask_size) = &self.ask_size {
214 debug_struct.field("ask_size", ask_size);
215 }
216 if let Some(pre_qty) = &self.pre_qty {
217 debug_struct.field("pre_qty", pre_qty);
218 }
219 if let Some(cur_pre_listing_phase) = &self.cur_pre_listing_phase {
220 debug_struct.field("cur_pre_listing_phase", cur_pre_listing_phase);
221 }
222 if let Some(pre_open_price) = &self.pre_open_price {
223 debug_struct.field("pre_open_price", pre_open_price);
224 }
225
226 debug_struct.finish()
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use itertools::Itertools;
233
234 use crate::fixture;
235
236 use super::*;
237
238 #[test]
239 fn deserialize() {
240 let json = fixture!("ws_linear_ticker");
241 let values = serde_json::from_str::<Vec<WsTicker>>(json)
242 .unwrap()
243 .into_iter()
244 .map(|t| t.data.try_unwrap_linear().unwrap())
245 .collect_vec();
246 assert_eq!(values.len(), 102);
247 }
248}