|
|
|
|
@ -7,7 +7,9 @@ import (
|
|
|
|
|
DbModels "go-admin/app/admin/models"
|
|
|
|
|
"go-admin/common/global"
|
|
|
|
|
"go-admin/common/helper"
|
|
|
|
|
"go-admin/models"
|
|
|
|
|
"go-admin/pkg/maphelper"
|
|
|
|
|
"go-admin/pkg/utility/snowflakehelper"
|
|
|
|
|
"go-admin/services/cacheservice"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
|
@ -68,10 +70,23 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac
|
|
|
|
|
result, err := e.handleSimpleStatusChange(status, orderSn, mapData)
|
|
|
|
|
|
|
|
|
|
//如果是 新开止盈止损 需要取消反单的止盈止损之后重下反单止盈止损
|
|
|
|
|
if status == "NEW" && (ot == "TAKE_PROFIT_MARKET" || ot == "STOP_LOSS_MARKET" || ot == "TAKE_PROFIT_LIMIT" || ot == "STOP_LOSS_LIMIT") &&
|
|
|
|
|
if status == "NEW" && (ot == "TAKE_PROFIT_MARKET" || ot == "STOP_MARKET" || ot == "TAKE_PROFIT" || ot == "STOP") &&
|
|
|
|
|
apiInfo.ReverseStatus == 1 && apiInfo.OpenStatus == 1 && apiInfo.ReverseApiId > 0 {
|
|
|
|
|
symbolCode, err := maphelper.GetString(mapData, "s")
|
|
|
|
|
|
|
|
|
|
if err := e.ReTakeOrStopOrder(&mapData, orderSn, &apiInfo); err != nil {
|
|
|
|
|
if err != nil {
|
|
|
|
|
e.Log.Errorf("获取symbolCode失败 symbol:%s err:%v", symbolCode, err)
|
|
|
|
|
return true, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
symbol, err := cacheservice.GetTradeSet(global.EXCHANGE_BINANCE, symbolCode, 1)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
e.Log.Errorf("获取symbol失败 symbol:%s err:%v", symbolCode, err)
|
|
|
|
|
return true, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := e.ReTakeOrStopOrder(&mapData, orderSn, &apiInfo, &symbol); err != nil {
|
|
|
|
|
return true, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -128,6 +143,7 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac
|
|
|
|
|
return true, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
price := maphelper.GetDecimal(mapData, "ap")
|
|
|
|
|
totalNum := maphelper.GetDecimal(mapData, "z")
|
|
|
|
|
|
|
|
|
|
mainOrder := DbModels.LineReverseOrder{
|
|
|
|
|
@ -136,6 +152,7 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac
|
|
|
|
|
PositionSide: positionSide,
|
|
|
|
|
TotalNum: totalNum,
|
|
|
|
|
Side: side,
|
|
|
|
|
Price: price,
|
|
|
|
|
}
|
|
|
|
|
e.changeOrderStatus(3, orderSn, mapData)
|
|
|
|
|
|
|
|
|
|
@ -175,8 +192,8 @@ func (e *ReverseService) changeOrderStatus(status int, orderSn string, mapData m
|
|
|
|
|
data["order_id"] = orderId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ap, ok := mapData["ap"].(bool); ok {
|
|
|
|
|
data["final_price"] = ap
|
|
|
|
|
if ap, ok := mapData["ap"].(string); ok {
|
|
|
|
|
data["final_price"], _ = decimal.NewFromString(ap)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if num, ok := mapData["z"].(string); ok {
|
|
|
|
|
@ -184,6 +201,10 @@ func (e *ReverseService) changeOrderStatus(status int, orderSn string, mapData m
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data["trigger_time"] = &now
|
|
|
|
|
} else if status == 2 {
|
|
|
|
|
if orderId, ok := mapData["i"].(float64); ok {
|
|
|
|
|
data["order_id"] = orderId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
db := e.Orm.Model(&DbModels.LineReverseOrder{}).
|
|
|
|
|
@ -284,6 +305,12 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r
|
|
|
|
|
side := reverseOrder.Side
|
|
|
|
|
totalNum := reverseOrder.TotalNum
|
|
|
|
|
|
|
|
|
|
symbol, err1 := cacheservice.GetTradeSet(global.EXCHANGE_BINANCE, reverseOrder.Symbol, 1)
|
|
|
|
|
|
|
|
|
|
if err1 != nil {
|
|
|
|
|
e.Log.Errorf("获取交易对失败 symbol:%s err:%v", reverseOrder.Symbol, err1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var querySql string
|
|
|
|
|
sqlStr := ""
|
|
|
|
|
|
|
|
|
|
@ -310,6 +337,8 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r
|
|
|
|
|
position.Status = 1
|
|
|
|
|
position.ReverseStatus = 0
|
|
|
|
|
position.PositionSide = positionSide
|
|
|
|
|
position.AveragePrice = reverseOrder.FinalPrice
|
|
|
|
|
position.PositionNo = snowflakehelper.GetOrderNo()
|
|
|
|
|
}
|
|
|
|
|
querySql = "api_id =? and position_side =? and symbol =? and status =1"
|
|
|
|
|
|
|
|
|
|
@ -319,9 +348,9 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set amount=@totalNum,updated_at=now(),status=2 where id =@id and status!=2 "
|
|
|
|
|
} else if reducePosition {
|
|
|
|
|
//只减仓
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set amount=amount - @totalNum,updated_at=now() where id =@id and status!=2 "
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set amount=amount - @totalNum,updated_at=now(),average_price=@averagePrice where id =@id and status!=2 "
|
|
|
|
|
} else {
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set total_amount=total_amount + @totalNum,amount=amount + @totalNum,updated_at=now() where id =@id and status!=2"
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set total_amount=total_amount + @totalNum,amount=amount + @totalNum,updated_at=now(),average_price=@averagePrice where id =@id and status!=2"
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
querySql = "reverse_api_id =? and position_side =? and symbol =? and reverse_status in (0,1)"
|
|
|
|
|
@ -330,12 +359,14 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r
|
|
|
|
|
totalNum = decimal.Zero
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set reverse_amount=@totalNum,updated_at=now(),reverse_status=2 where id =@id and reverse_status !=2"
|
|
|
|
|
} else if reducePosition {
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set reverse_amount=reverse_amount - @totalNum,updated_at=now() where id =@id and reverse_status !=2"
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set reverse_amount=reverse_amount - @totalNum,updated_at=now(),reverse_average_price=@averagePrice where id =@id and reverse_status !=2"
|
|
|
|
|
} else {
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set total_reverse_amount=total_reverse_amount + @totalNum,reverse_amount=reverse_amount + @totalNum,updated_at=now(),reverse_status =1 where id =@id and reverse_status !=2"
|
|
|
|
|
sqlStr = "UPDATE line_reverse_position set total_reverse_amount=total_reverse_amount + @totalNum,reverse_amount=reverse_amount + @totalNum,updated_at=now(),reverse_status =1,reverse_average_price=@averagePrice where id =@id and reverse_status !=2"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var averagePrice decimal.Decimal
|
|
|
|
|
|
|
|
|
|
err := e.Orm.Transaction(func(tx *gorm.DB) error {
|
|
|
|
|
err1 := tx.Model(&position).Where(querySql,
|
|
|
|
|
reverseOrder.ApiId, positionSide, reverseOrder.Symbol).First(&position).Error
|
|
|
|
|
@ -347,16 +378,69 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r
|
|
|
|
|
if err2 := tx.Create(&position).Error; err2 != nil {
|
|
|
|
|
return err2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
averagePrice = position.AveragePrice
|
|
|
|
|
} else {
|
|
|
|
|
return err1
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
var totalAmount decimal.Decimal
|
|
|
|
|
var totalPrice decimal.Decimal
|
|
|
|
|
if !position.Amount.IsZero() && !position.AveragePrice.IsZero() {
|
|
|
|
|
if isMain {
|
|
|
|
|
totalPrice = position.Amount.Mul(position.AveragePrice)
|
|
|
|
|
totalAmount = position.Amount
|
|
|
|
|
} else {
|
|
|
|
|
totalPrice = position.ReverseAmount.Mul(position.ReverseAveragePrice)
|
|
|
|
|
totalAmount = position.ReverseAmount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//加仓
|
|
|
|
|
if !reducePosition {
|
|
|
|
|
totalPrice = totalPrice.Add(reverseOrder.Price.Mul(reverseOrder.TotalNum))
|
|
|
|
|
totalAmount = totalAmount.Add(reverseOrder.TotalNum)
|
|
|
|
|
} else if reducePosition && !closePosition {
|
|
|
|
|
//只减仓
|
|
|
|
|
totalPrice = totalPrice.Sub(reverseOrder.Price.Mul(reverseOrder.TotalNum))
|
|
|
|
|
totalAmount = totalAmount.Sub(reverseOrder.TotalNum)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if totalAmount.IsZero() || totalPrice.IsZero() {
|
|
|
|
|
if isMain {
|
|
|
|
|
averagePrice = position.AveragePrice
|
|
|
|
|
} else {
|
|
|
|
|
if position.ReverseAveragePrice.IsZero() {
|
|
|
|
|
averagePrice = reverseOrder.Price
|
|
|
|
|
} else {
|
|
|
|
|
averagePrice = position.ReverseAveragePrice
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//平仓
|
|
|
|
|
if closePosition {
|
|
|
|
|
if isMain {
|
|
|
|
|
averagePrice = position.AveragePrice
|
|
|
|
|
} else {
|
|
|
|
|
averagePrice = position.ReverseAveragePrice
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
averagePrice = totalPrice.Div(totalAmount).Truncate(int32(symbol.PriceDigit))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbResult := tx.Exec(sqlStr, sql.Named("totalNum", totalNum), sql.Named("id", position.Id))
|
|
|
|
|
//关联订单的仓位id
|
|
|
|
|
if err2 := tx.Exec("UPDATE line_reverse_order set position_id=@positionId where id=@orderId and position_id = 0", sql.Named("positionId", position.Id), sql.Named("orderId", reverseOrder.Id)).Error; err2 != nil {
|
|
|
|
|
return err2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbResult := tx.Exec(sqlStr, sql.Named("totalNum", totalNum), sql.Named("id", position.Id), sql.Named("averagePrice", averagePrice))
|
|
|
|
|
if dbResult.Error != nil {
|
|
|
|
|
return dbResult.Error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reverseOrder.PositionId = position.Id
|
|
|
|
|
if dbResult.RowsAffected == 0 {
|
|
|
|
|
e.Log.Errorf("减仓数据 是否平仓单:%v :%v", closePosition, reverseOrder)
|
|
|
|
|
return errors.New("没有找到对应的持仓信息")
|
|
|
|
|
@ -471,8 +555,8 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//反向下单百分比
|
|
|
|
|
proportion = proportion.Div(decimal.NewFromInt(100)).Truncate(2)
|
|
|
|
|
amount = mainOrder.BuyPrice.Mul(proportion).Div(price).Truncate(int32(symbol.AmountDigit))
|
|
|
|
|
proportion = proportion.Div(decimal.NewFromInt(100)).Truncate(4)
|
|
|
|
|
amount = mainOrder.TotalNum.Mul(proportion).Truncate(int32(symbol.AmountDigit))
|
|
|
|
|
|
|
|
|
|
if amount.Cmp(decimal.Zero) <= 0 {
|
|
|
|
|
e.Log.Errorf("计算数量失败 symbol:%s custom:%s 数量小于0", mainOrder.Symbol, mainOrder.OrderSn)
|
|
|
|
|
@ -487,6 +571,7 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder,
|
|
|
|
|
order.Status = 1
|
|
|
|
|
order.Type = setting.ReverseOrderType
|
|
|
|
|
order.SignPrice = signPrice
|
|
|
|
|
order.PositionId = mainOrder.PositionId
|
|
|
|
|
|
|
|
|
|
if order.Remark != "" {
|
|
|
|
|
order.Status = 8
|
|
|
|
|
@ -498,12 +583,64 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if order.Status == 1 {
|
|
|
|
|
e.DoBianceOrder(&order, reverseApiInfo, &setting, reducePosition, closePosition)
|
|
|
|
|
err = e.DoBianceOrder(&order, reverseApiInfo, &setting, reducePosition, closePosition)
|
|
|
|
|
|
|
|
|
|
//Biance下单成共 且为平仓单时 取消止盈止损
|
|
|
|
|
if err == nil && closePosition {
|
|
|
|
|
e.DoCancelTakeProfitBatch(symbol.GetSymbol(), order.PositionSide, order.Side, -1, reverseApiInfo)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 取消止盈止损订单
|
|
|
|
|
// symbol: 交易对
|
|
|
|
|
// positionSide: 持仓方向
|
|
|
|
|
// side: 订单方向
|
|
|
|
|
// orderType: 订单类型 -1-全部 1-止盈 2-止损
|
|
|
|
|
// apiInfo: 下单api
|
|
|
|
|
func (e *ReverseService) DoCancelTakeProfitBatch(symbol, positionSide, side string, orderType int, apiInfo *DbModels.LineApiUser) error {
|
|
|
|
|
orderSns := e.GetTakeProfitBatch(symbol, positionSide, side, apiInfo.Id, orderType)
|
|
|
|
|
|
|
|
|
|
if len(orderSns) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(orderSns) > 0 {
|
|
|
|
|
futApi := FutRestApi{}
|
|
|
|
|
err := futApi.CancelBatchFutOrderLoop(*apiInfo, symbol, orderSns)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
e.Log.Errorf("币安撤单失败 symbol:%s custom:%v :%v", symbol, orderSns, err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取止盈止损订单
|
|
|
|
|
// symbol: 交易对
|
|
|
|
|
// positionSide: 持仓方向
|
|
|
|
|
// side: 订单方向
|
|
|
|
|
// apiId: 币安apiId
|
|
|
|
|
// orderType: 订单类型 -1-全部 1-止盈 2-止损
|
|
|
|
|
func (e *ReverseService) GetTakeProfitBatch(symbol, positionSide, side string, apiId int, orderType int) []string {
|
|
|
|
|
var orderSns []string
|
|
|
|
|
orderTypes := []int{1, 2}
|
|
|
|
|
|
|
|
|
|
if orderType == 1 {
|
|
|
|
|
orderTypes = []int{1}
|
|
|
|
|
} else if orderType == 2 {
|
|
|
|
|
orderTypes = []int{2}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.Orm.Model(&DbModels.LineReverseOrder{}).Where("symbol =? and position_side =? and side = ? and status =2 and order_type in ?", symbol, positionSide, side, orderTypes).Pluck("order_sn", &orderSns)
|
|
|
|
|
|
|
|
|
|
return orderSns
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理币安订单
|
|
|
|
|
// order: 反单信息
|
|
|
|
|
// apiInfo: 币安api信息
|
|
|
|
|
@ -546,13 +683,8 @@ func (e *ReverseService) DoBianceOrder(order *DbModels.LineReverseOrder, apiInfo
|
|
|
|
|
|
|
|
|
|
// 重下止盈止损
|
|
|
|
|
// mapData: 主单止盈止损回调
|
|
|
|
|
func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orderSn string, mainApiInfo *DbModels.LineApiUser) error {
|
|
|
|
|
symbol, err := maphelper.GetString(*mapData, "s")
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orderSn string, mainApiInfo *DbModels.LineApiUser, symbol *models.TradeSet) error {
|
|
|
|
|
orderType := 0 //订单类型 1-止盈 2-止损
|
|
|
|
|
side, err := maphelper.GetString(*mapData, "S")
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
@ -584,6 +716,12 @@ func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orde
|
|
|
|
|
positionSide = "LONG"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close := maphelper.GetBool(*mapData, "cp")
|
|
|
|
|
stopPrice := maphelper.GetDecimal(*mapData, "sp")
|
|
|
|
|
if stopPrice.IsZero() {
|
|
|
|
|
e.Log.Errorf("获取止盈止损单触发价失败 symbol:%s custom:%s :%v", symbol, orderSn, err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
apiInfo, err := GetApiInfo(mainApiInfo.ReverseApiId)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
@ -591,33 +729,96 @@ func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orde
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var reverseOrder DbModels.LineReverseOrder
|
|
|
|
|
e.Orm.Model(&DbModels.LineReverseOrder{}).
|
|
|
|
|
Where("symbol =? and api_id =? and position_side =? and side = ? and status =1", symbol, mainApiInfo.ReverseApiId, positionSide, side).
|
|
|
|
|
First(&reverseOrder)
|
|
|
|
|
|
|
|
|
|
//取消旧止盈止损
|
|
|
|
|
if reverseOrder.OrderSn != "" {
|
|
|
|
|
futApi := FutRestApi{}
|
|
|
|
|
err := futApi.CancelFutOrderRetry(apiInfo, symbol, reverseOrder.OrderSn)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
e.Log.Errorf("币安撤单失败 symbol:%s custom:%s :%v", symbol, orderSn, err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
switch ot {
|
|
|
|
|
case "STOP_MARKET", "STOP":
|
|
|
|
|
orderType = 2
|
|
|
|
|
case "TAKE_PROFIT_MARKET", "TAKE_PROFIT":
|
|
|
|
|
orderType = 1
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("不支持的订单类型 ot:%s", ot)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var reversePosition DbModels.LineReversePosition
|
|
|
|
|
|
|
|
|
|
e.Orm.Model(&reversePosition).
|
|
|
|
|
Where("symbol =? and reverse_api_id =? and position_side =? and reverse_status =1", symbol.GetSymbol(), apiInfo.Id, positionSide).
|
|
|
|
|
First(&reversePosition)
|
|
|
|
|
|
|
|
|
|
if reversePosition.Id == 0 {
|
|
|
|
|
e.Log.Errorf("获取反单持仓失败 symbol:%s custom:%s :%v", symbol, orderSn, err)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mainPercent := decimal.NewFromInt(1)
|
|
|
|
|
|
|
|
|
|
if !stopPrice.IsZero() && !reversePosition.AveragePrice.IsZero() {
|
|
|
|
|
mainPercent = stopPrice.Div(reversePosition.AveragePrice)
|
|
|
|
|
mainPercent = (mainPercent.Sub(decimal.NewFromInt(1))).Abs().Truncate(4)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var percent decimal.Decimal
|
|
|
|
|
switch {
|
|
|
|
|
//做多止损
|
|
|
|
|
case orderType == 2 && positionSide == "LONG", orderType == 1 && positionSide == "SHORT":
|
|
|
|
|
percent = decimal.NewFromInt(1).Sub(mainPercent)
|
|
|
|
|
case orderType == 2 && positionSide == "SHORT", orderType == 1 && positionSide == "LONG":
|
|
|
|
|
percent = decimal.NewFromInt(1).Add(mainPercent)
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("不支持的订单类型 ot:%s, ps:%s", ot, positionSide)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
|
price := reversePosition.AveragePrice.Mul(percent).Truncate(int32(symbol.PriceDigit))
|
|
|
|
|
lastPrice, _ := decimal.NewFromString(symbol.LastPrice)
|
|
|
|
|
newOrder := DbModels.LineReverseOrder{
|
|
|
|
|
PositionId: reversePosition.Id,
|
|
|
|
|
OrderSn: helper.GetOrderNo(),
|
|
|
|
|
OrderType: orderType,
|
|
|
|
|
Status: 1,
|
|
|
|
|
Price: price,
|
|
|
|
|
TotalNum: reversePosition.TotalReverseAmount,
|
|
|
|
|
Symbol: symbol.GetSymbol(),
|
|
|
|
|
Side: side,
|
|
|
|
|
PositionSide: positionSide,
|
|
|
|
|
FollowOrderSn: orderSn,
|
|
|
|
|
Type: ot,
|
|
|
|
|
SignPrice: lastPrice,
|
|
|
|
|
Category: 1,
|
|
|
|
|
ApiId: apiInfo.Id,
|
|
|
|
|
IsAddPosition: 2,
|
|
|
|
|
TriggerTime: &now,
|
|
|
|
|
BuyPrice: reversePosition.TotalReverseAmount.Mul(price).Truncate(int32(symbol.PriceDigit)),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err1 := e.Orm.Create(&newOrder).Error; err1 != nil {
|
|
|
|
|
e.Log.Errorf("保存反单止盈止损失败 symbol:%s custom:%s :%v", symbol, orderSn, err1)
|
|
|
|
|
return err1
|
|
|
|
|
}
|
|
|
|
|
params := FutOrderPlace{
|
|
|
|
|
ApiId: apiInfo.Id,
|
|
|
|
|
Symbol: symbol,
|
|
|
|
|
Symbol: symbol.GetSymbol(),
|
|
|
|
|
PositionSide: positionSide,
|
|
|
|
|
Side: side,
|
|
|
|
|
OrderType: ot,
|
|
|
|
|
Quantity: reverseOrder.TotalNum,
|
|
|
|
|
Price: reverseOrder.Price,
|
|
|
|
|
NewClientOrderId: reverseOrder.OrderSn,
|
|
|
|
|
Quantity: reversePosition.TotalReverseAmount,
|
|
|
|
|
Price: price,
|
|
|
|
|
StopPrice: price,
|
|
|
|
|
Profit: price,
|
|
|
|
|
NewClientOrderId: newOrder.OrderSn,
|
|
|
|
|
ClosePosition: close,
|
|
|
|
|
}
|
|
|
|
|
futApiV2 := FuturesResetV2{Service: e.Service}
|
|
|
|
|
futApiV2.OrderPlace(&apiInfo, params)
|
|
|
|
|
err = futApiV2.OrderPlaceLoop(&apiInfo, params)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
e.Log.Errorf("币安下单失败 symbol:%s custom:%s :%v", symbol.GetSymbol(), orderSn, err)
|
|
|
|
|
|
|
|
|
|
if err1 := e.Orm.Model(&newOrder).Updates(map[string]interface{}{"status": 8, "remark": err.Error(), "updated_at": time.Now()}).Error; err1 != nil {
|
|
|
|
|
e.Log.Errorf("更新订单状态失败 symbol:%s custom:%s :%v", newOrder.Symbol, newOrder.OrderSn, err1)
|
|
|
|
|
}
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.DoCancelTakeProfitBatch(symbol.GetSymbol(), positionSide, side, orderType, &apiInfo)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|