diff --git a/app/admin/service/dto/line_pre_order.go b/app/admin/service/dto/line_pre_order.go index 2788d33..aca435f 100644 --- a/app/admin/service/dto/line_pre_order.go +++ b/app/admin/service/dto/line_pre_order.go @@ -265,6 +265,11 @@ func (req *LinePreOrderAddPositionReq) Valid() error { return errors.New("减仓后止盈百分比不能为空") } + //减仓100% + if req.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) == 0 { + return errors.New("减仓数量百分百,后面的节点不需要添加") + } + return nil } @@ -281,7 +286,12 @@ func (req LineAddPreOrderReq) Valid() error { return errors.New("主单减仓价格百分比错误") } - for _, v := range req.Ext { + //减仓100% + if req.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) == 0 { + return errors.New("减仓数量百分百,后面的节点不需要添加") + } + + for index, v := range req.Ext { name := "加仓" if v.AddType < 1 || v.AddType > 2 { @@ -292,6 +302,10 @@ func (req LineAddPreOrderReq) Valid() error { name = "减仓" } + if v.AddType == 2 && v.AddPositionVal.Cmp(decimal.NewFromInt(100)) >= 0 && index < len(req.Ext)-1 { + return fmt.Errorf("减仓数量百分百,第%v节点 后面的节点不需要添加", index+1) + } + if v.AddPositionVal.IsZero() { return fmt.Errorf("%s单数量不能为空", name) } @@ -308,12 +322,6 @@ func (req LineAddPreOrderReq) Valid() error { (v.TpTpPriceRatio.IsZero() || v.TpTpPriceRatio.Cmp(decimal.NewFromInt(100)) > 0) { return errors.New("止盈后止盈价格不正确") } - - // if v.AddType == 1 && v.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) < 0 && - // v.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && - // (v.TpSlPriceRatio.Cmp(decimal.Zero) <= 0 || v.TpSlPriceRatio.Cmp(decimal.NewFromInt(100)) > 0) { - // return errors.New("止盈后止损价格不正确") - // } } return nil @@ -419,7 +427,12 @@ func (req LineBatchAddPreOrderReq) CheckParams() error { return errors.New("主单减仓价格百分比错误") } - for _, v := range req.Ext { + //减仓100% + if req.ReduceNumRatio.Cmp(decimal.NewFromInt(100)) == 0 { + return errors.New("减仓数量百分百,后面的节点不需要添加") + } + + for index, v := range req.Ext { name := "加仓" if v.AddType < 1 || v.AddType > 2 { @@ -430,6 +443,10 @@ func (req LineBatchAddPreOrderReq) CheckParams() error { name = "减仓" } + if v.AddType == 2 && v.AddPositionVal.Cmp(decimal.NewFromInt(100)) >= 0 && index < len(req.Ext)-1 { + return fmt.Errorf("减仓数量百分百,第%v节点 后面的节点不需要添加", index+1) + } + if v.AddPositionVal.IsZero() { return fmt.Errorf("%s单数量不能为空", name) } diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index d1117b9..e042451 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -539,8 +539,9 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP defultExt2.TotalBefore = defultExt.TotalAfter // if decimal.NewFromInt(100).Sub(req.ReduceNumRatio).Cmp(decimal.Zero) > 0 { - defultExt2.TotalAfter = mainAmount.Mul(decimal.NewFromInt(100).Sub(utility.SafeDiv(req.ReduceNumRatio, decimal.NewFromInt(100)))).Truncate(int32(tradeSet.AmountDigit)) - defultExt2.ReTakeRatio = utility.SafeDiv(req.ReducePriceRatio, utility.SafeDiv(decimal.NewFromInt(100).Sub(req.ReduceNumRatio), decimal.NewFromInt(100))).Truncate(2) + default2NumPercent := utility.SafeDiv(decimal.NewFromInt(100).Sub(req.ReduceNumRatio), decimal.NewFromInt(100)) + defultExt2.TotalAfter = mainAmount.Mul(default2NumPercent).Truncate(int32(tradeSet.AmountDigit)) + defultExt2.ReTakeRatio = utility.SafeDiv(req.ReducePriceRatio, default2NumPercent).Truncate(2) preOrderExts = append(preOrderExts, defultExt) preOrderExts = append(preOrderExts, defultExt2) diff --git a/pkg/utility/safego.go b/pkg/utility/safego.go index 4dd739e..ddf7a1b 100644 --- a/pkg/utility/safego.go +++ b/pkg/utility/safego.go @@ -15,7 +15,7 @@ func SafeGo(fn func()) { defer func() { if r := recover(); r != nil { // 记录 Goroutine ID、panic 信息和堆栈 - logger.Error(fmt.Sprintf("Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", getGoroutineID(), r, string(debug.Stack()))) + logger.Error(fmt.Sprintf("Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", GetGoroutineID(), r, string(debug.Stack()))) } }() fn() @@ -23,7 +23,7 @@ func SafeGo(fn func()) { } // 获取 Goroutine ID -func getGoroutineID() string { +func GetGoroutineID() string { buf := make([]byte, 64) n := runtime.Stack(buf, false) stack := string(buf[:n]) @@ -36,7 +36,7 @@ func SafeGoParam[T any](fn func(T), param T) { go func() { defer func() { if r := recover(); r != nil { - logger.Error(fmt.Sprintf(" SafeGoParam Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", getGoroutineID(), r, string(debug.Stack()))) + logger.Error(fmt.Sprintf(" SafeGoParam Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", GetGoroutineID(), r, string(debug.Stack()))) } }() fn(param) // 执行传入的函数 diff --git a/services/binanceservice/futuresrest.go b/services/binanceservice/futuresrest.go index 6855131..c688c5a 100644 --- a/services/binanceservice/futuresrest.go +++ b/services/binanceservice/futuresrest.go @@ -130,10 +130,13 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { logger.Errorf("handleReduceFilled 获取交易对设置失败,订单号:%s", preOrder.OrderSn) return } - rate := utility.StringAsFloat(preOrder.Rate) + + orderExt := models.LinePreOrderExt{} + db.Model(&orderExt).Where("order_id =?", preOrder.Id).First(&orderExt) + // rate := utility.StringAsFloat(orderExt.AddPositionVal) // 100%减仓 终止流程 - if rate >= 100 { + if orderExt.AddPositionVal.Cmp(decimal.NewFromInt(100)) >= 0 { //缓存 removeFutLossAndAddPosition(preOrder.MainId, preOrder.OrderSn) removePosition(db, preOrder) @@ -152,7 +155,6 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { return } - orderExt := models.LinePreOrderExt{} totalNum := getFuturesPositionAvailableQuantity(db, apiUserInfo, preOrder, tradeSet) price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit)) futApi := FutRestApi{} @@ -162,8 +164,6 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { mainId = preOrder.MainId } - db.Model(&orderExt).Where("order_id =?", preOrder.Pid).First(&orderExt) - for _, v := range orders { if v.OrderType == 1 { //亏损大于0 重新计算比例 diff --git a/services/binanceservice/spotreset.go b/services/binanceservice/spotreset.go index ddcbfad..ab12be3 100644 --- a/services/binanceservice/spotreset.go +++ b/services/binanceservice/spotreset.go @@ -174,14 +174,15 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { orderExt := models.LinePreOrderExt{} positionData := savePosition(db, preOrder) orders := make([]models.LinePreOrder, 0) - rate := utility.StringAsFloat(preOrder.Rate) + // rate := utility.StringAsFloat(preOrder.Rate) if err := db.Model(&DbModels.LinePreOrderStatus{}).Where("order_id =? ", preOrder.MainId).Update("reduce_status", 1).Error; err != nil { logger.Errorf("handleMainReduceFilled 更新主单减仓状态失败,订单号:%s", preOrder.OrderSn) } + db.Model(&orderExt).Where("order_id =?", preOrder.Id).Find(&orderExt) // 100%减仓 终止流程 - if rate >= 100 { + if orderExt.AddPositionVal.Cmp(decimal.NewFromInt(100)) >= 0 { //缓存 removeSpotLossAndAddPosition(preOrder.MainId, preOrder.OrderSn) removePosition(db, preOrder) @@ -193,7 +194,6 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { return } - db.Model(&orderExt).Where("order_id =?", preOrder.Pid).Find(&orderExt) totalNum := getSpotPositionAvailableQuantity(db, apiUserInfo, preOrder, tradeSet) //getSpotTotalNum(apiUserInfo, preOrder, tradeSet) totalNum = totalNum.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit)) price := utility.StrToDecimal(preOrder.Price) diff --git a/services/scriptservice/order.go b/services/scriptservice/order.go index 4a78831..ef01d27 100644 --- a/services/scriptservice/order.go +++ b/services/scriptservice/order.go @@ -1,12 +1,14 @@ package scriptservice import ( + "fmt" "go-admin/app/admin/models" "go-admin/app/admin/service" "go-admin/app/admin/service/dto" "go-admin/common/const/rediskey" "go-admin/common/helper" "go-admin/pkg/utility" + "runtime/debug" "strings" "sync" @@ -33,13 +35,26 @@ func (receiver *PreOrder) AddOrder(orm *gorm.DB) { } func workerWithLock(orm *gorm.DB, wg *sync.WaitGroup) { - defer func() { - wg.Done() - }() scriptId, err := helper.DefaultRedis.LPopList(rediskey.PreOrderScriptList) if err != nil { return } + + defer func() { + wg.Done() + if r := recover(); r != nil { + // 记录 Goroutine ID、panic 信息和堆栈 + err := string(debug.Stack()) + log.Error(fmt.Sprintf("Recovered from panic in Goroutine %s: %v\nStack Trace:\n%s", utility.GetGoroutineID(), r, err)) + + orm.Model(&models.LinePreScript{}).Where("id = ? ", scriptId).Updates(map[string]interface{}{ + "status": "1", + "error": err, + }, + ) + } + }() + var scriptInfo models.LinePreScript err = orm.Model(&models.LinePreScript{}).Where("id = ? AND status = '0'", scriptId).Find(&scriptInfo).Error if err != nil {