From 77d87d3be36e65a6050356eaf39b8f7198f81538 Mon Sep 17 00:00:00 2001 From: shanj <18996038927@163.com> Date: Mon, 14 Mar 2022 04:18:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=9B=E5=BB=BA=E9=87=91?= =?UTF-8?q?=E5=AD=97=E5=A1=94=E7=AD=96=E7=95=A5=E6=9C=BA=E5=99=A8=E4=BA=BA?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 3 + .../Binance.TradeRobot.API.xml | 13 +++ .../Controllers/ExchangeAccountController.cs | 11 +++ .../Controllers/RobotController.cs | 29 ++++++ Binance.TradeRobot.API/Startup.cs | 2 - .../Binance.TradeRobot.Business.xml | 36 ++++++- .../{ => Business}/BaseBusiness.cs | 0 .../ExchangeBusiness.cs | 32 +++++-- .../Business/RobotBusiness.cs | 93 +++++++++++++++++++ .../{User => Business}/UserBusiness.cs | 0 .../Extensions/RobotExtension.cs | 24 +++++ .../Base/MappingProfiles.cs | 2 + .../Binance.TradeRobot.Model.csproj | 4 - .../Binance.TradeRobot.Model.xml | 70 ++++++++++++++ .../Db/Policy/UPrep/PyramidPolicy.cs | 17 +++- .../Db/Robot/RobotAccount.cs | 46 +++++++++ .../Robot/AddPyramidPolicyRobotRequest.cs | 27 ++++++ .../Dto/Request/Robot/AddRobotRequest.cs | 17 ++++ 18 files changed, 409 insertions(+), 17 deletions(-) create mode 100644 Binance.TradeRobot.API/Controllers/RobotController.cs rename Binance.TradeRobot.Business/{ => Business}/BaseBusiness.cs (100%) rename Binance.TradeRobot.Business/{Exchange => Business}/ExchangeBusiness.cs (81%) create mode 100644 Binance.TradeRobot.Business/Business/RobotBusiness.cs rename Binance.TradeRobot.Business/{User => Business}/UserBusiness.cs (100%) create mode 100644 Binance.TradeRobot.Business/Extensions/RobotExtension.cs create mode 100644 Binance.TradeRobot.Model/Db/Robot/RobotAccount.cs create mode 100644 Binance.TradeRobot.Model/Dto/Request/Robot/AddPyramidPolicyRobotRequest.cs create mode 100644 Binance.TradeRobot.Model/Dto/Request/Robot/AddRobotRequest.cs diff --git a/.editorconfig b/.editorconfig index 0db2396..cd7ccf1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,3 +5,6 @@ dotnet_diagnostic.CS8618.severity = none # CS1591: 缺少对公共可见类型或成员的 XML 注释 dotnet_diagnostic.CS1591.severity = none + +# CS8625: 无法将 null 字面量转换为非 null 的引用类型。 +dotnet_diagnostic.CS8625.severity = none diff --git a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml index ecc2412..a4bb4d5 100644 --- a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml +++ b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml @@ -23,6 +23,19 @@ 交易策略 + + + 获取APIKey未使用的交易所账户列表 + + + + + + + 创建金字塔策略合约机器人 + + + 用户登录 diff --git a/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs b/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs index da80604..eb88f78 100644 --- a/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs +++ b/Binance.TradeRobot.API/Controllers/ExchangeAccountController.cs @@ -48,5 +48,16 @@ namespace Binance.TradeRobot.API.Controllers { return exchangeBusiness.GetExchangeAccountList(tradePolicy); } + + /// + /// 获取APIKey未使用的交易所账户列表 + /// + /// + /// + [HttpGet("{tradePolicy}")] + public IList GetNoUsedExchangeAccountList([FromRoute]Enums.TradePolicy tradePolicy) + { + return exchangeBusiness.GetNoUsedExchangeAccountList(tradePolicy); + } } } diff --git a/Binance.TradeRobot.API/Controllers/RobotController.cs b/Binance.TradeRobot.API/Controllers/RobotController.cs new file mode 100644 index 0000000..7e51e55 --- /dev/null +++ b/Binance.TradeRobot.API/Controllers/RobotController.cs @@ -0,0 +1,29 @@ +using Binance.TradeRobot.Business; +using Binance.TradeRobot.Model.Dto; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Binance.TradeRobot.API.Controllers +{ + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + public class RobotController : BaseApiController + { + private RobotBusiness robotBusiness; + + public RobotController(RobotBusiness robotBusiness) + { + this.robotBusiness = robotBusiness; + } + + /// + /// 创建金字塔策略合约机器人 + /// + /// + [HttpPost] + public void AddPyramidPolicyRobot([FromBody] AddPyramidPolicyRobotRequest addPyramidPolicyRobotRequest) + { + robotBusiness.AddPyramidPolicyRobot(addPyramidPolicyRobotRequest); + } + } +} diff --git a/Binance.TradeRobot.API/Startup.cs b/Binance.TradeRobot.API/Startup.cs index 0b2fc3d..ccd5fc5 100644 --- a/Binance.TradeRobot.API/Startup.cs +++ b/Binance.TradeRobot.API/Startup.cs @@ -4,13 +4,11 @@ using Binance.TradeRobot.Business; using Binance.TradeRobot.Common.Extensions; using Binance.TradeRobot.Common.Http; using Binance.TradeRobot.Model.Base; -using HY.TradingRobot.Model.Base; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; diff --git a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml index a3d173f..0d455e1 100644 --- a/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml +++ b/Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml @@ -4,12 +4,26 @@ Binance.TradeRobot.Business - + - 计算成员分红/本金比例 + 获取APIKey未使用交易所账户列表 - - 比例乘100 + + + + + + 检查机器人注册条件 + + + + + + + + 添加金字塔策略机器人 + + @@ -22,5 +36,19 @@ + + + 获取交易策略对应的业务类型 + + + + + + + 计算成员分红/本金比例 + + + 比例乘100 + diff --git a/Binance.TradeRobot.Business/BaseBusiness.cs b/Binance.TradeRobot.Business/Business/BaseBusiness.cs similarity index 100% rename from Binance.TradeRobot.Business/BaseBusiness.cs rename to Binance.TradeRobot.Business/Business/BaseBusiness.cs diff --git a/Binance.TradeRobot.Business/Exchange/ExchangeBusiness.cs b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs similarity index 81% rename from Binance.TradeRobot.Business/Exchange/ExchangeBusiness.cs rename to Binance.TradeRobot.Business/Business/ExchangeBusiness.cs index 3e19a6d..ca0b772 100644 --- a/Binance.TradeRobot.Business/Exchange/ExchangeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/ExchangeBusiness.cs @@ -1,4 +1,5 @@ -using Binance.TradeRobot.Common.DI; +using Binance.TradeRobot.Business.Extensions; +using Binance.TradeRobot.Common.DI; using Binance.TradeRobot.Common.Extensions; using Binance.TradeRobot.Model.Base; using Binance.TradeRobot.Model.Db; @@ -32,11 +33,7 @@ namespace Binance.TradeRobot.Business.Exchange throw new BusinessException("重复的APIKey或SecretKey"); var exchangeAccount = addExchangeAccountRequest.Map(); - if (addExchangeAccountRequest.TradePolicy == Enums.TradePolicy.金字塔) - exchangeAccount.BusinessType = Enums.BusinessType.UPrep; - - if (addExchangeAccountRequest.TradePolicy == Enums.TradePolicy.动量趋势v2) - exchangeAccount.BusinessType = Enums.BusinessType.Spot_Margin; + exchangeAccount.BusinessType = addExchangeAccountRequest.TradePolicy.GetBusinessType(); var exchangeAPIKey = new ExchangeAPIKey() { @@ -133,5 +130,28 @@ namespace Binance.TradeRobot.Business.Exchange ewh.Set(); } } + + /// + /// 获取APIKey未使用交易所账户列表 + /// + /// + /// + public IList GetNoUsedExchangeAccountList(Enums.TradePolicy tradePolicy) + { + var exchangeAccountList = fsql.Select().Where(ea => ea.TradePolicy == tradePolicy).ToList().Map>(); + var accountIdList = exchangeAccountList.Select(ea => ea.Id); + var exchangeAPIKeyList = fsql.Select().Where(k => k.RobotId == null && accountIdList.Contains(k.AccountId)) + .ToList() + .Map>(); + + foreach (var exchangeAccount in exchangeAccountList) + { + var currentExchangeAccountAPIKeyList = exchangeAPIKeyList.Where(k => k.AccountId == exchangeAccount.Id); + if (currentExchangeAccountAPIKeyList.Count() == 0) + continue; + exchangeAccount.ExchangeAPIKeyList.AddRange(currentExchangeAccountAPIKeyList); + } + return exchangeAccountList; + } } } diff --git a/Binance.TradeRobot.Business/Business/RobotBusiness.cs b/Binance.TradeRobot.Business/Business/RobotBusiness.cs new file mode 100644 index 0000000..6f798b1 --- /dev/null +++ b/Binance.TradeRobot.Business/Business/RobotBusiness.cs @@ -0,0 +1,93 @@ +using Binance.TradeRobot.Business.Extensions; +using Binance.TradeRobot.Common.DI; +using Binance.TradeRobot.Common.Extensions; +using Binance.TradeRobot.Model.Base; +using Binance.TradeRobot.Model.Db; +using Binance.TradeRobot.Model.Dto; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; +using System.Data.Common; +using Yitter.IdGenerator; + +namespace Binance.TradeRobot.Business +{ + [BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Self)] + public class RobotBusiness : BaseBusiness + { + public RobotBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IMemoryCache memoryCache) : base(fsql, logManager, idGenerator, memoryCache) + { + + } + + /// + /// 检查机器人注册条件 + /// + /// + /// + /// + private void CheckRobotRegister(AddRobotRequest addRobotRequest, out ExchangeAPIKey exchangeAPIKey) + { + exchangeAPIKey = null; + if (string.IsNullOrEmpty(addRobotRequest.Symbol) || addRobotRequest.ExchangeAPIKeyId == 0) + throw new BusinessException("参数不全"); + exchangeAPIKey = fsql.Select(addRobotRequest.ExchangeAPIKeyId).ToOne(); + if (exchangeAPIKey == null) + throw new BusinessException("选择的APIKey不存在"); + if (exchangeAPIKey.RobotId != null) + throw new BusinessException("APIKey已被其他机器人使用"); + + var accountId = exchangeAPIKey.AccountId; + if (fsql.Select().InnerJoin((ea, ek, r) => ea.Id == ek.AccountId) + .LeftJoin((ea, ek, r) => ek.RobotId == r.Id) + .Where((ea, ek, r) => ea.Id == accountId && + r.Symbol == addRobotRequest.Symbol).Any()) + throw new BusinessException("同一个交易所账号下只允许存在一个交易对"); + } + + private Robot CreateRobot(AddRobotRequest addRobotRequest) + { + return new Robot() + { + Id = idGenerator.NewLong(), + Symbol = addRobotRequest.Symbol, + TradePolicy = addRobotRequest.TradePolicy, + BusinessType = addRobotRequest.TradePolicy.GetBusinessType() + }; + } + + private RobotAccount CreateRobotAccount(long robotId) + { + return new RobotAccount() { Id = idGenerator.NewLong(), RobotId = robotId }; + } + + private void ExecuteAddRobotWithTran(Robot robot, RobotAccount robotAccount, long exchangeAPIKeyId, DbTransaction tran) + { + fsql.Insert(robot).WithTransaction(tran).ExecuteAffrows(); + fsql.Insert(robotAccount).WithTransaction(tran).ExecuteAffrows(); + fsql.Update(exchangeAPIKeyId).WithTransaction(tran).Set(ek => ek.RobotId, robot.Id).ExecuteAffrows(); + } + + /// + /// 添加金字塔策略机器人 + /// + /// + public void AddPyramidPolicyRobot(AddPyramidPolicyRobotRequest addPyramidPolicyRobotRequest) + { + CheckRobotRegister(addPyramidPolicyRobotRequest, out ExchangeAPIKey exchangeAPIKey); + var robot = CreateRobot(addPyramidPolicyRobotRequest); + var robotAccount = CreateRobotAccount(robot.Id); + var pyramidPolicy = addPyramidPolicyRobotRequest.Map(); + pyramidPolicy.Id = idGenerator.NewLong(); + pyramidPolicy.RobotId = robot.Id; + fsql.Transaction(() => + { + var tran = fsql.Ado.TransactionCurrentThread; + ExecuteAddRobotWithTran(robot, robotAccount, addPyramidPolicyRobotRequest.ExchangeAPIKeyId, tran); + fsql.Insert(pyramidPolicy).ExecuteAffrows(); + }); + + //调整仓位杠杆倍数 + + } + } +} diff --git a/Binance.TradeRobot.Business/User/UserBusiness.cs b/Binance.TradeRobot.Business/Business/UserBusiness.cs similarity index 100% rename from Binance.TradeRobot.Business/User/UserBusiness.cs rename to Binance.TradeRobot.Business/Business/UserBusiness.cs diff --git a/Binance.TradeRobot.Business/Extensions/RobotExtension.cs b/Binance.TradeRobot.Business/Extensions/RobotExtension.cs new file mode 100644 index 0000000..af53670 --- /dev/null +++ b/Binance.TradeRobot.Business/Extensions/RobotExtension.cs @@ -0,0 +1,24 @@ +using Binance.TradeRobot.Model.Base; +using System.Collections.Generic; + +namespace Binance.TradeRobot.Business.Extensions +{ + public static class RobotExtension + { + private static IDictionary BusinessTypeDic = new Dictionary() + { + {Enums.TradePolicy.金字塔, Enums.BusinessType.UPrep }, + { Enums.TradePolicy.动量趋势v2, Enums.BusinessType.Spot_Margin} + }; + + /// + /// 获取交易策略对应的业务类型 + /// + /// + /// + public static Enums.BusinessType GetBusinessType(this Enums.TradePolicy tradePolicy) + { + return BusinessTypeDic[tradePolicy]; + } + } +} diff --git a/Binance.TradeRobot.Model/Base/MappingProfiles.cs b/Binance.TradeRobot.Model/Base/MappingProfiles.cs index 2027e10..b5ea5f2 100644 --- a/Binance.TradeRobot.Model/Base/MappingProfiles.cs +++ b/Binance.TradeRobot.Model/Base/MappingProfiles.cs @@ -15,6 +15,8 @@ namespace Binance.TradeRobot.Model.Base CreateMap(); CreateMap(); CreateMap(); + + CreateMap(); } } } diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj index 8c08b5a..78b48d1 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj @@ -12,8 +12,4 @@ - - - - diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml index b25f981..4ce0f16 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml @@ -94,11 +94,51 @@ 交易所账号Id + + + 杠杆倍数(1-125整数) + + + + + 仓位 + + + + + 金字塔 + + 运行时长(s) + + + 平仓次数 + + + + + 现货/杠杆持仓金额 + + + + + 现货/杠杆持仓数量 + + + + + 总收益 + + + + + 盈利次数 + + 投资本金 @@ -164,6 +204,36 @@ 交易策略 + + + 信号周期 + + + + + 杠杆倍数 + + + + + 仓位 + + + + + 金字塔 + + + + + 交易对 + + + + + 交易所APIKeyId + + 密码需要Md5小写加密 diff --git a/Binance.TradeRobot.Model/Db/Policy/UPrep/PyramidPolicy.cs b/Binance.TradeRobot.Model/Db/Policy/UPrep/PyramidPolicy.cs index 090169f..0a0603a 100644 --- a/Binance.TradeRobot.Model/Db/Policy/UPrep/PyramidPolicy.cs +++ b/Binance.TradeRobot.Model/Db/Policy/UPrep/PyramidPolicy.cs @@ -6,7 +6,6 @@ namespace Binance.TradeRobot.Model.Db [Table(DisableSyncStructure = true)] public partial class PyramidPolicy { - [Column(IsPrimary = true)] public long Id { get; set; } @@ -14,6 +13,22 @@ namespace Binance.TradeRobot.Model.Db public Enums.SignalPeriod SignalPeriod { get; set; } public long RobotId { get; set; } + + /// + /// ܸ˱(1-125) + /// + public int Leverage { get; set; } = 1; + + /// + /// λ + /// + [Column(DbType = "decimal(18,8)")] + public decimal Position { get; set; } = 0M; + + /// + /// + /// + public int Pyramid { get; set; } = 0; } } diff --git a/Binance.TradeRobot.Model/Db/Robot/RobotAccount.cs b/Binance.TradeRobot.Model/Db/Robot/RobotAccount.cs new file mode 100644 index 0000000..838922f --- /dev/null +++ b/Binance.TradeRobot.Model/Db/Robot/RobotAccount.cs @@ -0,0 +1,46 @@ +using FreeSql.DataAnnotations; + +namespace Binance.TradeRobot.Model.Db +{ + + [Table(DisableSyncStructure = true)] + public partial class RobotAccount + { + + [Column(IsPrimary = true)] + public long Id { get; set; } + + /// + /// 平仓次数 + /// + public long ClosePositionCount { get; set; } = 0; + + + public long RobotId { get; set; } + + /// + /// 现货/杠杆持仓金额 + /// + [Column(DbType = "decimal(18,8)")] + public decimal SoptCurrentcyAmount { get; set; } = 0.0M; + + /// + /// 现货/杠杆持仓数量 + /// + [Column(DbType = "decimal(18,8)")] + public decimal SpotCurrencyQuantity { get; set; } = 0.0M; + + /// + /// 总收益 + /// + [Column(DbType = "decimal(18,8)")] + public decimal TotalProfit { get; set; } = 0.0M; + + /// + /// 盈利次数 + /// + public long WinCount { get; set; } = 0; + + } + +} diff --git a/Binance.TradeRobot.Model/Dto/Request/Robot/AddPyramidPolicyRobotRequest.cs b/Binance.TradeRobot.Model/Dto/Request/Robot/AddPyramidPolicyRobotRequest.cs new file mode 100644 index 0000000..ae46774 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/Robot/AddPyramidPolicyRobotRequest.cs @@ -0,0 +1,27 @@ +using Binance.TradeRobot.Model.Base; + +namespace Binance.TradeRobot.Model.Dto +{ + public class AddPyramidPolicyRobotRequest : AddRobotRequest + { + /// + /// 信号周期 + /// + public Enums.SignalPeriod SignalPeriod { get; set; } + + /// + /// 杠杆倍数 + /// + public int Leverage { get; set; } + + /// + /// 仓位 + /// + public decimal Position { get; set; } + + /// + /// 金字塔 + /// + public int Pyramid { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Request/Robot/AddRobotRequest.cs b/Binance.TradeRobot.Model/Dto/Request/Robot/AddRobotRequest.cs new file mode 100644 index 0000000..e1f86fe --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/Robot/AddRobotRequest.cs @@ -0,0 +1,17 @@ +using Binance.TradeRobot.Model.Base; + +namespace Binance.TradeRobot.Model.Dto +{ + public class AddRobotRequest + { + /// + /// 交易对 + /// + public string Symbol { get; set; } + public Enums.TradePolicy TradePolicy { get; set; } + /// + /// 交易所APIKeyId + /// + public long ExchangeAPIKeyId { get; set; } + } +}