nautilus_binance/futures/websocket/
messages.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Binance Futures WebSocket message types.
17//!
18//! Futures streams use standard JSON encoding (not SBE like Spot).
19
20use nautilus_model::{
21    data::{Data, OrderBookDeltas},
22    instruments::InstrumentAny,
23};
24use nautilus_network::websocket::WebSocketClient;
25use serde::{Deserialize, Serialize};
26use ustr::Ustr;
27
28use crate::common::enums::{
29    BinanceFuturesOrderType, BinanceKlineInterval, BinanceOrderStatus, BinanceSide,
30    BinanceTimeInForce, BinanceWsMethod,
31};
32
33/// Output message from the Futures WebSocket handler.
34#[derive(Debug, Clone)]
35pub enum NautilusFuturesWsMessage {
36    /// Market data (trades, quotes).
37    Data(Vec<Data>),
38    /// Order book deltas.
39    Deltas(OrderBookDeltas),
40    /// Instrument update.
41    Instrument(Box<InstrumentAny>),
42    /// Error from the server.
43    Error(BinanceFuturesWsErrorMsg),
44    /// Raw JSON message (for debugging or unhandled types).
45    RawJson(serde_json::Value),
46    /// WebSocket reconnected - subscriptions should be restored.
47    Reconnected,
48}
49
50/// Error message from Binance Futures WebSocket.
51#[derive(Debug, Clone)]
52pub struct BinanceFuturesWsErrorMsg {
53    /// Error code from Binance.
54    pub code: i64,
55    /// Error message.
56    pub msg: String,
57}
58
59/// Handler command for client-handler communication.
60#[derive(Debug)]
61#[allow(
62    clippy::large_enum_variant,
63    reason = "Commands are ephemeral and immediately consumed"
64)]
65pub enum BinanceFuturesHandlerCommand {
66    /// Set the WebSocket client reference.
67    SetClient(WebSocketClient),
68    /// Disconnect from the WebSocket.
69    Disconnect,
70    /// Initialize instruments in the handler cache.
71    InitializeInstruments(Vec<InstrumentAny>),
72    /// Update a single instrument in the handler cache.
73    UpdateInstrument(InstrumentAny),
74    /// Subscribe to streams.
75    Subscribe { streams: Vec<String> },
76    /// Unsubscribe from streams.
77    Unsubscribe { streams: Vec<String> },
78}
79
80// ------------------------------------------------------------------------------------------------
81// JSON Stream Messages from Binance Futures WebSocket
82// ------------------------------------------------------------------------------------------------
83
84/// Aggregate trade stream message.
85#[derive(Debug, Clone, Deserialize)]
86pub struct BinanceFuturesAggTradeMsg {
87    /// Event type.
88    #[serde(rename = "e")]
89    pub event_type: String,
90    /// Event time in milliseconds.
91    #[serde(rename = "E")]
92    pub event_time: i64,
93    /// Symbol.
94    #[serde(rename = "s")]
95    pub symbol: Ustr,
96    /// Aggregate trade ID.
97    #[serde(rename = "a")]
98    pub agg_trade_id: u64,
99    /// Price.
100    #[serde(rename = "p")]
101    pub price: String,
102    /// Quantity.
103    #[serde(rename = "q")]
104    pub quantity: String,
105    /// First trade ID.
106    #[serde(rename = "f")]
107    pub first_trade_id: u64,
108    /// Last trade ID.
109    #[serde(rename = "l")]
110    pub last_trade_id: u64,
111    /// Trade time in milliseconds.
112    #[serde(rename = "T")]
113    pub trade_time: i64,
114    /// Is buyer the market maker.
115    #[serde(rename = "m")]
116    pub is_buyer_maker: bool,
117}
118
119/// Trade stream message.
120#[derive(Debug, Clone, Deserialize)]
121pub struct BinanceFuturesTradeMsg {
122    /// Event type.
123    #[serde(rename = "e")]
124    pub event_type: String,
125    /// Event time in milliseconds.
126    #[serde(rename = "E")]
127    pub event_time: i64,
128    /// Symbol.
129    #[serde(rename = "s")]
130    pub symbol: Ustr,
131    /// Trade ID.
132    #[serde(rename = "t")]
133    pub trade_id: u64,
134    /// Price.
135    #[serde(rename = "p")]
136    pub price: String,
137    /// Quantity.
138    #[serde(rename = "q")]
139    pub quantity: String,
140    /// Trade time in milliseconds.
141    #[serde(rename = "T")]
142    pub trade_time: i64,
143    /// Is buyer the market maker.
144    #[serde(rename = "m")]
145    pub is_buyer_maker: bool,
146}
147
148/// Order book depth update stream message.
149#[derive(Debug, Clone, Deserialize)]
150pub struct BinanceFuturesDepthUpdateMsg {
151    /// Event type.
152    #[serde(rename = "e")]
153    pub event_type: String,
154    /// Event time in milliseconds.
155    #[serde(rename = "E")]
156    pub event_time: i64,
157    /// Transaction time in milliseconds.
158    #[serde(rename = "T")]
159    pub transaction_time: i64,
160    /// Symbol.
161    #[serde(rename = "s")]
162    pub symbol: Ustr,
163    /// First update ID.
164    #[serde(rename = "U")]
165    pub first_update_id: u64,
166    /// Final update ID.
167    #[serde(rename = "u")]
168    pub final_update_id: u64,
169    /// Previous final update ID.
170    #[serde(rename = "pu")]
171    pub prev_final_update_id: u64,
172    /// Bids [price, quantity].
173    #[serde(rename = "b")]
174    pub bids: Vec<[String; 2]>,
175    /// Asks [price, quantity].
176    #[serde(rename = "a")]
177    pub asks: Vec<[String; 2]>,
178}
179
180/// Mark price stream message.
181#[derive(Debug, Clone, Deserialize)]
182pub struct BinanceFuturesMarkPriceMsg {
183    /// Event type.
184    #[serde(rename = "e")]
185    pub event_type: String,
186    /// Event time in milliseconds.
187    #[serde(rename = "E")]
188    pub event_time: i64,
189    /// Symbol.
190    #[serde(rename = "s")]
191    pub symbol: Ustr,
192    /// Mark price.
193    #[serde(rename = "p")]
194    pub mark_price: String,
195    /// Index price.
196    #[serde(rename = "i")]
197    pub index_price: String,
198    /// Estimated settle price.
199    #[serde(rename = "P")]
200    pub estimated_settle_price: String,
201    /// Funding rate.
202    #[serde(rename = "r")]
203    pub funding_rate: String,
204    /// Next funding time in milliseconds.
205    #[serde(rename = "T")]
206    pub next_funding_time: i64,
207}
208
209/// Book ticker stream message.
210#[derive(Debug, Clone, Deserialize)]
211pub struct BinanceFuturesBookTickerMsg {
212    /// Event type.
213    #[serde(rename = "e")]
214    pub event_type: String,
215    /// Update ID.
216    #[serde(rename = "u")]
217    pub update_id: u64,
218    /// Event time in milliseconds.
219    #[serde(rename = "E")]
220    pub event_time: i64,
221    /// Transaction time in milliseconds.
222    #[serde(rename = "T")]
223    pub transaction_time: i64,
224    /// Symbol.
225    #[serde(rename = "s")]
226    pub symbol: Ustr,
227    /// Best bid price.
228    #[serde(rename = "b")]
229    pub best_bid_price: String,
230    /// Best bid quantity.
231    #[serde(rename = "B")]
232    pub best_bid_qty: String,
233    /// Best ask price.
234    #[serde(rename = "a")]
235    pub best_ask_price: String,
236    /// Best ask quantity.
237    #[serde(rename = "A")]
238    pub best_ask_qty: String,
239}
240
241/// Kline/candlestick stream message.
242#[derive(Debug, Clone, Deserialize)]
243pub struct BinanceFuturesKlineMsg {
244    /// Event type.
245    #[serde(rename = "e")]
246    pub event_type: String,
247    /// Event time in milliseconds.
248    #[serde(rename = "E")]
249    pub event_time: i64,
250    /// Symbol.
251    #[serde(rename = "s")]
252    pub symbol: Ustr,
253    /// Kline data.
254    #[serde(rename = "k")]
255    pub kline: BinanceFuturesKlineData,
256}
257
258/// Kline data within kline message.
259#[derive(Debug, Clone, Deserialize)]
260pub struct BinanceFuturesKlineData {
261    /// Kline start time.
262    #[serde(rename = "t")]
263    pub start_time: i64,
264    /// Kline close time.
265    #[serde(rename = "T")]
266    pub close_time: i64,
267    /// Symbol.
268    #[serde(rename = "s")]
269    pub symbol: Ustr,
270    /// Kline interval.
271    #[serde(rename = "i")]
272    pub interval: BinanceKlineInterval,
273    /// First trade ID.
274    #[serde(rename = "f")]
275    pub first_trade_id: i64,
276    /// Last trade ID.
277    #[serde(rename = "L")]
278    pub last_trade_id: i64,
279    /// Open price.
280    #[serde(rename = "o")]
281    pub open: String,
282    /// Close price.
283    #[serde(rename = "c")]
284    pub close: String,
285    /// High price.
286    #[serde(rename = "h")]
287    pub high: String,
288    /// Low price.
289    #[serde(rename = "l")]
290    pub low: String,
291    /// Base asset volume.
292    #[serde(rename = "v")]
293    pub volume: String,
294    /// Number of trades.
295    #[serde(rename = "n")]
296    pub num_trades: i64,
297    /// Is this kline closed.
298    #[serde(rename = "x")]
299    pub is_closed: bool,
300    /// Quote asset volume.
301    #[serde(rename = "q")]
302    pub quote_volume: String,
303    /// Taker buy base asset volume.
304    #[serde(rename = "V")]
305    pub taker_buy_volume: String,
306    /// Taker buy quote asset volume.
307    #[serde(rename = "Q")]
308    pub taker_buy_quote_volume: String,
309}
310
311/// Liquidation order stream message.
312#[derive(Debug, Clone, Deserialize)]
313pub struct BinanceFuturesLiquidationMsg {
314    /// Event type.
315    #[serde(rename = "e")]
316    pub event_type: String,
317    /// Event time in milliseconds.
318    #[serde(rename = "E")]
319    pub event_time: i64,
320    /// Order data.
321    #[serde(rename = "o")]
322    pub order: BinanceFuturesLiquidationOrder,
323}
324
325/// Liquidation order details.
326#[derive(Debug, Clone, Deserialize)]
327pub struct BinanceFuturesLiquidationOrder {
328    /// Symbol.
329    #[serde(rename = "s")]
330    pub symbol: Ustr,
331    /// Order side.
332    #[serde(rename = "S")]
333    pub side: BinanceSide,
334    /// Order type.
335    #[serde(rename = "o")]
336    pub order_type: BinanceFuturesOrderType,
337    /// Time in force.
338    #[serde(rename = "f")]
339    pub time_in_force: BinanceTimeInForce,
340    /// Original quantity.
341    #[serde(rename = "q")]
342    pub original_qty: String,
343    /// Price.
344    #[serde(rename = "p")]
345    pub price: String,
346    /// Average price.
347    #[serde(rename = "ap")]
348    pub average_price: String,
349    /// Order status.
350    #[serde(rename = "X")]
351    pub status: BinanceOrderStatus,
352    /// Last filled quantity.
353    #[serde(rename = "l")]
354    pub last_filled_qty: String,
355    /// Accumulated filled quantity.
356    #[serde(rename = "z")]
357    pub accumulated_qty: String,
358    /// Trade time in milliseconds.
359    #[serde(rename = "T")]
360    pub trade_time: i64,
361}
362
363// ------------------------------------------------------------------------------------------------
364// Subscription Request/Response
365// ------------------------------------------------------------------------------------------------
366
367/// WebSocket subscription request.
368#[derive(Debug, Clone, Serialize)]
369pub struct BinanceFuturesWsSubscribeRequest {
370    /// Request method.
371    pub method: BinanceWsMethod,
372    /// Stream names to subscribe.
373    pub params: Vec<String>,
374    /// Request ID.
375    pub id: u64,
376}
377
378/// WebSocket subscription response.
379#[derive(Debug, Clone, Deserialize)]
380pub struct BinanceFuturesWsSubscribeResponse {
381    /// Response result (null on success).
382    pub result: Option<serde_json::Value>,
383    /// Request ID echoed back.
384    pub id: u64,
385}
386
387/// WebSocket error response.
388#[derive(Debug, Clone, Deserialize)]
389pub struct BinanceFuturesWsErrorResponse {
390    /// Error code.
391    pub code: i64,
392    /// Error message.
393    pub msg: String,
394    /// Request ID if available.
395    pub id: Option<u64>,
396}