diff --git a/app/admin/models/line_pre_order_ext.go b/app/admin/models/line_pre_order_ext.go index 9836848..060baa8 100644 --- a/app/admin/models/line_pre_order_ext.go +++ b/app/admin/models/line_pre_order_ext.go @@ -12,6 +12,7 @@ type LinePreOrderExt struct { MainOrderId int `json:"mainOrderId" gorm:"type:bigint;comment:主单id"` OrderId int `json:"orderId" gorm:"type:bigint;comment:订单id"` AddType int `json:"addType" gorm:"type:tinyint;comment:类型 1-加仓 2-减仓"` + ExpirateHour int `json:"expirateHour" gorm:"type:int;comment:过期时间(0=永久有效)"` OrderType string `json:"orderType" gorm:"type:varchar(20);comment:订单类型 LIMIT-限价 MARKET-市价"` PriceRatio decimal.Decimal `json:"priceRatio" gorm:"type:decimal(10,2);comment: (加仓/减仓)触发价格百分比"` AddPositionType int `json:"addPositionType" gorm:"type:int;comment:(加仓/减仓)类型 1-百分比 2-实际金额"` diff --git a/app/admin/service/dto/line_pre_order_ext.go b/app/admin/service/dto/line_pre_order_ext.go index 5d8c630..a167034 100644 --- a/app/admin/service/dto/line_pre_order_ext.go +++ b/app/admin/service/dto/line_pre_order_ext.go @@ -48,6 +48,7 @@ type LineAddPreOrderExtReq struct { TpTpPriceRatio decimal.Decimal `json:"tpTpPriceRatio" comment:"止盈后止盈价格百分比"` TpSlPriceRatio decimal.Decimal `json:"tpSlPriceRatio" comment:"止盈后止损价格百分比"` ReTakeProfitRatio decimal.Decimal `json:"reTakeProfitRatio" comment:"亏损回本止盈百分比"` + ExpirateHour int `json:"expirateHour" comment:"过期时间小时"` } type LinePreOrderExtInsertReq struct { diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index 25d2d7c..1cb234d 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -582,6 +582,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP TpSlPriceRatio: addPosition.TpSlPriceRatio, AddPositionType: addPosition.AddPositionType, AddPositionVal: addPosition.AddPositionVal, + ExpirateHour: addPosition.ExpirateHour, } mainParam.AddType = addPosition.AddType @@ -809,6 +810,13 @@ func createPreAddPosition(preOrder *models.LinePreOrder, v models.LinePreOrderEx percentage = decimal.NewFromInt(1).Add(v.PriceRatio.Div(decimal.NewFromInt(100))) } + //过期时间 + if v.ExpirateHour <= 0 { + data.ExpireTime = time.Now().AddDate(2, 0, 0) + } else { + data.ExpireTime = time.Now().Add(time.Hour * time.Duration(v.ExpirateHour)) + } + dataPrice := price.Mul(percentage).Truncate(int32(tradeSet.PriceDigit)) data.Price = dataPrice.String() @@ -854,6 +862,13 @@ func createPreReduceOrder(preOrder *models.LinePreOrder, ext models.LinePreOrder stopOrder.Site = "BUY" } + //过期时间 + if ext.ExpirateHour <= 0 { + stopOrder.ExpireTime = time.Now().AddDate(2, 0, 0) + } else { + stopOrder.ExpireTime = time.Now().Add(time.Hour * time.Duration(ext.ExpirateHour)) + } + binanceservice.SetPrice(&stopOrder, preOrder, tradeSet) } diff --git a/app/jobs/examples.go b/app/jobs/examples.go index fb9990e..a5a9406 100644 --- a/app/jobs/examples.go +++ b/app/jobs/examples.go @@ -7,10 +7,14 @@ import ( "go-admin/app/admin/service" "go-admin/app/admin/service/dto" "go-admin/common/const/rediskey" + "go-admin/common/global" "go-admin/common/helper" + "go-admin/pkg/utility" + "go-admin/services/binanceservice" "time" "github.com/bytedance/sonic" + "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk" sysservice "github.com/go-admin-team/go-admin-core/sdk/service" "gorm.io/gorm" @@ -100,9 +104,95 @@ func (receiver DeleteExpireOrder) Exec(arg interface{}) error { //删除主单 db.Model(&models.LinePreOrder{}).Where("id = ?", order.Id).Unscoped().Delete(&models.LinePreOrder{}) } + + //子订单 加仓、检查过期 + childOrders := make([]models.LinePreOrder, 0) + err = db.Model(&models.LinePreOrder{}).Where("pid >0 AND order_type IN (0,4) AND status=0 AND expire_time <= ?", time.Now()).Select("id", "order_category", "order_type").Find(&childOrders).Error + + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + + removeExpirateChildOrder(childOrders, db) + return nil } +func removeExpirateChildOrder(childOrders []models.LinePreOrder, db *gorm.DB) { + childOrderId := make([]int, 0) + futAddKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE) + spotAddKey := fmt.Sprintf(rediskey.SpotAddPositionList, global.EXCHANGE_BINANCE) + futReduceKey := fmt.Sprintf(rediskey.FuturesReduceList, global.EXCHANGE_BINANCE) + spotReduceKey := fmt.Sprintf(rediskey.SpotReduceList, global.EXCHANGE_BINANCE) + futAddPositionStr, _ := helper.DefaultRedis.GetAllList(futAddKey) + spotAdPositionStr, _ := helper.DefaultRedis.GetAllList(spotAddKey) + futReduceStr, _ := helper.DefaultRedis.GetAllList(futReduceKey) + spotReduceStr, _ := helper.DefaultRedis.GetAllList(spotReduceKey) + futAddPositionCache := binanceservice.AddPositionList{} + spotAddPositionCache := binanceservice.AddPositionList{} + futReduceCache := binanceservice.ReduceListItem{} + spotReduceCache := binanceservice.ReduceListItem{} + futAddPositionMap := map[int]string{} + spotAddPositionMap := map[int]string{} + futReduceMap := map[int]string{} + spotReduceMap := map[int]string{} + + for _, item := range futAddPositionStr { + sonic.Unmarshal([]byte(item), &futAddPositionCache) + futAddPositionMap[futAddPositionCache.Id] = item + } + + for _, item := range spotAdPositionStr { + sonic.Unmarshal([]byte(item), &spotAddPositionCache) + spotAddPositionMap[spotAddPositionCache.Id] = item + } + + for _, item := range futReduceStr { + sonic.Unmarshal([]byte(item), &futReduceCache) + futReduceMap[futReduceCache.Id] = item + } + + for _, item := range spotReduceStr { + sonic.Unmarshal([]byte(item), &spotReduceCache) + spotReduceMap[spotReduceCache.Id] = item + } + + for _, childOrder := range childOrders { + switch { + //加仓单 + case childOrder.OrderType == 0 && childOrder.OrderCategory == 3: + if val, ok := futAddPositionMap[childOrder.Id]; ok { + helper.DefaultRedis.LRem(futAddKey, val) + } + + if val, ok := spotAddPositionMap[childOrder.Id]; ok { + helper.DefaultRedis.LRem(spotAddKey, val) + } + + //减仓单 + case childOrder.OrderType == 4 && childOrder.OrderCategory == 1: + if val, ok := futReduceMap[childOrder.Id]; ok { + helper.DefaultRedis.LRem(futReduceKey, val) + } + + if val, ok := spotReduceMap[childOrder.Id]; ok { + helper.DefaultRedis.LRem(spotReduceKey, val) + } + default: + continue + } + childOrderId = append(childOrderId, childOrder.Id) + } + + idArrays := utility.SplitSlice(childOrderId, 1000) + + for _, idArray := range idArrays { + if err := db.Delete(&models.LinePreOrder{}, idArray).Error; err != nil { + logger.Errorf("删除过期子订单失败,err", err) + } + } +} + // UpRange 更新涨跌幅 type UpRange struct { } diff --git a/config/settings.yml b/config/settings.yml index d0a7c5c..b9e5368 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -31,7 +31,7 @@ settings: # sqlserver: sqlserver://用户名:密码@地址?database=数据库名 driver: mysql # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms - source: root:root@tcp(192.168.1.12:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms + source: root:123456@tcp(127.0.0.1:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms # databases: # 'locaohost:8000': # driver: mysql diff --git a/pkg/utility/slices.go b/pkg/utility/slices.go index 8ce5aa7..6f0dd22 100644 --- a/pkg/utility/slices.go +++ b/pkg/utility/slices.go @@ -42,8 +42,8 @@ func HasSuffix(data string, suffixs []string) bool { } // SplitSlice 将 []string 切片根据最大数量分割成二维数组 -func SplitSlice(slice []string, maxSize int) [][]string { - var result [][]string +func SplitSlice[T any](slice []T, maxSize int) [][]T { + var result [][]T // 遍历切片,每次取 maxSize 个元素 for i := 0; i < len(slice); i += maxSize {