1use nautilus_model::{
27 data::{Data, OrderBookDeltas},
28 events::{
29 AccountState, OrderAccepted, OrderCanceled, OrderFilled, OrderRejected, OrderUpdated,
30 },
31 identifiers::{ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId},
32 instruments::InstrumentAny,
33};
34use nautilus_network::websocket::WebSocketClient;
35use serde::{Deserialize, Serialize};
36use ustr::Ustr;
37
38use crate::{
39 common::enums::{
40 BinanceAlgoStatus, BinanceAlgoType, BinanceFuturesOrderType, BinanceKlineInterval,
41 BinanceMarginType, BinanceOrderStatus, BinancePositionSide, BinanceSide,
42 BinanceTimeInForce, BinanceWorkingType, BinanceWsMethod,
43 },
44 futures::http::BinanceFuturesInstrument,
45};
46
47#[derive(Debug, Clone)]
52pub enum NautilusWsMessage {
53 Data(NautilusDataWsMessage),
55 Exec(Box<NautilusExecWsMessage>),
57 ExecRaw(BinanceFuturesExecWsMessage),
59 Error(BinanceFuturesWsErrorMsg),
61 Reconnected,
63}
64
65#[derive(Debug, Clone)]
69pub enum NautilusDataWsMessage {
70 Data(Vec<Data>),
72 DepthUpdate {
74 deltas: OrderBookDeltas,
75 first_update_id: u64,
76 prev_final_update_id: u64,
77 },
78 Instrument(Box<InstrumentAny>),
80 RawJson(serde_json::Value),
82}
83
84#[derive(Debug, Clone)]
90pub enum NautilusExecWsMessage {
91 AccountUpdate(AccountState),
93 OrderAccepted(OrderAccepted),
95 OrderCanceled(OrderCanceled),
97 OrderRejected(OrderRejected),
99 OrderFilled(OrderFilled),
101 OrderUpdated(OrderUpdated),
103 ListenKeyExpired,
105 Reconnected,
107}
108
109#[derive(Debug, Clone)]
115pub enum BinanceFuturesExecWsMessage {
116 AccountUpdate(BinanceFuturesAccountUpdateMsg),
118 OrderUpdate(Box<BinanceFuturesOrderUpdateMsg>),
120 AlgoUpdate(Box<BinanceFuturesAlgoUpdateMsg>),
122 MarginCall(BinanceFuturesMarginCallMsg),
124 AccountConfigUpdate(BinanceFuturesAccountConfigMsg),
126 ListenKeyExpired,
128}
129
130#[derive(Debug, Clone)]
132pub struct BinanceFuturesWsErrorMsg {
133 pub code: i64,
135 pub msg: String,
137}
138
139#[derive(Debug)]
141#[allow(
142 clippy::large_enum_variant,
143 reason = "Commands are ephemeral and immediately consumed"
144)]
145pub enum DataHandlerCommand {
146 SetClient(WebSocketClient),
148 Disconnect,
150 InitializeInstruments(Vec<InstrumentAny>),
152 UpdateInstrument(InstrumentAny),
154 Subscribe { streams: Vec<String> },
156 Unsubscribe { streams: Vec<String> },
158}
159
160#[derive(Debug)]
162#[allow(
163 clippy::large_enum_variant,
164 reason = "Commands are ephemeral and immediately consumed"
165)]
166pub enum ExecHandlerCommand {
167 SetClient(WebSocketClient),
169 Disconnect,
171 InitializeInstruments(Vec<BinanceFuturesInstrument>),
173 UpdateInstrument(BinanceFuturesInstrument),
175 Subscribe { streams: Vec<String> },
177 RegisterOrder {
179 client_order_id: ClientOrderId,
180 trader_id: TraderId,
181 strategy_id: StrategyId,
182 instrument_id: InstrumentId,
183 },
184 RegisterCancel {
186 client_order_id: ClientOrderId,
187 trader_id: TraderId,
188 strategy_id: StrategyId,
189 instrument_id: InstrumentId,
190 venue_order_id: Option<VenueOrderId>,
191 },
192 RegisterModify {
194 client_order_id: ClientOrderId,
195 trader_id: TraderId,
196 strategy_id: StrategyId,
197 instrument_id: InstrumentId,
198 venue_order_id: Option<VenueOrderId>,
199 },
200}
201
202#[derive(Debug, Clone, Deserialize)]
204pub struct BinanceFuturesAggTradeMsg {
205 #[serde(rename = "e")]
207 pub event_type: String,
208 #[serde(rename = "E")]
210 pub event_time: i64,
211 #[serde(rename = "s")]
213 pub symbol: Ustr,
214 #[serde(rename = "a")]
216 pub agg_trade_id: u64,
217 #[serde(rename = "p")]
219 pub price: String,
220 #[serde(rename = "q")]
222 pub quantity: String,
223 #[serde(rename = "f")]
225 pub first_trade_id: u64,
226 #[serde(rename = "l")]
228 pub last_trade_id: u64,
229 #[serde(rename = "T")]
231 pub trade_time: i64,
232 #[serde(rename = "m")]
234 pub is_buyer_maker: bool,
235}
236
237#[derive(Debug, Clone, Deserialize)]
239pub struct BinanceFuturesTradeMsg {
240 #[serde(rename = "e")]
242 pub event_type: String,
243 #[serde(rename = "E")]
245 pub event_time: i64,
246 #[serde(rename = "s")]
248 pub symbol: Ustr,
249 #[serde(rename = "t")]
251 pub trade_id: u64,
252 #[serde(rename = "p")]
254 pub price: String,
255 #[serde(rename = "q")]
257 pub quantity: String,
258 #[serde(rename = "T")]
260 pub trade_time: i64,
261 #[serde(rename = "m")]
263 pub is_buyer_maker: bool,
264}
265
266#[derive(Debug, Clone, Deserialize)]
268pub struct BinanceFuturesDepthUpdateMsg {
269 #[serde(rename = "e")]
271 pub event_type: String,
272 #[serde(rename = "E")]
274 pub event_time: i64,
275 #[serde(rename = "T")]
277 pub transaction_time: i64,
278 #[serde(rename = "s")]
280 pub symbol: Ustr,
281 #[serde(rename = "U")]
283 pub first_update_id: u64,
284 #[serde(rename = "u")]
286 pub final_update_id: u64,
287 #[serde(rename = "pu")]
289 pub prev_final_update_id: u64,
290 #[serde(rename = "b")]
292 pub bids: Vec<[String; 2]>,
293 #[serde(rename = "a")]
295 pub asks: Vec<[String; 2]>,
296}
297
298#[derive(Debug, Clone, Deserialize)]
300pub struct BinanceFuturesMarkPriceMsg {
301 #[serde(rename = "e")]
303 pub event_type: String,
304 #[serde(rename = "E")]
306 pub event_time: i64,
307 #[serde(rename = "s")]
309 pub symbol: Ustr,
310 #[serde(rename = "p")]
312 pub mark_price: String,
313 #[serde(rename = "i")]
315 pub index_price: String,
316 #[serde(rename = "P")]
318 pub estimated_settle_price: String,
319 #[serde(rename = "r")]
321 pub funding_rate: String,
322 #[serde(rename = "T")]
324 pub next_funding_time: i64,
325}
326
327#[derive(Debug, Clone, Deserialize)]
329pub struct BinanceFuturesBookTickerMsg {
330 #[serde(rename = "e")]
332 pub event_type: String,
333 #[serde(rename = "u")]
335 pub update_id: u64,
336 #[serde(rename = "E")]
338 pub event_time: i64,
339 #[serde(rename = "T")]
341 pub transaction_time: i64,
342 #[serde(rename = "s")]
344 pub symbol: Ustr,
345 #[serde(rename = "b")]
347 pub best_bid_price: String,
348 #[serde(rename = "B")]
350 pub best_bid_qty: String,
351 #[serde(rename = "a")]
353 pub best_ask_price: String,
354 #[serde(rename = "A")]
356 pub best_ask_qty: String,
357}
358
359#[derive(Debug, Clone, Deserialize)]
361pub struct BinanceFuturesKlineMsg {
362 #[serde(rename = "e")]
364 pub event_type: String,
365 #[serde(rename = "E")]
367 pub event_time: i64,
368 #[serde(rename = "s")]
370 pub symbol: Ustr,
371 #[serde(rename = "k")]
373 pub kline: BinanceFuturesKlineData,
374}
375
376#[derive(Debug, Clone, Deserialize)]
378pub struct BinanceFuturesKlineData {
379 #[serde(rename = "t")]
381 pub start_time: i64,
382 #[serde(rename = "T")]
384 pub close_time: i64,
385 #[serde(rename = "s")]
387 pub symbol: Ustr,
388 #[serde(rename = "i")]
390 pub interval: BinanceKlineInterval,
391 #[serde(rename = "f")]
393 pub first_trade_id: i64,
394 #[serde(rename = "L")]
396 pub last_trade_id: i64,
397 #[serde(rename = "o")]
399 pub open: String,
400 #[serde(rename = "c")]
402 pub close: String,
403 #[serde(rename = "h")]
405 pub high: String,
406 #[serde(rename = "l")]
408 pub low: String,
409 #[serde(rename = "v")]
411 pub volume: String,
412 #[serde(rename = "n")]
414 pub num_trades: i64,
415 #[serde(rename = "x")]
417 pub is_closed: bool,
418 #[serde(rename = "q")]
420 pub quote_volume: String,
421 #[serde(rename = "V")]
423 pub taker_buy_volume: String,
424 #[serde(rename = "Q")]
426 pub taker_buy_quote_volume: String,
427}
428
429#[derive(Debug, Clone, Deserialize)]
431pub struct BinanceFuturesLiquidationMsg {
432 #[serde(rename = "e")]
434 pub event_type: String,
435 #[serde(rename = "E")]
437 pub event_time: i64,
438 #[serde(rename = "o")]
440 pub order: BinanceFuturesLiquidationOrder,
441}
442
443#[derive(Debug, Clone, Deserialize)]
445pub struct BinanceFuturesLiquidationOrder {
446 #[serde(rename = "s")]
448 pub symbol: Ustr,
449 #[serde(rename = "S")]
451 pub side: BinanceSide,
452 #[serde(rename = "o")]
454 pub order_type: BinanceFuturesOrderType,
455 #[serde(rename = "f")]
457 pub time_in_force: BinanceTimeInForce,
458 #[serde(rename = "q")]
460 pub original_qty: String,
461 #[serde(rename = "p")]
463 pub price: String,
464 #[serde(rename = "ap")]
466 pub average_price: String,
467 #[serde(rename = "X")]
469 pub status: BinanceOrderStatus,
470 #[serde(rename = "l")]
472 pub last_filled_qty: String,
473 #[serde(rename = "z")]
475 pub accumulated_qty: String,
476 #[serde(rename = "T")]
478 pub trade_time: i64,
479}
480
481#[derive(Debug, Clone, Serialize)]
483pub struct BinanceFuturesWsSubscribeRequest {
484 pub method: BinanceWsMethod,
486 pub params: Vec<String>,
488 pub id: u64,
490}
491
492#[derive(Debug, Clone, Deserialize)]
494pub struct BinanceFuturesWsSubscribeResponse {
495 pub result: Option<serde_json::Value>,
497 pub id: u64,
499}
500
501#[derive(Debug, Clone, Deserialize)]
503pub struct BinanceFuturesWsErrorResponse {
504 pub code: i64,
506 pub msg: String,
508 pub id: Option<u64>,
510}
511
512#[derive(Debug, Clone, Deserialize)]
514pub struct BinanceFuturesAccountUpdateMsg {
515 #[serde(rename = "e")]
517 pub event_type: String,
518 #[serde(rename = "E")]
520 pub event_time: i64,
521 #[serde(rename = "T")]
523 pub transaction_time: i64,
524 #[serde(rename = "a")]
526 pub account: AccountUpdateData,
527}
528
529#[derive(Debug, Clone, Deserialize)]
531pub struct AccountUpdateData {
532 #[serde(rename = "m")]
534 pub reason: AccountUpdateReason,
535 #[serde(rename = "B", default)]
537 pub balances: Vec<BalanceUpdate>,
538 #[serde(rename = "P", default)]
540 pub positions: Vec<PositionUpdate>,
541}
542
543#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
545#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
546pub enum AccountUpdateReason {
547 Deposit,
548 Withdraw,
549 Order,
550 FundingFee,
551 WithdrawReject,
552 Adjustment,
553 InsuranceClear,
554 AdminDeposit,
555 AdminWithdraw,
556 MarginTransfer,
557 MarginTypeChange,
558 AssetTransfer,
559 OptionsPremiumFee,
560 OptionsSettleProfit,
561 AutoExchange,
562 CoinSwapDeposit,
563 CoinSwapWithdraw,
564 #[serde(other)]
565 Unknown,
566}
567
568#[derive(Debug, Clone, Deserialize)]
570pub struct BalanceUpdate {
571 #[serde(rename = "a")]
573 pub asset: Ustr,
574 #[serde(rename = "wb")]
576 pub wallet_balance: String,
577 #[serde(rename = "cw")]
579 pub cross_wallet_balance: String,
580 #[serde(rename = "bc", default)]
582 pub balance_change: Option<String>,
583}
584
585#[derive(Debug, Clone, Deserialize)]
587pub struct PositionUpdate {
588 #[serde(rename = "s")]
590 pub symbol: Ustr,
591 #[serde(rename = "pa")]
593 pub position_amount: String,
594 #[serde(rename = "ep")]
596 pub entry_price: String,
597 #[serde(rename = "bep", default)]
599 pub break_even_price: Option<String>,
600 #[serde(rename = "cr")]
602 pub accumulated_realized: String,
603 #[serde(rename = "up")]
605 pub unrealized_pnl: String,
606 #[serde(rename = "mt")]
608 pub margin_type: BinanceMarginType,
609 #[serde(rename = "iw")]
611 pub isolated_wallet: String,
612 #[serde(rename = "ps")]
614 pub position_side: BinancePositionSide,
615}
616
617#[derive(Debug, Clone, Deserialize)]
619pub struct BinanceFuturesOrderUpdateMsg {
620 #[serde(rename = "e")]
622 pub event_type: String,
623 #[serde(rename = "E")]
625 pub event_time: i64,
626 #[serde(rename = "T")]
628 pub transaction_time: i64,
629 #[serde(rename = "o")]
631 pub order: OrderUpdateData,
632}
633
634#[derive(Debug, Clone, Deserialize)]
636pub struct OrderUpdateData {
637 #[serde(rename = "s")]
639 pub symbol: Ustr,
640 #[serde(rename = "c")]
642 pub client_order_id: String,
643 #[serde(rename = "S")]
645 pub side: BinanceSide,
646 #[serde(rename = "o")]
648 pub order_type: BinanceFuturesOrderType,
649 #[serde(rename = "f")]
651 pub time_in_force: BinanceTimeInForce,
652 #[serde(rename = "q")]
654 pub original_qty: String,
655 #[serde(rename = "p")]
657 pub original_price: String,
658 #[serde(rename = "ap")]
660 pub average_price: String,
661 #[serde(rename = "sp")]
663 pub stop_price: String,
664 #[serde(rename = "x")]
666 pub execution_type: BinanceExecutionType,
667 #[serde(rename = "X")]
669 pub order_status: BinanceOrderStatus,
670 #[serde(rename = "i")]
672 pub order_id: i64,
673 #[serde(rename = "l")]
675 pub last_filled_qty: String,
676 #[serde(rename = "z")]
678 pub cumulative_filled_qty: String,
679 #[serde(rename = "L")]
681 pub last_filled_price: String,
682 #[serde(rename = "N", default)]
684 pub commission_asset: Option<Ustr>,
685 #[serde(rename = "n", default)]
687 pub commission: Option<String>,
688 #[serde(rename = "T")]
690 pub trade_time: i64,
691 #[serde(rename = "t")]
693 pub trade_id: i64,
694 #[serde(rename = "b", default)]
696 pub bids_notional: Option<String>,
697 #[serde(rename = "a", default)]
699 pub asks_notional: Option<String>,
700 #[serde(rename = "m")]
702 pub is_maker: bool,
703 #[serde(rename = "R")]
705 pub is_reduce_only: bool,
706 #[serde(rename = "wt")]
708 pub working_type: BinanceWorkingType,
709 #[serde(rename = "ot")]
711 pub original_order_type: BinanceFuturesOrderType,
712 #[serde(rename = "ps")]
714 pub position_side: BinancePositionSide,
715 #[serde(rename = "cp", default)]
717 pub close_position: Option<bool>,
718 #[serde(rename = "AP", default)]
720 pub activation_price: Option<String>,
721 #[serde(rename = "cr", default)]
723 pub callback_rate: Option<String>,
724 #[serde(rename = "pP", default)]
726 pub price_protect: Option<bool>,
727 #[serde(rename = "rp")]
729 pub realized_profit: String,
730 #[serde(rename = "V", default)]
732 pub stp_mode: Option<String>,
733 #[serde(rename = "pm", default)]
735 pub price_match: Option<String>,
736 #[serde(rename = "gtd", default)]
738 pub good_till_date: Option<i64>,
739}
740
741impl OrderUpdateData {
742 #[must_use]
744 pub fn is_liquidation(&self) -> bool {
745 self.client_order_id.starts_with("autoclose-")
746 }
747
748 #[must_use]
750 pub fn is_adl(&self) -> bool {
751 self.client_order_id.starts_with("adl_autoclose")
752 }
753
754 #[must_use]
756 pub fn is_settlement(&self) -> bool {
757 self.client_order_id.starts_with("settlement_autoclose-")
758 }
759
760 #[must_use]
762 pub fn is_exchange_generated(&self) -> bool {
763 self.is_liquidation() || self.is_adl() || self.is_settlement()
764 }
765}
766
767#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
769#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
770pub enum BinanceExecutionType {
771 New,
773 Canceled,
775 Calculated,
777 Expired,
779 Trade,
781 Amendment,
783}
784
785#[derive(Debug, Clone, Deserialize)]
787pub struct BinanceFuturesMarginCallMsg {
788 #[serde(rename = "e")]
790 pub event_type: String,
791 #[serde(rename = "E")]
793 pub event_time: i64,
794 #[serde(rename = "cw")]
796 pub cross_wallet_balance: String,
797 #[serde(rename = "p")]
799 pub positions: Vec<MarginCallPosition>,
800}
801
802#[derive(Debug, Clone, Deserialize)]
804pub struct MarginCallPosition {
805 #[serde(rename = "s")]
807 pub symbol: Ustr,
808 #[serde(rename = "ps")]
810 pub position_side: BinancePositionSide,
811 #[serde(rename = "pa")]
813 pub position_amount: String,
814 #[serde(rename = "mt")]
816 pub margin_type: BinanceMarginType,
817 #[serde(rename = "iw")]
819 pub isolated_wallet: String,
820 #[serde(rename = "mp")]
822 pub mark_price: String,
823 #[serde(rename = "up")]
825 pub unrealized_pnl: String,
826 #[serde(rename = "mm")]
828 pub maintenance_margin: String,
829}
830
831#[derive(Debug, Clone, Deserialize)]
833pub struct BinanceFuturesAccountConfigMsg {
834 #[serde(rename = "e")]
836 pub event_type: String,
837 #[serde(rename = "E")]
839 pub event_time: i64,
840 #[serde(rename = "T")]
842 pub transaction_time: i64,
843 #[serde(rename = "ac", default)]
845 pub leverage_config: Option<LeverageConfig>,
846 #[serde(rename = "ai", default)]
848 pub asset_index: Option<AssetIndexConfig>,
849}
850
851#[derive(Debug, Clone, Deserialize)]
853pub struct LeverageConfig {
854 #[serde(rename = "s")]
856 pub symbol: Ustr,
857 #[serde(rename = "l")]
859 pub leverage: u32,
860}
861
862#[derive(Debug, Clone, Deserialize)]
864pub struct AssetIndexConfig {
865 #[serde(rename = "s")]
867 pub symbol: Ustr,
868}
869
870#[derive(Debug, Clone, Deserialize)]
880pub struct BinanceFuturesAlgoUpdateMsg {
881 #[serde(rename = "e")]
883 pub event_type: String,
884 #[serde(rename = "E")]
886 pub event_time: i64,
887 #[serde(rename = "T")]
889 pub transaction_time: i64,
890 #[serde(rename = "ao")]
892 pub algo_order: AlgoOrderUpdateData,
893}
894
895#[derive(Debug, Clone, Deserialize)]
897pub struct AlgoOrderUpdateData {
898 #[serde(rename = "caid")]
900 pub client_algo_id: String,
901 #[serde(rename = "aid")]
903 pub algo_id: i64,
904 #[serde(rename = "at")]
906 pub algo_type: BinanceAlgoType,
907 #[serde(rename = "o")]
909 pub order_type: BinanceFuturesOrderType,
910 #[serde(rename = "s")]
912 pub symbol: Ustr,
913 #[serde(rename = "S")]
915 pub side: BinanceSide,
916 #[serde(rename = "ps")]
918 pub position_side: BinancePositionSide,
919 #[serde(rename = "f")]
921 pub time_in_force: BinanceTimeInForce,
922 #[serde(rename = "q")]
924 pub quantity: String,
925 #[serde(rename = "X")]
927 pub algo_status: BinanceAlgoStatus,
928 #[serde(rename = "tp")]
930 pub trigger_price: String,
931 #[serde(rename = "p")]
933 pub price: String,
934 #[serde(rename = "wt")]
936 pub working_type: BinanceWorkingType,
937 #[serde(rename = "pm", default)]
939 pub price_match: Option<String>,
940 #[serde(rename = "cp", default)]
942 pub close_position: Option<bool>,
943 #[serde(rename = "pP", default)]
945 pub price_protect: Option<bool>,
946 #[serde(rename = "R", default)]
948 pub reduce_only: Option<bool>,
949 #[serde(rename = "tt", default)]
951 pub trigger_time: Option<i64>,
952 #[serde(rename = "gtd", default)]
954 pub good_till_date: Option<i64>,
955 #[serde(rename = "ai", default)]
957 pub actual_order_id: Option<String>,
958 #[serde(rename = "ap", default)]
960 pub avg_price: Option<String>,
961 #[serde(rename = "aq", default)]
963 pub executed_qty: Option<String>,
964 #[serde(rename = "act", default)]
966 pub actual_order_type: Option<String>,
967 #[serde(rename = "cr", default)]
969 pub callback_rate: Option<String>,
970 #[serde(rename = "V", default)]
972 pub stp_mode: Option<String>,
973}
974
975#[derive(Debug, Clone, Deserialize)]
977pub struct BinanceFuturesListenKeyExpiredMsg {
978 #[serde(rename = "e")]
980 pub event_type: String,
981 #[serde(rename = "E")]
983 pub event_time: i64,
984}