From c139408473b172c5533de1aec8a192cdda29714e Mon Sep 17 00:00:00 2001 From: kulikov-dev Date: Mon, 9 Sep 2024 08:37:20 +0100 Subject: [PATCH] Add TRADE_LITE for USD-M Futures websocket https://www.binance.com/en/support/announcement/introducing-trade-lite-for-usd%E2%93%A2-m-futures-websocket-2024-09-03-f2809259702b46f7abdc9c97b977908f https://developers.binance.com/docs/derivatives/usds-margined-futures/user-data-streams/Event-Trade-Lite --- .../SocketSubscriptionTests.cs | 1 + .../Subscriptions/UsdFutures/TradeUpdate.txt | 22 ++++++ Binance.Net/Binance.Net.xml | 74 ++++++++++++++++++- .../BinanceSocketClientUsdFuturesApi.cs | 3 +- .../IBinanceSocketClientUsdFuturesApi.cs | 2 + .../Socket/BinanceFuturesStreamTradeUpdate.cs | 72 ++++++++++++++++++ .../BinanceUsdFuturesUserDataSubscription.cs | 10 +++ 7 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 Binance.Net.UnitTests/Subscriptions/UsdFutures/TradeUpdate.txt create mode 100644 Binance.Net/Objects/Models/Futures/Socket/BinanceFuturesStreamTradeUpdate.cs diff --git a/Binance.Net.UnitTests/SocketSubscriptionTests.cs b/Binance.Net.UnitTests/SocketSubscriptionTests.cs index fd42285f0..614496e37 100644 --- a/Binance.Net.UnitTests/SocketSubscriptionTests.cs +++ b/Binance.Net.UnitTests/SocketSubscriptionTests.cs @@ -70,6 +70,7 @@ public async Task ValidateUsdFuturesSubscriptions() await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onMarginUpdate: handler), "MarginUpdate"); await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onAccountUpdate: handler), "AccountUpdate"); await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onOrderUpdate : handler), "OrderUpdate", ignoreProperties: new List { "si", "ss" }); + await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onTradeUpdate: handler), "TradeUpdate"); await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onStrategyUpdate : handler), "StrategyUpdate"); await tester.ValidateAsync((client, handler) => client.UsdFuturesApi.SubscribeToUserDataUpdatesAsync("123", onConditionalOrderTriggerRejectUpdate: handler), "ConditionalTrigger"); } diff --git a/Binance.Net.UnitTests/Subscriptions/UsdFutures/TradeUpdate.txt b/Binance.Net.UnitTests/Subscriptions/UsdFutures/TradeUpdate.txt new file mode 100644 index 000000000..3702536e5 --- /dev/null +++ b/Binance.Net.UnitTests/Subscriptions/UsdFutures/TradeUpdate.txt @@ -0,0 +1,22 @@ +> { "method": "SUBSCRIBE", "params": [ "123" ], "id": "|1|" } +< { "result": null, "id": |1| } += +{ + "stream": "123", + "data": + { + "e":"TRADE_LITE", + "E":1721895408092, + "T":1721895408214, + "s":"BTCUSDT", + "q":"0.001", + "p":"0", + "m":false, + "c":"z8hcUoOsqEdKMeKPSABslD", + "S":"BUY", + "L":"64089.20", + "l":"0.040", + "t":109100866, + "i":8886774 + } +} \ No newline at end of file diff --git a/Binance.Net/Binance.Net.xml b/Binance.Net/Binance.Net.xml index 6ed9d5553..c22e6ec57 100644 --- a/Binance.Net/Binance.Net.xml +++ b/Binance.Net/Binance.Net.xml @@ -2320,7 +2320,7 @@ - + @@ -12493,7 +12493,7 @@ Cancellation token for closing this subscription - + Subscribes to the account update stream. Prior to using this, the restClient.UsdFuturesApi.Account.StartUserStreamAsync method should be called to start the stream and obtaining a listen key. @@ -12503,6 +12503,7 @@ The event handler for whenever a margin has changed The event handler for whenever an account update is received The event handler for whenever an order status update is received + The event handler for whenever an trade status update is received Responds when the listen key for the stream has expired. Initiate a new instance of the stream here The event handler for whenever a strategy update is received The event handler for whenever a grid update is received @@ -28685,6 +28686,72 @@ Auxiliary number for quick calculation + + + Update data about a trade + + + + + Transaction time + + + + + The symbol the order is for + + + + + The quantity of the order + + + + + The price of the order + + + + + Whether the buyer is the maker + + + + + The new client order id + + + special client order id: + starts with "autoclose-": liquidation order + "adl_autoclose": ADL auto close order + "settlement_autoclose-": settlement order for delisting or delivery + + + + + The side of the order + + + + + The price of the last filled trade + + + + + The quantity of the last filled trade of this order + + + + + The trade id + + + + + The id of the order as assigned by Binance + + Strategy update @@ -29019,13 +29086,14 @@ - + ctor + diff --git a/Binance.Net/Clients/UsdFuturesApi/BinanceSocketClientUsdFuturesApi.cs b/Binance.Net/Clients/UsdFuturesApi/BinanceSocketClientUsdFuturesApi.cs index 1527e013f..6191d4f84 100644 --- a/Binance.Net/Clients/UsdFuturesApi/BinanceSocketClientUsdFuturesApi.cs +++ b/Binance.Net/Clients/UsdFuturesApi/BinanceSocketClientUsdFuturesApi.cs @@ -393,6 +393,7 @@ public async Task> SubscribeToUserDataUpdatesAsyn Action>? onMarginUpdate = null, Action>? onAccountUpdate = null, Action>? onOrderUpdate = null, + Action>? onTradeUpdate = null, Action>? onListenKeyExpired = null, Action>? onStrategyUpdate = null, Action>? onGridUpdate = null, @@ -401,7 +402,7 @@ public async Task> SubscribeToUserDataUpdatesAsyn { listenKey.ValidateNotNull(nameof(listenKey)); - var subscription = new BinanceUsdFuturesUserDataSubscription(_logger, new List { listenKey }, onOrderUpdate, onConfigUpdate, onMarginUpdate, onAccountUpdate, onListenKeyExpired, onStrategyUpdate, onGridUpdate, onConditionalOrderTriggerRejectUpdate); + var subscription = new BinanceUsdFuturesUserDataSubscription(_logger, new List { listenKey }, onOrderUpdate, onTradeUpdate, onConfigUpdate, onMarginUpdate, onAccountUpdate, onListenKeyExpired, onStrategyUpdate, onGridUpdate, onConditionalOrderTriggerRejectUpdate); return await SubscribeAsync(BaseAddress.AppendPath("stream"), subscription, ct).ConfigureAwait(false); } diff --git a/Binance.Net/Interfaces/Clients/UsdFuturesApi/IBinanceSocketClientUsdFuturesApi.cs b/Binance.Net/Interfaces/Clients/UsdFuturesApi/IBinanceSocketClientUsdFuturesApi.cs index 7beb20a7b..e43b4617a 100644 --- a/Binance.Net/Interfaces/Clients/UsdFuturesApi/IBinanceSocketClientUsdFuturesApi.cs +++ b/Binance.Net/Interfaces/Clients/UsdFuturesApi/IBinanceSocketClientUsdFuturesApi.cs @@ -322,6 +322,7 @@ Task> SubscribeToTradeUpdatesAsync(IEnumerableThe event handler for whenever a margin has changed /// The event handler for whenever an account update is received /// The event handler for whenever an order status update is received + /// The event handler for whenever an trade status update is received /// Responds when the listen key for the stream has expired. Initiate a new instance of the stream here /// The event handler for whenever a strategy update is received /// The event handler for whenever a grid update is received @@ -334,6 +335,7 @@ Task> SubscribeToUserDataUpdatesAsync( Action>? onMarginUpdate = null, Action>? onAccountUpdate = null, Action>? onOrderUpdate = null, + Action>? onTradeUpdate = null, Action>? onListenKeyExpired = null, Action>? onStrategyUpdate = null, Action>? onGridUpdate = null, diff --git a/Binance.Net/Objects/Models/Futures/Socket/BinanceFuturesStreamTradeUpdate.cs b/Binance.Net/Objects/Models/Futures/Socket/BinanceFuturesStreamTradeUpdate.cs new file mode 100644 index 000000000..86b474f5c --- /dev/null +++ b/Binance.Net/Objects/Models/Futures/Socket/BinanceFuturesStreamTradeUpdate.cs @@ -0,0 +1,72 @@ +using Binance.Net.Enums; + +namespace Binance.Net.Objects.Models.Futures.Socket +{ + /// + /// Update data about a trade + /// + public record BinanceFuturesStreamTradeUpdate : BinanceStreamEvent + { + /// + /// Transaction time + /// + [JsonPropertyName("T")] + public DateTime TransactionTime { get; set; } + /// + /// The symbol the order is for + /// + [JsonPropertyName("s")] + public string Symbol { get; set; } = string.Empty; + /// + /// The quantity of the order + /// + [JsonPropertyName("q")] + public decimal Quantity { get; set; } + /// + /// The price of the order + /// + [JsonPropertyName("p")] + public decimal Price { get; set; } + /// + /// Whether the buyer is the maker + /// + [JsonPropertyName("m")] + public bool BuyerIsMaker { get; set; } + /// + /// The new client order id + /// + /// + /// special client order id: + /// starts with "autoclose-": liquidation order + /// "adl_autoclose": ADL auto close order + /// "settlement_autoclose-": settlement order for delisting or delivery + /// + [JsonPropertyName("c")] + public string ClientOrderId { get; set; } = string.Empty; + /// + /// The side of the order + /// + [JsonPropertyName("S")] + public OrderSide Side { get; set; } + /// + /// The price of the last filled trade + /// + [JsonPropertyName("L")] + public decimal PriceLastFilledTrade { get; set; } + /// + /// The quantity of the last filled trade of this order + /// + [JsonPropertyName("l")] + public decimal QuantityOfLastFilledTrade { get; set; } + /// + /// The trade id + /// + [JsonPropertyName("t")] + public long TradeId { get; set; } + /// + /// The id of the order as assigned by Binance + /// + [JsonPropertyName("i")] + public long OrderId { get; set; } + } +} diff --git a/Binance.Net/Objects/Sockets/Subscriptions/BinanceUsdFuturesUserDataSubscription.cs b/Binance.Net/Objects/Sockets/Subscriptions/BinanceUsdFuturesUserDataSubscription.cs index 9c7a5e208..81161a85f 100644 --- a/Binance.Net/Objects/Sockets/Subscriptions/BinanceUsdFuturesUserDataSubscription.cs +++ b/Binance.Net/Objects/Sockets/Subscriptions/BinanceUsdFuturesUserDataSubscription.cs @@ -16,6 +16,7 @@ internal class BinanceUsdFuturesUserDataSubscription : Subscription ListenerIdentifiers { get; set; } private readonly Action>? _orderHandler; + private readonly Action>? _tradeHandler; private readonly Action>? _configHandler; private readonly Action>? _marginHandler; private readonly Action>? _accountHandler; @@ -36,6 +37,8 @@ internal class BinanceUsdFuturesUserDataSubscription : Subscription); if (string.Equals(identifier, "ORDER_TRADE_UPDATE", StringComparison.Ordinal)) return typeof(BinanceCombinedStream); + if (string.Equals(identifier, "TRADE_LITE", StringComparison.Ordinal)) + return typeof(BinanceCombinedStream); if (string.Equals(identifier, "listenKeyExpired", StringComparison.Ordinal)) return typeof(BinanceCombinedStream); if (string.Equals(identifier, "STRATEGY_UPDATE", StringComparison.Ordinal)) @@ -54,6 +57,7 @@ internal class BinanceUsdFuturesUserDataSubscription : Subscription /// /// + /// /// /// /// @@ -65,6 +69,7 @@ public BinanceUsdFuturesUserDataSubscription( ILogger logger, List topics, Action>? orderHandler, + Action>? tradeHandler, Action>? configHandler, Action>? marginHandler, Action>? accountHandler, @@ -81,6 +86,7 @@ public BinanceUsdFuturesUserDataSubscription( _strategyHandler = strategyHandler; _gridHandler = gridHandler; _condOrderHandler = condOrderHandler; + _tradeHandler = tradeHandler; ListenerIdentifiers = new HashSet(topics); } @@ -145,6 +151,10 @@ public override CallResult DoHandleMessage(SocketConnection connection, DataEven { _condOrderHandler?.Invoke(message.As(condUpdate.Data, condUpdate.Stream, null, SocketUpdateType.Update)); } + else if (message.Data is BinanceCombinedStream tradeUpdate) + { + _tradeHandler?.Invoke(message.As(tradeUpdate.Data, tradeUpdate.Stream, tradeUpdate.Data.Symbol, SocketUpdateType.Update)); + } return new CallResult(null); }