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