1、订单增加策略模板
This commit is contained in:
		| @ -9,38 +9,40 @@ import ( | ||||
|  | ||||
| type LinePreOrder struct { | ||||
| 	models.Model | ||||
| 	ExchangeType      string          `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 (字典 exchange_type)"` | ||||
| 	Pid               int             `json:"pid" gorm:"type:int unsigned;omitempty;comment:pid"` | ||||
| 	MainId            int             `json:"mainId" gorm:"type:int;comment:主单id"` | ||||
| 	ApiId             int             `json:"apiId" gorm:"type:varchar(255);omitempty;comment:api用户"` | ||||
| 	GroupId           string          `json:"groupId" gorm:"type:int unsigned;omitempty;comment:交易对组id"` | ||||
| 	Symbol            string          `json:"symbol" gorm:"type:varchar(255);omitempty;comment:交易对"` | ||||
| 	QuoteSymbol       string          `json:"quoteSymbol" gorm:"type:varchar(255);omitempty;comment:计较货币"` | ||||
| 	SignPrice         string          `json:"signPrice" gorm:"type:decimal(18,8);omitempty;comment:对标价"` | ||||
| 	SignPriceU        decimal.Decimal `json:"signPriceU" gorm:"type:decimal(18,8);omitempty;comment:交易对对标U的行情价"` | ||||
| 	SignPriceType     string          `json:"signPriceType" gorm:"type:enum('new','tall','low','mixture','entrust','add');omitempty;comment:对标价类型: new=最新价格;tall=24小时最高;low=24小时最低;mixture=标记价;entrust=委托实价;add=补仓"` | ||||
| 	Rate              string          `json:"rate" gorm:"type:decimal(18,2);omitempty;comment:下单百分比"` | ||||
| 	Price             string          `json:"price" gorm:"type:decimal(18,8);omitempty;comment:触发价格"` | ||||
| 	Num               string          `json:"num" gorm:"type:decimal(18,8);omitempty;comment:购买数量"` | ||||
| 	BuyPrice          string          `json:"buyPrice" gorm:"type:decimal(18,8);omitempty;comment:购买金额"` | ||||
| 	SymbolType        int             `json:"symbolType" gorm:"type:int;comment:交易对类型:1=现货;2=合约"` | ||||
| 	OrderCategory     int             `json:"orderCategory" gorm:"type:int;comment:订单类型: 1=主单 2=对冲单 3-加仓单"` | ||||
| 	Site              string          `json:"site" gorm:"type:enum('BUY','SELL');omitempty;comment:购买方向:BUY=买;SELL=卖"` | ||||
| 	OrderSn           string          `json:"orderSn" gorm:"type:varchar(255);omitempty;comment:订单号"` | ||||
| 	OrderType         int             `json:"orderType" gorm:"type:int;omitempty;comment:订单类型:0=主单 1=止盈 2=止损 3=平仓 4=减仓"` | ||||
| 	Desc              string          `json:"desc" gorm:"type:text;omitempty;comment:订单描述"` | ||||
| 	Status            int             `json:"status" gorm:"type:int;omitempty;comment:是否被触发:0=待触发;1=已触发;2=下单失败;4=已取消;5=委托中;6=已成交;9=已平仓"` | ||||
| 	CoverType         int             `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"` | ||||
| 	ExpireTime        time.Time       `json:"expireTime" gorm:"comment:过期时间"` | ||||
| 	MainOrderType     string          `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价(LIMIT)市价(MARKET)"` | ||||
| 	LossAmount        decimal.Decimal `json:"lossAmount" gorm:"type:decimal(18,8);comment:亏损金额(U)"` | ||||
| 	TriggerTime       *time.Time      `json:"triggerTime" gorm:"type:datetime;comment:触发时间"` | ||||
| 	Child             []LinePreOrder  `json:"child" gorm:"-"` | ||||
| 	ApiName           string          `json:"api_name" gorm:"->"` | ||||
| 	ChildNum          int64           `json:"child_num" gorm:"->"` | ||||
| 	AddPositionStatus int             `json:"add_position_status" gorm:"->"` | ||||
| 	ReduceStatus      int             `json:"reduce_status" gorm:"->"` | ||||
| 	Childs            []LinePreOrder  `json:"childs" gorm:"foreignKey:pid;references:id"` | ||||
| 	ExchangeType         string          `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 (字典 exchange_type)"` | ||||
| 	StrategyTemplateType int             `json:"strategyTemplateType" gorm:"type:tinyint;comment:策略类型 0-无 1-波段涨跌幅"` | ||||
| 	StrategyTemplateId   int             `json:"strategyTemplateId" gorm:"type:bigint;comment:策略模板id"` | ||||
| 	Pid                  int             `json:"pid" gorm:"type:int unsigned;omitempty;comment:pid"` | ||||
| 	MainId               int             `json:"mainId" gorm:"type:int;comment:主单id"` | ||||
| 	ApiId                int             `json:"apiId" gorm:"type:varchar(255);omitempty;comment:api用户"` | ||||
| 	GroupId              string          `json:"groupId" gorm:"type:int unsigned;omitempty;comment:交易对组id"` | ||||
| 	Symbol               string          `json:"symbol" gorm:"type:varchar(255);omitempty;comment:交易对"` | ||||
| 	QuoteSymbol          string          `json:"quoteSymbol" gorm:"type:varchar(255);omitempty;comment:计较货币"` | ||||
| 	SignPrice            string          `json:"signPrice" gorm:"type:decimal(18,8);omitempty;comment:对标价"` | ||||
| 	SignPriceU           decimal.Decimal `json:"signPriceU" gorm:"type:decimal(18,8);omitempty;comment:交易对对标U的行情价"` | ||||
| 	SignPriceType        string          `json:"signPriceType" gorm:"type:enum('new','tall','low','mixture','entrust','add');omitempty;comment:对标价类型: new=最新价格;tall=24小时最高;low=24小时最低;mixture=标记价;entrust=委托实价;add=补仓"` | ||||
| 	Rate                 string          `json:"rate" gorm:"type:decimal(18,2);omitempty;comment:下单百分比"` | ||||
| 	Price                string          `json:"price" gorm:"type:decimal(18,8);omitempty;comment:触发价格"` | ||||
| 	Num                  string          `json:"num" gorm:"type:decimal(18,8);omitempty;comment:购买数量"` | ||||
| 	BuyPrice             string          `json:"buyPrice" gorm:"type:decimal(18,8);omitempty;comment:购买金额"` | ||||
| 	SymbolType           int             `json:"symbolType" gorm:"type:int;comment:交易对类型:1=现货;2=合约"` | ||||
| 	OrderCategory        int             `json:"orderCategory" gorm:"type:int;comment:订单类型: 1=主单 2=对冲单 3-加仓单"` | ||||
| 	Site                 string          `json:"site" gorm:"type:enum('BUY','SELL');omitempty;comment:购买方向:BUY=买;SELL=卖"` | ||||
| 	OrderSn              string          `json:"orderSn" gorm:"type:varchar(255);omitempty;comment:订单号"` | ||||
| 	OrderType            int             `json:"orderType" gorm:"type:int;omitempty;comment:订单类型:0=主单 1=止盈 2=止损 3=平仓 4=减仓"` | ||||
| 	Desc                 string          `json:"desc" gorm:"type:text;omitempty;comment:订单描述"` | ||||
| 	Status               int             `json:"status" gorm:"type:int;omitempty;comment:是否被触发:0=待触发;1=已触发;2=下单失败;4=已取消;5=委托中;6=已成交;9=已平仓"` | ||||
| 	CoverType            int             `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"` | ||||
| 	ExpireTime           time.Time       `json:"expireTime" gorm:"comment:过期时间"` | ||||
| 	MainOrderType        string          `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价(LIMIT)市价(MARKET)"` | ||||
| 	LossAmount           decimal.Decimal `json:"lossAmount" gorm:"type:decimal(18,8);comment:亏损金额(U)"` | ||||
| 	TriggerTime          *time.Time      `json:"triggerTime" gorm:"type:datetime;comment:触发时间"` | ||||
| 	Child                []LinePreOrder  `json:"child" gorm:"-"` | ||||
| 	ApiName              string          `json:"api_name" gorm:"->"` | ||||
| 	ChildNum             int64           `json:"child_num" gorm:"->"` | ||||
| 	AddPositionStatus    int             `json:"add_position_status" gorm:"->"` | ||||
| 	ReduceStatus         int             `json:"reduce_status" gorm:"->"` | ||||
| 	Childs               []LinePreOrder  `json:"childs" gorm:"foreignKey:pid;references:id"` | ||||
| 	// LinePreOrder 线上预埋单\ | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
|  | ||||
| @ -186,6 +186,8 @@ func (s *LinePreOrderDeleteReq) GetId() interface{} { | ||||
|  | ||||
| type LineAddPreOrderReq struct { | ||||
| 	ExchangeType            string          `json:"exchange_type" vd:"len($)>0"` //交易所类型 | ||||
| 	StrategyTemplateType    int             `json:"strategy_template_type"`      //策略类型 0-无 1-波段涨跌幅 | ||||
| 	StrategyTemplateId      int             `json:"strategy_template_id"`        //策略id | ||||
| 	OrderType               int             `json:"order_type"`                  //订单类型 | ||||
| 	Symbol                  string          `json:"symbol"`                      //交易对 | ||||
| 	ApiUserId               string          `json:"api_id" `                     //下单用户 | ||||
| @ -283,6 +285,10 @@ func (req LineAddPreOrderReq) Valid() error { | ||||
| 		return errors.New("主单减仓价格百分比不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if req.StrategyTemplateType == 1 && req.StrategyTemplateId == 0 { | ||||
| 		return errors.New("请选择策略") | ||||
| 	} | ||||
|  | ||||
| 	if req.ReduceNumRatio.IsZero() { | ||||
| 		return errors.New("主单减仓数量百分比不能为空") | ||||
| 	} | ||||
| @ -367,6 +373,8 @@ type LineTreeOrder struct { | ||||
| // LineBatchAddPreOrderReq 批量添加订单请求参数 | ||||
| type LineBatchAddPreOrderReq struct { | ||||
| 	ExchangeType          string                  `json:"exchange_type"`            //交易所类型 字典exchange_type | ||||
| 	StrategyTemplateType  int                     `json:"strategy_template_type"`   //策略类型 0-无 1-波段涨跌幅 | ||||
| 	StrategyTemplateId    int                     `json:"strategy_template_id"`     //策略id | ||||
| 	SymbolType            int                     `json:"symbol_type"`              //主单交易对类型 0-现货 1-合约 | ||||
| 	OrderType             int                     `json:"order_type"`               //订单类型 | ||||
| 	SymbolGroupId         string                  `json:"symbol_group_id"`          //交易对组id | ||||
| @ -404,6 +412,10 @@ func (req LineBatchAddPreOrderReq) CheckParams() error { | ||||
| 		return errors.New("请选择交易所") | ||||
| 	} | ||||
|  | ||||
| 	if req.StrategyTemplateType == 1 && req.StrategyTemplateId == 0 { | ||||
| 		return errors.New("请选择策略") | ||||
| 	} | ||||
|  | ||||
| 	if req.ApiUserId == "" { | ||||
| 		return errors.New("选择下单用户") | ||||
| 	} | ||||
|  | ||||
| @ -74,6 +74,13 @@ const ( | ||||
| 	AveRequestToken     = "ave_request_token"      // AVE请求token | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	//现货最后成交价 sort set {exchangeType,symbol} | ||||
| 	SpotTickerLastPrice = "spot_ticker_last_price:%s:%s" | ||||
| 	//合约最后成交价 sort set {exchangeType,symbol} | ||||
| 	FutureTickerLastPrice = "fut_ticker_last_price:%s:%s" | ||||
| ) | ||||
|  | ||||
| // 用户下单 | ||||
| const ( | ||||
| 	MemberShipPre = "member_ship_pre:%v" //用户开通会员预下单 单价缓存{payable_amount} | ||||
|  | ||||
| @ -5,6 +5,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| @ -609,7 +610,7 @@ func (e *RedisHelper) SignelAdd(key string, score float64, member string) error | ||||
| 	_, err := e.client.ZRemRangeByScore(e.ctx, key, scoreStr, scoreStr).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("删除score失败", err.Error()) | ||||
| 		fmt.Printf("删除score失败,err:%s", err.Error()) | ||||
| 	} | ||||
| 	_, err = e.client.ZAdd(e.ctx, key, &redis.Z{ | ||||
| 		Score:  score, | ||||
| @ -642,6 +643,46 @@ func (e *RedisHelper) DelSortSet(key, member string) error { | ||||
| 	return e.client.ZRem(e.ctx, key, member).Err() | ||||
| } | ||||
|  | ||||
| // RemoveBeforeScore 移除 Sorted Set 中分数小于等于指定值的数据 | ||||
| // key: Sorted Set 的键 | ||||
| // score: 分数上限,所有小于等于此分数的元素将被移除 | ||||
| // 返回值: 移除的元素数量和可能的错误 | ||||
| func (e *RedisHelper) RemoveBeforeScore(key string, score float64) (int64, error) { | ||||
| 	if key == "" { | ||||
| 		return 0, errors.New("key 不能为空") | ||||
| 	} | ||||
| 	if math.IsNaN(score) || math.IsInf(score, 0) { | ||||
| 		return 0, errors.New("score 必须是有效数字") | ||||
| 	} | ||||
|  | ||||
| 	// 使用 ZRemRangeByScore 移除数据 | ||||
| 	count, err := e.client.ZRemRangeByScore(e.ctx, key, "-inf", strconv.FormatFloat(score, 'f', -1, 64)).Result() | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("移除 Sorted Set 数据失败, key: %s, score: %f, err: %v", key, score, err) | ||||
| 	} | ||||
|  | ||||
| 	return count, nil | ||||
| } | ||||
|  | ||||
| // GetNextAfterScore 获取指定分数及之后的第一条数据(包含指定分数) | ||||
| func (e *RedisHelper) GetNextAfterScore(key string, score float64) (string, error) { | ||||
| 	// 使用 ZRangeByScore 获取大于等于 score 的第一条数据 | ||||
| 	zs, err := e.client.ZRangeByScoreWithScores(e.ctx, key, &redis.ZRangeBy{ | ||||
| 		Min:    fmt.Sprintf("%f", score), // 包含指定分数 | ||||
| 		Max:    "+inf",                   // 上限为正无穷 | ||||
| 		Offset: 0,                        // 从第 0 条开始 | ||||
| 		Count:  1,                        // 只取 1 条 | ||||
| 	}).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("获取数据失败: %v", err) | ||||
| 	} | ||||
| 	if len(zs) == 0 { | ||||
| 		return "", nil // 没有符合条件的元素 | ||||
| 	} | ||||
| 	return zs[0].Member.(string), nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| 获取sort set 所有数据 | ||||
| */ | ||||
|  | ||||
| @ -4,6 +4,7 @@ import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"go-admin/common/const/rediskey" | ||||
| 	"go-admin/common/global" | ||||
| 	"go-admin/common/helper" | ||||
| 	"go-admin/config" | ||||
| @ -15,6 +16,7 @@ import ( | ||||
| 	"go-admin/models" | ||||
|  | ||||
| 	log "github.com/go-admin-team/go-admin-core/logger" | ||||
| 	"github.com/shopspring/decimal" | ||||
|  | ||||
| 	"github.com/bytedance/sonic" | ||||
| 	"go.uber.org/zap" | ||||
| @ -133,7 +135,19 @@ func handleTickerAllMessage(msg []byte) { | ||||
| 			// log.Debug(symbol, "ticker@all ws处理失败", err) | ||||
| 			continue | ||||
| 		} | ||||
| 		tradeSet.LastPrice = utility.StringFloat64Cut(data["c"].(string), int32(tradeSet.PriceDigit)) | ||||
| 		var utcTime int64 | ||||
| 		var lastPrice decimal.Decimal | ||||
| 		lastPriceKey := fmt.Sprintf(rediskey.FutureTickerLastPrice, global.EXCHANGE_BINANCE, symbol) | ||||
|  | ||||
| 		if e, ok := data["E"]; ok { | ||||
| 			utcTime = utility.ToInt64(e) | ||||
| 		} | ||||
|  | ||||
| 		if e, ok := data["c"]; ok { | ||||
| 			lastPrice = utility.StrToDecimal(e.(string)).Truncate(int32(tradeSet.PriceDigit)) | ||||
| 		} | ||||
|  | ||||
| 		tradeSet.LastPrice = lastPrice.String() | ||||
| 		tradeSet.OpenPrice = utility.StrToFloatCut(data["o"].(string), int32(tradeSet.PriceDigit)) | ||||
| 		tradeSet.HighPrice = utility.StringFloat64Cut(data["h"].(string), int32(tradeSet.PriceDigit)) | ||||
| 		tradeSet.LowPrice = utility.StringFloat64Cut(data["l"].(string), int32(tradeSet.PriceDigit)) | ||||
| @ -147,6 +161,16 @@ func handleTickerAllMessage(msg []byte) { | ||||
| 				log.Error(symbol, "ticker@all ws处理失败", err) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		//行情存储时间 | ||||
| 		lastUtc := utcTime - 1000*60*60 | ||||
| 		if _, err := helper.DefaultRedis.RemoveBeforeScore(lastPriceKey, float64(lastUtc)); err != nil { | ||||
| 			log.Errorf("移除 合约交易对:%s %d之前的最新成交价失败,err:%v", symbol, lastUtc, err) | ||||
| 		} | ||||
|  | ||||
| 		if err := helper.DefaultRedis.AddSortSet(lastPriceKey, float64(utcTime), lastPrice.String()); err != nil { | ||||
| 			log.Errorf("添加 合约交易对:%s %d之前的最新成交价失败,err:%v", symbol, lastUtc, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(trades) > 0 { | ||||
|  | ||||
| @ -204,6 +204,7 @@ func handleTickerMessage(msg []byte) { | ||||
| 		} | ||||
|  | ||||
| 		key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbolName) | ||||
| 		lastPriceKey := fmt.Sprintf(rediskey.SpotTickerLastPrice, global.EXCHANGE_BINANCE, symbolName) | ||||
| 		tcVal, _ := helper.DefaultRedis.GetString(key) | ||||
| 		tradeSet := models.TradeSet{} | ||||
| 		if err := sonic.UnmarshalString(tcVal, &tradeSet); err != nil { | ||||
| @ -212,7 +213,19 @@ func handleTickerMessage(msg []byte) { | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		tradeSet.LastPrice = utility.StringFloat64Cut(dataMap["c"].(string), int32(tradeSet.PriceDigit)) | ||||
|  | ||||
| 		var utcTime int64 | ||||
| 		var lastPrice decimal.Decimal | ||||
|  | ||||
| 		if e, ok := dataMap["E"]; ok { | ||||
| 			utcTime = utility.ToInt64(e) | ||||
| 		} | ||||
|  | ||||
| 		if e, ok := dataMap["c"]; ok { | ||||
| 			lastPrice = utility.StrToDecimal(e.(string)).Truncate(int32(tradeSet.PriceDigit)) | ||||
| 		} | ||||
|  | ||||
| 		tradeSet.LastPrice = lastPrice.String() | ||||
| 		tradeSet.OpenPrice = utility.StrToFloatCut(dataMap["o"].(string), int32(tradeSet.PriceDigit)) | ||||
| 		tradeSet.HighPrice = utility.StringFloat64Cut(dataMap["h"].(string), int32(tradeSet.PriceDigit)) | ||||
| 		tradeSet.LowPrice = utility.StringFloat64Cut(dataMap["l"].(string), int32(tradeSet.PriceDigit)) | ||||
| @ -236,6 +249,17 @@ func handleTickerMessage(msg []byte) { | ||||
| 				log.Error("redis保存交易对失败", tradeSet.Coin, tradeSet.Currency) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		//行情存储时间 | ||||
| 		lastUtc := utcTime - 1000*60*60 | ||||
|  | ||||
| 		if _, err := helper.DefaultRedis.RemoveBeforeScore(lastPriceKey, float64(lastUtc)); err != nil { | ||||
| 			log.Errorf("移除 现货交易对:%s %d之前的最新成交价失败,err:%v", symbolName, lastUtc, err) | ||||
| 		} | ||||
|  | ||||
| 		if err := helper.DefaultRedis.AddSortSet(lastPriceKey, float64(utcTime), lastPrice.String()); err != nil { | ||||
| 			log.Errorf("添加 现货交易对:%s %d之前的最新成交价失败,err:%v", symbolName, lastUtc, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//判断触发现货下单 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user