180 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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
 | |
| }
 |