using Binance.TradeRobot.Common.DI; using Binance.TradeRobot.Model.Base; using Binance.TradeRobot.Model.Db; using FreeSql; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using SDKAdapter.Model; using System; using System.Collections.Generic; using System.Linq; using Yitter.IdGenerator; namespace Binance.TradeRobot.Business { [BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Interface)] internal class D21OrderPublishBusiness : BaseSpotOrderPublishBusiness, ISpotOrderPublishBusiness { public Enums.TradePolicy TradePolicy => Enums.TradePolicy.D21; public D21OrderPublishBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IMemoryCache memoryCache, DingBusiness dingBusiness, RobotBusiness robotBusiness, UserBusiness userBusiness) : base(fsql, logManager, idGenerator, memoryCache, dingBusiness, robotBusiness, userBusiness) { } public void OnSpotOrderPublish(SpotOrderPublishInfo spotOrderPublishInfo) { //var logger = logManager.GetLogger(spotOrderPublishInfo.LoggerName); var step = string.Empty; var logList = new List(); try { //step = "检查订单是否入库"; CheckOrderExists(spotOrderPublishInfo.OrderId); //step = "查询订单所属机器人"; var robot = robotBusiness.GetD21PolicyRobotList(spotOrderPublishInfo.RobotId, isLoadRecentTradeProfit: false, isLoadAPIKey: true).FirstOrDefault(); if (robot == null) throw new BusinessException($"未找到机器人"); IUpdate updateSpotOrder = fsql.Update(spotOrderPublishInfo.OrderId).Set(o => o.State, spotOrderPublishInfo.SpotOrderState); IUpdate updateRobotAccount = null; IList> updateUserList = null; List insertUserAccountProfitLossRecordList = null; if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Rejected || spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Expired || spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Canceled) { logList.Add(new ExecutionLog() { Id = idGenerator.NewLong(), CreateTime = DateTime.Now, OrderId = spotOrderPublishInfo.OrderId, RobotId = spotOrderPublishInfo.RobotId, SourceSingal = Enums.SingalType.订单推送, Content = $"收到订单推送,订单号:{spotOrderPublishInfo.OrderId},订单方向:{spotOrderPublishInfo.TradeDirection},订单类型:{spotOrderPublishInfo.OrderType},订单状态:{spotOrderPublishInfo.SpotOrderState}{(spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Rejected ? $",拒绝原因:{spotOrderPublishInfo.RejectedReason}" : string.Empty)}" }); } if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Filled) { var avgTradePrice = spotOrderPublishInfo.CummulativeTradeAmount / spotOrderPublishInfo.CummulativeTradeQuantity; //计算成交均价 logList.Add(new ExecutionLog() { Id = idGenerator.NewLong(), CreateTime = DateTime.Now, OrderId = spotOrderPublishInfo.OrderId, RobotId = spotOrderPublishInfo.RobotId, SourceSingal = Enums.SingalType.订单推送, Content = $"收到订单" + $"推送,订单号:{spotOrderPublishInfo.OrderId},订单方向:{spotOrderPublishInfo.TradeDirection},订单类型:{spotOrderPublishInfo.OrderType},订单状态:{spotOrderPublishInfo.SpotOrderState},成交额:{spotOrderPublishInfo.LastTradeAmount},成交量:{spotOrderPublishInfo.LastTradeQuantity},成交价:{spotOrderPublishInfo.LastTradePrice},手续费({spotOrderPublishInfo.FeeUnit}):{spotOrderPublishInfo.Fee}" }); //更新交易信息 updateSpotOrder = updateSpotOrder.Set(o => o.TradeAmount, spotOrderPublishInfo.CummulativeTradeAmount) .Set(o => o.TradeQuantity, spotOrderPublishInfo.CummulativeTradeQuantity) .Set(o => o.TradePrice, avgTradePrice) .Set(o => o.TradeFee, spotOrderPublishInfo.Fee) .Set(o => o.TradeFeeUnit, spotOrderPublishInfo.FeeUnit) .Set(o => o.LastTradeTime, spotOrderPublishInfo.LastTradeTime); if (spotOrderPublishInfo.TradeDirection == Enums.TradeDirection.Buy) { var quantity = spotOrderPublishInfo.CummulativeTradeQuantity - spotOrderPublishInfo.Fee; //扣除基础币手续费,得到真实购买数量 updateRobotAccount = fsql.Update(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity + quantity) .Set(ra => ra.SpotCurrencyAmount + spotOrderPublishInfo.CummulativeTradeAmount); if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET) { //市价买单完全成交,根据策略挂止损单 } } else if (spotOrderPublishInfo.TradeDirection == Enums.TradeDirection.Sell) { updateUserList = new List>(); insertUserAccountProfitLossRecordList = new List(); if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET) { //市价卖单完全成交,取消尚未触发的限价止损单 } var interest = 0M; //借币利息 var loanAmount = robot.RobotAccount.LoanAmount; //借币金额 if (loanAmount > 0M) { //还币 var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey); interest = apiClient.IsolatedMarginRepay(robot.Symbol, loanAmount); } var buyAmount = spotOrderPublishInfo.CummulativeTradeQuantity * robot.RobotAccount.SpotCurrencyAvgPrice; //本次卖出对应的持仓金额 var profit = spotOrderPublishInfo.CummulativeTradeQuantity * (avgTradePrice - robot.RobotAccount.SpotCurrencyAvgPrice) - spotOrderPublishInfo.Fee - interest; //计算利润 updateSpotOrder = updateSpotOrder.SetIf(interest > 0M, o => o.LoanInterest, interest) .Set(o => o.Profit, profit) .Set(o => o.HistoryTotalProfit, robot.RobotAccount.TotalProfit + profit); updateRobotAccount = fsql.Update(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity - spotOrderPublishInfo.CummulativeTradeQuantity) .Set(ra => ra.SpotCurrencyAmount - buyAmount) .Set(ra => ra.TotalProfit + profit) .Set(ra => ra.ClosePositionCount + 1) .SetIf(profit > 0M, ra => ra.WinCount + 1) .SetIf(interest > 0M, ra => ra.LoanAmount - loanAmount); var capitalChangeType = profit > 0M ? Enums.CapitalChangeType.Add : Enums.CapitalChangeType.Reduce; var userList = userBusiness.GetUserList(multiplyBy100: false); foreach (var user in userList) { var changeAmount = profit * user.DividendRatio; //根据用户分红比例计算本次分红或亏损 user.ChangeAmount(capitalChangeType, Math.Abs(changeAmount), false); var updateUser = fsql.Update(user.Id).Set(u => u.CostAmount, user.CostAmount) .Set(u => u.Profit, user.Profit); updateUserList.Add(updateUser); insertUserAccountProfitLossRecordList.Add(new UserAccountProfitLossRecord() { Id = idGenerator.NewLong(), BusinessType = robot.BusinessType, ChangeAmount = changeAmount, CreateTime = DateTime.Now, ExchangeId = robot.ExchangeId, OrderId = spotOrderPublishInfo.OrderId, OrderProfit = profit, UserId = user.Id, RobotId = robot.Id, DividendRatio = user.DividendRatio, UserProfit = user.Profit }); } } } fsql.Transaction(() => { fsql.Insert(logList).ExecuteAffrows(); updateSpotOrder.ExecuteAffrows(); updateRobotAccount?.ExecuteAffrows(); if (insertUserAccountProfitLossRecordList != null && insertUserAccountProfitLossRecordList.Count() > 0) fsql.Insert(insertUserAccountProfitLossRecordList).ExecuteAffrows(); if (updateUserList != null && updateUserList.Count() > 0) foreach (var u in updateUserList) u.ExecuteAffrows(); }); } catch (Exception ex) { HandleError(ex, logList, spotOrderPublishInfo.LoggerName, spotOrderPublishInfo.RobotId, spotOrderPublishInfo.OrderId, step); } } } }