币安量化交易
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
16 KiB

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;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using Yitter.IdGenerator;
namespace Binance.TradeRobot.Business
{
[BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Self)]
public class RobotBusiness : BaseBusiness
{
private GlobalContext globalContext;
public RobotBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IMemoryCache memoryCache, GlobalContext globalContext) : base(fsql, logManager, idGenerator, memoryCache)
{
this.globalContext = globalContext;
}
/// <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("同一个交易所账号下只允许存在一个交易对");
}
public void StartRobot(long robotId)
{
fsql.Update<Robot>(robotId).Set(r => r.State, Enums.RobotState.Runing).ExecuteAffrows();
var robot = GetRobotList(robotId).FirstOrDefault();
//监听K线和订单
globalContext.SubscribeKLine(robot);
}
public void StopRobot(long robotId)
{
var robot = GetRobotList(robotId).FirstOrDefault();
fsql.Update<Robot>(robotId).Set(r => r.State, Enums.RobotState.Stop).ExecuteAffrows();
var sameRunningCount = GetRobotList(symbol: robot.Symbol, robotState: Enums.RobotState.Runing, exchange: robot.ExchangeId).Count();
if (sameRunningCount == 0)
{
//取消监听K线和订单
globalContext.UnSubscribeKLine(robot);
}
}
/// <summary>
/// 添加机器人和账户
/// </summary>
/// <param name="addRobotRequest"></param>
/// <param name="tran"></param>
/// <returns>机器人Id</returns>
private long AddRobotWithTran(AddRobotRequest addRobotRequest, DbTransaction tran)
{
var robotId = idGenerator.NewLong();
fsql.Insert(new Robot()
{
Id = robotId,
Symbol = addRobotRequest.Symbol.ToUpper(),
TradePolicy = addRobotRequest.TradePolicy,
BusinessType = addRobotRequest.TradePolicy.GetBusinessType(),
ExchangeId = addRobotRequest.ExchangeId,
CreateTime = DateTime.Now,
RunningTime = 0,
State = Enums.RobotState.Stop
}).WithTransaction(tran).ExecuteAffrows();
fsql.Insert(new RobotAccount()
{
Id = idGenerator.NewLong(),
RobotId = robotId
}).WithTransaction(tran).ExecuteAffrows();
fsql.Update<ExchangeAPIKey>(addRobotRequest.ExchangeAPIKeyId).WithTransaction(tran).Set(ek => ek.RobotId, robotId).ExecuteAffrows();
return robotId;
}
/// <summary>
/// 添加金字塔策略机器人
/// </summary>
/// <param name="addRobotRequest"></param>
public void AddPyramidPolicyRobot(AddRobotRequest addRobotRequest)
{
CheckRobotRegister(addRobotRequest, out ExchangeAPIKey exchangeAPIKey);
var pyramidPolicy = new PyramidPolicy();
pyramidPolicy.Id = idGenerator.NewLong();
fsql.Transaction(() =>
{
var tran = fsql.Ado.TransactionCurrentThread;
pyramidPolicy.RobotId = AddRobotWithTran(addRobotRequest, tran);
fsql.Insert(pyramidPolicy).ExecuteAffrows();
});
//调整仓位杠杆倍数
}
/// <summary>
/// 添加动2.1策略机器人
/// </summary>
/// <param name="addRobotRequest"></param>
public void AddD21PolicyRobot(AddRobotRequest addRobotRequest)
{
addRobotRequest.TradePolicy = Enums.TradePolicy.D21;
CheckRobotRegister(addRobotRequest, out _);
var d21Policy = new D21Policy()
{
Id = idGenerator.NewLong(),
CreateTime = DateTime.Now,
ExecutionMode = Enums.ExecutionMode.Both,
IsEnabledIncreasePurchase = true,
IsEnableRemedyForErrorCrossSignal = true
};
fsql.Transaction(() =>
{
var tran = fsql.Ado.TransactionCurrentThread;
d21Policy.RobotId = AddRobotWithTran(addRobotRequest, tran);
fsql.Insert(d21Policy).ExecuteAffrows();
});
}
/// <summary>
/// 查询机器人基本信息
/// </summary>
/// <param name="robotId">如果robotId有值,将忽略其他条件</param>
/// <param name="symbol"></param>
/// <param name="robotState"></param>
/// <param name="exchange"></param>
/// <returns></returns>
public IList<RobotResponse> GetRobotList(long? robotId = null,
string symbol = "",
Enums.RobotState? robotState = null,
Enums.Exchange? exchange = null)
{
var select = fsql.Select<Robot, ExchangeAPIKey>().InnerJoin((r, e) => r.Id == e.RobotId);
if (robotId != null)
select = select.Where((r, e) => r.Id == robotId);
else
select = select.WhereIf(!string.IsNullOrEmpty(symbol), (r, e) => r.Symbol == symbol)
.WhereIf(robotState != null, (r, e) => r.State == robotState)
.WhereIf(exchange != null, (r, e) => r.ExchangeId == exchange);
return select.ToList((r, e) => new Robot()
{
Id = r.Id,
BusinessType = r.BusinessType,
ExchangeId = r.ExchangeId,
Symbol = r.Symbol,
State = r.State,
RunningTime = r.RunningTime,
CreateTime = r.CreateTime,
TradePolicy = r.TradePolicy,
ExchangeAccountId = e.AccountId,
ExchangeAPIKey = e.APIKey,
ExchangeSecretKey = e.SecretKey
}).Map<IList<RobotResponse>>();
}
/// <summary>
/// 获取动2.1策略机器人列表
/// </summary>
/// <param name="robotState">机器人状态</param>
/// <param name="signalPeriod">信号周期</param>
/// <param name="symbol">交易对</param>
/// <param name="isLoadRecentTradeProfit">是否加载近期交易利润,默认true</param>
/// <param name="isLoadAPIKey">是否加载机器人绑定的APIKey,默认false</param>
/// <returns></returns>
public IList<D21PolicyRobotResponse> GetD21PolicyRobotList(Enums.RobotState? robotState = null,
Enums.SignalPeriod? signalPeriod = null,
string symbol = "",
bool isLoadRecentTradeProfit = true,
bool isLoadAPIKey = false)
{
var robotList = fsql.Select<Robot, SymbolInfo, RobotAccount, D21Policy, ExchangeAPIKey>().InnerJoin((r, s, ra, d, e) => r.Id == ra.RobotId)
.InnerJoin((r, s, ra, d, e) => r.Symbol == s.Symbol && r.ExchangeId == s.ExchangeId)
.InnerJoin((r, s, ra, d, e) => r.Id == d.RobotId)
.InnerJoin((r, s, ra, d, e) => r.Id == e.RobotId)
.WhereIf(robotState != null, (r, s, ra, d, e) => r.State == robotState)
.WhereIf(signalPeriod != null, (r, s, ra, d, e) => d.PeriodicSignal == signalPeriod)
.WhereIf(!string.IsNullOrEmpty(symbol), (r, s, ra, d, e) => r.Symbol == symbol)
.Where((r, s, ra, d, e) => r.TradePolicy == Enums.TradePolicy.D21)
.ToList((r, s, ra, d, e) => new Robot()
{
Id = r.Id,
BusinessType = r.BusinessType,
ExchangeId = r.ExchangeId,
Symbol = r.Symbol,
State = r.State,
RunningTime = r.RunningTime,
CreateTime = r.CreateTime,
TradePolicy = r.TradePolicy,
SymbolId = s.Id,
SymbolSaleQuantityAccuracy = s.SaleQuantityAccuracy,
RobotAccountId = ra.Id,
ClosePositionCount = ra.ClosePositionCount,
WinCount = ra.WinCount,
LoanAmount = ra.LoanAmount,
SoptCurrentcyAmount = ra.SoptCurrentcyAmount,
SpotCurrencyQuantity = ra.SpotCurrencyQuantity,
TotalProfit = ra.TotalProfit,
ExchangeAccountId = e.AccountId,
ExchangeAPIKey = e.APIKey,
ExchangeSecretKey = e.SecretKey,
D21ExecutionMode = d.ExecutionMode,
D21IsEnabledIncreasePurchase = d.IsEnabledIncreasePurchase,
D21IsEnableRemedyForErrorCrossSignal = d.IsEnableRemedyForErrorCrossSignal,
D21MaxFollowPurchaseRatio = d.MaxFollowPurchaseRatio,
D21PeriodicSignal = d.PeriodicSignal,
D21PolicyId = d.Id,
D21Position = d.Position,
D21Assets = d.Assets,
D21Level1PositionStopLossRatio = d.Level1PositionStopLossRatio,
D21Level1PriceStopLossRatio = d.Level1PriceStopLossRatio,
D21Level2PositionStopLossRatio = d.Level2PositionStopLossRatio,
D21Level2PriceStopLossRatio = d.Level2PriceStopLossRatio,
D21MaxExchangeLoanRatio = d.MaxExchangeLoanRatio,
D21MaxSystemLoanRatio = d.MaxSystemLoanRatio,
D21CreateTime = d.CreateTime
}).Map<IList<D21PolicyRobotResponse>>();
if (isLoadRecentTradeProfit)
{
//统计近期订单利润
}
if (!isLoadAPIKey)
{
foreach (var r in robotList)
r.ExchangeAPIKey = null;
}
return robotList;
}
}
}