diff --git a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml index 7550e80..bb6e78e 100644 --- a/Binance.TradeRobot.API/Binance.TradeRobot.API.xml +++ b/Binance.TradeRobot.API/Binance.TradeRobot.API.xml @@ -48,18 +48,18 @@ - + - 获取现货/逐仓杠杆订单记录(最近20条) + 获取现货/逐仓杠杆订单记录 - + - + - 获取执行日志记录(最近50条) + 获取执行日志记录 - + diff --git a/Binance.TradeRobot.API/Controllers/OrderController.cs b/Binance.TradeRobot.API/Controllers/OrderController.cs index 7962408..0121fc9 100644 --- a/Binance.TradeRobot.API/Controllers/OrderController.cs +++ b/Binance.TradeRobot.API/Controllers/OrderController.cs @@ -17,25 +17,25 @@ namespace Binance.TradeRobot.API.Controllers } /// - /// 获取现货/逐仓杠杆订单记录(最近20条) + /// 获取现货/逐仓杠杆订单记录 /// - /// + /// /// - [HttpGet("{robotId}")] - public IList GetSpotOrderList([FromRoute] long robotId) + [HttpPost] + public SpotOrderPageResponse GetSpotOrderList([FromBody] QueryOrderRequest queryOrderRequest) { - return orderBusiness.GetSpotOrderList(robotId); + return orderBusiness.GetSpotOrderList(queryOrderRequest); } /// - /// 获取执行日志记录(最近50条) + /// 获取执行日志记录 /// - /// + /// /// - [HttpGet("{robotId}")] - public IList GetExecutionLogList([FromRoute] long robotId) + [HttpPost] + public ExecutionLogPageResponse GetExecutionLogList([FromBody] QueryLogRequest queryLogRequest) { - return orderBusiness.GetExecutionLogList(robotId); + return orderBusiness.GetExecutionLogList(queryLogRequest); } } } diff --git a/Binance.TradeRobot.Business/Business/OrderBusiness.cs b/Binance.TradeRobot.Business/Business/OrderBusiness.cs index bcc6dfc..0eb3382 100644 --- a/Binance.TradeRobot.Business/Business/OrderBusiness.cs +++ b/Binance.TradeRobot.Business/Business/OrderBusiness.cs @@ -3,7 +3,6 @@ using Binance.TradeRobot.Model.Db; using Binance.TradeRobot.Model.Dto; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; -using System.Collections.Generic; using Yitter.IdGenerator; namespace Binance.TradeRobot.Business @@ -16,14 +15,34 @@ namespace Binance.TradeRobot.Business } - public IList GetSpotOrderList(long robotId) + public SpotOrderPageResponse GetSpotOrderList(QueryOrderRequest queryOrderRequest) { - return fsql.Select().Where(o => o.RobotId == robotId).OrderByDescending(o => o.CreateTime).Page(1, 20).ToList(); + if (queryOrderRequest.PageSize > 100) + queryOrderRequest.PageSize = 100; + return new SpotOrderPageResponse() + { + Items = fsql.Select().Where(o => o.RobotId == queryOrderRequest.RobotId) + .OrderByDescending(o => o.CreateTime) + .Page(queryOrderRequest.PageIndex, queryOrderRequest.PageSize) + .Count(out long totalCount) + .ToList(), + TotalCount = totalCount + }; } - public IList GetExecutionLogList(long robotId) + public ExecutionLogPageResponse GetExecutionLogList(QueryLogRequest queryLogRequest) { - return fsql.Select().Where(l => l.RobotId == robotId).OrderByDescending(l => l.CreateTime).Page(1, 50).ToList(); + if (queryLogRequest.PageSize > 100) + queryLogRequest.PageSize = 100; + return new ExecutionLogPageResponse() + { + Items = fsql.Select().Where(l => l.RobotId == queryLogRequest.RobotId) + .OrderByDescending(l => l.CreateTime) + .Page(queryLogRequest.PageIndex, queryLogRequest.PageSize) + .Count(out long totalCount) + .ToList(), + TotalCount = totalCount + }; } } } diff --git a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs index 25d0758..8f58b63 100644 --- a/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs +++ b/Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs @@ -134,25 +134,25 @@ 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}" - }); - } - } + //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; //借币金额 @@ -275,6 +275,7 @@ namespace Binance.TradeRobot.Business var stopLossOrder = new SpotOrder() { Id = stopOrderId, + ClientOrderId = stopLossClientOrderId, CreateTime = DateTime.Now, ExchangeId = d21Robot.ExchangeId, LoanAmount = 0M, @@ -297,17 +298,5 @@ namespace Binance.TradeRobot.Business Content = $"{(isFirstStopLoss ? 1 : 2)}级止损挂单成功,订单号:{stopOrderId},挂单数量:{stopQuantity}" }); } - - private void CancelStopLossOrder(D21PolicyRobotResponse d21Robot, BaseAPIClient baseAPIClient) - { - var stopLossOrderIdList = fsql.Select().Where(o => o.OrderType == Enums.OrderType.STOP_LOSS_LIMIT && - o.State == Enums.SpotOrderState.Created && - o.RobotId == d21Robot.Id).ToList(o => o.Id); - if (stopLossOrderIdList == null || stopLossOrderIdList.Count() == 0) - return; - - foreach (var stopLossOrderId in stopLossOrderIdList) - baseAPIClient.CancelIsolateMarginOrder(d21Robot.Symbol, stopLossOrderId); - } } } diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs index 1eba94e..94f6686 100644 --- a/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/TradeBusiness/BaseTradeBusiness.cs @@ -2,8 +2,10 @@ using Binance.TradeRobot.Model.Db; using Binance.TradeRobot.Model.Dto; using Microsoft.Extensions.Caching.Memory; +using SDKAdapter.APIClient; using System; using System.Collections.Generic; +using System.Linq; using System.Text; using Yitter.IdGenerator; @@ -53,5 +55,19 @@ namespace Binance.TradeRobot.Business var random = new Random(guid.GetHashCode()); return $"{Convert.ToChar(random.Next(97, 123))}{guid.ToString().Substring(0, 4)}_{robotId}_{(int)tradePolicy}"; } + + protected void CancelStopLossOrder(RobotResponse d21Robot, BaseAPIClient baseAPIClient = null) + { + if (baseAPIClient == null) + baseAPIClient = GetBaseAPIClient(d21Robot.ExchangeId, d21Robot.ExchangeAPIKey.AccountId, d21Robot.ExchangeAPIKey.APIKey, d21Robot.ExchangeAPIKey.SecretKey); + var stopLossOrderList = fsql.Select().Where(o => o.OrderType == Enums.OrderType.STOP_LOSS_LIMIT && + o.State == Enums.SpotOrderState.Created && + o.RobotId == d21Robot.Id).ToList(o => new { o.Id, o.ClientOrderId }); + if (stopLossOrderList == null || stopLossOrderList.Count() == 0) + return; + + foreach (var stopLossOrder in stopLossOrderList) + baseAPIClient.CancelIsolateMarginOrder(d21Robot.Symbol, stopLossOrder.Id, stopLossOrder.ClientOrderId); + } } } diff --git a/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs index 120c95c..a2c0132 100644 --- a/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs +++ b/Binance.TradeRobot.Business/Business/TradeBusiness/Spot/D21TradeBusiness.cs @@ -218,6 +218,7 @@ namespace Binance.TradeRobot.Business var buyOrder = new SpotOrder() { Id = orderId, + ClientOrderId = clientOrderId, CreateTime = DateTime.Now, ExchangeId = robot.ExchangeId, LoanAmount = diffAmount, @@ -304,8 +305,14 @@ namespace Binance.TradeRobot.Business } #endregion + #region 取消止损限价单 + step = "取消止损限价单"; + CancelStopLossOrder(robot); + #endregion + #region 验证卖币数量 step = "验证卖币数量"; + Thread.Sleep(1000); var saleQuantity = robot.RobotAccount.SpotCurrencyQuantity.CutDecimal(symbolInfo.SaleQuantityAccuracy); if (saleQuantity == 0M) throw new BusinessException("没有足够的卖币数量"); @@ -326,6 +333,7 @@ namespace Binance.TradeRobot.Business var sellOrder = new SpotOrder() { Id = orderId, + ClientOrderId = clientOrderId, CreateTime = DateTime.Now, ExchangeId = robot.ExchangeId, OrderType = Enums.OrderType.MARKET, diff --git a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml index b0482ae..7854b54 100644 --- a/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml +++ b/Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml @@ -199,6 +199,11 @@ 借币利息 + + + 客户端订单号 + + 交易所Id diff --git a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs index c6e1ea5..6e459a6 100644 --- a/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs +++ b/Binance.TradeRobot.Model/Db/Order/SpotOrder.cs @@ -12,6 +12,13 @@ namespace Binance.TradeRobot.Model.Db [Column(DbType = "bigint", IsPrimary = true)] public long Id { get; set; } + /// + /// 客户端订单号 + /// + [Column(StringLength = 50)] + public string ClientOrderId { get; set; } + + [Column(DbType = "datetime")] public DateTime CreateTime { get; set; } diff --git a/Binance.TradeRobot.Model/Dto/Request/Order/QueryLogRequest.cs b/Binance.TradeRobot.Model/Dto/Request/Order/QueryLogRequest.cs new file mode 100644 index 0000000..273401b --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/Order/QueryLogRequest.cs @@ -0,0 +1,11 @@ +namespace Binance.TradeRobot.Model.Dto +{ + public class QueryLogRequest + { + public long RobotId { get; set; } + + public int PageIndex { get; set; } + + public int PageSize { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Request/Order/QueryOrderRequest.cs b/Binance.TradeRobot.Model/Dto/Request/Order/QueryOrderRequest.cs new file mode 100644 index 0000000..3d619a2 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Request/Order/QueryOrderRequest.cs @@ -0,0 +1,11 @@ +namespace Binance.TradeRobot.Model.Dto +{ + public class QueryOrderRequest + { + public long RobotId { get; set; } + + public int PageIndex { get; set; } + + public int PageSize { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Response/Order/ExecutionLogPageResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Order/ExecutionLogPageResponse.cs new file mode 100644 index 0000000..73edbe7 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Response/Order/ExecutionLogPageResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Binance.TradeRobot.Model.Dto +{ + public class ExecutionLogPageResponse + { + public long TotalCount { get; set; } + + public IList Items { get; set; } + } +} diff --git a/Binance.TradeRobot.Model/Dto/Response/Order/SpotOrderPageResponse.cs b/Binance.TradeRobot.Model/Dto/Response/Order/SpotOrderPageResponse.cs new file mode 100644 index 0000000..c366130 --- /dev/null +++ b/Binance.TradeRobot.Model/Dto/Response/Order/SpotOrderPageResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Binance.TradeRobot.Model.Dto +{ + public class SpotOrderPageResponse + { + public long TotalCount { get; set; } + + public IList Items { get; set; } + } +} diff --git a/SDKAdapter/APIClient/BaseAPIClient.cs b/SDKAdapter/APIClient/BaseAPIClient.cs index 1b920c5..7542980 100644 --- a/SDKAdapter/APIClient/BaseAPIClient.cs +++ b/SDKAdapter/APIClient/BaseAPIClient.cs @@ -98,8 +98,9 @@ namespace SDKAdapter.APIClient /// /// /// + /// /// - public virtual void CancelIsolateMarginOrder(string symbol, long orderId) + public virtual void CancelIsolateMarginOrder(string symbol, long orderId, string clientOrderId) { throw new NotImplementedException(); } diff --git a/SDKAdapter/APIClient/BinanceAPIClient.cs b/SDKAdapter/APIClient/BinanceAPIClient.cs index ed4570b..e11f5d8 100644 --- a/SDKAdapter/APIClient/BinanceAPIClient.cs +++ b/SDKAdapter/APIClient/BinanceAPIClient.cs @@ -135,9 +135,9 @@ namespace SDKAdapter.APIClient return r.Data.Id; } - public override void CancelIsolateMarginOrder(string symbol, long orderId) + public override void CancelIsolateMarginOrder(string symbol, long orderId, string clientOrderId) { - _ = binanceClient.SpotApi.Trading.CancelMarginOrderAsync(symbol, orderId, isIsolated: true); + _ = binanceClient.SpotApi.Trading.CancelMarginOrderAsync(symbol, orderId, isIsolated: true, newClientOrderId: clientOrderId).Result; } } } diff --git a/SDKTestConsole/Program.cs b/SDKTestConsole/Program.cs index f0bb522..bf4b6a1 100644 --- a/SDKTestConsole/Program.cs +++ b/SDKTestConsole/Program.cs @@ -4,7 +4,9 @@ using Binance.TradeRobot.Model.Base; using CryptoExchange.Net.Authentication; using Newtonsoft.Json; using SDKAdapter.APIClient; +using SDKAdapter.WebSockets.Order.Spot; using System; +using System.Threading.Tasks; namespace SDKTestConsole { @@ -12,15 +14,44 @@ namespace SDKTestConsole { private static System.Threading.Timer timer; + private static SpotOrderWebSocketClient orderWebSocketClient; static void Main(string[] args) { - var apiKey = "RsQ5RuhYbNRXCTGAQXhwb5Dt3jgPnwKXfR1OXz0qWmf3IsAC7zPQd14WGIr18rDA"; - var secret = "yxW4PPb65rVpdo7fMt2mZcbNOtjOe3J4fMSRVtX5YJfj7kRzHW3dY6xfoW4jje1I"; + var apiKey = "pXKdUPbGN4DNar2f2HRoL2qxHoCWcLNf9V5uHTL2lBVCxz66eE8PMPwBw9h8RbKf"; + var secret = "c14tJd7kpMnePKRDoo4nzZk4bIn9bDO8ZCYo69amB4uspLgO5s4GlzYvTwD2zYav"; var client = BaseAPIClient.Create(Enums.Exchange.Binance, 0, apiKey, secret); //逐仓杠杆账户资产 - var marginList = client.GetIsolatedMarginAccountAssets(); - var s = JsonConvert.SerializeObject(marginList); + //var marginList = client.GetIsolatedMarginAccountAssets(); + //var s = JsonConvert.SerializeObject(marginList); + + //var spotClientOption = new BinanceApiClientOptions() + //{ + // BaseAddress = "https://api.binance.com", + // ApiCredentials = new ApiCredentials(apiKey, secret) + //}; + //var usdFuturesClientOption = new BinanceApiClientOptions() + //{ + // BaseAddress = "https://fapi.binance.com", + // ApiCredentials = new ApiCredentials(apiKey, secret) + //}; + //var binanceClient = new BinanceClient(new BinanceClientOptions() + //{ + // UsdFuturesApiOptions = usdFuturesClientOption, + // SpotApiOptions = spotClientOption + //}); + + var binanceSocketClient = new BinanceSocketClient(); + //var newClientOrderId = "abcd_286129845448773_1"; + //var orderId = client.IsolatedMarginPlaceOrder("ETHUSDT", Enums.TradeDirection.Buy, Enums.OrderType.MARKET, quoteAmount: 20M, newClientOrderId: newClientOrderId); + + var logger = NLog.LogManager.GetLogger("test"); + + + + + var stopLossClientOrderId = "stoploss2_286129845448773_1"; + long stopLossOrderId = 0; var spotClientOption = new BinanceApiClientOptions() {