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
}
///
- /// 获取现货/逐仓杠杆订单记录
+ /// 获取现货/逐仓杠杆订单记录(最近20条)
///
///
///
@@ -28,7 +28,7 @@ namespace Binance.TradeRobot.API.Controllers
}
///
- /// 获取执行日志记录
+ /// 获取执行日志记录(最近50条)
///
///
///
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 @@
+
+
+
+
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)
+ ///
+ /// 创建客户端订单号
+ ///
+ ///
+ ///
+ ///
+ 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
///
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
///
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);
}
///
@@ -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
/// 币安逐仓杠杆需要单独的运行实例
///
- 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}";
}
}
///
/// 订单推送日志Key
///
- 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 @@
-
+
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 ignoreOrderStateList;
+
+ public BinanceSpotOrderWebSocketClient(Enums.BusinessType businessType,
+ long accountId,
+ string apiKey,
+ string secret,
+ NLog.ILogger logger,
+ Action 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.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 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 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 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.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;
- }
- }
-}