Browse Source

市价止损 市价卖出取消止损

master
shanji 3 years ago
parent
commit
44dbcf18cd
  1. 10
      Binance.TradeRobot.API/Binance.TradeRobot.API.xml
  2. 2
      Binance.TradeRobot.API/Controllers/RobotController.cs
  3. 5
      Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml
  4. 20
      Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishBusiness.cs
  5. 124
      Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs
  6. 5
      Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml
  7. 11
      SDKAdapter/APIClient/BaseAPIClient.cs
  8. 5
      SDKAdapter/APIClient/BinanceAPIClient.cs

10
Binance.TradeRobot.API/Binance.TradeRobot.API.xml

@ -74,6 +74,11 @@
</summary> </summary>
<param name="robotId"></param> <param name="robotId"></param>
</member> </member>
<member name="M:Binance.TradeRobot.API.Controllers.RobotController.RefreshRobotRuningTime">
<summary>
刷新机器人运行时长
</summary>
</member>
<member name="M:Binance.TradeRobot.API.Controllers.RobotController.AddPyramidPolicyRobot(Binance.TradeRobot.Model.Dto.AddRobotRequest)"> <member name="M:Binance.TradeRobot.API.Controllers.RobotController.AddPyramidPolicyRobot(Binance.TradeRobot.Model.Dto.AddRobotRequest)">
<summary> <summary>
创建金字塔策略机器人 创建金字塔策略机器人
@ -92,6 +97,11 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Binance.TradeRobot.API.Controllers.RobotController.D21Remedy">
<summary>
D21补救检查
</summary>
</member>
<member name="M:Binance.TradeRobot.API.Controllers.SingalController.D21Singal(Binance.TradeRobot.Model.Dto.D21SingalRequest)"> <member name="M:Binance.TradeRobot.API.Controllers.SingalController.D21Singal(Binance.TradeRobot.Model.Dto.D21SingalRequest)">
<summary> <summary>
D21杠杆/合约信号接口 D21杠杆/合约信号接口

2
Binance.TradeRobot.API/Controllers/RobotController.cs

@ -41,6 +41,7 @@ namespace Binance.TradeRobot.API.Controllers
/// 刷新机器人运行时长 /// 刷新机器人运行时长
/// </summary> /// </summary>
[HttpPost] [HttpPost]
[AllowAnonymous]
public void RefreshRobotRuningTime() public void RefreshRobotRuningTime()
{ {
robotBusiness.RefreshRobotRuningTime(); robotBusiness.RefreshRobotRuningTime();
@ -80,6 +81,7 @@ namespace Binance.TradeRobot.API.Controllers
/// D21补救检查 /// D21补救检查
/// </summary> /// </summary>
[HttpPost] [HttpPost]
[AllowAnonymous]
public void D21Remedy() public void D21Remedy()
{ {
robotBusiness.D21Remedy(); robotBusiness.D21Remedy();

5
Binance.TradeRobot.Business/Binance.TradeRobot.Business.xml

@ -27,6 +27,11 @@
<param name="exchangeAPIKey"></param> <param name="exchangeAPIKey"></param>
<exception cref="T:Binance.TradeRobot.Model.Base.BusinessException"></exception> <exception cref="T:Binance.TradeRobot.Model.Base.BusinessException"></exception>
</member> </member>
<member name="M:Binance.TradeRobot.Business.RobotBusiness.RefreshRobotRuningTime">
<summary>
刷新机器人运行时长
</summary>
</member>
<member name="M:Binance.TradeRobot.Business.RobotBusiness.AddRobotWithTran(Binance.TradeRobot.Model.Dto.AddRobotRequest,System.Data.Common.DbTransaction)"> <member name="M:Binance.TradeRobot.Business.RobotBusiness.AddRobotWithTran(Binance.TradeRobot.Model.Dto.AddRobotRequest,System.Data.Common.DbTransaction)">
<summary> <summary>
添加机器人和账户 添加机器人和账户

20
Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/BaseSpotOrderPublishBusiness.cs

@ -14,6 +14,7 @@ namespace Binance.TradeRobot.Business
protected DingBusiness dingBusiness; protected DingBusiness dingBusiness;
protected RobotBusiness robotBusiness; protected RobotBusiness robotBusiness;
protected UserBusiness userBusiness; protected UserBusiness userBusiness;
protected ExchangeBusiness exchangeBusiness;
public BaseSpotOrderPublishBusiness(IFreeSql fsql, public BaseSpotOrderPublishBusiness(IFreeSql fsql,
NLogManager logManager, NLogManager logManager,
@ -21,11 +22,13 @@ namespace Binance.TradeRobot.Business
IMemoryCache memoryCache, IMemoryCache memoryCache,
DingBusiness dingBusiness, DingBusiness dingBusiness,
RobotBusiness robotBusiness, RobotBusiness robotBusiness,
UserBusiness userBusiness) : base(fsql, logManager, idGenerator, memoryCache) UserBusiness userBusiness,
ExchangeBusiness exchangeBusiness) : base(fsql, logManager, idGenerator, memoryCache)
{ {
this.dingBusiness = dingBusiness; this.dingBusiness = dingBusiness;
this.robotBusiness = robotBusiness; this.robotBusiness = robotBusiness;
this.userBusiness = userBusiness; this.userBusiness = userBusiness;
this.exchangeBusiness = exchangeBusiness;
} }
/// <summary> /// <summary>
@ -42,7 +45,7 @@ namespace Binance.TradeRobot.Business
if (!isOrderExists) if (!isOrderExists)
{ {
tryCount--; tryCount--;
Thread.Sleep(1000); Thread.Sleep(3000);
continue; continue;
} }
return; return;
@ -71,5 +74,18 @@ namespace Binance.TradeRobot.Business
logManager.GetLogger(loggerName).Error(ex, errorMsg); logManager.GetLogger(loggerName).Error(ex, errorMsg);
dingBusiness.Send($"{errorMsg} {ex.Message}"); dingBusiness.Send($"{errorMsg} {ex.Message}");
} }
/// <summary>
/// 创建客户端订单号
/// </summary>
/// <param name="robotId"></param>
/// <param name="tradePolicy"></param>
/// <returns></returns>
protected string CreateClientOrderId(long robotId, Enums.TradePolicy tradePolicy)
{
var guid = Guid.NewGuid();
var random = new Random(guid.GetHashCode());
return $"{Convert.ToChar(random.Next(97, 123))}{guid.ToString().Substring(0, 4)}_{robotId}_{(int)tradePolicy}";
}
} }
} }

124
Binance.TradeRobot.Business/Business/OrderPublishBusiness/Spot/D21OrderPublishBusiness.cs

@ -1,9 +1,12 @@
using Binance.TradeRobot.Common.DI; using Binance.TradeRobot.Common.DI;
using Binance.TradeRobot.Common.Extensions;
using Binance.TradeRobot.Model.Base; using Binance.TradeRobot.Model.Base;
using Binance.TradeRobot.Model.Db; using Binance.TradeRobot.Model.Db;
using Binance.TradeRobot.Model.Dto;
using FreeSql; using FreeSql;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SDKAdapter.APIClient;
using SDKAdapter.Model; using SDKAdapter.Model;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -17,7 +20,7 @@ namespace Binance.TradeRobot.Business
{ {
public Enums.TradePolicy TradePolicy => Enums.TradePolicy.D21; 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 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)
{ {
} }
@ -37,6 +40,8 @@ namespace Binance.TradeRobot.Business
if (robot == null) if (robot == null)
throw new BusinessException($"未找到机器人"); throw new BusinessException($"未找到机器人");
var symbolInfo = exchangeBusiness.GetSymbol(spotOrderPublishInfo.Exchange, spotOrderPublishInfo.Symbol);
var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey); var apiClient = GetBaseAPIClient(robot.ExchangeId, robot.ExchangeAPIKey.AccountId, robot.ExchangeAPIKey.APIKey, robot.ExchangeAPIKey.SecretKey);
IUpdate<SpotOrder> updateSpotOrder = fsql.Update<SpotOrder>(spotOrderPublishInfo.OrderId).Set(o => o.State, spotOrderPublishInfo.SpotOrderState); IUpdate<SpotOrder> updateSpotOrder = fsql.Update<SpotOrder>(spotOrderPublishInfo.OrderId).Set(o => o.State, spotOrderPublishInfo.SpotOrderState);
@ -44,6 +49,7 @@ namespace Binance.TradeRobot.Business
IList<IUpdate<User>> updateUserList = null; IList<IUpdate<User>> updateUserList = null;
List<UserAccountProfitLossRecord> insertUserAccountProfitLossRecordList = null; List<UserAccountProfitLossRecord> insertUserAccountProfitLossRecordList = null;
IUpdate<D21Policy> updateD21Policy = null; IUpdate<D21Policy> updateD21Policy = null;
List<SpotOrder> insertStopLossOrderList = null;
if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Rejected || if (spotOrderPublishInfo.SpotOrderState == Enums.SpotOrderState.Rejected ||
@ -97,8 +103,30 @@ namespace Binance.TradeRobot.Business
if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET) if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET)
{ {
//市价买单完全成交,根据策略挂止损单 #region 市价买单挂止损
insertStopLossOrderList = new List<SpotOrder>();
try
{
if (robot.D21Policy.Level1PositionStopLossRatio > 0 && robot.D21Policy.Level1PriceStopLossRatio > 0)
StopLossOrderPlace(robot, symbolInfo, avgTradePrice, quantity, insertStopLossOrderList, logList, apiClient, true);
if (robot.D21Policy.Level2PositionStopLossRatio > 0 &&
robot.D21Policy.Level2PriceStopLossRatio > 0 &&
robot.D21Policy.Level2PositionStopLossRatio + robot.D21Policy.Level1PositionStopLossRatio == 100)
StopLossOrderPlace(robot, symbolInfo, avgTradePrice, quantity, insertStopLossOrderList, logList, apiClient, false);
}
catch (Exception ex)
{
logList.Add(new ExecutionLog()
{
Id = idGenerator.NewLong(),
SourceSingal = Enums.SingalType.,
RobotId = robot.Id,
CreateTime = DateTime.Now,
Content = $"止损单挂单失败,{ex.Message}"
});
}
#endregion
} }
} }
else if (spotOrderPublishInfo.TradeDirection == Enums.TradeDirection.Sell) else if (spotOrderPublishInfo.TradeDirection == Enums.TradeDirection.Sell)
@ -109,7 +137,21 @@ namespace Binance.TradeRobot.Business
if (spotOrderPublishInfo.OrderType == Enums.OrderType.MARKET) 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 interest = 0M; //借币利息
@ -173,9 +215,6 @@ namespace Binance.TradeRobot.Business
}); });
} }
} }
} }
fsql.Transaction(() => fsql.Transaction(() =>
@ -189,6 +228,8 @@ namespace Binance.TradeRobot.Business
if (updateUserList != null && updateUserList.Count() > 0) if (updateUserList != null && updateUserList.Count() > 0)
foreach (var u in updateUserList) foreach (var u in updateUserList)
u.ExecuteAffrows(); u.ExecuteAffrows();
if (insertStopLossOrderList != null && insertStopLossOrderList.Count() > 0)
fsql.Insert(insertStopLossOrderList).ExecuteAffrows();
}); });
} }
@ -197,5 +238,76 @@ namespace Binance.TradeRobot.Business
HandleError(ex, logList, spotOrderPublishInfo.LoggerName, spotOrderPublishInfo.RobotId, spotOrderPublishInfo.OrderId, step); HandleError(ex, logList, spotOrderPublishInfo.LoggerName, spotOrderPublishInfo.RobotId, spotOrderPublishInfo.OrderId, step);
} }
} }
/// <summary>
/// 挂止损单
/// </summary>
/// <param name="d21Robot"></param>
/// <param name="symbolInfo"></param>
/// <param name="avgTradePrice"></param>
/// <param name="buyQuantity"></param>
/// <param name="insertStopLossOrderList"></param>
/// <param name="logList"></param>
/// <param name="baseAPIClient"></param>
/// <param name="isFirstStopLoss"></param>
private void StopLossOrderPlace(D21PolicyRobotResponse d21Robot,
SymbolInfo symbolInfo,
decimal avgTradePrice,
decimal buyQuantity,
IList<SpotOrder> insertStopLossOrderList,
IList<ExecutionLog> logList,
BaseAPIClient baseAPIClient,
bool isFirstStopLoss)
{
var positionStopLossRatio = (isFirstStopLoss ? d21Robot.D21Policy.Level1PositionStopLossRatio : d21Robot.D21Policy.Level2PositionStopLossRatio) / 100;
var priceStopLossRatio = (isFirstStopLoss ? d21Robot.D21Policy.Level1PriceStopLossRatio : d21Robot.D21Policy.Level2PriceStopLossRatio) / 100;
var stopPrice = avgTradePrice - avgTradePrice * priceStopLossRatio;
var stopQuantity = (buyQuantity * positionStopLossRatio).CutDecimal(symbolInfo.SaleQuantityAccuracy);
var stopLossClientOrderId = CreateClientOrderId(d21Robot.Id, d21Robot.TradePolicy);
var stopOrderId = baseAPIClient.IsolatedMarginPlaceOrder(d21Robot.Symbol,
Enums.TradeDirection.Sell,
Enums.OrderType.STOP_LOSS_LIMIT,
stopPrice: stopPrice,
price: stopPrice,
quantity: stopQuantity,
newClientOrderId: stopLossClientOrderId);
var stopLossOrder = new SpotOrder()
{
Id = stopOrderId,
CreateTime = DateTime.Now,
ExchangeId = d21Robot.ExchangeId,
LoanAmount = 0M,
OrderType = Enums.OrderType.STOP_LOSS_LIMIT,
PolicyType = Enums.TradePolicy.D21,
RobotId = d21Robot.Id,
State = Enums.SpotOrderState.Created,
Symbol = d21Robot.Symbol,
TradeDirection = Enums.TradeDirection.Sell
};
insertStopLossOrderList.Add(stopLossOrder);
logList.Add(new ExecutionLog()
{
Id = idGenerator.NewLong(),
SourceSingal = Enums.SingalType.,
RobotId = d21Robot.Id,
OrderId = stopOrderId,
CreateTime = DateTime.Now,
Content = $"{(isFirstStopLoss ? 1 : 2)}级止损挂单成功,订单号:{stopOrderId},挂单数量:{stopQuantity}"
});
}
private void CancelStopLossOrder(D21PolicyRobotResponse d21Robot, BaseAPIClient baseAPIClient)
{
var stopLossOrderIdList = fsql.Select<SpotOrder>().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);
}
} }
} }

5
Binance.TradeRobot.Model/Binance.TradeRobot.Model.xml

@ -749,11 +749,6 @@
运行时长(s) 运行时长(s)
</summary> </summary>
</member> </member>
<member name="P:Binance.TradeRobot.Model.Dto.RobotResponse.SymbolInfo">
<summary>
订单推送日志Key
</summary>
</member>
<member name="P:Binance.TradeRobot.Model.Dto.RobotResponse.RobotAccount"> <member name="P:Binance.TradeRobot.Model.Dto.RobotResponse.RobotAccount">
<summary> <summary>
机器人账户对象 机器人账户对象

11
SDKAdapter/APIClient/BaseAPIClient.cs

@ -92,5 +92,16 @@ namespace SDKAdapter.APIClient
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
/// <summary>
/// 取消逐仓杠杆订单
/// </summary>
/// <param name="symbol"></param>
/// <param name="orderId"></param>
/// <exception cref="NotImplementedException"></exception>
public virtual void CancelIsolateMarginOrder(string symbol, long orderId)
{
throw new NotImplementedException();
}
} }
} }

5
SDKAdapter/APIClient/BinanceAPIClient.cs

@ -134,5 +134,10 @@ namespace SDKAdapter.APIClient
throw new Exception($"下单失败 {orderType} {tradeDirection} {r.Error?.Message}"); throw new Exception($"下单失败 {orderType} {tradeDirection} {r.Error?.Message}");
return r.Data.Id; return r.Data.Id;
} }
public override void CancelIsolateMarginOrder(string symbol, long orderId)
{
_ = binanceClient.SpotApi.Trading.CancelMarginOrderAsync(symbol, orderId, isIsolated: true);
}
} }
} }

Loading…
Cancel
Save