1、主单增加减仓、加仓状态

2、bug修复
This commit is contained in:
2025-02-20 12:00:04 +08:00
parent b132ee879b
commit ade768c28a
13 changed files with 312 additions and 52 deletions

View File

@ -625,6 +625,10 @@ func (e LinePreOrder) CalculateBreakEevenRatio(c *gin.Context) {
return
}
if req.Symbol == "" {
return
}
// data := dto.CalculateBreakEvenRatioResp{}
_, err = s.GenerateOrder(&req)
if err != nil {

View File

@ -183,7 +183,7 @@ func (s *LinePreOrderDeleteReq) GetId() interface{} {
type LineAddPreOrderReq struct {
ExchangeType string `json:"exchange_type" vd:"len($)>0"` //交易所类型
OrderType int `json:"order_type"` //订单类型
Symbol string `json:"symbol" vd:"len($)>0"` //交易对
Symbol string `json:"symbol"` //交易对
ApiUserId string `json:"api_id" ` //下单用户
Site string `json:"site" ` //购买方向
BuyPrice string `json:"buy_price" vd:"$>0"` //购买金额 U
@ -341,15 +341,15 @@ func (req LineBatchAddPreOrderReq) CheckParams() error {
return errors.New("加仓单下跌价格不能为空")
}
if v.ReduceNumRatio.IsZero() || v.ReduceNumRatio.Cmp(decimal.Zero) > 0 {
if v.ReduceNumRatio.IsZero() || v.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) > 0 {
return errors.New("减仓数量不正确")
}
if v.ReducePriceRatio.IsZero() || v.ReducePriceRatio.Cmp(decimal.Zero) > 0 {
if v.ReducePriceRatio.IsZero() || v.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) > 0 {
return errors.New("减仓下跌价格不正确")
}
if v.ReduceTakeProfitRatio.IsZero() || v.ReduceTakeProfitRatio.Cmp(decimal.Zero) > 0 {
if v.ReduceTakeProfitRatio.IsZero() || v.ReduceTakeProfitRatio.Cmp(decimal.NewFromInt(100)) > 0 {
return errors.New("减仓后止盈价格不正确")
}
}
@ -371,8 +371,8 @@ type LeverReq struct {
Symbol string `json:"symbol"`
Leverage int `json:"leverage"`
GroupId int `json:"group_id"`
IsAll int `json:"is_all"` // 1= 全部 0=不是全部
ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type
IsAll int `json:"is_all"` // 1= 全部 0=不是全部
ExchangeType string `json:"exchangeType"` //交易所类型 字典exchange_type
}
func (c LeverReq) CheckParams() error {
@ -387,11 +387,11 @@ func (c LeverReq) CheckParams() error {
type MarginTypeReq struct {
ApiUserIds string `json:"api_user_ids"`
Symbol string `json:"symbol"` // 交易对
MarginType string `json:"margin_type"` //全仓 CROSSED 逐仓 ISOLATED
GroupId int `json:"group_id"` // 交易对组id
IsAll int `json:"is_all"` // 1= 全部 0=不是全部
ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type
Symbol string `json:"symbol"` // 交易对
MarginType string `json:"margin_type"` //全仓 CROSSED 逐仓 ISOLATED
GroupId int `json:"group_id"` // 交易对组id
IsAll int `json:"is_all"` // 1= 全部 0=不是全部
ExchangeType string `json:"exchangeType"` //交易所类型 字典exchange_type
}
type CancelOpenOrderReq struct {
@ -399,7 +399,7 @@ type CancelOpenOrderReq struct {
Symbol string `json:"symbol"`
OrderSn string `json:"order_sn"`
OrderType int `json:"order_type"`
ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type
ExchangeType string `json:"exchangeType"` //交易所类型 字典exchange_type
}
type GetChildOrderReq struct {

View File

@ -323,7 +323,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
//获取交易对
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key)
orderCount := e.CheckRepeatOrder(req.OrderType, id, req.Site, tradeSet.Coin)
orderCount := e.CheckRepeatOrder(req.SymbolType, id, req.Site, tradeSet.Coin)
if orderCount > 0 {
*errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 该交易对已存在,请勿重复下单", id, req.Symbol))
continue
@ -571,6 +571,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
stopOrder.MainId = AddOrder.Id
stopOrder.OrderType = 4
stopOrder.Status = 0
stopOrder.BuyPrice = "0"
stopOrder.Rate = req.ReducePriceRatio.String()
stopNum := utility.StrToDecimal(AddOrder.Num).Mul(req.ReduceNumRatio.Div(decimal.NewFromInt(100)).Truncate(4))
stopOrder.Num = stopNum.Truncate(int32(tradeSet.AmountDigit)).String()
@ -807,9 +808,9 @@ func makeReduceTakeAndStoploss(parentOrder *models.LinePreOrder, ext models.Line
}
// CheckRepeatOrder 检查重复下单 检查基础货币
func (e *LinePreOrder) CheckRepeatOrder(orderType int, apiUserId, site, baseCoin string) int64 {
func (e *LinePreOrder) CheckRepeatOrder(symbolType int, apiUserId, site, baseCoin string) int64 {
var count int64
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND pid=0 AND symbol like ? AND order_type = ? AND site = ? AND `status` IN (1,5,6)", apiUserId, baseCoin+"%", orderType, site).Count(&count)
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND pid=0 AND symbol like ? AND symbol_type = ? AND site = ? AND `status` IN (1,5,6)", apiUserId, baseCoin+"%", symbolType, site).Count(&count)
return count
}
@ -897,6 +898,7 @@ func (e *LinePreOrder) AddBatchPreOrder(batchReq *dto.LineBatchAddPreOrderReq, p
req.Price = batchReq.Price
req.Profit = batchReq.Profit
req.Ext = batchReq.Ext
req.SymbolType = batchReq.SymbolType
// req.StopPrice = batchReq.StopPrice
req.ReducePriceRatio = batchReq.ReducePriceRatio
req.PriceType = batchReq.PriceType
@ -1176,6 +1178,8 @@ func (e *LinePreOrder) ClearAll() error {
"stop_loss_markt",
"_PreSpotOrderList_",
"_PreFutOrderList_",
"spot_reduce_list",
"futures_reduce_list",
}
err = helper.DefaultRedis.DeleteKeysByPrefix(prefixs...)
if err != nil {

View File

@ -25,6 +25,7 @@ import (
"time"
"github.com/bytedance/sonic"
"github.com/shopspring/decimal"
"gorm.io/driver/mysql"
"github.com/go-admin-team/go-admin-core/sdk"
@ -225,19 +226,28 @@ func (t LimitOrderTimeoutDuration) ReSpotOrderPlace(db *gorm.DB, order models.Li
logger.Error(fmt.Sprintf("取消现货委托失败:order_sn:%s err:%+v", order.OrderSn, err))
return err
} else {
var remainingQuantity decimal.Decimal
spotOrder, err := spotApi.GetOrderByOrderSnLoop(order.Symbol, order.OrderSn, apiUserinfo, 4)
if err == nil {
origQty := utility.StrToDecimal(spotOrder.OrigQuoteOrderQty)
excuteQty := utility.StrToDecimal(spotOrder.ExecutedQty)
remainingQuantity = origQty.Sub(excuteQty).Abs()
}
if remainingQuantity.Cmp(decimal.Zero) <= 0 {
logger.Errorf("剩余数量为0 无需重新下市价单mainid%v", order.MainId)
return nil
}
tradeSet, _ := binanceservice.GetTradeSet(order.Symbol, 0)
newClientOrderId := snowflakehelper.GetOrderId()
order.Num = remainingQuantity.Truncate(int32(tradeSet.AmountDigit)).String()
order.Desc = fmt.Sprintf("取消限价单,重下市价单源订单号:%s ", order.OrderSn)
order.OrderSn = utility.Int64ToString(snowflakehelper.GetOrderId())
order.MainOrderType = "MARKET"
// var newOrder models.LinePreOrder
// copier.Copy(&newOrder, order)
// newOrder.Id = 0
// newOrder.OrderSn = utility.Int64ToString(newClientOrderId)
// newOrder.CreatedAt = time.Now()
// newOrder.MainOrderType = "MARKET"
// err = db.Model(&models.LinePreOrder{}).Create(&newOrder).Error
err := db.Model(&order).Updates(map[string]interface{}{"desc": order.Desc, "order_sn": order.OrderSn, "main_order_type": order.MainOrderType}).Error
err = db.Model(&order).Updates(map[string]interface{}{"desc": order.Desc, "order_sn": order.OrderSn, "main_order_type": order.MainOrderType}).Error
if err != nil {
logger.Error(fmt.Sprintf("生成新市价单失败 err:%+v", err))
@ -251,7 +261,7 @@ func (t LimitOrderTimeoutDuration) ReSpotOrderPlace(db *gorm.DB, order models.Li
TimeInForce: "GTC",
Price: utility.StringToDecimal(order.Price),
StopPrice: utility.StrToDecimal(order.Price),
Quantity: utility.StringToDecimal(order.Num),
Quantity: remainingQuantity,
NewClientOrderId: utility.Int64ToString(newClientOrderId),
}
if err := spotApi.OrderPlace(db, params); err != nil {
@ -281,8 +291,24 @@ func (t LimitOrderTimeoutDuration) ReFutOrderPlace(db *gorm.DB, order models.Lin
logger.Error(fmt.Sprintf("取消现货委托失败:order_sn:%s err:%+v", order.OrderSn, err))
return err
} else {
var remainingQuantity decimal.Decimal
spotOrder, err := futApi.GetOrderByOrderSnLoop(order.Symbol, order.OrderSn, apiUserinfo, 4)
if err == nil {
origQty := utility.StrToDecimal(spotOrder.OrigQty)
excuteQty := utility.StrToDecimal(spotOrder.ExecutedQty)
remainingQuantity = origQty.Sub(excuteQty).Abs()
}
if remainingQuantity.Cmp(decimal.Zero) <= 0 {
logger.Errorf("剩余数量为0 无需重新下市价单mainid%v", order.MainId)
return nil
}
tradeSet, _ := binanceservice.GetTradeSet(order.Symbol, 0)
newClientOrderId := snowflakehelper.GetOrderId()
orderType := "MARKET"
order.Num = remainingQuantity.Truncate(int32(tradeSet.AmountDigit)).String()
order.Desc = fmt.Sprintf("取消限价单,重下市价单 源订单号:%s", order.OrderSn)
order.OrderSn = utility.Int64ToString(newClientOrderId)
@ -294,31 +320,32 @@ func (t LimitOrderTimeoutDuration) ReFutOrderPlace(db *gorm.DB, order models.Lin
// newOrder.MainOrderType = "MARKET"
// err = db.Model(&models.LinePreOrder{}).Create(&newOrder).Error
var positionSide string
if order.Site == "BUY" {
positionSide = "SHORT"
} else {
positionSide = "LONG"
}
err = db.Model(&order).Updates(map[string]interface{}{"desc": order.Desc, "order_sn": order.OrderSn}).Error
if err != nil {
logger.Error(fmt.Sprintf("生成合约新市价单失败 err:%+v", err))
return err
}
if order.OrderType == 4 {
orderType = "STOP_MARKET"
}
// params := binanceservice.FutOrderPlace{
// ApiId: order.ApiId,
// Symbol: order.Symbol,
// Side: order.Site,
// Quantity: remainingQuantity,
// Price: utility.StringToDecimal(order.Price),
// SideType: "MARKET",
// OpenOrder: 0,
// OrderType: "MARKET",
// NewClientOrderId: utility.Int64ToString(newClientOrderId),
// }
params := binanceservice.FutOrderPlace{
ApiId: order.ApiId,
Symbol: order.Symbol,
Side: order.Site,
Quantity: utility.StringToDecimal(order.Num),
Price: utility.StringToDecimal(order.Price),
SideType: "MARKET",
OpenOrder: 0,
StopPrice: utility.StringToDecimal(order.Price),
Profit: utility.StringToDecimal(order.Price),
OrderType: orderType,
NewClientOrderId: utility.Int64ToString(newClientOrderId),
}
if err := futApi.OrderPlace(db, params); err != nil {
if err := futApi.ClosePositionLoop(order.Symbol, order.OrderSn, remainingQuantity, order.Site, positionSide, apiUserinfo, "MARKET", "0", decimal.Zero, 3); err != nil {
logger.Error(fmt.Sprintf("重新下合约市价单失败 err:%+v", err))
err := db.Model(&order).Updates(map[string]interface{}{"status": "2", "desc": order.Desc + " err:" + err.Error()}).Error
if err != nil {

View File

@ -22,3 +22,55 @@ type StoplossMarket struct {
Symbol string `json:"symbol"`
Type int `json:"type" comment:"对冲类型 1-现货 2-合约"`
}
type BinanceSpotOrder struct {
Symbol string `json:"symbol"` // 交易对
OrderID int64 `json:"orderId"` // 系统的订单ID
OrderListID int64 `json:"orderListId"` // 除非此单是订单列表的一部分, 否则此值为 -1
ClientOrderID string `json:"clientOrderId"` // 客户自己设置的ID
Price string `json:"price"` // 订单价格
OrigQty string `json:"origQty"` // 用户设置的原始订单数量
ExecutedQty string `json:"executedQty"` // 交易的订单数量
OrigQuoteOrderQty string `json:"origQuoteOrderQty"` // 原始的交易金额
CummulativeQuoteQty string `json:"cummulativeQuoteQty"` // 累计交易的金额
Status string `json:"status"` // 订单状态
TimeInForce string `json:"timeInForce"` // 订单的时效方式
Type string `json:"type"` // 订单类型,比如市价单,现价单等
Side string `json:"side"` // 订单方向,买还是卖
StopPrice string `json:"stopPrice"` // 止损价格
IcebergQty string `json:"icebergQty"` // 冰山数量
Time int64 `json:"time"` // 订单时间
UpdateTime int64 `json:"updateTime"` // 最后更新时间
IsWorking bool `json:"isWorking"` // 订单是否出现在orderbook中
WorkingTime int64 `json:"workingTime"` // 订单添加到 order book 的时间
SelfTradePreventionMode string `json:"selfTradePreventionMode"` // 如何处理自我交易模式
}
type BinanceFutureOrder struct {
AvgPrice string `json:"avgPrice"` // 平均成交价
ClientOrderID string `json:"clientOrderId"` // 用户自定义的订单号
CumQuote string `json:"cumQuote"` // 成交金额
ExecutedQty string `json:"executedQty"` // 成交量
OrderID int64 `json:"orderId"` // 系统订单号
OrigQty string `json:"origQty"` // 原始委托数量
OrigType string `json:"origType"` // 触发前订单类型
Price string `json:"price"` // 委托价格
ReduceOnly bool `json:"reduceOnly"` // 是否仅减仓
Side string `json:"side"` // 买卖方向
PositionSide string `json:"positionSide"` // 持仓方向
Status string `json:"status"` // 订单状态
StopPrice string `json:"stopPrice"` // 触发价,对`TRAILING_STOP_MARKET`无效
ClosePosition bool `json:"closePosition"` // 是否条件全平仓
Symbol string `json:"symbol"` // 交易对
Time int64 `json:"time"` // 订单时间
TimeInForce string `json:"timeInForce"` // 有效方法
Type string `json:"type"` // 订单类型
ActivatePrice string `json:"activatePrice"` // 跟踪止损激活价格, 仅`TRAILING_STOP_MARKET` 订单返回此字段
PriceRate string `json:"priceRate"` // 跟踪止损回调比例, 仅`TRAILING_STOP_MARKET` 订单返回此字段
UpdateTime int64 `json:"updateTime"` // 更新时间
WorkingType string `json:"workingType"` // 条件价格触发类型
PriceProtect bool `json:"priceProtect"` // 是否开启条件单触发保护
PriceMatch string `json:"priceMatch"` // 盘口价格下单模式
SelfTradePreventionMode string `json:"selfTradePreventionMode"` // 订单自成交保护模式
GoodTillDate int64 `json:"goodTillDate"` // 订单TIF为GTD时的自动取消时间
}

View File

@ -9,6 +9,7 @@ import (
"go-admin/common/global"
"go-admin/common/helper"
"go-admin/models"
"go-admin/models/binancedto"
"go-admin/models/spot"
"go-admin/pkg/httputils"
"go-admin/pkg/utility"
@ -529,3 +530,61 @@ func (e SpotRestApi) GetSpotSymbolLastPrice(targetSymbol string) (lastPrice deci
// }
return lastPrice
}
func (e SpotRestApi) GetOrderByOrderSn(symbol, orderSn string, apiUserInfo DbModels.LineApiUser) (order binancedto.BinanceSpotOrder, err error) {
result := binancedto.BinanceSpotOrder{}
params := map[string]string{
"symbol": symbol,
"origClientOrderId": orderSn,
}
client := GetClient(&apiUserInfo)
body, code, err := client.SendSpotAuth("/api/v3/order", "GET", params)
if err != nil || code != 200 {
log.Error("查询现货委托 参数:", params)
log.Error("查询现货委托失败 code:", code)
log.Error("查询现货委托失败 err:", err)
dataMap := make(map[string]interface{})
if err.Error() != "" {
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, err.Error())
}
}
code, ok := dataMap["code"]
if ok {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%s", apiUserInfo.Id, symbol, ErrorMaps[code.(float64)])
}
if strings.Contains(err.Error(), "Unknown order sent.") {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, ErrorMaps[-2011])
}
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, err.Error())
}
sonic.Unmarshal(body, &result)
if result.OrderID == 0 {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, "订单不存在")
}
return result, nil
}
/*
查询现货委托
*/
func (e SpotRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo DbModels.LineApiUser, retryCount int) (order binancedto.BinanceSpotOrder, err error) {
result, err := e.GetOrderByOrderSn(symbol, ordersn, apiUserInfo)
if err != nil {
for x := 1; x < retryCount; x++ {
result, err = e.GetOrderByOrderSn(symbol, ordersn, apiUserInfo)
if err == nil {
break
}
}
}
return result, err
}

View File

@ -215,3 +215,35 @@ func TestFutOrderPlace(t *testing.T) {
fmt.Println("err:", err)
}
func TestFutureQueryOrder(t *testing.T) {
futureApi := FutRestApi{}
// dsn := "root:root@tcp(192.168.1.12:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
// db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
helper.InitDefaultRedis("192.168.1.12:6379", "", 2)
apiUserInfo, _ := GetApiInfo(49)
order, err := futureApi.GetOrderByOrderSnLoop("TRUMPUSDT", "380211842506555392", apiUserInfo, 3)
if err != nil {
fmt.Println("err:", err)
}
fmt.Println("future order:", order)
}
func TestSpotQueryOrder(t *testing.T) {
spotApi := SpotRestApi{}
// dsn := "root:root@tcp(192.168.1.12:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
// db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
helper.InitDefaultRedis("192.168.1.12:6379", "", 2)
apiUserInfo, _ := GetApiInfo(49)
order, err := spotApi.GetOrderByOrderSnLoop("ADAUSDT", "380577197825458177", apiUserInfo, 3)
if err != nil {
fmt.Println("err:", err)
}
fmt.Println("spot order:", order)
}

View File

@ -9,6 +9,7 @@ import (
"go-admin/common/global"
"go-admin/common/helper"
"go-admin/models"
"go-admin/models/binancedto"
"go-admin/models/futuresdto"
"go-admin/pkg/httputils"
"go-admin/pkg/utility"
@ -936,3 +937,66 @@ func (e FutRestApi) GetFutSymbolLastPrice(targetSymbol string) (lastPrice decima
// }
return lastPrice
}
func (e FutRestApi) GetOrderByOrderSn(symbol, orderSn string, apiUserInfo DbModels.LineApiUser) (order binancedto.BinanceFutureOrder, err error) {
result := binancedto.BinanceFutureOrder{}
params := map[string]string{
"symbol": symbol,
"origClientOrderId": orderSn,
}
client := GetClient(&apiUserInfo)
body, code, err := client.SendFuturesAuth("/fapi/v1/order", "GET", params)
if err != nil || code != 200 {
log.Error("查询合约委托 参数:", params)
log.Error("查询合约委托失败 code:", code)
log.Error("查询合约委托失败 err:", err)
dataMap := make(map[string]interface{})
if err.Error() != "" {
if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, err.Error())
}
}
code, ok := dataMap["code"]
if ok {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%s", apiUserInfo.Id, symbol, ErrorMaps[code.(float64)])
}
if strings.Contains(err.Error(), "Unknown order sent.") {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, ErrorMaps[-2011])
}
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, err.Error())
}
sonic.Unmarshal(body, &result)
if result.OrderID == 0 {
return result, fmt.Errorf("api_id:%d 交易对:%s 查询订单失败:%+v", apiUserInfo.Id, symbol, "订单不存在")
}
return result, nil
}
/*
查询现货委托
*/
// 根据订单号获取订单信息,如果获取失败,则进行重试
func (e FutRestApi) GetOrderByOrderSnLoop(symbol, ordersn string, apiUserInfo DbModels.LineApiUser, retryCount int) (order binancedto.BinanceFutureOrder, err error) {
result, err := e.GetOrderByOrderSn(symbol, ordersn, apiUserInfo)
// 如果获取失败,则进行重试
if err != nil {
// 调用GetOrderByOrderSn方法获取订单信息
for x := 1; x < retryCount; x++ {
// 如果获取成功,则跳出循环
result, err = e.GetOrderByOrderSn(symbol, ordersn, apiUserInfo)
if err == nil {
break
}
}
}
// 返回订单信息和错误信息
return result, err
}

View File

@ -88,7 +88,7 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi
}
//判断是否有已触发交易对
count, _ := GetSymbolTriggerCount(db, v.Symbol, 2)
count, _ := GetSymbolTriggerCount(db, v.Symbol, v.ApiId, 2)
if count > 0 {
return
@ -316,7 +316,7 @@ func FutAddPositionTrigger(db *gorm.DB, v *AddPositionList, item string, futApi
defer lock.Release()
setting, _ := GetSystemSetting(db)
tradeSet, _ := GetTradeSet(v.Symbol, 0)
tradeSet, _ := GetTradeSet(v.Symbol, 1)
if tradeSet.LastPrice == "" {
log.Errorf("合约加仓触发 查询交易对失败 交易对:%s ordersn:%s", v.Symbol, v.OrderSn)

View File

@ -111,16 +111,20 @@ func handleFutOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderSta
// 减仓回调
func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id =? ", preOrder.MainId).Update("reduce_status", 1).Error; err != nil {
logger.Errorf("handleReduceFilled 更新主单减仓状态失败,订单号:%s", preOrder.OrderSn)
}
apiUserInfo, _ := GetApiInfo(preOrder.ApiId)
if apiUserInfo.Id == 0 {
logger.Errorf("handleMainReduceFilled 获取api信息失败,订单号:%s", preOrder.OrderSn)
logger.Errorf("handleReduceFilled 获取api信息失败,订单号:%s", preOrder.OrderSn)
return
}
tradeSet, err := GetTradeSet(preOrder.Symbol, 1)
if err != nil {
logger.Errorf("handleMainReduceFilled 获取交易对设置失败,订单号:%s", preOrder.OrderSn)
logger.Errorf("handleReduceFilled 获取交易对设置失败,订单号:%s", preOrder.OrderSn)
return
}
@ -128,7 +132,7 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
parentOrder, err := GetOrderById(db, preOrder.Pid)
if err != nil {
logger.Errorf("handleMainReduceFilled 获取主单失败,订单号:%s", preOrder.OrderSn)
logger.Errorf("handleReduceFilled 获取主单失败,订单号:%s", preOrder.OrderSn)
return
}
parentPrice := utility.StrToDecimal(parentOrder.Price)
@ -353,7 +357,7 @@ func removeFutLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
// preOrder 主单
func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) {
orders := []models.LinePreOrder{}
tradeSet, _ := GetTradeSet(preOrder.Symbol, 0)
tradeSet, _ := GetTradeSet(preOrder.Symbol, 1)
if tradeSet.Coin == "" {
logger.Error("获取交易对失败")
@ -366,6 +370,10 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) {
}
if preOrder.OrderCategory == 3 {
if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id = ?", preOrder.MainId).Update("add_position_status", 1).Error; err != nil {
logger.Errorf("更新主单加仓状态失败, 主单号:%s, 错误信息:%v", preOrder.MainId, err)
}
if err := cancelSymbolTakeAndStop(db, preOrder.MainId, preOrder.SymbolType); err != nil {
logger.Errorf("取消止盈止损订单失败 orderSn:%s err:%v", preOrder.OrderSn, err)
}

View File

@ -144,10 +144,10 @@ func GetSymbolTakeAndStop(db *gorm.DB, mainId int, symbolType int) ([]models.Lin
// 获取交易对触发数量
// symbol 交易对
// symbolType 交易对类型 1-现货 2-合约
func GetSymbolTriggerCount(db *gorm.DB, symbol string, symbolType int) (int64, error) {
func GetSymbolTriggerCount(db *gorm.DB, symbol string, apiId, symbolType int) (int64, error) {
var count int64
if err := db.Model(&models.LinePreOrder{}).Where("symbol =? AND symbol_type =? AND order_type =0 AND pid=0 AND status IN (1,5,6)", symbol, symbolType).Count(&count).Error; err != nil {
if err := db.Model(&models.LinePreOrder{}).Where("symbol =? AND api_id =? AND symbol_type =? AND order_type =0 AND pid=0 AND status IN (1,5,6)", symbol, apiId, symbolType).Count(&count).Error; err != nil {
logger.Error("查询交易对触发数量失败:", err)
return count, err
}

View File

@ -84,7 +84,7 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
}
//判断是否有已触发交易对
count, _ := GetSymbolTriggerCount(db, v.Symbol, 2)
count, _ := GetSymbolTriggerCount(db, v.Symbol, v.ApiId, 1)
if count > 0 {
return

View File

@ -158,6 +158,10 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
orders := make([]models.LinePreOrder, 0)
rate := utility.StringAsFloat(preOrder.Rate)
if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id =? ", preOrder.MainId).Update("reduce_status", 1).Error; err != nil {
logger.Errorf("handleMainReduceFilled 更新主单减仓状态失败,订单号:%s", preOrder.OrderSn)
}
// 100%减仓 终止流程
if rate >= 100 {
removeSpotLossAndAddPosition(preOrder)
@ -436,6 +440,12 @@ func removeSpotLossAndAddPosition(preOrder *DbModels.LinePreOrder) {
// 主单成交
func handleMainOrderFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
if preOrder.OrderCategory == 3 {
if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id = ?", preOrder.MainId).Update("add_position_status", 1).Error; err != nil {
logger.Errorf("更新主单加仓状态失败, 主单号:%s, 错误信息:%v", preOrder.MainId, err)
}
}
processTakeProfitAndStopLossOrders(db, preOrder)
}