1、有更新,还没测完,暂时归档

This commit is contained in:
2025-11-05 16:26:21 +08:00
parent 643eab3496
commit bd7a6d3870
15 changed files with 536 additions and 296 deletions

View File

@ -19,6 +19,7 @@ import (
"time"
"github.com/bytedance/sonic"
"github.com/go-admin-team/go-admin-core/logger"
log "github.com/go-admin-team/go-admin-core/logger"
"github.com/shopspring/decimal"
"gorm.io/gorm"
@ -35,6 +36,8 @@ func JudgeFuturesPrice(tradeSet models.TradeSet) {
return
}
futApi := FutRestApi{}
orderService := orderservice.OrderService{}
orderService.Orm = db
for _, item := range preOrderVal {
preOrder := dto.PreOrderRedisList{}
@ -57,14 +60,32 @@ func JudgeFuturesPrice(tradeSet models.TradeSet) {
//多
if (strings.ToUpper(preOrder.Site) == "BUY" && orderPrice.Cmp(tradePrice) >= 0) ||
(strings.ToUpper(preOrder.Site) == "SELL" && orderPrice.Cmp(tradePrice) <= 0) {
futTriggerOrder(db, &preOrder, item, futApi)
apiInfo, _ := GetApiInfo(preOrder.ApiId)
if err := commonservice.JudgeWebsocketTimeout(apiInfo.ApiKey, 2); err != nil {
log.Errorf("合约行情订阅超时,apiKey:%s err:%v", apiInfo.ApiKey, err)
if err1 := orderService.ErrorTrigger(preOrder.Id, 2,
global.EXCHANGE_BINANCE, item,
fmt.Sprintf("行情触发失败,err:%v", err)); err1 != nil {
log.Error("触发失败", err1)
}
continue
} else {
futTriggerOrder(db, &preOrder, item, futApi)
}
}
}
}
// 分布式锁下单
// 分布式锁下单(合约预设主单触发)
// 参数说明:
// - db: 数据库连接,用于查询与更新预下单状态
// - v: 预下单信息(包含价格、数量、订单号等)
// - item: 从 Redis 列表读取的原始字符串,用于幂等删除
// - futApi: 合约下单 API 封装
// 逻辑:在 FutTrigger 锁下校验订单有效性,执行下单并更新状态,最后用原始 item 删除缓存,避免序列化差异导致删除失败。
func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi FutRestApi) {
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.SpotTrigger, v.ApiId, v.Symbol), 200, 5, 100*time.Millisecond)
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.FutTrigger, v.ApiId, v.Symbol), 200, 5, 100*time.Millisecond)
if ok, err := lock.AcquireWait(context.Background()); err != nil {
log.Debug("获取锁失败", err)
@ -110,29 +131,21 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi
Quantity: num,
NewClientOrderId: v.OrderSn,
}
preOrderVal, _ := sonic.MarshalString(&v)
if err := futApi.OrderPlaceLoop(db, params, 3); err != nil {
log.Error("下单失败", v.Symbol, " err:", err)
err := db.Model(&DbModels.LinePreOrder{}).Where("id =? and status='0'", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
err = db.Model(&DbModels.LinePreOrder{}).Where("id =? and status='0'", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
if err != nil {
log.Error("更新预下单状态失败")
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Error("删除redis 预下单失败:", err)
}
return
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? ", preOrder.Id).Updates(map[string]interface{}{"trigger_time": time.Now()}).Error; err != nil {
@ -303,7 +316,7 @@ func FuturesReduceTrigger(db *gorm.DB, reduceOrder positiondto.ReduceListItem, f
apiInfo, _ := GetApiInfo(reduceOrder.ApiId)
if apiInfo.Id == 0 {
log.Error("现货减仓 查询api用户不存在")
log.Error("合约减仓 查询api用户不存在")
return false
}
for _, takeOrder := range takeOrders {
@ -399,6 +412,12 @@ func JudgeFutAddPosition(trade models.TradeSet) {
}
// 合约加仓触发
// 参数说明:
// - db: 数据库连接
// - v: 加仓触发信息
// - item: Redis 列表原始条目,用于精确删除
// - futApi: 合约下单 API 封装
// 逻辑:在 FutTrigger 锁下校验缓存与订单有效性,按系统加仓溢价调整价格,触发限价下单并删除原始缓存条目。
func FutAddPositionTrigger(db *gorm.DB, v *positiondto.AddPositionList, item string, futApi FutRestApi) {
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.FutTrigger, v.ApiId, v.Symbol), 20, 5, 100*time.Millisecond)
@ -452,29 +471,21 @@ func FutAddPositionTrigger(db *gorm.DB, v *positiondto.AddPositionList, item str
Quantity: num.Truncate(int32(tradeSet.AmountDigit)),
NewClientOrderId: v.OrderSn,
}
preOrderVal, _ := sonic.MarshalString(&v)
if err := futApi.OrderPlaceLoop(db, params, 3); err != nil {
log.Error("下单失败", v.Symbol, " err:", err)
err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status =0", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
err = db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status =0", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
if err != nil {
log.Error("下单失败后修改订单失败")
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Error("删除redis 预下单失败:", err)
}
return
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Error("删除redis 预下单失败:", err)
}
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? ", preOrder.Id).Updates(map[string]interface{}{"trigger_time": time.Now()}).Error; err != nil {
@ -490,3 +501,66 @@ func FutAddPositionTrigger(db *gorm.DB, v *positiondto.AddPositionList, item str
return
}
}
// 触发止盈单
// Deprecated 暂时不用了
func FuturesTakeTrigger(db *gorm.DB, spotApi *SpotRestApi, takeOrder dto.TakeProfitRedisList, key, item string, futApi FutRestApi) {
// tradeSet, err := cacheservice.GetTradeSet(global.EXCHANGE_BINANCE, takeOrder.Symbol, 2)
// if err != nil {
// logger.Errorf("触发止盈单 查询交易对失败 交易对:%s ordersn:%s err:%v", takeOrder.Symbol, takeOrder.OrderSn, err)
// }
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.FutTrigger, takeOrder.ApiId, takeOrder.Symbol), 20, 5, 100*time.Millisecond)
if ok, err := lock.AcquireWait(context.Background()); err != nil {
log.Error("获取锁失败", err)
return
} else if ok {
defer lock.Release()
hasrecord, _ := helper.DefaultRedis.IsElementInList(key, item)
if !hasrecord {
log.Debug("止损缓存中不存在", item)
return
}
apiInfo, _ := GetApiInfo(takeOrder.ApiId)
if apiInfo.Id == 0 {
log.Error("现货止盈 查询api用户不存在")
return
}
// price := takeOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.StopLossPremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit))
// num := utility.StrToDecimal(stopOrder.Num).Truncate(int32(tradeSet.AmountDigit))
params := OrderPlacementService{
ApiId: takeOrder.ApiId,
Side: takeOrder.Site,
Type: "LIMIT",
TimeInForce: "GTC",
Symbol: takeOrder.Symbol,
// Price: price,
// Quantity: num,
NewClientOrderId: takeOrder.OrderSn,
}
if err := spotApi.OrderPlaceLoop(db, params, 3); err != nil {
log.Errorf("现货止盈挂单失败 id%s err:%v", takeOrder.Id, err)
} else {
if err := db.Model(&DbModels.LinePreOrder{}).
Where("id = ? ", takeOrder.Id).
Updates(map[string]interface{}{"trigger_time": time.Now()}).Error; err != nil {
log.Errorf("现货止盈更新状态失败 id%s err:%v", takeOrder.Id, err)
}
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Errorf("现货止盈 删除缓存失败 id:%v err:%v", takeOrder.Id, err)
}
} else {
logger.Errorf("触发止盈单 不存在待触发主单 %s", item)
}
}