package binanceservice import ( "fmt" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" "go-admin/common/const/rediskey" "go-admin/common/global" "go-admin/common/helper" models2 "go-admin/models" "go-admin/models/positiondto" "go-admin/pkg/utility" "github.com/bytedance/sonic" "github.com/go-admin-team/go-admin-core/logger" "github.com/shopspring/decimal" "gorm.io/gorm" ) // 缓存减仓节点和重新生成 // reduceOrder:原始减仓单 // reduceOrderStrategy:减仓策略 func CacheOrderStrategyAndReCreate(db *gorm.DB, reduceOrder positiondto.ReduceListItem, symbolType int, tradeSet models2.TradeSet, setting models.LineSystemSetting) error { reduceOrderStrategy := models.LineOrderReduceStrategy{} var key string if symbolType == 1 { key = fmt.Sprintf(rediskey.SpotOrderReduceStrategyList, global.EXCHANGE_BINANCE) } else { key = fmt.Sprintf(rediskey.FutOrderReduceStrategyList, global.EXCHANGE_BINANCE) } if err := db.Model(&reduceOrderStrategy).Where("order_id =?", reduceOrder.Id).Find(&reduceOrderStrategy).Error; err != nil { logger.Errorf("获取减仓策略失败,err:%v", err) return err } if reduceOrderStrategy.Id > 0 { items := make([]models.LineReduceStrategyItem, 0) strategyCache := dto.LineOrderReduceStrategyResp{ OrderId: reduceOrder.Id, Symbol: reduceOrder.Symbol, MainId: reduceOrder.MainId, Side: reduceOrder.Side, } sonic.Unmarshal([]byte(reduceOrderStrategy.ItemContent), &items) for _, item := range items { var rate decimal.Decimal var triggerRate decimal.Decimal if reduceOrder.Side == "SELL" { rate = (decimal.NewFromInt(100).Sub(item.LossPercent)).Div(decimal.NewFromInt(100)) if setting.ReduceEarlyTriggerPercent.Cmp(decimal.Zero) > 0 { triggerRate = rate.Add(setting.ReduceEarlyTriggerPercent.Div(decimal.NewFromInt(100))) } else { triggerRate = rate } } else { rate = (decimal.NewFromInt(100).Add(item.LossPercent)).Div(decimal.NewFromInt(100)) if setting.ReduceEarlyTriggerPercent.Cmp(decimal.Zero) > 0 { triggerRate = rate.Sub(setting.ReduceEarlyTriggerPercent.Div(decimal.NewFromInt(100))) } else { triggerRate = rate } } price := reduceOrder.Price.Mul(rate).Truncate(int32(tradeSet.PriceDigit)) triggerPrice := reduceOrder.Price.Mul(triggerRate).Truncate(int32(tradeSet.PriceDigit)) num := reduceOrder.Num //百分比大于0就重新计算 否则就是主减仓单数量 if item.QuantityPercent.Cmp(decimal.Zero) > 0 { num = reduceOrder.Num.Mul(item.QuantityPercent.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) } strategyCache.Items = append(strategyCache.Items, dto.LineOrderReduceStrategyRespItem{ LossPercent: item.LossPercent, OrderType: item.OrderType, Price: price, TriggerPrice: triggerPrice, Num: num, }) } str, _ := sonic.MarshalString(strategyCache) if str != "" { if err := helper.DefaultRedis.HSetField(key, utility.IntToString(reduceOrder.Id), str); err != nil { logger.Errorf("减仓单缓存减仓策略,err:%v", err) } } } return nil } // 根据订单id获取订单减仓策略 func GetReduceStrategyById(db *gorm.DB, orderId int) (models.LineOrderReduceStrategy, error) { result := models.LineOrderReduceStrategy{} if err := db.Model(result).Where("order_id =?", orderId).Select("id", "order_id").First(&result).Error; err != nil { return result, err } return result, nil } // 减仓单成功回调 func ReduceCallBack(db *gorm.DB, preOrder *models.LinePreOrder) error { reduceOrderId := preOrder.Id var key string if preOrder.ReduceOrderId > 0 { reduceOrderId = preOrder.ReduceOrderId } switch preOrder.SymbolType { case 1: key = fmt.Sprintf(rediskey.SpotOrderReduceStrategyList, global.EXCHANGE_BINANCE) case 2: key = fmt.Sprintf(rediskey.FutOrderReduceStrategyList, global.EXCHANGE_BINANCE) default: return fmt.Errorf("交易对类型错误") } arrays, _ := helper.DefaultRedis.HGetAllFields(key) cache := dto.LineOrderReduceStrategyResp{} for _, v := range arrays { sonic.Unmarshal([]byte(v), &cache) if cache.OrderId == reduceOrderId { if err := helper.DefaultRedis.HDelField(key, utility.IntToString(cache.OrderId)); err != nil { logger.Errorf("移除减仓单减仓策略失败redis err:%v", err) } } } orderReduceStrategy, _ := GetReduceStrategyById(db, reduceOrderId) if orderReduceStrategy.Id > 0 { if err := db.Model(&orderReduceStrategy).Update("actived", 1).Error; err != nil { logger.Errorf("更新减仓单减仓策略状态失败 order_id:%d err:%v", orderReduceStrategy.OrderId, err) } } return nil } // 移除减仓后减仓策略 // mainId 主单id // symbolType 交易对类型 func RemoveReduceReduceCacheByMainId(mainId int, symbolType int) error { var key string switch symbolType { case 1: key = fmt.Sprintf(rediskey.SpotOrderReduceStrategyList, global.EXCHANGE_BINANCE) case 2: key = fmt.Sprintf(rediskey.FutOrderReduceStrategyList, global.EXCHANGE_BINANCE) default: return fmt.Errorf("交易对类型错误") } arrays, _ := helper.DefaultRedis.HGetAllFields(key) cache := dto.LineOrderReduceStrategyResp{} for _, v := range arrays { sonic.Unmarshal([]byte(v), &cache) if cache.MainId == mainId { if err := helper.DefaultRedis.HDelField(key, utility.IntToString(cache.OrderId)); err != nil { logger.Errorf("移除减仓单减仓策略失败redis err:%v", err) } } } return nil }