diff --git a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs index 8f58b63..d8a23db 100644 --- a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs +++ b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs @@ -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 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(); + } + 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(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity + quantity) + updateRobotAccount = fsql.Update(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>(); insertUserAccountProfitLossRecordList = new List(); - //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(robot.RobotAccount.Id).Set(ra => ra.SpotCurrencyQuantity - spotOrderPublishInfo.CummulativeTradeQuantity) + updateRobotAccount = fsql.Update(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(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) diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs index a2c0132..f9aa652 100644 --- a/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs @@ -310,18 +310,25 @@ namespace Binance.TradeRobot.Business CancelStopLossOrder(robot); #endregion - #region 验证卖币数量 - step = "验证卖币数量"; + #region 查询卖币数量 + step = "查询卖币数量"; Thread.Sleep(1000); - var saleQuantity = robot.RobotAccount.SpotCurrencyQuantity.CutDecimal(symbolInfo.SaleQuantityAccuracy); + var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey); + var isolatedMarginAccountAssetList = apiClient.GetIsolatedMarginAccountAssets(); + var currentAsset = isolatedMarginAccountAssetList.FirstOrDefault(x => x.Symbol == robot.Symbol); + var saleQuantity = currentAsset.BaseFree.CutDecimal(symbolInfo.SaleQuantityAccuracy); if (saleQuantity == 0M) throw new BusinessException("没有足够的卖币数量"); + + //var saleQuantity = robot.RobotAccount.SpotCurrencyQuantity.CutDecimal(symbolInfo.SaleQuantityAccuracy); + //if (saleQuantity == 0M) + // throw new BusinessException("没有足够的卖币数量"); #endregion #region 下单 step = "下单"; var newestPrice = globalContext.GetSpotNewestPrice(robot.KLineKey) ?? singalRequest.ClosePrice; - var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey); + var clientOrderId = CreateClientOrderId(robot.Id, robot.TradePolicy); var orderId = apiClient.IsolatedMarginPlaceOrder(robot.Symbol, diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml index 7854b54..b8cd636 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml @@ -276,7 +276,7 @@ - 交易所账户持仓数 + 交易所账户持仓数(废弃) diff --git a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs index 6e459a6..3c297e4 100644 --- a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs +++ b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs @@ -125,7 +125,7 @@ namespace Binance.TradeRobot.Model.Db public decimal RobotAccountSpotCurrencyQuantity { get; set; } = 0.0M; /// - /// 交易所账户持仓数 + /// 交易所账户持仓数(废弃) /// [Column(DbType = "decimal(18,8)")] public decimal ExchangeAccountSpotCurrencyQuantity { get; set; } = 0.0M; diff --git a/SDKTestConsole/Program.cs b/SDKTestConsole/Program.cs index bf4b6a1..3cc7271 100644 --- a/SDKTestConsole/Program.cs +++ b/SDKTestConsole/Program.cs @@ -17,8 +17,8 @@ namespace SDKTestConsole private static SpotOrderWebSocketClient orderWebSocketClient; static void Main(string[] args) { - var apiKey = "pXKdUPbGN4DNar2f2HRoL2qxHoCWcLNf9V5uHTL2lBVCxz66eE8PMPwBw9h8RbKf"; - var secret = "c14tJd7kpMnePKRDoo4nzZk4bIn9bDO8ZCYo69amB4uspLgO5s4GlzYvTwD2zYav"; + var apiKey = "RsQ5RuhYbNRXCTGAQXhwb5Dt3jgPnwKXfR1OXz0qWmf3IsAC7zPQd14WGIr18rDA"; + var secret = "yxW4PPb65rVpdo7fMt2mZcbNOtjOe3J4fMSRVtX5YJfj7kRzHW3dY6xfoW4jje1I"; var client = BaseAPIClient.Create(Enums.Exchange.Binance, 0, apiKey, secret); //逐仓杠杆账户资产 @@ -49,10 +49,6 @@ namespace SDKTestConsole - - var stopLossClientOrderId = "stoploss2_286129845448773_1"; - long stopLossOrderId = 0; - var spotClientOption = new BinanceApiClientOptions() { BaseAddress = "https://api.binance.com", @@ -69,14 +65,8 @@ namespace SDKTestConsole SpotApiOptions = spotClientOption }); - var binanceSocketClient = new BinanceSocketClient(); - - var r = client.GetIsolatedMarginAccountAssets(); - - - //25.07786941 - var i = client.IsolatedMarginRepay("GMTUSDT", 0.00009176M); - + var r = binanceClient.SpotApi.Trading.GetMarginOrderAsync("GMTUSDT", 901880136, isIsolated: true).Result; + Console.WriteLine(JsonConvert.SerializeObject(r.Data)); Console.ReadKey(); } }