Skip to main content

rust_okx/api/market/
responses.rs

1use serde::Deserialize;
2
3use crate::{NumberString, model::InstType};
4
5/// The latest ticker snapshot for an instrument.
6#[derive(Debug, Clone, Deserialize)]
7#[serde(rename_all = "camelCase")]
8#[non_exhaustive]
9pub struct Ticker {
10    /// Instrument type.
11    pub inst_type: InstType,
12    /// Instrument ID, e.g. `BTC-USDT`.
13    pub inst_id: String,
14    /// Last traded price.
15    pub last: NumberString,
16    /// Last traded size.
17    #[serde(default)]
18    pub last_sz: NumberString,
19    /// Best ask price.
20    #[serde(default)]
21    pub ask_px: NumberString,
22    /// Best ask size.
23    #[serde(default)]
24    pub ask_sz: NumberString,
25    /// Best bid price.
26    #[serde(default)]
27    pub bid_px: NumberString,
28    /// Best bid size.
29    #[serde(default)]
30    pub bid_sz: NumberString,
31    /// Open price over the last 24 hours.
32    #[serde(default)]
33    pub open24h: NumberString,
34    /// Highest price over the last 24 hours.
35    #[serde(default)]
36    pub high24h: NumberString,
37    /// Lowest price over the last 24 hours.
38    #[serde(default)]
39    pub low24h: NumberString,
40    /// Trading volume (base ccy) over the last 24 hours.
41    #[serde(default)]
42    pub vol24h: NumberString,
43    /// Trading volume (quote ccy) over the last 24 hours.
44    #[serde(default)]
45    pub vol_ccy24h: NumberString,
46    /// Opening price (UTC 0).
47    #[serde(default)]
48    pub sod_utc0: NumberString,
49    /// Opening price (UTC 8).
50    #[serde(default)]
51    pub sod_utc8: NumberString,
52    /// Ticker timestamp (Unix milliseconds).
53    pub ts: NumberString,
54}
55
56/// The latest index ticker snapshot.
57#[derive(Debug, Clone, Deserialize)]
58#[serde(rename_all = "camelCase")]
59#[non_exhaustive]
60pub struct IndexTicker {
61    /// Index instrument ID, e.g. `BTC-USD`.
62    pub inst_id: String,
63    /// Index price.
64    #[serde(default)]
65    pub idx_px: NumberString,
66    /// Open price over the last 24 hours.
67    #[serde(default)]
68    pub open24h: NumberString,
69    /// Highest price over the last 24 hours.
70    #[serde(default)]
71    pub high24h: NumberString,
72    /// Lowest price over the last 24 hours.
73    #[serde(default)]
74    pub low24h: NumberString,
75    /// Opening price (UTC 0).
76    #[serde(default)]
77    pub sod_utc0: NumberString,
78    /// Opening price (UTC 8).
79    #[serde(default)]
80    pub sod_utc8: NumberString,
81    /// Timestamp (Unix milliseconds).
82    #[serde(default)]
83    pub ts: NumberString,
84}
85
86/// An order book snapshot.
87#[derive(Debug, Clone, Deserialize)]
88#[serde(rename_all = "camelCase")]
89#[non_exhaustive]
90pub struct OrderBook {
91    /// Ask levels, sorted from best (lowest) price.
92    pub asks: Vec<OrderBookLevel>,
93    /// Bid levels, sorted from best (highest) price.
94    pub bids: Vec<OrderBookLevel>,
95    /// Snapshot timestamp (Unix milliseconds).
96    pub ts: NumberString,
97}
98
99/// A single price level in an [`OrderBook`].
100///
101/// On the wire OKX encodes a level as the array
102/// `[price, size, deprecated, order_count]`.
103#[derive(Debug, Clone, Deserialize)]
104#[serde(from = "BookLevelRaw")]
105#[non_exhaustive]
106pub struct OrderBookLevel {
107    /// Price at this level.
108    pub price: NumberString,
109    /// Aggregated size available at this level.
110    pub size: NumberString,
111    /// Deprecated field (always `0`), retained for wire compatibility.
112    pub deprecated: NumberString,
113    /// Number of orders aggregated at this level.
114    pub order_count: NumberString,
115}
116
117type BookLevelRaw = (NumberString, NumberString, NumberString, NumberString);
118
119impl From<BookLevelRaw> for OrderBookLevel {
120    fn from(raw: BookLevelRaw) -> Self {
121        Self {
122            price: raw.0,
123            size: raw.1,
124            deprecated: raw.2,
125            order_count: raw.3,
126        }
127    }
128}
129
130/// A single candlestick (OHLCV) bar.
131///
132/// On the wire OKX encodes a bar as a 9-element string array.
133#[derive(Debug, Clone, Deserialize)]
134#[serde(from = "CandleRaw")]
135#[non_exhaustive]
136pub struct Candle {
137    /// Opening timestamp (Unix milliseconds).
138    pub ts: NumberString,
139    /// Open price.
140    pub open: NumberString,
141    /// Highest price.
142    pub high: NumberString,
143    /// Lowest price.
144    pub low: NumberString,
145    /// Close price.
146    pub close: NumberString,
147    /// Trading volume in contracts / base currency.
148    pub vol: NumberString,
149    /// Trading volume in quote currency.
150    pub vol_ccy: NumberString,
151    /// Trading volume in quote currency (alternate calculation).
152    pub vol_ccy_quote: NumberString,
153    /// `1` if the bar is closed/confirmed, `0` otherwise.
154    pub confirm: NumberString,
155}
156
157type CandleRaw = (
158    NumberString,
159    NumberString,
160    NumberString,
161    NumberString,
162    NumberString,
163    NumberString,
164    NumberString,
165    NumberString,
166    NumberString,
167);
168
169impl From<CandleRaw> for Candle {
170    fn from(raw: CandleRaw) -> Self {
171        Self {
172            ts: raw.0,
173            open: raw.1,
174            high: raw.2,
175            low: raw.3,
176            close: raw.4,
177            vol: raw.5,
178            vol_ccy: raw.6,
179            vol_ccy_quote: raw.7,
180            confirm: raw.8,
181        }
182    }
183}
184
185/// A public trade record.
186#[derive(Debug, Clone, Deserialize)]
187#[serde(rename_all = "camelCase")]
188#[non_exhaustive]
189pub struct MarketTrade {
190    /// Instrument ID.
191    pub inst_id: String,
192    /// Trade ID.
193    #[serde(default)]
194    pub trade_id: String,
195    /// Trade price.
196    #[serde(default)]
197    pub px: NumberString,
198    /// Trade size.
199    #[serde(default)]
200    pub sz: NumberString,
201    /// Trade side (`buy` or `sell`).
202    #[serde(default)]
203    pub side: String,
204    /// Trade source.
205    #[serde(default)]
206    pub source: String,
207    /// Trade timestamp (Unix milliseconds).
208    #[serde(default)]
209    pub ts: NumberString,
210}
211
212/// A block-trading ticker snapshot.
213///
214/// OKX block ticker rows are sparser than regular ticker rows, so fields that
215/// are required by [`Ticker`] are optional/defaulted here.
216#[derive(Debug, Clone, Deserialize)]
217#[serde(rename_all = "camelCase")]
218#[non_exhaustive]
219pub struct BlockTicker {
220    /// Instrument type, when present.
221    #[serde(default)]
222    pub inst_type: String,
223    /// Instrument ID, e.g. `BTC-USDT-SWAP`.
224    #[serde(default)]
225    pub inst_id: String,
226    /// Last traded price, when present.
227    #[serde(default)]
228    pub last: NumberString,
229    /// Last traded size, when present.
230    #[serde(default)]
231    pub last_sz: NumberString,
232    /// Best ask price, when present.
233    #[serde(default)]
234    pub ask_px: NumberString,
235    /// Best ask size, when present.
236    #[serde(default)]
237    pub ask_sz: NumberString,
238    /// Best bid price, when present.
239    #[serde(default)]
240    pub bid_px: NumberString,
241    /// Best bid size, when present.
242    #[serde(default)]
243    pub bid_sz: NumberString,
244    /// Open price over the last 24 hours, when present.
245    #[serde(default)]
246    pub open24h: NumberString,
247    /// Highest price over the last 24 hours, when present.
248    #[serde(default)]
249    pub high24h: NumberString,
250    /// Lowest price over the last 24 hours, when present.
251    #[serde(default)]
252    pub low24h: NumberString,
253    /// Trading volume over the last 24 hours, when present.
254    #[serde(default)]
255    pub vol24h: NumberString,
256    /// Trading volume in currency units over the last 24 hours, when present.
257    #[serde(default)]
258    pub vol_ccy24h: NumberString,
259    /// Opening price (UTC 0), when present.
260    #[serde(default)]
261    pub sod_utc0: NumberString,
262    /// Opening price (UTC 8), when present.
263    #[serde(default)]
264    pub sod_utc8: NumberString,
265    /// Ticker timestamp (Unix milliseconds), when present.
266    #[serde(default)]
267    pub ts: NumberString,
268}
269
270/// A public block-trade record.
271pub type BlockTrade = MarketTrade;
272
273/// A public option trade record grouped by instrument family.
274#[derive(Debug, Clone, Deserialize)]
275#[serde(rename_all = "camelCase")]
276#[non_exhaustive]
277pub struct OptionInstrumentFamilyTrade {
278    /// Instrument ID, when present.
279    #[serde(default)]
280    pub inst_id: String,
281    /// Instrument family, when present.
282    #[serde(default)]
283    pub inst_family: String,
284    /// Trade ID, when present.
285    #[serde(default)]
286    pub trade_id: String,
287    /// Trade price.
288    #[serde(default)]
289    pub px: NumberString,
290    /// Trade size.
291    #[serde(default)]
292    pub sz: NumberString,
293    /// Trade side (`buy` or `sell`), when present.
294    #[serde(default)]
295    pub side: String,
296    /// Trade timestamp (Unix milliseconds), when present.
297    #[serde(default)]
298    pub ts: NumberString,
299}
300
301/// OKX platform 24-hour trading volume.
302#[derive(Debug, Clone, Deserialize)]
303#[serde(rename_all = "camelCase")]
304#[non_exhaustive]
305pub struct PlatformVolume {
306    /// 24-hour volume in USD.
307    #[serde(default)]
308    pub vol_usd: NumberString,
309    /// 24-hour volume in CNY.
310    #[serde(default)]
311    pub vol_cny: NumberString,
312}
313
314/// The components that make up an OKX index.
315#[derive(Debug, Clone, Deserialize)]
316#[serde(rename_all = "camelCase")]
317#[non_exhaustive]
318pub struct IndexComponents {
319    /// Index name.
320    #[serde(default)]
321    pub index: String,
322    /// Component list.
323    #[serde(default)]
324    pub components: Vec<IndexComponent>,
325    /// Timestamp (Unix milliseconds).
326    #[serde(default)]
327    pub ts: NumberString,
328}
329
330/// A single index component.
331#[derive(Debug, Clone, Deserialize)]
332#[serde(rename_all = "camelCase")]
333#[non_exhaustive]
334pub struct IndexComponent {
335    /// Exchange name.
336    #[serde(default)]
337    pub exch: String,
338    /// Symbol used by the component exchange.
339    #[serde(default)]
340    pub symbol: String,
341    /// Component price.
342    #[serde(default)]
343    pub sym_px: NumberString,
344    /// Component weight.
345    #[serde(default)]
346    pub wgt: NumberString,
347    /// Conversion price.
348    #[serde(default)]
349    pub cnv_px: NumberString,
350}
351
352/// The USD/CNY exchange rate.
353#[derive(Debug, Clone, Deserialize)]
354#[serde(rename_all = "camelCase")]
355#[non_exhaustive]
356pub struct ExchangeRate {
357    /// USD/CNY rate.
358    #[serde(default)]
359    pub usd_cny: NumberString,
360}
361
362/// A single candlestick bar for index/mark-price endpoints (6-element array).
363#[derive(Debug, Clone, Deserialize)]
364#[serde(from = "IndexCandleRaw")]
365#[non_exhaustive]
366pub struct IndexCandle {
367    /// Opening timestamp (Unix milliseconds).
368    pub ts: NumberString,
369    /// Open price.
370    pub open: NumberString,
371    /// Highest price.
372    pub high: NumberString,
373    /// Lowest price.
374    pub low: NumberString,
375    /// Close price.
376    pub close: NumberString,
377    /// `1` if the bar is closed/confirmed, `0` otherwise.
378    pub confirm: NumberString,
379}
380
381type IndexCandleRaw = (
382    NumberString,
383    NumberString,
384    NumberString,
385    NumberString,
386    NumberString,
387    NumberString,
388);
389
390impl From<IndexCandleRaw> for IndexCandle {
391    fn from(raw: IndexCandleRaw) -> Self {
392        Self {
393            ts: raw.0,
394            open: raw.1,
395            high: raw.2,
396            low: raw.3,
397            close: raw.4,
398            confirm: raw.5,
399        }
400    }
401}
402
403/// Grouped option trades returned by the instrument-family-trades endpoint.
404#[derive(Debug, Clone, Deserialize)]
405#[serde(rename_all = "camelCase")]
406#[non_exhaustive]
407pub struct OptionFamilyTradeGroup {
408    /// 24-hour volume.
409    #[serde(default)]
410    pub vol24h: NumberString,
411    /// Option type (`C` or `P`).
412    #[serde(default)]
413    pub opt_type: String,
414    /// Individual trades within this group.
415    #[serde(default)]
416    pub trade_info: Vec<OptionInstrumentFamilyTrade>,
417}