|
|
@ -9,6 +9,7 @@ using Microsoft.Extensions.DependencyInjection; |
|
|
|
using SDKAdapter.APIClient; |
|
|
|
using SDKAdapter.Model; |
|
|
|
using System; |
|
|
|
using System.Collections.Concurrent; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using Yitter.IdGenerator; |
|
|
@ -18,11 +19,27 @@ namespace Binance.TradeRobot.Business |
|
|
|
[BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Interface)] |
|
|
|
internal class D21OrderPublishBusiness : BaseSpotOrderPublishBusiness, ISpotOrderPublishBusiness |
|
|
|
{ |
|
|
|
private ConcurrentDictionary<long, decimal> spotFeeDictionary; |
|
|
|
|
|
|
|
public Enums.TradePolicy TradePolicy => Enums.TradePolicy.D21; |
|
|
|
|
|
|
|
public D21OrderPublishBusiness(IFreeSql fsql, NLogManager logManager, IIdGenerator idGenerator, IMemoryCache memoryCache, DingBusiness dingBusiness, RobotBusiness robotBusiness, UserBusiness userBusiness, ExchangeBusiness exchangeBusiness) : base(fsql, logManager, idGenerator, memoryCache, dingBusiness, robotBusiness, userBusiness, exchangeBusiness) |
|
|
|
{ |
|
|
|
spotFeeDictionary = new ConcurrentDictionary<long, decimal>(); |
|
|
|
} |
|
|
|
|
|
|
|
private decimal AddSpotFee(long orderId, decimal currentTradeFee, bool deleteKey) |
|
|
|
{ |
|
|
|
if (!spotFeeDictionary.TryGetValue(orderId, out decimal fee)) |
|
|
|
{ |
|
|
|
fee = 0M; |
|
|
|
spotFeeDictionary.TryAdd(orderId, fee); |
|
|
|
} |
|
|
|
fee += currentTradeFee; |
|
|
|
spotFeeDictionary[orderId] = fee; |
|
|
|
if (deleteKey) |
|
|
|
spotFeeDictionary.TryRemove(orderId, out _); |
|
|
|
return fee; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -67,8 +84,26 @@ namespace Binance.TradeRobot.Business |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.PartiallyFilled) |
|
|
|
{ |
|
|
|
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 = null; |
|
|
|
|
|
|
|
_ = AddSpotFee(spotOrderPublishInfo.OrderId, spotOrderPublishInfo.Fee, false); |
|
|
|
} |
|
|
|
|
|
|
|
if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Filled) |
|
|
|
{ |
|
|
|
var fee = AddSpotFee(spotOrderPublishInfo.OrderId, spotOrderPublishInfo.Fee, true); |
|
|
|
|
|
|
|
var avgTradePrice = spotOrderPublishInfo.CummulativeTradeAmount / spotOrderPublishInfo.CummulativeTradeQuantity; //计算成交均价
|
|
|
|
logList.Add(new ExecutionLog() |
|
|
|
{ |
|
|
@ -77,29 +112,31 @@ namespace Binance.TradeRobot.Business |
|
|
|
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}" |
|
|
|
Content = $"收到订单推送,订单号:{spotOrderPublishInfo.OrderId},订单方向:{spotOrderPublishInfo.TradeDirection},订单类型:{spotOrderPublishInfo.OrderType},订单状态:{spotOrderPublishInfo.SpotOrderState},成交额:{spotOrderPublishInfo.LastTradeAmount},成交量:{spotOrderPublishInfo.LastTradeQuantity},成交价:{spotOrderPublishInfo.LastTradePrice},手续费({spotOrderPublishInfo.FeeUnit}):{spotOrderPublishInfo.Fee},总手续费:{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.TradeFee, fee) |
|
|
|
.Set(o => o.TradeFeeUnit, spotOrderPublishInfo.FeeUnit) |
|
|
|
.Set(o => o.LastTradeTime, spotOrderPublishInfo.LastTradeTime); |
|
|
|
|
|
|
|
//查询交易所真实资产
|
|
|
|
var currentAsset = apiClient.GetIsolatedMarginAccountAssets().FirstOrDefault(x => x.Symbol == spotOrderPublishInfo.Symbol); |
|
|
|
|
|
|
|
if (spotOrderPublishInfo.TradeDirection == Enums.TradeDirection.Buy) |
|
|
|
{ |
|
|
|
var quantity = spotOrderPublishInfo.CummulativeTradeQuantity - spotOrderPublishInfo.Fee; //扣除基础币手续费,得到真实购买数量
|
|
|
|
var quantity = spotOrderPublishInfo.CummulativeTradeQuantity - fee; //扣除基础币手续费,得到真实购买数量
|
|
|
|
//基础币可用资产,交易所账户持币数量
|
|
|
|
|
|
|
|
//更新机器人账户
|
|
|
|
updateRobotAccount = fsql.Update<RobotAccount>(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity + quantity) |
|
|
|
updateRobotAccount = fsql.Update<RobotAccount>(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity, currentAsset.BaseFree) |
|
|
|
.Set(ra => ra.SpotCurrencyAmount + spotOrderPublishInfo.CummulativeTradeAmount); |
|
|
|
|
|
|
|
//交易所账户真实持币数量
|
|
|
|
var exchangAccountSpotCurrencyQuantity = apiClient.GetIsolatedMarginAccountAssets().FirstOrDefault(x => x.Symbol == spotOrderPublishInfo.Symbol).BaseFree; |
|
|
|
updateSpotOrder = updateSpotOrder.Set(o => o.RobotAccountSpotCurrencyQuantity, robot.RobotAccount.SpotCurrencyQuantity + quantity) |
|
|
|
.Set(o => o.ExchangeAccountSpotCurrencyQuantity, exchangAccountSpotCurrencyQuantity); |
|
|
|
|
|
|
|
updateSpotOrder = updateSpotOrder.Set(o => o.RobotAccountSpotCurrencyQuantity, currentAsset.BaseFree); |
|
|
|
|
|
|
|
if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET) |
|
|
|
{ |
|
|
@ -134,28 +171,9 @@ namespace Binance.TradeRobot.Business |
|
|
|
updateUserList = new List<IUpdate<User>>(); |
|
|
|
insertUserAccountProfitLossRecordList = new List<UserAccountProfitLossRecord>(); |
|
|
|
|
|
|
|
//if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET)
|
|
|
|
//{
|
|
|
|
//市价卖单完全成交,取消尚未触发的限价止损单
|
|
|
|
//try
|
|
|
|
//{
|
|
|
|
// CancelStopLossOrder(robot, apiClient);
|
|
|
|
//}
|
|
|
|
//catch (Exception ex)
|
|
|
|
//{
|
|
|
|
// logList.Add(new ExecutionLog()
|
|
|
|
// {
|
|
|
|
// Id = idGenerator.NewLong(),
|
|
|
|
// SourceSingal = Enums.SingalType.订单推送,
|
|
|
|
// RobotId = robot.Id,
|
|
|
|
// CreateTime = DateTime.Now,
|
|
|
|
// Content = $"取消止损单失败,{ex.Message}"
|
|
|
|
// });
|
|
|
|
//}
|
|
|
|
//}
|
|
|
|
|
|
|
|
var interest = 0M; //借币利息
|
|
|
|
var loanAmount = robot.RobotAccount.LoanAmount; //借币金额
|
|
|
|
var loanAmount = currentAsset.QuoteBorrowed; //借币金额
|
|
|
|
if (loanAmount > 0M) |
|
|
|
{ |
|
|
|
//还币
|
|
|
@ -163,25 +181,22 @@ namespace Binance.TradeRobot.Business |
|
|
|
logList[0].Content = $"{logList[0].Content},借币金额:{loanAmount},还币利息:{interest}"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var buyAmount = spotOrderPublishInfo.CummulativeTradeQuantity * robot.RobotAccount.SpotCurrencyAvgPrice; //本次卖出对应的持仓金额
|
|
|
|
var profit = spotOrderPublishInfo.CummulativeTradeQuantity * (avgTradePrice - robot.RobotAccount.SpotCurrencyAvgPrice) - spotOrderPublishInfo.Fee - interest; //计算利润
|
|
|
|
var profit = spotOrderPublishInfo.CummulativeTradeQuantity * (avgTradePrice - robot.RobotAccount.SpotCurrencyAvgPrice) - fee - interest; //计算利润
|
|
|
|
|
|
|
|
|
|
|
|
updateRobotAccount = fsql.Update<RobotAccount>(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity - spotOrderPublishInfo.CummulativeTradeQuantity) |
|
|
|
updateRobotAccount = fsql.Update<RobotAccount>(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity, currentAsset.BaseFree) |
|
|
|
.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 exchangAccountSpotCurrencyQuantity = apiClient.GetIsolatedMarginAccountAssets().FirstOrDefault(x => x.Symbol == spotOrderPublishInfo.Symbol).BaseFree; |
|
|
|
.SetIf(interest > 0M, ra => ra.LoanAmount, 0M); |
|
|
|
|
|
|
|
|
|
|
|
updateSpotOrder = updateSpotOrder.SetIf(interest > 0M, o => o.LoanInterest, interest) |
|
|
|
.Set(o => o.Profit, profit) |
|
|
|
.Set(o => o.HistoryTotalProfit, robot.RobotAccount.TotalProfit + profit) |
|
|
|
.Set(o => o.RobotAccountSpotCurrencyQuantity, robot.RobotAccount.SpotCurrencyQuantity - spotOrderPublishInfo.CummulativeTradeQuantity) |
|
|
|
.Set(o => o.ExchangeAccountSpotCurrencyQuantity, exchangAccountSpotCurrencyQuantity); |
|
|
|
.Set(o => o.RobotAccountSpotCurrencyQuantity, currentAsset.BaseFree); |
|
|
|
|
|
|
|
if (profit > 0) //盈利复投
|
|
|
|
updateD21Policy = fsql.Update<D21Policy>(robot.D21Policy.Id).Set(p => p.Position + profit); |
|
|
@ -220,7 +235,7 @@ namespace Binance.TradeRobot.Business |
|
|
|
fsql.Transaction(() => |
|
|
|
{ |
|
|
|
fsql.Insert(logList).ExecuteAffrows(); |
|
|
|
updateSpotOrder.ExecuteAffrows(); |
|
|
|
updateSpotOrder?.ExecuteAffrows(); |
|
|
|
updateRobotAccount?.ExecuteAffrows(); |
|
|
|
updateD21Policy?.ExecuteAffrows(); |
|
|
|
if (insertUserAccountProfitLossRecordList != null && insertUserAccountProfitLossRecordList.Count() > 0) |
|
|
|