15
15
16
16
from __future__ import annotations
17
17
18
- from decimal import Decimal
19
18
from typing import TYPE_CHECKING
20
19
21
20
import msgspec
39
38
from nautilus_trader .adapters .bybit .http .errors import should_retry
40
39
from nautilus_trader .adapters .bybit .schemas .common import BYBIT_PONG
41
40
from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountExecution
41
+ from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountExecutionFast
42
+ from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountExecutionFastMsg
42
43
from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountExecutionMsg
43
44
from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountOrderMsg
44
45
from nautilus_trader .adapters .bybit .schemas .ws import BybitWsAccountWalletMsg
@@ -170,11 +171,13 @@ def __init__(
170
171
self ._product_types = product_types
171
172
self ._use_gtd = config .use_gtd
172
173
self ._use_ws_trade_api = config .use_ws_trade_api
174
+ self ._use_ws_execution_fast = config .use_ws_execution_fast
173
175
self ._use_http_batch_api = config .use_http_batch_api
174
176
175
177
self ._log .info (f"Account type: { account_type_to_str (account_type )} " , LogColor .BLUE )
176
178
self ._log .info (f"Product types: { [p .value for p in product_types ]} " , LogColor .BLUE )
177
179
self ._log .info (f"{ config .use_gtd = } " , LogColor .BLUE )
180
+ self ._log .info (f"{ config .use_ws_execution_fast = } " , LogColor .BLUE )
178
181
self ._log .info (f"{ config .use_ws_trade_api = } " , LogColor .BLUE )
179
182
self ._log .info (f"{ config .use_http_batch_api = } " , LogColor .BLUE )
180
183
self ._log .info (f"{ config .ws_trade_timeout_secs = } " , LogColor .BLUE )
@@ -248,6 +251,9 @@ def __init__(
248
251
249
252
self ._decoder_ws_account_order_update = msgspec .json .Decoder (BybitWsAccountOrderMsg )
250
253
self ._decoder_ws_account_execution_update = msgspec .json .Decoder (BybitWsAccountExecutionMsg )
254
+ self ._decoder_ws_account_execution_fast_update = msgspec .json .Decoder (
255
+ BybitWsAccountExecutionFastMsg ,
256
+ )
251
257
# self._decoder_ws_account_position_update = msgspec.json.Decoder(BybitWsAccountPositionMsg)
252
258
self ._decoder_ws_account_wallet_update = msgspec .json .Decoder (BybitWsAccountWalletMsg )
253
259
@@ -269,10 +275,15 @@ async def _connect(self) -> None:
269
275
await self ._update_account_state ()
270
276
271
277
await self ._ws_client .connect ()
272
- await self . _ws_client . subscribe_executions_update ()
278
+
273
279
await self ._ws_client .subscribe_orders_update ()
274
280
await self ._ws_client .subscribe_wallet_update ()
275
281
282
+ if self ._use_ws_execution_fast :
283
+ await self ._ws_client .subscribe_executions_fast_update ()
284
+ else :
285
+ await self ._ws_client .subscribe_executions_update ()
286
+
276
287
if self ._use_ws_trade_api :
277
288
await self ._ws_order_client .connect ()
278
289
@@ -991,6 +1002,8 @@ def _handle_ws_message_private(self, raw: bytes) -> None:
991
1002
self ._handle_account_order_update (raw )
992
1003
elif "execution" in ws_message .topic :
993
1004
self ._handle_account_execution_update (raw )
1005
+ elif "execution.fast" in ws_message .topic :
1006
+ self ._handle_account_execution_fast_update (raw )
994
1007
elif "wallet" == ws_message .topic :
995
1008
self ._handle_account_wallet_update (raw )
996
1009
else :
@@ -1006,7 +1019,18 @@ def _handle_account_execution_update(self, raw: bytes) -> None:
1006
1019
except Exception as e :
1007
1020
self ._log .exception (f"Failed to handle account execution update: { e } " , e )
1008
1021
1009
- def _process_execution (self , execution : BybitWsAccountExecution ) -> None :
1022
+ def _handle_account_execution_fast_update (self , raw : bytes ) -> None :
1023
+ try :
1024
+ msg = self ._decoder_ws_account_execution_fast_update .decode (raw )
1025
+ for trade in msg .data :
1026
+ self ._process_execution (trade )
1027
+ except Exception as e :
1028
+ self ._log .exception (f"Failed to handle account execution update: { e } " , e )
1029
+
1030
+ def _process_execution (
1031
+ self ,
1032
+ execution : BybitWsAccountExecution | BybitWsAccountExecutionFast ,
1033
+ ) -> None :
1010
1034
instrument_id = self ._get_cached_instrument_id (execution .symbol , execution .category )
1011
1035
client_order_id = ClientOrderId (execution .orderLinkId ) if execution .orderLinkId else None
1012
1036
venue_order_id = VenueOrderId (execution .orderId )
@@ -1047,6 +1071,13 @@ def _process_execution(self, execution: BybitWsAccountExecution) -> None:
1047
1071
if instrument is None :
1048
1072
raise ValueError (f"Cannot handle trade event: instrument { instrument_id } not found" )
1049
1073
1074
+ quote_currency = instrument .quote_currency
1075
+ fee = instrument .maker_fee if execution .isMaker else instrument .taker_fee
1076
+
1077
+ last_qty = Quantity (float (execution .execQty ), instrument .size_precision )
1078
+ last_px = Price (float (execution .execPrice ), instrument .price_precision )
1079
+ commission_amount = last_qty * last_px * fee
1080
+
1050
1081
self .generate_order_filled (
1051
1082
strategy_id = strategy_id ,
1052
1083
instrument_id = instrument_id ,
@@ -1056,10 +1087,10 @@ def _process_execution(self, execution: BybitWsAccountExecution) -> None:
1056
1087
trade_id = TradeId (execution .execId ),
1057
1088
order_side = order_side ,
1058
1089
order_type = order_type ,
1059
- last_qty = Quantity ( float ( execution . execQty ), instrument . size_precision ) ,
1060
- last_px = Price ( float ( execution . execPrice ), instrument . price_precision ) ,
1061
- quote_currency = instrument . quote_currency ,
1062
- commission = Money (Decimal ( execution . execFee ), instrument . quote_currency ),
1090
+ last_qty = last_qty ,
1091
+ last_px = last_px ,
1092
+ quote_currency = quote_currency ,
1093
+ commission = Money (commission_amount , quote_currency ),
1063
1094
liquidity_side = LiquiditySide .MAKER if execution .isMaker else LiquiditySide .TAKER ,
1064
1095
ts_event = millis_to_nanos (float (execution .execTime )),
1065
1096
)
0 commit comments