From 7932ae1fc07025e8c18cf5dafe5a124a7e4c8d77 Mon Sep 17 00:00:00 2001 From: shanj <18996038927@163.com> Date: Thu, 12 May 2022 06:28:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=81=E8=A3=85=E5=A4=9A=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E6=89=80API=E8=AF=B7=E6=B1=82=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 3 + Binance.TradeRobot.API.sln | 8 ++- .../Business/BaseBusiness.cs | 22 +++---- .../Business/ExchangeBusiness.cs | 11 ++-- .../TradeBusiness/D21TradeBusiness.cs | 12 ++-- Binance.TradeRobot.Model/Base/Enums.cs | 21 ++++++ .../Binance.TradeRobot.Model.xml | 46 ++++++++++++- .../Db/Order/SpotOrder.cs | 3 + .../Dto/Response/Robot/RobotResponse.cs | 4 +- SDKAdapter/APIClient/BaseAPIClient.cs | 38 +++++++++++ SDKAdapter/APIClient/BinanceAPIClient.cs | 60 +++++++++++++++++ .../Model/IsolatedMarginAccountAsset.cs | 65 +++++++++++++++++++ .../Market/SpotMarketWebSocketClient.cs | 14 ++-- SDKTestConsole/Program.cs | 25 +++++++ SDKTestConsole/SDKTestConsole.csproj | 17 +++++ 15 files changed, 311 insertions(+), 38 deletions(-) create mode 100644 SDKAdapter/APIClient/BaseAPIClient.cs create mode 100644 SDKAdapter/APIClient/BinanceAPIClient.cs create mode 100644 SDKAdapter/Model/IsolatedMarginAccountAsset.cs create mode 100644 SDKTestConsole/Program.cs create mode 100644 SDKTestConsole/SDKTestConsole.csproj diff --git a/.editorconfig b/.editorconfig index 6332a8c..9405a89 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,6 @@ dotnet_diagnostic.CS8625.severity = none # CS8602: 解引用可能出现空引用。 dotnet_diagnostic.CS8602.severity = none + +# CS8603: 可能返回 null 引用。 +dotnet_diagnostic.CS8603.severity = none diff --git a/Binance.TradeRobot.API.sln b/Binance.TradeRobot.API.sln index 6994f53..d8bc8f3 100644 --- a/Binance.TradeRobot.API.sln +++ b/Binance.TradeRobot.API.sln @@ -16,7 +16,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SDKAdapter", "SDKAdapter\SDKAdapter.csproj", "{E461043B-179D-4625-BF2F-C00EAB1C8213}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDKAdapter", "SDKAdapter\SDKAdapter.csproj", "{E461043B-179D-4625-BF2F-C00EAB1C8213}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SDKTestConsole", "SDKTestConsole\SDKTestConsole.csproj", "{69458842-D4E0-4BB8-8E5A-254CC9074A23}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -44,6 +46,10 @@ Global {E461043B-179D-4625-BF2F-C00EAB1C8213}.Debug|Any CPU.Build.0 = Debug|Any CPU {E461043B-179D-4625-BF2F-C00EAB1C8213}.Release|Any CPU.ActiveCfg = Release|Any CPU {E461043B-179D-4625-BF2F-C00EAB1C8213}.Release|Any CPU.Build.0 = Release|Any CPU + {69458842-D4E0-4BB8-8E5A-254CC9074A23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69458842-D4E0-4BB8-8E5A-254CC9074A23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69458842-D4E0-4BB8-8E5A-254CC9074A23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69458842-D4E0-4BB8-8E5A-254CC9074A23}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Binance.TradeRobot.Business/Business/BaseBusiness.cs b/Binance.TradeRobot.Business/Business/BaseBusiness.cs index aa76080..ff2d937 100644 --- a/Binance.TradeRobot.Business/Business/BaseBusiness.cs +++ b/Binance.TradeRobot.Business/Business/BaseBusiness.cs @@ -1,7 +1,9 @@ using Binance.Net.Clients; using Binance.Net.Objects; +using Binance.TradeRobot.Model.Base; using CryptoExchange.Net.Authentication; using Microsoft.Extensions.Caching.Memory; +using SDKAdapter.APIClient; using System; using Yitter.IdGenerator; @@ -25,23 +27,15 @@ namespace Binance.TradeRobot.Business expirationTimeSpan = TimeSpan.FromDays(1); } - protected BinanceClient GetBinanceClient(string apiKey, string secret) + protected BaseAPIClient GetBaseAPIClient(Enums.Exchange exchange, long uid, string apiKey, string secret) { - if (!memoryCache.TryGetValue(apiKey, out BinanceClient binanceClient)) + var cacheKey = exchange == Enums.Exchange.Binance ? uid.ToString() : apiKey; + if (!memoryCache.TryGetValue(cacheKey, out BaseAPIClient baseAPIClient)) { - var apiClientOption = new BinanceApiClientOptions() - { - BaseAddress = "https://fapi.binance.com", - ApiCredentials = new ApiCredentials(apiKey, secret) - }; - binanceClient = new BinanceClient(new BinanceClientOptions() - { - UsdFuturesApiOptions = apiClientOption, - SpotApiOptions = apiClientOption - }); - memoryCache.Set(apiKey, binanceClient, expirationTimeSpan); + baseAPIClient = BaseAPIClient.Create(exchange, uid, apiKey, secret); + memoryCache.Set(cacheKey, baseAPIClient, expirationTimeSpan); } - return binanceClient; + return baseAPIClient; } } } diff --git a/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs index f6de8f4..3b02a64 100644 --- a/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs @@ -102,14 +102,13 @@ namespace Binance.TradeRobot.Business.Exchange { try { - var binanceClient = GetBinanceClient(exchangeAccount.ExchangeAPIKeyList[0].APIKey, exchangeAccount.ExchangeAPIKeyList[0].SecretKey); if (exchangeAccount.BusinessType == Enums.BusinessType.UPrep) { - var result = binanceClient.UsdFuturesApi.Account.GetBalancesAsync().Result; - if (result.Success) - { - exchangeAccount.UPrepUSDT = result.Data.FirstOrDefault(b => b.Asset == "USDT")?.WalletBalance ?? 0; - } + //var result = binanceClient.UsdFuturesApi.Account.GetBalancesAsync().Result; + //if (result.Success) + //{ + // exchangeAccount.UPrepUSDT = result.Data.FirstOrDefault(b => b.Asset == "USDT")?.WalletBalance ?? 0; + //} } else if (exchangeAccount.BusinessType == Enums.BusinessType.Spot) { diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs index 49713a2..926d4ec 100644 --- a/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/TradeBusiness/D21TradeBusiness.cs @@ -128,13 +128,13 @@ namespace Binance.TradeRobot.Business } #endregion + #region 获取账户余额 + + #endregion + #region 计算下单数量 - var recentSellOrder = fsql.Select().Where(o => o.RobotId == robot.Id && - o.TradeDirection == Enums.TradeDirection.Sell && - validStateList.Contains(o.State)) - .OrderByDescending(o => o.LastTradeTime) - .ToOne(); - + var previewTradeAmount = d21Robot.D21Policy.Position; //预估交易额 + #endregion } diff --git a/Binance.TradeRobot.Model/Base/Enums.cs b/Binance.TradeRobot.Model/Base/Enums.cs index 9d165e7..d62ec66 100644 --- a/Binance.TradeRobot.Model/Base/Enums.cs +++ b/Binance.TradeRobot.Model/Base/Enums.cs @@ -148,6 +148,27 @@ namespace Binance.TradeRobot.Model.Base Buy, Sell } + /// + /// 订单类型 + /// LIMIT 限价单 + /// MARKET 市价单 + /// STOP_LOSS 止损单 + /// STOP_LOSS_LIMIT 限价止损单 + /// TAKE_PROFIT 止盈单 + /// TAKE_PROFIT_LIMIT 限价止盈单 + /// LIMIT_MAKER 限价只挂单 + /// + public enum OrderType + { + LIMIT, + MARKET, + STOP_LOSS, + STOP_LOSS_LIMIT, + TAKE_PROFIT, + TAKE_PROFIT_LIMIT, + LIMIT_MAKER + } + /// /// 信号周期 1m=0,3m=1,5m=2,15m=3,30m=4,1h=5,2h=6,4h=7,6h=8,8h=9,12h=10,1d=11,3d=12,1w=13,1M=14 /// diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml index 0b1c0fd..ca4fc63 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml @@ -94,9 +94,39 @@ 借币状态 Loading=0 returned=1 - + - 订单状态 + 现货订单订单状态 + + + + + 已创建 + + + + + 部分成交 + + + + + 完全成交 + + + + + 用户取消 + + + + + 拒绝 + + + + + 交易引擎取消 没有完全成交 @@ -104,6 +134,18 @@ 交易方向 Buy=0,Sell=1 + + + 订单类型 + LIMIT 限价单 + MARKET 市价单 + STOP_LOSS 止损单 + STOP_LOSS_LIMIT 限价止损单 + TAKE_PROFIT 止盈单 + TAKE_PROFIT_LIMIT 限价止盈单 + LIMIT_MAKER 限价只挂单 + + 信号周期 1m=0,3m=1,5m=2,15m=3,30m=4,1h=5,2h=6,4h=7,6h=8,8h=9,12h=10,1d=11,3d=12,1w=13,1M=14 diff --git a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs index 9fd3119..3fc7970 100644 --- a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs +++ b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs @@ -94,6 +94,9 @@ namespace Binance.TradeRobot.Model.Db [Column(DbType = "decimal(18,8)")] public decimal TradeQuantity { get; set; } + [Column(MapType = typeof(int), DbType = "int")] + public Enums.OrderType OrderType { get; set; } + } } diff --git a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs index 96618d0..c80a86c 100644 --- a/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs +++ b/Binance.TradeRobot.Model/Dto/Response/Robot/RobotResponse.cs @@ -22,9 +22,9 @@ namespace Binance.TradeRobot.Model.Dto public Enums.Exchange ExchangeId { get; set; } - public string ExecuteLogKey { get { return $"Execute-{ExchangeId}-{TradePolicy}-{Symbol}"; } } + public virtual string ExecuteLogKey { get { return $"Execute-{ExchangeId}-{TradePolicy}-{Symbol}"; } } - public string KLineKey { get { return $"KLine-{ExchangeId}-{Symbol}"; }} + public virtual string KLineKey { get { return $"KLine-{ExchangeId}-{Symbol}"; } } /// /// 机器人账户对象 diff --git a/SDKAdapter/APIClient/BaseAPIClient.cs b/SDKAdapter/APIClient/BaseAPIClient.cs new file mode 100644 index 0000000..c8d638b --- /dev/null +++ b/SDKAdapter/APIClient/BaseAPIClient.cs @@ -0,0 +1,38 @@ +using Binance.TradeRobot.Model.Base; +using SDKAdapter.Model; +using System; +using System.Collections.Generic; + +namespace SDKAdapter.APIClient +{ + public class BaseAPIClient + { + public static BaseAPIClient Create(Enums.Exchange exchange, long uid, string apiKey, string secret) + { + if (exchange == Enums.Exchange.Binance) + return new BinanceAPIClient(uid, apiKey, secret); + return null; + } + + protected long AccountId { get; private set; } + protected string ApiKey { get; private set; } + protected string Secret { get; private set; } + + public BaseAPIClient(long uid, string apiKey, string secret) + { + this.AccountId = uid; + this.ApiKey = apiKey; + this.Secret = secret; + } + + /// + /// 获取逐仓杠杆账户资产 + /// + /// + /// + public virtual IList GetIsolatedMarginAccountAssets() + { + throw new NotImplementedException(); + } + } +} diff --git a/SDKAdapter/APIClient/BinanceAPIClient.cs b/SDKAdapter/APIClient/BinanceAPIClient.cs new file mode 100644 index 0000000..0617f11 --- /dev/null +++ b/SDKAdapter/APIClient/BinanceAPIClient.cs @@ -0,0 +1,60 @@ +using Binance.Net.Clients; +using Binance.Net.Objects; +using CryptoExchange.Net.Authentication; +using SDKAdapter.Model; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SDKAdapter.APIClient +{ + public class BinanceAPIClient : BaseAPIClient + { + private BinanceClient binanceClient; + + public BinanceAPIClient(long uid, string apiKey, string secret) : base(uid, apiKey, secret) + { + 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 + }); + } + + public override IList GetIsolatedMarginAccountAssets() + { + var r = binanceClient.SpotApi.Account.GetIsolatedMarginAccountAsync().Result; + if (!r.Success) + throw new Exception($"获取逐仓杠杆账户信息失败 {r.Error?.Message}"); + + return r.Data.Assets.Select(asset => new IsolatedMarginAccountAsset() + { + Symbol = asset.Symbol, + + BaseAsset = asset.BaseAsset.Asset, + BaseBorrowed = asset.BaseAsset.Borrowed, + BaseFree = asset.BaseAsset.Free, + BaseInterest = asset.BaseAsset.Interest, + BaseLocked = asset.BaseAsset.Locked, + BaseNetAsset = asset.BaseAsset.NetAsset, + + QuoteAsset = asset.QuoteAsset.Asset, + QuoteBorrowed = asset.QuoteAsset.Borrowed, + QuoteFree = asset.QuoteAsset.Free, + QuoteInterest = asset.QuoteAsset.Interest, + QuoteLocked = asset.QuoteAsset.Locked, + QuoteNetAsset = asset.QuoteAsset.NetAsset + }).ToList(); + } + } +} diff --git a/SDKAdapter/Model/IsolatedMarginAccountAsset.cs b/SDKAdapter/Model/IsolatedMarginAccountAsset.cs new file mode 100644 index 0000000..a34dd86 --- /dev/null +++ b/SDKAdapter/Model/IsolatedMarginAccountAsset.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SDKAdapter.Model +{ + /// + /// 逐仓杠杆账户资产 + /// + public class IsolatedMarginAccountAsset + { + public string Symbol { get; set; } + + /// + /// 基础币 + /// + public string BaseAsset { get; set; } + + /// + /// 基础币借币金额 + /// + public decimal BaseBorrowed { get; set; } + /// + /// 基础币可用资产 + /// + public decimal BaseFree { get; set; } + /// + /// 基础币借币利息 + /// + public decimal BaseInterest { get; set; } + /// + /// 基础币锁定资产 + /// + public decimal BaseLocked { get; set; } + /// + /// 基础币净资产 + /// + public decimal BaseNetAsset { get; set; } + + /// + /// 报价币 + /// + public string QuoteAsset { get; set; } + /// + /// 报价币借币金额 + /// + public decimal QuoteBorrowed { get; set; } + /// + /// 报价币可用资产 + /// + public decimal QuoteFree { get; set; } + /// + /// 报价币借币利息 + /// + public decimal QuoteInterest { get; set; } + /// + /// 报价币锁定资产 + /// + public decimal QuoteLocked { get; set; } + /// + /// 报价币净资产 + /// + public decimal QuoteNetAsset { get; set; } + } +} diff --git a/SDKAdapter/WebSockets/Market/SpotMarketWebSocketClient.cs b/SDKAdapter/WebSockets/Market/SpotMarketWebSocketClient.cs index 8c275d4..9ed4e7a 100644 --- a/SDKAdapter/WebSockets/Market/SpotMarketWebSocketClient.cs +++ b/SDKAdapter/WebSockets/Market/SpotMarketWebSocketClient.cs @@ -5,6 +5,13 @@ namespace SDKAdapter.WebSockets.Market { public class SpotMarketWebSocketClient { + public static SpotMarketWebSocketClient Create(Enums.Exchange exchange, string symbol, NLog.ILogger logger) + { + if (exchange == Enums.Exchange.Binance) + return new BinanceSpotMarketWebSocketClient(symbol, logger); + return null; + } + /// /// 更新间隔(ms) /// @@ -54,12 +61,5 @@ namespace SDKAdapter.WebSockets.Market LastUpdateTime = DateTime.Now; } } - - public static SpotMarketWebSocketClient Create(Enums.Exchange exchange, string symbol, NLog.ILogger logger) - { - if (exchange == Enums.Exchange.Binance) - return new BinanceSpotMarketWebSocketClient(symbol, logger); - return null; - } } } diff --git a/SDKTestConsole/Program.cs b/SDKTestConsole/Program.cs new file mode 100644 index 0000000..e575dd9 --- /dev/null +++ b/SDKTestConsole/Program.cs @@ -0,0 +1,25 @@ +using Binance.Net.Clients; +using Binance.Net.Objects; +using Binance.TradeRobot.Model.Base; +using CryptoExchange.Net.Authentication; +using Newtonsoft.Json; +using SDKAdapter.APIClient; +using System; + +namespace SDKTestConsole +{ + internal class Program + { + static void Main(string[] args) + { + var apiKey = "NnLXgcdUAZ8FAye4Qge3zrrdg5o7ufoWbgtYsKzgfIXz0OMz27G1Kx4SykMzw7YS"; + var secret = "lpJ3t50osPx6lEUerVFMdoKsZ6uHPc769OFPGtfhcoPANpv97CEcvR3pz3Bezhhv"; + + var marginList = BaseAPIClient.Create(Enums.Exchange.Binance, 0, apiKey, secret).GetIsolatedMarginAccountAssets(); + + var s = JsonConvert.SerializeObject(marginList); + Console.WriteLine(s); + Console.ReadKey(); + } + } +} diff --git a/SDKTestConsole/SDKTestConsole.csproj b/SDKTestConsole/SDKTestConsole.csproj new file mode 100644 index 0000000..40d2d0d --- /dev/null +++ b/SDKTestConsole/SDKTestConsole.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + +