rust_okx/ws/model/block.rs
1//! Block trading channel models (`rfqs`, `quotes`, `struc-block-trades`, `block-tickers`).
2//!
3//! Mixed public and private channels.
4
5use serde::Deserialize;
6use serde_json::Value;
7
8use super::ExtraFields;
9use crate::model::NumberString;
10
11/// A leg embedded in block RFQ, quote, and structure-block-trade messages.
12#[derive(Debug, Clone, Default, Deserialize)]
13#[serde(rename_all = "camelCase")]
14#[non_exhaustive]
15pub struct BlockLeg {
16 /// Instrument ID of this leg, e.g., `BTC-USD-240329-40000-C`.
17 #[serde(default)]
18 pub inst_id: String,
19 /// Trade mode: `cross`, `isolated`, or `cash`.
20 #[serde(default)]
21 pub td_mode: String,
22 /// Margin currency (cross MARGIN orders in Futures mode only).
23 #[serde(default)]
24 pub ccy: String,
25 /// Leg size in base currency or contracts.
26 #[serde(default)]
27 pub sz: NumberString,
28 /// Leg side: `buy` or `sell`.
29 #[serde(default)]
30 pub side: String,
31 /// Position side: `long`, `short`, or `net`.
32 #[serde(default)]
33 pub pos_side: String,
34 /// Leg price.
35 #[serde(default)]
36 pub px: NumberString,
37 /// Trade ID for this leg (only present after execution).
38 #[serde(default)]
39 pub trade_id: String,
40 /// Target currency for the leg quantity (spot only): `base_ccy` or `quote_ccy`.
41 #[serde(default)]
42 pub tgt_ccy: String,
43 /// Fee charged for this leg (negative means deducted; positive means rebate).
44 #[serde(default)]
45 pub fee: NumberString,
46 /// Fee currency for this leg.
47 #[serde(default)]
48 pub fee_ccy: String,
49 /// The quote currency used for trading (spot only).
50 #[serde(default)]
51 pub trade_quote_ccy: String,
52 /// Unrecognized fields retained for forward compatibility.
53 #[serde(flatten, default)]
54 pub extra: ExtraFields,
55}
56
57/// Block-trading `rfqs` channel row.
58///
59/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-rfqs-channel>
60#[derive(Debug, Clone, Default, Deserialize)]
61#[serde(rename_all = "camelCase")]
62#[non_exhaustive]
63pub struct BlockRfqUpdate {
64 /// OKX-assigned RFQ ID.
65 #[serde(default)]
66 pub rfq_id: String,
67 /// Client-supplied RFQ ID (empty for Maker).
68 #[serde(default)]
69 pub cl_rfq_id: String,
70 /// RFQ tag.
71 #[serde(default)]
72 pub tag: String,
73 /// Taker's anonymized trader code.
74 #[serde(default)]
75 pub trader_code: String,
76 /// Time until which this RFQ is valid (Unix milliseconds).
77 #[serde(default)]
78 pub valid_until: NumberString,
79 /// List of counterparty trader codes invited to quote.
80 #[serde(default)]
81 pub counterparties: Vec<String>,
82 /// Legs that make up this RFQ.
83 #[serde(default)]
84 pub legs: Vec<BlockLeg>,
85 /// Whether partial execution is allowed on this RFQ.
86 #[serde(default)]
87 pub allow_partial_execution: bool,
88 /// RFQ state.
89 ///
90 /// Documented values: `active`, `canceled`, `filled`, `expired`, `traded_away`, `failed`.
91 #[serde(default)]
92 pub state: String,
93 /// Flow type; only applicable to Makers (empty for Takers).
94 #[serde(default)]
95 pub flow_type: String,
96 /// Group ID when this RFQ belongs to an RFQ group.
97 #[serde(default)]
98 pub group_id: String,
99 /// Account allocation details (taker only).
100 #[serde(default)]
101 pub acct_alloc: Vec<Value>,
102 /// RFQ creation time (Unix milliseconds).
103 #[serde(default)]
104 pub c_time: NumberString,
105 /// Last update time (Unix milliseconds).
106 #[serde(default)]
107 pub u_time: NumberString,
108 /// Unrecognized fields retained for forward compatibility.
109 #[serde(flatten, default)]
110 pub extra: ExtraFields,
111}
112
113/// Block-trading `quotes` channel row.
114///
115/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-quotes-channel>
116#[derive(Debug, Clone, Default, Deserialize)]
117#[serde(rename_all = "camelCase")]
118#[non_exhaustive]
119pub struct BlockQuoteUpdate {
120 /// OKX-assigned quote ID.
121 #[serde(default)]
122 pub quote_id: String,
123 /// Client-supplied quote ID (empty for Taker).
124 #[serde(default)]
125 pub cl_quote_id: String,
126 /// RFQ ID being responded to.
127 #[serde(default)]
128 pub rfq_id: String,
129 /// Client-supplied RFQ ID (empty for Maker).
130 #[serde(default)]
131 pub cl_rfq_id: String,
132 /// Quote tag.
133 #[serde(default)]
134 pub tag: String,
135 /// Maker's anonymized trader code.
136 #[serde(default)]
137 pub trader_code: String,
138 /// Quote side from the maker's perspective: `buy` or `sell`.
139 #[serde(default)]
140 pub quote_side: String,
141 /// Time until which this quote is valid (Unix milliseconds).
142 #[serde(default)]
143 pub valid_until: NumberString,
144 /// Legs that make up this quote.
145 #[serde(default)]
146 pub legs: Vec<BlockLeg>,
147 /// Quote state.
148 ///
149 /// Documented values: `active`, `canceled`, `filled`, `expired`, `failed`.
150 #[serde(default)]
151 pub state: String,
152 /// Reason for the current state (e.g., `mmp_canceled`).
153 #[serde(default)]
154 pub reason: String,
155 /// Quote creation time (Unix milliseconds).
156 #[serde(default)]
157 pub c_time: NumberString,
158 /// Last update time (Unix milliseconds).
159 #[serde(default)]
160 pub u_time: NumberString,
161 /// Unrecognized fields retained for forward compatibility.
162 #[serde(flatten, default)]
163 pub extra: ExtraFields,
164}
165
166/// Structure-block-trade channel row (private `struc-block-trades`).
167///
168/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-structure-block-trades-channel>
169#[derive(Debug, Clone, Default, Deserialize)]
170#[serde(rename_all = "camelCase")]
171#[non_exhaustive]
172pub struct StructureBlockTradeUpdate {
173 /// Block trade ID that groups one or more legs.
174 #[serde(default)]
175 pub block_td_id: String,
176 /// OKX-assigned RFQ ID.
177 #[serde(default)]
178 pub rfq_id: String,
179 /// Client-supplied RFQ ID.
180 #[serde(default)]
181 pub cl_rfq_id: String,
182 /// OKX-assigned quote ID.
183 #[serde(default)]
184 pub quote_id: String,
185 /// Client-supplied quote ID.
186 #[serde(default)]
187 pub cl_quote_id: String,
188 /// Tag associated with this trade.
189 #[serde(default)]
190 pub tag: String,
191 /// Whether the trade execution was successful.
192 #[serde(default)]
193 pub is_successful: bool,
194 /// Error code when `is_successful` is `false`; empty otherwise.
195 #[serde(default)]
196 pub error_code: String,
197 /// Taker's anonymized trader code.
198 #[serde(default)]
199 pub t_trader_code: String,
200 /// Maker's anonymized trader code.
201 #[serde(default)]
202 pub m_trader_code: String,
203 /// Legs that make up this block trade.
204 #[serde(default)]
205 pub legs: Vec<BlockLeg>,
206 /// Account allocation details for this trade.
207 #[serde(default)]
208 pub acct_alloc: Vec<Value>,
209 /// Trade creation time (Unix milliseconds).
210 #[serde(default)]
211 pub c_time: NumberString,
212 /// Unrecognized fields retained for forward compatibility.
213 #[serde(flatten, default)]
214 pub extra: ExtraFields,
215}
216
217/// Public block-trade channel row (`public-block-trades`).
218///
219/// Each push represents a single filled instrument trade.
220///
221/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-public-block-trades-channel>
222#[derive(Debug, Clone, Default, Deserialize)]
223#[serde(rename_all = "camelCase")]
224#[non_exhaustive]
225pub struct PublicBlockTradeUpdate {
226 /// Instrument ID, e.g., `BTC-USD-231020-5000-P`.
227 #[serde(default)]
228 pub inst_id: String,
229 /// Trade ID.
230 #[serde(default)]
231 pub trade_id: String,
232 /// Fill price.
233 #[serde(default)]
234 pub px: NumberString,
235 /// Fill size.
236 #[serde(default)]
237 pub sz: NumberString,
238 /// Fill side: `buy` or `sell` (taker perspective).
239 #[serde(default)]
240 pub side: String,
241 /// Implied volatility (options only).
242 #[serde(default)]
243 pub fill_vol: NumberString,
244 /// Forward price (options only).
245 #[serde(default)]
246 pub fwd_px: NumberString,
247 /// Index price (futures / swap / option).
248 #[serde(default)]
249 pub idx_px: NumberString,
250 /// Mark price (futures / swap / option).
251 #[serde(default)]
252 pub mark_px: NumberString,
253 /// Group RFQ ID; empty for normal trades.
254 #[serde(default)]
255 pub group_id: String,
256 /// Push time (Unix milliseconds).
257 #[serde(default)]
258 pub ts: NumberString,
259 /// Unrecognized fields retained for forward compatibility.
260 #[serde(flatten, default)]
261 pub extra: ExtraFields,
262}
263
264/// Public structure-block-trade channel row (`public-struc-block-trades`).
265///
266/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-public-structure-block-trades-channel>
267#[derive(Debug, Clone, Default, Deserialize)]
268#[serde(rename_all = "camelCase")]
269#[non_exhaustive]
270pub struct PublicStructureBlockTradeUpdate {
271 /// Block trade ID.
272 #[serde(default)]
273 pub block_td_id: String,
274 /// Group RFQ ID; empty for normal trades.
275 #[serde(default)]
276 pub group_id: String,
277 /// Legs of the structure block trade.
278 ///
279 /// Each leg carries `instId`, `px`, `sz`, `side`, and `tradeId`.
280 #[serde(default)]
281 pub legs: Vec<BlockLeg>,
282 /// Trade creation time (Unix milliseconds).
283 #[serde(default)]
284 pub c_time: NumberString,
285 /// Unrecognized fields retained for forward compatibility.
286 #[serde(flatten, default)]
287 pub extra: ExtraFields,
288}
289
290/// `block-tickers` channel row.
291///
292/// OKX docs: <https://www.okx.com/docs-v5/en/#block-trading-websocket-block-tickers-channel>
293#[derive(Debug, Clone, Default, Deserialize)]
294#[serde(rename_all = "camelCase")]
295#[non_exhaustive]
296pub struct BlockTickerUpdate {
297 /// Instrument type, e.g., `SWAP`, `FUTURES`, `OPTION`.
298 #[serde(default)]
299 pub inst_type: String,
300 /// Instrument ID, e.g., `LTC-USD-SWAP`.
301 #[serde(default)]
302 pub inst_id: String,
303 /// 24h block-trading volume in currency units.
304 #[serde(default)]
305 pub vol_ccy24h: NumberString,
306 /// 24h block-trading volume in contracts.
307 #[serde(default)]
308 pub vol24h: NumberString,
309 /// Ticker data generation time (Unix milliseconds).
310 #[serde(default)]
311 pub ts: NumberString,
312 /// Unrecognized fields retained for forward compatibility.
313 #[serde(flatten, default)]
314 pub extra: ExtraFields,
315}