From 9d83872e1e797d0da6560de7f6aba1cb252a72dd Mon Sep 17 00:00:00 2001
From: shanj <18996038927@163.com>
Date: Tue, 17 May 2022 04:45:23 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E5=9B=9E=E8=B0=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .editorconfig                                 |   3 +
 .../Controllers/OrderController.cs            |   4 +-
 .../Binance.TradeRobot.Business.csproj        |   4 +
 .../Spot/BaseSpotOrderPublishTradeBusiness.cs |  20 ++
 .../Spot/D21OrderPublishTradeBusiness.cs      |  10 +
 .../TradeBusiness/BaseTradeBusiness.cs        |  10 +-
 .../{ => Spot}/D21TradeBusiness.cs            |   4 +-
 Binance.TradeRobot.Business/GlobalContext.cs  |  20 +-
 .../Dto/Response/Robot/RobotResponse.cs       |  18 +-
 SDKAdapter/Model/SpotOrderTradePublishInfo.cs |   8 +-
 SDKAdapter/SDKAdapter.csproj                  |   2 +-
 .../Spot/BinanceSpotOrderWebSocketClient.cs   | 183 ++++++++++++++++++
 .../SpotOrderWebSocketClient.cs               |   7 +-
 .../BinanceSpotOrderWebSocketClient.cs        | 112 -----------
 14 files changed, 265 insertions(+), 140 deletions(-)
 create mode 100644 Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishTradeBusiness.cs
 create mode 100644 Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishTradeBusiness.cs
 rename Binance.TradeRobot.Business/Business/TradeBusiness/{ => Spot}/D21TradeBusiness.cs (99%)
 create mode 100644 SDKAdapter/WebSockets/Order/Spot/BinanceSpotOrderWebSocketClient.cs
 rename SDKAdapter/WebSockets/Order/{SpotOrder => Spot}/SpotOrderWebSocketClient.cs (87%)
 delete mode 100644 SDKAdapter/WebSockets/Order/SpotOrder/BinanceSpotOrderWebSocketClient.cs

diff --git a/.editorconfig b/.editorconfig
index 43784d5..7bb5195 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -20,3 +20,6 @@ dotnet_diagnostic.CS8600.severity = none
 
 # CS8601: 引用类型赋值可能为 null。
 dotnet_diagnostic.CS8601.severity = none
+
+# CS8629: 可为 null 的值类型可为 null。
+dotnet_diagnostic.CS8629.severity = none
diff --git a/Binance.TradeRobot.API/Controllers/OrderController.cs b/Binance.TradeRobot.API/Controllers/OrderController.cs
index 8f52fd5..7962408 100644
--- a/Binance.TradeRobot.API/Controllers/OrderController.cs
+++ b/Binance.TradeRobot.API/Controllers/OrderController.cs
@@ -17,7 +17,7 @@ namespace Binance.TradeRobot.API.Controllers
         }
 
         /// <summary>
-        /// 获取现货/逐仓杠杆订单记录
+        /// 获取现货/逐仓杠杆订单记录(最近20条)
         /// </summary>
         /// <param name="robotId"></param>
         /// <returns></returns>
@@ -28,7 +28,7 @@ namespace Binance.TradeRobot.API.Controllers
         }
 
         /// <summary>
-        /// 获取执行日志记录
+        /// 获取执行日志记录(最近50条)
         /// </summary>
         /// <param name="robotId"></param>
         /// <returns></returns>
diff --git a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj
index 2f34003..366c9da 100644
--- a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj
+++ b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj
@@ -24,4 +24,8 @@
     <ProjectReference Include="..\SDKAdapter\SDKAdapter.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="Business\OrderPublishBusiness\UPrep\" />
+  </ItemGroup>
+
 </Project>
diff --git a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishTradeBusiness.cs b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishTradeBusiness.cs
new file mode 100644
index 0000000..61aa287
--- /dev/null
+++ b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishTradeBusiness.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.Caching.Memory;
+using SDKAdapter.Model;
+using System;
+using Yitter.IdGenerator;
+
+namespace Binance.TradeRobot.Business
+{
+    public class BaseSpotOrderPublishTradeBusiness : BaseBusiness
+    {
+        public BaseSpotOrderPublishTradeBusiness(IFreeSql fsql,
+                                                 NLogManager logManager,
+                                                 IIdGenerator idGenerator,
+                                                 IMemoryCache memoryCache) : base(fsql, logManager, idGenerator, memoryCache) { }
+
+        public virtual void OnSpotOrderPublish(SpotOrderTradePublishInfo spotOrderTradePublishInfo)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
diff --git a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishTradeBusiness.cs b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishTradeBusiness.cs
new file mode 100644
index 0000000..0d08849
--- /dev/null
+++ b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishTradeBusiness.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Binance.TradeRobot.Business.Business.OrderPublishBusiness.Spot
+{
+    internal class D21OrderPublishTradeBusiness
+    {
+    }
+}
diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs
index a3a5a4a..1942324 100644
--- a/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs
+++ b/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs
@@ -41,11 +41,17 @@ namespace Binance.TradeRobot.Business
             dingBusiness.Send($"{errorMsg} {ex.Message}");
         }
 
-        protected string CreateClientOrderId(long robotId)
+        /// <summary>
+        /// 创建客户端订单号
+        /// </summary>
+        /// <param name="robotId"></param>
+        /// <param name="tradePolicy"></param>
+        /// <returns></returns>
+        protected string CreateClientOrderId(long robotId, Enums.TradePolicy tradePolicy)
         {
             var guid = Guid.NewGuid();
             var random = new Random(guid.GetHashCode());
-            return $"{Convert.ToChar(random.Next(97, 123))}{guid.ToString().Substring(0, 4)}_{robotId}";
+            return $"{Convert.ToChar(random.Next(97, 123))}{guid.ToString().Substring(0, 4)}_{robotId}_{(int)tradePolicy}";
         }
     }
 }
diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs
similarity index 99%
rename from Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs
rename to Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs
index 4fc8feb..1d193dc 100644
--- a/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs
+++ b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs
@@ -209,7 +209,7 @@ namespace Binance.TradeRobot.Business
 
                 #region 下单
                 step = "下单";
-                var clientOrderId = CreateClientOrderId(robot.Id);
+                var clientOrderId = CreateClientOrderId(robot.Id, robot.TradePolicy);
                 var orderId = apiClient.IsolatedMarginPlaceOrder(robot.Symbol,
                                                                  Enums.TradeDirection.Buy,
                                                                  Enums.OrderType.MARKET,
@@ -313,7 +313,7 @@ namespace Binance.TradeRobot.Business
                 var newestPrice = globalContext.GetSpotNewestPrice(robot.KLineKey) ?? singalRequest.ClosePrice;
                 var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey);
 
-                var clientOrderId = CreateClientOrderId(robot.Id);
+                var clientOrderId = CreateClientOrderId(robot.Id, robot.TradePolicy);
                 var orderId = apiClient.IsolatedMarginPlaceOrder(robot.Symbol,
                                                                  Enums.TradeDirection.Sell,
                                                                  Enums.OrderType.MARKET,
diff --git a/Binance.TradeRobot.Business/GlobalContext.cs b/Binance.TradeRobot.Business/GlobalContext.cs
index 712611a..962823a 100644
--- a/Binance.TradeRobot.Business/GlobalContext.cs
+++ b/Binance.TradeRobot.Business/GlobalContext.cs
@@ -1,8 +1,9 @@
 using Binance.TradeRobot.Common.DI;
 using Binance.TradeRobot.Model.Dto;
 using Microsoft.Extensions.DependencyInjection;
+using SDKAdapter.Model;
 using SDKAdapter.WebSockets.Market;
-using SDKAdapter.WebSockets.Order.SpotOrder;
+using SDKAdapter.WebSockets.Order.Spot;
 using System.Collections.Generic;
 
 namespace Binance.TradeRobot.Business
@@ -52,17 +53,17 @@ namespace Binance.TradeRobot.Business
         /// <param name="robot"></param>
         public void SubscribeOrderPublish(RobotResponse robot)
         {
-            if (!spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishListenKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
+            if (!spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
             {
                 spotOrderWebSocketClient = SpotOrderWebSocketClient.Create(robot.BusinessType,
                                                                            robot.ExchangeId,
                                                                            robot.ExchangeAPIKey.AccountId,
                                                                            robot.ExchangeAPIKey.APIKey,
                                                                            robot.ExchangeAPIKey.SecretKey,
-                                                                           logManager.GetLogger(robot.OrderPublishListenKey),
-                                                                           (e) => { });
+                                                                           logManager.GetLogger(robot.OrderPublishKey),
+                                                                           OnSpotOrderPublish);
             }
-            spotOrderWebSocketClient.Start();
+            spotOrderWebSocketClient.Start(robot.Symbol);
         }
 
 
@@ -73,8 +74,8 @@ namespace Binance.TradeRobot.Business
         /// <param name="robot"></param>
         public void UnSubscribeOrderPublish(RobotResponse robot)
         {
-            if (spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishListenKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
-                spotOrderWebSocketClient.Stop();
+            if (spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
+                spotOrderWebSocketClient.Stop(robot.Symbol);
         }
 
         /// <summary>
@@ -88,5 +89,10 @@ namespace Binance.TradeRobot.Business
                 return spotMarketWebSocketClient.NewestPrice;
             return null;
         }
+
+        public void OnSpotOrderPublish(SpotOrderTradePublishInfo spotOrderTradePublishInfo)
+        {
+            
+        }
     }
 }
diff --git a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
index 43d4b63..a989bd3 100644
--- a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
+++ b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs
@@ -30,27 +30,27 @@ namespace Binance.TradeRobot.Model.Dto
         /// 订单推送监听实例Key
         /// <para>币安逐仓杠杆需要单独的运行实例</para>
         /// </summary>
-        public virtual string OrderPublishListenKey
+        public virtual string OrderPublishKey
         {
             get
             {
                 string key = $"{BusinessType}-{ExchangeAPIKey.AccountId}";           //币安现货,币安合约,同一个账户内不区分websocket实例
                 if (ExchangeId == Enums.Exchange.Binance && BusinessType == Enums.BusinessType.IsolateMargin)
                     key = $"{BusinessType}-{ExchangeAPIKey.AccountId}-{Symbol}";     //币安逐仓杠杆,同一个账户内的每个交易对需要区分websocket实例
-                return $"OrderPublish(Origin)-{ExchangeId}-{key}";
+                return $"OrderPublish-{ExchangeId}-{key}";
             }
         }
 
         /// <summary>
         /// 订单推送日志Key
         /// </summary>
-        public virtual string OrderPublishLogKey
-        {
-            get
-            {
-                return $"OrderPublish-{ExchangeId}-{BusinessType}-{Symbol}";
-            }
-        }
+        //public virtual string OrderPublishLogKey
+        //{
+        //    get
+        //    {
+        //        return $"OrderPublish-{ExchangeId}-{BusinessType}-{Symbol}";
+        //    }
+        //}
 
         public SymbolInfoResponse SymbolInfo { get; set; }
 
diff --git a/SDKAdapter/Model/SpotOrderTradePublishInfo.cs b/SDKAdapter/Model/SpotOrderTradePublishInfo.cs
index 5eced01..782e97b 100644
--- a/SDKAdapter/Model/SpotOrderTradePublishInfo.cs
+++ b/SDKAdapter/Model/SpotOrderTradePublishInfo.cs
@@ -7,12 +7,16 @@ namespace SDKAdapter.Model
 {
     public class SpotOrderTradePublishInfo
     {
+        public long OrderId { get; set; }
+
+        public long RobotId { get; set; }
+
+        public Enums.TradePolicy TradePolicy { get; set; }
+
         public Enums.Exchange Exchange { get; set; }
 
         public long AccountId { get; set; }
 
-        public long OrderId { get; set; }
-
         public string ClientOrderId { get; set; }
 
         public string Symbol { get; set; }
diff --git a/SDKAdapter/SDKAdapter.csproj b/SDKAdapter/SDKAdapter.csproj
index 80ec790..0d2ae08 100644
--- a/SDKAdapter/SDKAdapter.csproj
+++ b/SDKAdapter/SDKAdapter.csproj
@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <Folder Include="WebSockets\Order\UPrepOrder\" />
+    <Folder Include="WebSockets\Order\UPrep\" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/SDKAdapter/WebSockets/Order/Spot/BinanceSpotOrderWebSocketClient.cs b/SDKAdapter/WebSockets/Order/Spot/BinanceSpotOrderWebSocketClient.cs
new file mode 100644
index 0000000..4e54df0
--- /dev/null
+++ b/SDKAdapter/WebSockets/Order/Spot/BinanceSpotOrderWebSocketClient.cs
@@ -0,0 +1,183 @@
+using Binance.Net.Clients;
+using Binance.Net.Objects;
+using Binance.TradeRobot.Model.Base;
+using CryptoExchange.Net.Authentication;
+using Newtonsoft.Json;
+using SDKAdapter.Model;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+namespace SDKAdapter.WebSockets.Order.Spot
+{
+    public class BinanceSpotOrderWebSocketClient : SpotOrderWebSocketClient
+    {
+        private BinanceSocketClient binanceSocketClient;
+        private BinanceClient binanceClient;
+        private CancellationTokenSource cancellationTokenSource;
+        private string listenKey;
+        private IList<Binance.Net.Enums.OrderStatus> ignoreOrderStateList;
+
+        public BinanceSpotOrderWebSocketClient(Enums.BusinessType businessType,
+                                               long accountId,
+                                               string apiKey,
+                                               string secret,
+                                               NLog.ILogger logger,
+                                               Action<SpotOrderTradePublishInfo> onOrderUpdated) : base(businessType,
+                                                                                                       accountId,
+                                                                                                       apiKey,
+                                                                                                       secret,
+                                                                                                       logger,
+                                                                                                       onOrderUpdated)
+        {
+            var spotClientOption = new BinanceApiClientOptions()
+            {
+                BaseAddress = "https://api.binance.com",
+                ApiCredentials = new ApiCredentials(apiKey, secret)
+            };
+            //var usdFuturesClientOption = new BinanceApiClientOptions()
+            //{
+            //    BaseAddress = "https://fapi.binance.com",
+            //    ApiCredentials = new ApiCredentials(apiKey, secret)
+            //};
+            binanceClient = new BinanceClient(new BinanceClientOptions()
+            {
+                //UsdFuturesApiOptions = usdFuturesClientOption,
+                SpotApiOptions = spotClientOption
+            });
+            binanceSocketClient = new BinanceSocketClient();
+            listenKey = string.Empty;
+            ignoreOrderStateList = new List<Binance.Net.Enums.OrderStatus>()
+            {
+                Binance.Net.Enums.OrderStatus.New,
+                Binance.Net.Enums.OrderStatus.PendingCancel,
+                Binance.Net.Enums.OrderStatus.Insurance,
+                Binance.Net.Enums.OrderStatus.Adl
+            };
+        }
+
+        public override void Start(string symbol = "")
+        {
+            if (IsConnected)
+                return;
+            IsConnected = true;
+            cancellationTokenSource = new CancellationTokenSource();
+            var getListenKeyResponse = binanceClient.SpotApi.Account.StartIsolatedMarginUserStreamAsync(symbol).Result;
+            if (!getListenKeyResponse.Success)
+                throw new Exception(getListenKeyResponse.Error?.Message ?? "");
+            listenKey = getListenKeyResponse.Data;
+            _ = binanceSocketClient.SpotStreams.SubscribeToUserDataUpdatesAsync(listenKey,
+                (e) =>
+                {
+                    try
+                    {
+                        var originData = new StringBuilder();
+                        var isStop = false;
+                        if (ignoreOrderStateList.Contains(e.Data.Status))
+                        {
+                            originData.Append($"不支持的订单状态{e.Data.Status}");
+                            isStop = true;
+                        }
+
+                        else if (string.IsNullOrEmpty(e.Data.ClientOrderId))
+                        {
+                            originData.Append($"缺少ClientOrderId");
+                            isStop = true;
+                        }
+
+                        long? robotId = null;
+                        Enums.TradePolicy? tradePolicy = null;
+
+                        if (!isStop)
+                        {
+                            var match = Regex.Match(e.Data.ClientOrderId, @"^([a-z0-9]{5})_(\d{15,})_(\d{1,2})$");
+                            if (!match.Success)
+                            {
+                                originData.Append($"非机器人交易的ClientOrderId");
+                                isStop = true;
+                            }
+                            else
+                            {
+                                robotId = long.Parse(match.Groups[2].Value);
+                                tradePolicy = (Enums.TradePolicy)int.Parse(match.Groups[3].Value);
+                            }
+                        }
+                        originData.Append($" {JsonConvert.SerializeObject(e.Data)}");
+                        logger.Info(originData);
+                        if (isStop)
+                            return;
+
+                        var orderState = Enums.SpotOrderState.Unknow;
+                        switch (e.Data.Status)
+                        {
+                            case Binance.Net.Enums.OrderStatus.PartiallyFilled:
+                            case Binance.Net.Enums.OrderStatus.Filled:
+                            case Binance.Net.Enums.OrderStatus.Canceled:
+                                orderState = (Enums.SpotOrderState)(int)e.Data.Status;
+                                break;
+                            case Binance.Net.Enums.OrderStatus.Rejected:
+                                orderState = Enums.SpotOrderState.Rejected;
+                                break;
+                            case Binance.Net.Enums.OrderStatus.Expired:
+                                orderState = Enums.SpotOrderState.Expired;
+                                break;
+                        }
+
+                        OnOrderUpdated?.Invoke(new SpotOrderTradePublishInfo()
+                        {
+                            OrderId = e.Data.Id,
+                            RobotId = robotId.Value,
+                            TradePolicy = tradePolicy.Value,
+                            Symbol = e.Data.Symbol,
+                            AccountId = this.AccountId,
+                            OrderType = (Enums.OrderType)(int)e.Data.Type,
+                            SpotOrderState = orderState,
+                            TradeDirection = (Enums.TradeDirection)(int)e.Data.Side,
+                            ClientOrderId = e.Data.ClientOrderId,
+                            CummulativeTradeAmount = e.Data.QuoteQuantityFilled,
+                            CummulativeTradeQuantity = e.Data.QuantityFilled,
+                            Exchange = Enums.Exchange.Binance,
+                            Fee = e.Data.Fee,
+                            FeeUnit = e.Data.FeeAsset,
+                            LastTradeAmount = e.Data.LastQuoteQuantity,
+                            LastTradePrice = e.Data.LastPriceFilled,
+                            LastTradeQuantity = e.Data.LastQuantityFilled,
+                            LastTradeTime = e.Data.UpdateTime,
+                            CreateTime = e.Data.CreateTime
+                        });
+                    }
+                    catch (Exception ex)
+                    {
+                        logger.Error(ex);
+                    }
+                },
+                (e) =>
+                {
+
+                },
+                (e) =>
+                {
+
+                },
+                (e) =>
+                {
+
+                },
+                cancellationTokenSource.Token);
+        }
+
+        public override void Stop(string symbol = "")
+        {
+            if (!IsConnected)
+                return;
+            IsConnected = false;
+            cancellationTokenSource.Cancel();
+            binanceSocketClient.SpotStreams.Dispose();
+            cancellationTokenSource = null;
+            _ = binanceClient.SpotApi.Account.CloseIsolatedMarginUserStreamAsync(symbol, listenKey).Result;
+            listenKey = string.Empty;
+        }
+    }
+}
diff --git a/SDKAdapter/WebSockets/Order/SpotOrder/SpotOrderWebSocketClient.cs b/SDKAdapter/WebSockets/Order/Spot/SpotOrderWebSocketClient.cs
similarity index 87%
rename from SDKAdapter/WebSockets/Order/SpotOrder/SpotOrderWebSocketClient.cs
rename to SDKAdapter/WebSockets/Order/Spot/SpotOrderWebSocketClient.cs
index bc918c7..2cd05bd 100644
--- a/SDKAdapter/WebSockets/Order/SpotOrder/SpotOrderWebSocketClient.cs
+++ b/SDKAdapter/WebSockets/Order/Spot/SpotOrderWebSocketClient.cs
@@ -2,7 +2,7 @@
 using SDKAdapter.Model;
 using System;
 
-namespace SDKAdapter.WebSockets.Order.SpotOrder
+namespace SDKAdapter.WebSockets.Order.Spot
 {
     public class SpotOrderWebSocketClient
     {
@@ -19,17 +19,18 @@ namespace SDKAdapter.WebSockets.Order.SpotOrder
         public static SpotOrderWebSocketClient Create(Enums.BusinessType businessType, Enums.Exchange exchange, long accountId, string apiKey, string secret, NLog.ILogger logger, Action<SpotOrderTradePublishInfo> onOrderUpdated)
         {
             if (exchange == Enums.Exchange.Binance)
-                return new BinanceSpotOrderWebSocketClient(businessType, accountId, apiKey, secret, logger);
+                return new BinanceSpotOrderWebSocketClient(businessType, accountId, apiKey, secret, logger, onOrderUpdated);
             return null;
         }
 
-        public SpotOrderWebSocketClient(Enums.BusinessType businessType, long accountId, string apiKey, string secret, NLog.ILogger logger)
+        public SpotOrderWebSocketClient(Enums.BusinessType businessType, long accountId, string apiKey, string secret, NLog.ILogger logger, Action<SpotOrderTradePublishInfo> onOrderUpdated)
         {
             this.BusinessType = businessType;
             this.AccountId = accountId;
             this.ApiKey = apiKey;
             this.Secret = secret;
             this.logger = logger;
+            this.OnOrderUpdated = onOrderUpdated;
         }
 
         public virtual void Start(string symbol = "")
diff --git a/SDKAdapter/WebSockets/Order/SpotOrder/BinanceSpotOrderWebSocketClient.cs b/SDKAdapter/WebSockets/Order/SpotOrder/BinanceSpotOrderWebSocketClient.cs
deleted file mode 100644
index a11f6ad..0000000
--- a/SDKAdapter/WebSockets/Order/SpotOrder/BinanceSpotOrderWebSocketClient.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using Binance.Net.Clients;
-using Binance.Net.Objects;
-using Binance.TradeRobot.Model.Base;
-using CryptoExchange.Net.Authentication;
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace SDKAdapter.WebSockets.Order.SpotOrder
-{
-    public class BinanceSpotOrderWebSocketClient : SpotOrderWebSocketClient
-    {
-        private BinanceSocketClient binanceSocketClient;
-        private BinanceClient binanceClient;
-        private CancellationTokenSource cancellationTokenSource;
-        private string listenKey;
-        private IList<Binance.Net.Enums.OrderStatus> unSupportStateList;
-
-        public BinanceSpotOrderWebSocketClient(Enums.BusinessType businessType, long accountId, string apiKey, string secret, NLog.ILogger logger)
-                                              : base(businessType, accountId, apiKey, secret, logger)
-        {
-            var spotClientOption = new BinanceApiClientOptions()
-            {
-                BaseAddress = "https://api.binance.com",
-                ApiCredentials = new ApiCredentials(apiKey, secret)
-            };
-            //var usdFuturesClientOption = new BinanceApiClientOptions()
-            //{
-            //    BaseAddress = "https://fapi.binance.com",
-            //    ApiCredentials = new ApiCredentials(apiKey, secret)
-            //};
-            binanceClient = new BinanceClient(new BinanceClientOptions()
-            {
-                //UsdFuturesApiOptions = usdFuturesClientOption,
-                SpotApiOptions = spotClientOption
-            });
-            binanceSocketClient = new BinanceSocketClient();
-            listenKey = string.Empty;
-            unSupportStateList = new List<Binance.Net.Enums.OrderStatus>()
-            {
-                Binance.Net.Enums.OrderStatus.PendingCancel,
-                Binance.Net.Enums.OrderStatus.Insurance,
-                Binance.Net.Enums.OrderStatus.Adl
-            };
-        }
-
-        public override void Start(string symbol = "")
-        {
-            if (IsConnected)
-                return;
-            IsConnected = true;
-            cancellationTokenSource = new CancellationTokenSource();
-            var getListenKeyResponse = binanceClient.SpotApi.Account.StartIsolatedMarginUserStreamAsync(symbol).Result;
-            if (!getListenKeyResponse.Success)
-                throw new Exception(getListenKeyResponse.Error?.Message ?? "");
-            listenKey = getListenKeyResponse.Data;
-            binanceSocketClient.SpotStreams.SubscribeToUserDataUpdatesAsync(listenKey,
-                (e) =>
-                {
-                    logger.Info(JsonConvert.SerializeObject(e.Data));
-                    if (unSupportStateList.Contains(e.Data.Status))
-                        return;
-                    OnOrderUpdated?.Invoke(new Model.SpotOrderTradePublishInfo()
-                    {
-                        OrderId = e.Data.Id,
-                        Symbol = e.Data.Symbol,
-                        AccountId = this.AccountId,
-                        OrderType = (Enums.OrderType)(int)e.Data.Type,
-                        SpotOrderState = (Enums.SpotOrderState)(int)e.Data.Status,
-                        TradeDirection = (Enums.TradeDirection)(int)e.Data.Side,
-                        ClientOrderId = e.Data.ClientOrderId,
-                        CummulativeTradeAmount = e.Data.QuoteQuantityFilled,
-                        CummulativeTradeQuantity = e.Data.QuantityFilled,
-                        Exchange = Enums.Exchange.Binance,
-                        Fee = e.Data.Fee,
-                        FeeUnit = e.Data.FeeAsset,
-                        LastTradeAmount = e.Data.LastQuoteQuantity,
-                        LastTradePrice = e.Data.LastPriceFilled,
-                        LastTradeQuantity = e.Data.LastQuantityFilled,
-                        LastTradeTime = e.Data.UpdateTime,
-                        CreateTime = e.Data.CreateTime
-                    });
-                },
-                (e) =>
-                {
-
-                },
-                (e) =>
-                {
-
-                },
-                (e) =>
-                {
-
-                },
-                cancellationTokenSource.Token);
-        }
-
-        public override void Stop(string symbol = "")
-        {
-            if (!IsConnected)
-                return;
-            IsConnected = false;
-            cancellationTokenSource.Cancel();
-            binanceSocketClient.SpotStreams.Dispose();
-            cancellationTokenSource = null;
-            _ = binanceClient.SpotApi.Account.CloseIsolatedMarginUserStreamAsync(symbol, listenKey).Result;
-            listenKey = string.Empty;
-        }
-    }
-}