diff --git a/app/admin/service/dto/line_pre_order.go b/app/admin/service/dto/line_pre_order.go index 56a8d76..4166c36 100644 --- a/app/admin/service/dto/line_pre_order.go +++ b/app/admin/service/dto/line_pre_order.go @@ -353,31 +353,34 @@ type LineTreeOrder struct { // LineBatchAddPreOrderReq 批量添加订单请求参数 type LineBatchAddPreOrderReq struct { - ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type - SymbolType int `json:"symbol_type"` //主单交易对类型 0-现货 1-合约 - OrderType int `json:"order_type"` //订单类型 - SymbolGroupId string `json:"symbol_group_id"` //交易对组id - Symbol string `json:"symbol"` //交易对 - ApiUserId string `json:"api_id"` //下单用户 - Site string `json:"site"` //购买方向 - BuyPrice string `json:"buy_price"` //购买金额 U - PricePattern string `json:"price_pattern"` //价格模式 - Price string `json:"price"` //下单价百分比 - Profit string `json:"profit"` //止盈价 - StopPrice string `json:"stop_price"` //止损价 - PriceType string `json:"price_type"` //价格类型 - SaveTemplate string `json:"save_template"` //是否保存模板 - TemplateName string `json:"template_name"` //模板名字 - OrderNum int `json:"order_num"` //脚本运行次数 - Script string `json:"script"` //是否是脚本运行 1 = 是 0= 否 - CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货 - ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 - MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) - ReducePriceRatio decimal.Decimal `json:"reduce_price"` //主单减仓价格百分比 - ReduceNumRatio decimal.Decimal `json:"reduce_num"` //主单减仓数量百分比 - ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比 - ReduceStopLossRatio decimal.Decimal `json:"reduce_stop_price"` //主单减仓后止损价百分比 - Ext []LineAddPreOrderExtReq `json:"ext"` //拓展字段 + ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type + SymbolType int `json:"symbol_type"` //主单交易对类型 0-现货 1-合约 + OrderType int `json:"order_type"` //订单类型 + SymbolGroupId string `json:"symbol_group_id"` //交易对组id + Symbol string `json:"symbol"` //交易对 + ApiUserId string `json:"api_id"` //下单用户 + Site string `json:"site"` //购买方向 + BuyPrice string `json:"buy_price"` //购买金额 U + PricePattern string `json:"price_pattern"` //价格模式 + Price string `json:"price"` //下单价百分比 + ProfitNumRatio decimal.Decimal `json:"profit_num_ratio"` //止盈数量百分比 + ProfitTpTpPriceRatio decimal.Decimal `json:"profit_tp_tp_price_ratio"` //止盈后止盈价百分比 + ProfitTpSlPriceRatio decimal.Decimal `json:"profit_tp_sl_price_ratio"` //止盈后止损价百分比 + Profit string `json:"profit"` //止盈价 + StopPrice string `json:"stop_price"` //止损价 + PriceType string `json:"price_type"` //价格类型 + SaveTemplate string `json:"save_template"` //是否保存模板 + TemplateName string `json:"template_name"` //模板名字 + OrderNum int `json:"order_num"` //脚本运行次数 + Script string `json:"script"` //是否是脚本运行 1 = 是 0= 否 + CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货 + ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 + MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) + ReducePriceRatio decimal.Decimal `json:"reduce_price"` //主单减仓价格百分比 + ReduceNumRatio decimal.Decimal `json:"reduce_num"` //主单减仓数量百分比 + ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比 + ReduceStopLossRatio decimal.Decimal `json:"reduce_stop_price"` //主单减仓后止损价百分比 + Ext []LineAddPreOrderExtReq `json:"ext"` //拓展字段 } func (req LineBatchAddPreOrderReq) CheckParams() error { diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index 5e36941..96ebcc9 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -244,7 +244,49 @@ func (e *LinePreOrder) Remove(d *dto.LinePreOrderDeleteReq, p *actions.DataPermi } positions := map[string]positiondto.LinePreOrderPositioinDelReq{} + addPosition := binanceservice.AddPositionList{} + reduceItem := binanceservice.ReduceListItem{} + futAddPosition := map[int]string{} + spotAddPosition := map[int]string{} + futReduces := map[int]string{} + spotRedces := map[int]string{} + futAddPositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE) + spotAddPositionKey := fmt.Sprintf(rediskey.FuturesReduceList, global.EXCHANGE_BINANCE) + futReduceKey := fmt.Sprintf(rediskey.SpotAddPositionList, global.EXCHANGE_BINANCE) + spotReduceKey := fmt.Sprintf(rediskey.SpotReduceList, global.EXCHANGE_BINANCE) + futAddPositionVal, _ := helper.DefaultRedis.GetAllList(futAddPositionKey) + futReduceVal, _ := helper.DefaultRedis.GetAllList(spotAddPositionKey) + spotAddPositionVal, _ := helper.DefaultRedis.GetAllList(futReduceKey) + spotReduceVal, _ := helper.DefaultRedis.GetAllList(spotReduceKey) + + for _, v := range futAddPositionVal { + sonic.Unmarshal([]byte(v), &addPosition) + if addPosition.MainId > 0 { + futAddPosition[addPosition.MainId] = v + } + } + + for _, v := range spotAddPositionVal { + sonic.Unmarshal([]byte(v), &addPosition) + if addPosition.MainId > 0 { + spotAddPosition[addPosition.MainId] = v + } + } + + for _, v := range futReduceVal { + sonic.Unmarshal([]byte(v), &reduceItem) + if reduceItem.MainId > 0 { + futReduces[reduceItem.MainId] = v + } + } + + for _, v := range spotReduceVal { + sonic.Unmarshal([]byte(v), &reduceItem) + if reduceItem.MainId > 0 { + spotRedces[reduceItem.MainId] = v + } + } //删除的缓存 for _, order := range list { redisList := dto.PreOrderRedisList{ @@ -261,6 +303,21 @@ func (e *LinePreOrder) Remove(d *dto.LinePreOrderDeleteReq, p *actions.DataPermi apiIds = append(apiIds, order.ApiId) } + //清除待加仓、待减仓 + if val, ok := futAddPosition[order.Id]; ok { + helper.DefaultRedis.LRem(futAddPositionKey, val) + } + + if val, ok := spotAddPosition[order.Id]; ok { + helper.DefaultRedis.LRem(spotAddPositionKey, val) + } + if val, ok := futReduces[order.Id]; ok { + helper.DefaultRedis.LRem(futReduceKey, val) + } + if val, ok := spotRedces[order.Id]; ok { + helper.DefaultRedis.LRem(spotReduceKey, val) + } + tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf(global.TICKER_SPOT, order.ExchangeType, order.Symbol)) redisList.Price = utility.StringToDecimal(redisList.Price).Truncate(int32(tradeSet.PriceDigit)).String() marshal, _ := sonic.Marshal(redisList) @@ -483,6 +540,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP defultExt2.TotalAfter = mainAmount.Mul(decimal.NewFromInt(100).Sub(req.ReduceNumRatio)).Div(decimal.NewFromInt(100)).Truncate(int32(tradeSet.AmountDigit)) defultExt2.ReTakeRatio = req.ReducePriceRatio.Div(decimal.NewFromInt(100).Sub(req.ReduceNumRatio).Div(decimal.NewFromInt(100))).Truncate(2) preOrderExts = append(preOrderExts, defultExt) + preOrderExts = append(preOrderExts, defultExt2) calculateResp := dto.CalculateBreakEvenRatioResp{} mainParam := dto.CalculateBreakEevenRatioReq{ @@ -550,7 +608,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP //加仓、减仓状态 tx.Model(&models.LinePreOrderStatus{}).Create(&preOrderStatus) - + preOrderExts[0].OrderId = AddOrder.Id list := dto.PreOrderRedisList{ Id: AddOrder.Id, Symbol: AddOrder.Symbol, @@ -626,7 +684,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP stopOrder.Num = stopNum.Truncate(int32(tradeSet.AmountDigit)).String() tx.Model(&models.LinePreOrder{}).Omit("id", "save_template", "template_name").Create(&stopOrder) - + preOrderExts[1].OrderId = stopOrder.Id if req.ReduceNumRatio.Cmp(decimal.Zero) > 0 && req.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) < 0 { if newOrders, err := makeReduceTakeAndStoploss(&stopOrder, defultExt2, tradeSet, false); err != nil { logger.Errorf("主单减仓生成止盈、减仓失败 err:%v", err) @@ -643,10 +701,10 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP //添加止盈单 for index, v := range preOrderExts { preOrderExts[index].MainOrderId = AddOrder.Id - // if index == 0 { - // preOrderExts[index].OrderId = AddOrder.Id - // continue - // } + if index < 2 { + // preOrderExts[index].OrderId = AddOrder.Id + continue + } var newOrder models.LinePreOrder if v.AddType == 1 { @@ -801,10 +859,10 @@ func makeFuturesTakeAndReduce(preOrder *models.LinePreOrder, ext models.LinePreO orders := make([]models.LinePreOrder, 0) var side string - if strings.ToUpper(preOrder.Site) == "BUY" { - side = "SELL" - } else { + if (preOrder.OrderType != 0 && strings.ToUpper(preOrder.Site) == "BUY") || (preOrder.OrderType == 0 && strings.ToUpper(preOrder.Site) == "SELL") { side = "BUY" + } else { + side = "SELL" } if ext.TakeProfitRatio.Cmp(decimal.Zero) > 0 { @@ -1055,6 +1113,9 @@ func (e *LinePreOrder) AddBatchPreOrder(batchReq *dto.LineBatchAddPreOrderReq, p req.PricePattern = batchReq.PricePattern req.Price = batchReq.Price req.Profit = batchReq.Profit + req.ProfitNumRatio = batchReq.ProfitNumRatio + req.ProfitTpTpPriceRatio = batchReq.ProfitTpSlPriceRatio + req.ProfitTpSlPriceRatio = batchReq.ProfitTpSlPriceRatio req.Ext = batchReq.Ext req.SymbolType = batchReq.SymbolType // req.StopPrice = batchReq.StopPrice @@ -1663,8 +1724,10 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err continue } - //撤销合约的委托 - api.CancelAllFutOrder(apiUserInfo, list.Symbol) + //撤销合约的委托(根据方向撤) + orderSns, _ := binanceservice.GetOpenOrderSns(e.Orm, []int{list.Id}) + api.CancelBatchFutOrder(apiUserInfo, list.Symbol, orderSns) + // api.CancelAllFutOrder(apiUserInfo, list.Symbol) //side=BUY&positionSide=LONG是开多, //side=SELL&positionSide=LONG是平多, //side=SELL&positionSide=SHORT是开空, diff --git a/common/const/rediskey/redis_key.go b/common/const/rediskey/redis_key.go index 820f41b..56d5372 100644 --- a/common/const/rediskey/redis_key.go +++ b/common/const/rediskey/redis_key.go @@ -50,9 +50,10 @@ const ( SpotReduceList = "spot_reduce_list:%s" //现货减仓待触发 {交易所类型code} FuturesStopLossList = "futures_stoploss_list:%s" //合约止损待触发列表 {交易所类型code} FuturesReduceList = "futures_reduce_list:%s" //合约减仓待触发 {交易所类型code} - - SpotAddPositionList = "spot_add_position_list:%s" //现货加仓待触发 {交易所code} - FuturesAddPositionList = "futures_add_position_list:%s" //合约加仓待触发 {交易所code} + //现货加仓待触发 {交易所code} + SpotAddPositionList = "spot_add_position_list:%s" + //合约加仓待触发 {交易所code} + FuturesAddPositionList = "futures_add_position_list:%s" //现货持仓 {exchangeType,apiuserid,symbol,side} SpotPosition = "spot_position:%s:%v:%s_%s" //合约持仓 {exchangeType,apiuserid,symbol,side} diff --git a/services/binanceservice/commonservice.go b/services/binanceservice/commonservice.go index adcd648..8a47ac0 100644 --- a/services/binanceservice/commonservice.go +++ b/services/binanceservice/commonservice.go @@ -471,7 +471,7 @@ func getOpenPositionMainOrderId(db *gorm.DB, newId, apiId, symbolType int, excha } // 获取需要取消的订单号 -func getOpenOrderSns(db *gorm.DB, mainIds []int) ([]string, error) { +func GetOpenOrderSns(db *gorm.DB, mainIds []int) ([]string, error) { result := []string{} //委托中的订单 diff --git a/services/binanceservice/futuresjudgeservice.go b/services/binanceservice/futuresjudgeservice.go index 1c098ce..1d53614 100644 --- a/services/binanceservice/futuresjudgeservice.go +++ b/services/binanceservice/futuresjudgeservice.go @@ -201,8 +201,8 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, futApi FutRes return } else if ok { defer lock.Release() - takeOrder := DbModels.LinePreOrder{} - if err := db.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type =1", reduceOrder.Pid).Find(&takeOrder).Error; err != nil { + takeOrders := make([]DbModels.LinePreOrder, 0) + if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_type =1 AND status IN (1,5)", reduceOrder.MainId).Find(&takeOrders).Error; err != nil { log.Error("查询止盈单失败") return } @@ -214,18 +214,19 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, futApi FutRes return } - apiInfo, _ := GetApiInfo(takeOrder.ApiId) + apiInfo, _ := GetApiInfo(reduceOrder.ApiId) if apiInfo.Id == 0 { log.Error("现货减仓 查询api用户不存在") return } + for _, takeOrder := range takeOrders { + err := CancelFutOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn) - err := CancelFutOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn) - - if err != nil { - log.Error("合约止盈撤单失败", err) - return + if err != nil { + log.Error("合约止盈撤单失败", err) + return + } } price := reduceOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.ReducePremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)) diff --git a/services/binanceservice/futuresrest.go b/services/binanceservice/futuresrest.go index 5cd72a9..8d4b76b 100644 --- a/services/binanceservice/futuresrest.go +++ b/services/binanceservice/futuresrest.go @@ -154,7 +154,6 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { orderExt := models.LinePreOrderExt{} totalNum := getFuturesPositionAvailableQuantity(db, apiUserInfo, preOrder, tradeSet) - totalNum = totalNum.Truncate(int32(tradeSet.AmountDigit)) price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit)) futApi := FutRestApi{} mainId := preOrder.Id @@ -199,7 +198,7 @@ func nextFuturesReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, return } - if err := db.Model(&models.LinePreOrderExt{}).Where("id =?", nextOrder.Id).First(&nextExt).Error; err != nil { + if err := db.Model(&models.LinePreOrderExt{}).Where("order_id =? and add_type =2", nextOrder.Id).First(&nextExt).Error; err != nil { logger.Errorf("获取下一个单失败 err:%v", err) } @@ -223,6 +222,10 @@ func nextFuturesReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, // 计算减仓数量 num = totalNum.Mul(nextExt.AddPositionVal.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) nextOrder.Num = num.String() + + if err := db.Model(&nextOrder).Update("num", nextOrder.Num).Error; err != nil { + logger.Errorf("更新减仓单数量失败 err:%v", err) + } } processFutReduceOrder(nextOrder, utility.StrToDecimal(nextOrder.Price).Truncate(int32(tradeSet.PriceDigit)), num) @@ -321,16 +324,12 @@ func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) { removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn) removePosition(db, preOrder) - spotApi := SpotRestApi{} apiUserInfo, _ := GetApiInfo(preOrder.ApiId) if apiUserInfo.Id > 0 { - req := CancelOpenOrdersReq{ - Symbol: preOrder.Symbol, - ApiId: preOrder.ApiId, - } - if err := spotApi.CancelOpenOrders(db, req); err != nil { - logger.Errorf("止盈单成功 取消其它订单失败 订单号:%s:", err) + mainIds := []int{preOrder.MainId} + if err := cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, false); err != nil { + logger.Errorf("止损单成功 取消其它订单失败 订单号:%s:", err) } } @@ -353,12 +352,12 @@ func handleTakeProfit(db *gorm.DB, preOrder *DbModels.LinePreOrder) { removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn) removePosition(db, preOrder) - futApi := FutRestApi{} apiUserInfo, _ := GetApiInfo(preOrder.ApiId) if apiUserInfo.Id > 0 { - if err := futApi.CancelAllFutOrder(apiUserInfo, preOrder.Symbol); err != nil { - logger.Errorf("止盈单成功 取消其它订单失败 订单号:%s:", err) + mainOrder, _ := GetOrderById(db, preOrder.MainId) + if err := cancelPositionOtherOrders(apiUserInfo, db, &mainOrder, false); err != nil { + logger.Errorf("止损单成功 取消其它订单失败 订单号:%s:", err) } } @@ -445,9 +444,9 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd logger.Errorf("处理主单加仓失败, 主单号:%s, 错误信息: %v", preOrder.MainId, err) return } - } else { + } else if first { // 处理其他主单逻辑 - if err := cancelPositionOtherOrders(apiInfo, db, preOrder); err != nil { + if err := cancelPositionOtherOrders(apiInfo, db, preOrder, true); err != nil { logger.Errorf("取消主单相关订单失败, 订单号:%s, 错误信息: %v", preOrder.OrderSn, err) return } @@ -497,7 +496,7 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd positionData := savePosition(db, preOrder) orderExt := models.LinePreOrderExt{} db.Model(&orderExt).Where("order_id =?", extOrderId).First(&orderExt) - num := getFuturesPositionAvailableQuantity(db, apiInfo, preOrder, tradeSet).Truncate(int32(tradeSet.AmountDigit)) + totalNum := getFuturesPositionAvailableQuantity(db, apiInfo, preOrder, tradeSet).Truncate(int32(tradeSet.AmountDigit)) // 更新订单数量并处理止盈、止损、减仓 for _, order := range orders { @@ -505,7 +504,7 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd order.Price = price.String() // 更新止盈止损订单数量 - num = updateOrderQuantity(db, order, preOrder, &orderExt, num, first, tradeSet) + num := updateOrderQuantity(db, order, preOrder, &orderExt, totalNum, first, tradeSet) // 根据订单类型处理 switch order.OrderType { @@ -552,7 +551,7 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd } } - nextFuturesReduceTrigger(db, mainId, num, tradeSet) + nextFuturesReduceTrigger(db, mainId, totalNum, tradeSet) } // 处理主单加仓 @@ -569,7 +568,8 @@ func handleMainOrderAddPosition(db *gorm.DB, preOrder *models.LinePreOrder) erro } // 取消主单相关订单 -func cancelPositionOtherOrders(apiUserInfo DbModels.LineApiUser, db *gorm.DB, preOrder *models.LinePreOrder) error { +// changeMainOrderStatus 是否修改主单状态 +func cancelPositionOtherOrders(apiUserInfo DbModels.LineApiUser, db *gorm.DB, preOrder *models.LinePreOrder, changeMainOrderStatus bool) error { mainOrders, err := getOpenPositionMainOrderId(db, preOrder.Id, preOrder.ApiId, preOrder.SymbolType, preOrder.ExchangeType, preOrder.Symbol, preOrder.Site) if err != nil { return err @@ -589,25 +589,36 @@ func cancelPositionOtherOrders(apiUserInfo DbModels.LineApiUser, db *gorm.DB, pr } } + // 批量取消订单 + err = cancelMainOrders(mainIds, db, apiUserInfo, preOrder.Symbol, changeMainOrderStatus) + + return err +} + +// 根据mainid 取消订单 +// @changeMainOrderStatus 是否更新主单状态 +func cancelMainOrders(mainIds []int, db *gorm.DB, apiUserInfo DbModels.LineApiUser, symbol string, changeMainOrderStatus bool) error { if len(mainIds) > 0 { - orderSns, err := getOpenOrderSns(db, mainIds) + orderSns, err := GetOpenOrderSns(db, mainIds) if err != nil { return err } - // 批量取消订单 orderArray := utility.SplitSlice(orderSns, 10) futApi := FutRestApi{} for _, item := range orderArray { - err := futApi.CancelBatchFutOrder(apiUserInfo, preOrder.Symbol, item) + err := futApi.CancelBatchFutOrder(apiUserInfo, symbol, item) if err != nil { logger.Errorf("批量取消订单失败 orderSns:%v", item) } } - if err := db.Exec("UPDATE line_pre_order SET `status`=4, `desc`=CONCAT(`desc`, ' 新单触发取消') WHERE id IN ? AND `status` =6", mainIds).Error; err != nil { - logger.Errorf("合约 新下单成功后更新主单取消状态失败, 新主单号:%s, 错误信息:%v", preOrder.MainId, err) + //需要修改主单状态 + if changeMainOrderStatus { + if err := db.Exec("UPDATE line_pre_order SET `status`=4, `desc`=CONCAT(`desc`, ' 新单触发取消') WHERE id IN ? AND `status` =6", mainIds).Error; err != nil { + logger.Errorf("合约 新下单成功后更新主单取消状态失败, 交易对:%s, 错误信息:%v", symbol, err) + } } } return nil @@ -633,7 +644,7 @@ func updateOrderQuantity(db *gorm.DB, order models.LinePreOrder, preOrder *model // order.Num = num.String() // } else - if first && order.OrderCategory == 1 && ext.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && ext.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 { + if first && (order.OrderCategory == 1 || order.OrderCategory == 3) && order.OrderType == 1 && ext.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && ext.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 { // 计算止盈数量 num = num.Mul(ext.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) order.Num = num.String() diff --git a/services/binanceservice/spotjudgeservice.go b/services/binanceservice/spotjudgeservice.go index 047e5cd..ff85199 100644 --- a/services/binanceservice/spotjudgeservice.go +++ b/services/binanceservice/spotjudgeservice.go @@ -308,8 +308,8 @@ func SpotReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, spotApi SpotRest return } else if ok { defer lock.Release() - takeOrder := DbModels.LinePreOrder{} - if err := db.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type =1", reduceOrder.Pid).Find(&takeOrder).Error; err != nil { + takeOrders := make([]DbModels.LinePreOrder, 0) + if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_type =1 AND status IN (1,5)", reduceOrder.MainId).Find(&takeOrders).Error; err != nil { log.Error("查询止盈单失败") return } @@ -320,18 +320,20 @@ func SpotReduceTrigger(db *gorm.DB, reduceOrder ReduceListItem, spotApi SpotRest return } - apiInfo, _ := GetApiInfo(takeOrder.ApiId) + apiInfo, _ := GetApiInfo(reduceOrder.ApiId) if apiInfo.Id == 0 { log.Error("现货减仓 查询api用户不存在") return } - err := CancelOpenOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn) + for _, takeOrder := range takeOrders { + err := CancelOpenOrderByOrderSnLoop(apiInfo, takeOrder.Symbol, takeOrder.OrderSn) - if err != nil { - log.Error("现货止盈撤单失败", err) - return + if err != nil { + log.Error("现货止盈撤单失败", err) + return + } } price := reduceOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.ReducePremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)) diff --git a/services/binanceservice/spotreset.go b/services/binanceservice/spotreset.go index 6718086..ddcbfad 100644 --- a/services/binanceservice/spotreset.go +++ b/services/binanceservice/spotreset.go @@ -195,7 +195,7 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { db.Model(&orderExt).Where("order_id =?", preOrder.Pid).Find(&orderExt) totalNum := getSpotPositionAvailableQuantity(db, apiUserInfo, preOrder, tradeSet) //getSpotTotalNum(apiUserInfo, preOrder, tradeSet) - totalNum = totalNum.Truncate(int32(tradeSet.AmountDigit)) + totalNum = totalNum.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit)) price := utility.StrToDecimal(preOrder.Price) if err := db.Model(&models.LinePreOrder{}).Where("pid =? AND order_type IN (1,2) AND status=0", preOrder.Id).Find(&orders).Error; err != nil { @@ -244,7 +244,7 @@ func nextSpotReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, tr return true } - if err := db.Model(&models.LinePreOrderExt{}).Where("id =?", nextOrder.Id).First(&nextExt).Error; err != nil { + if err := db.Model(&models.LinePreOrderExt{}).Where("order_id =? and add_type =2", nextOrder.Id).First(&nextExt).Error; err != nil { logger.Errorf("获取下一个单失败 err:%v", err) } @@ -265,12 +265,12 @@ func nextSpotReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, tr //减仓配置 且减仓比例大于0小于100 if nextExt.Id > 0 && nextExt.AddType == 2 && nextExt.AddPositionVal.Cmp(decimal.Zero) > 0 && nextExt.AddPositionVal.Cmp(decimal.Zero) < 100 { num := totalNum.Mul(nextExt.AddPositionVal.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) - // percentag = positionData.TotalLoss.Div(num).Div(price).Mul(decimal.NewFromInt(100)).Truncate(2) nextOrder.Num = num.String() + + if err := db.Model(&nextOrder).Update("num", nextOrder.Num).Error; err != nil { + logger.Errorf("更新减仓单数量失败 err:%v", err) + } } - // percentag = nextExt.PriceRatio.Add(percentag) - // nextOrder.Rate = percentag.String() - // nextOrder.Price = price.Mul(decimal.NewFromInt(1).Add(percentag.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.AmountDigit)).String() //减仓待触发 processSpotReduceOrder(nextOrder) @@ -638,7 +638,7 @@ func parseOrderStatus(status interface{}, mapData map[string]interface{}) (int, return 5, reason case "FILLED": // 完全成交 return 6, reason - case "CANCELED", "EXPIRED": // 取消 + case "CANCELED", "EXPIRED", "EXPIRED_IN_MATCH": // 取消 return 4, reason default: return 0, reason @@ -729,13 +729,17 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd spotApi := SpotRestApi{} orderExt := models.LinePreOrderExt{} db.Model(&orderExt).Where("order_id =?", extOrderId).First(&orderExt) - num = num.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit)) + totalNum := num.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit)) + num = totalNum + // if orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) < 0 { + // num = num.Mul(orderExt.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) + // } //止盈止损 for _, order := range orders { order.Num = num.String() - if fist && order.OrderCategory == 1 && orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 { + if fist && order.OrderCategory == 1 && order.OrderType == 1 && orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 { //主单第一次且止盈数量不是100% 止盈数量 order.Num = num.Mul(orderExt.TakeProfitNumRatio.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)).String() } @@ -777,7 +781,7 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd } //待触发减仓单 - nextSpotReduceTrigger(db, mainId, num, tradeSet) + nextSpotReduceTrigger(db, mainId, totalNum, tradeSet) } // 根据下单百分比计算价格 @@ -947,6 +951,8 @@ func CancelOpenOrderByOrderSnLoop(apiInfo DbModels.LineApiUser, symbol string, o err = nil break } + + time.Sleep(time.Millisecond * 300) } return err }