18 changed files with 409 additions and 17 deletions
@ -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; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 创建金字塔策略合约机器人
|
|||
/// </summary>
|
|||
/// <param name="addPyramidPolicyRobotRequest"></param>
|
|||
[HttpPost] |
|||
public void AddPyramidPolicyRobot([FromBody] AddPyramidPolicyRobotRequest addPyramidPolicyRobotRequest) |
|||
{ |
|||
robotBusiness.AddPyramidPolicyRobot(addPyramidPolicyRobotRequest); |
|||
} |
|||
} |
|||
} |
@ -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) |
|||
{ |
|||
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查机器人注册条件
|
|||
/// </summary>
|
|||
/// <param name="addRobotRequest"></param>
|
|||
/// <param name="exchangeAPIKey"></param>
|
|||
/// <exception cref="BusinessException"></exception>
|
|||
private void CheckRobotRegister(AddRobotRequest addRobotRequest, out ExchangeAPIKey exchangeAPIKey) |
|||
{ |
|||
exchangeAPIKey = null; |
|||
if (string.IsNullOrEmpty(addRobotRequest.Symbol) || addRobotRequest.ExchangeAPIKeyId == 0) |
|||
throw new BusinessException("参数不全"); |
|||
exchangeAPIKey = fsql.Select<ExchangeAPIKey>(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<ExchangeAccount, ExchangeAPIKey, Robot>().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<ExchangeAPIKey>(exchangeAPIKeyId).WithTransaction(tran).Set(ek => ek.RobotId, robot.Id).ExecuteAffrows(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 添加金字塔策略机器人
|
|||
/// </summary>
|
|||
/// <param name="addPyramidPolicyRobotRequest"></param>
|
|||
public void AddPyramidPolicyRobot(AddPyramidPolicyRobotRequest addPyramidPolicyRobotRequest) |
|||
{ |
|||
CheckRobotRegister(addPyramidPolicyRobotRequest, out ExchangeAPIKey exchangeAPIKey); |
|||
var robot = CreateRobot(addPyramidPolicyRobotRequest); |
|||
var robotAccount = CreateRobotAccount(robot.Id); |
|||
var pyramidPolicy = addPyramidPolicyRobotRequest.Map<PyramidPolicy>(); |
|||
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(); |
|||
}); |
|||
|
|||
//调整仓位杠杆倍数
|
|||
|
|||
} |
|||
} |
|||
} |
@ -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<Enums.TradePolicy, Enums.BusinessType> BusinessTypeDic = new Dictionary<Enums.TradePolicy, Enums.BusinessType>() |
|||
{ |
|||
{Enums.TradePolicy.金字塔, Enums.BusinessType.UPrep }, |
|||
{ Enums.TradePolicy.动量趋势v2, Enums.BusinessType.Spot_Margin} |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// 获取交易策略对应的业务类型
|
|||
/// </summary>
|
|||
/// <param name="tradePolicy"></param>
|
|||
/// <returns></returns>
|
|||
public static Enums.BusinessType GetBusinessType(this Enums.TradePolicy tradePolicy) |
|||
{ |
|||
return BusinessTypeDic[tradePolicy]; |
|||
} |
|||
} |
|||
} |
@ -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; } |
|||
|
|||
/// <summary>
|
|||
/// 平仓次数
|
|||
/// </summary>
|
|||
public long ClosePositionCount { get; set; } = 0; |
|||
|
|||
|
|||
public long RobotId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 现货/杠杆持仓金额
|
|||
/// </summary>
|
|||
[Column(DbType = "decimal(18,8)")] |
|||
public decimal SoptCurrentcyAmount { get; set; } = 0.0M; |
|||
|
|||
/// <summary>
|
|||
/// 现货/杠杆持仓数量
|
|||
/// </summary>
|
|||
[Column(DbType = "decimal(18,8)")] |
|||
public decimal SpotCurrencyQuantity { get; set; } = 0.0M; |
|||
|
|||
/// <summary>
|
|||
/// 总收益
|
|||
/// </summary>
|
|||
[Column(DbType = "decimal(18,8)")] |
|||
public decimal TotalProfit { get; set; } = 0.0M; |
|||
|
|||
/// <summary>
|
|||
/// 盈利次数
|
|||
/// </summary>
|
|||
public long WinCount { get; set; } = 0; |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,27 @@ |
|||
using Binance.TradeRobot.Model.Base; |
|||
|
|||
namespace Binance.TradeRobot.Model.Dto |
|||
{ |
|||
public class AddPyramidPolicyRobotRequest : AddRobotRequest |
|||
{ |
|||
/// <summary>
|
|||
/// 信号周期
|
|||
/// </summary>
|
|||
public Enums.SignalPeriod SignalPeriod { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 杠杆倍数
|
|||
/// </summary>
|
|||
public int Leverage { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 仓位
|
|||
/// </summary>
|
|||
public decimal Position { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 金字塔
|
|||
/// </summary>
|
|||
public int Pyramid { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
using Binance.TradeRobot.Model.Base; |
|||
|
|||
namespace Binance.TradeRobot.Model.Dto |
|||
{ |
|||
public class AddRobotRequest |
|||
{ |
|||
/// <summary>
|
|||
/// 交易对
|
|||
/// </summary>
|
|||
public string Symbol { get; set; } |
|||
public Enums.TradePolicy TradePolicy { get; set; } |
|||
/// <summary>
|
|||
/// 交易所APIKeyId
|
|||
/// </summary>
|
|||
public long ExchangeAPIKeyId { get; set; } |
|||
} |
|||
} |
Loading…
Reference in new issue