1bug修复
This commit is contained in:
		| @ -295,7 +295,7 @@ func (req LineAddPreOrderReq) Valid() error { | ||||
| 		return errors.New("主单减仓数量百分比不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if req.ReducePriceRatio.IsZero() || req.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) >= 0 { | ||||
| 	if req.PricePattern != "mixture" && (req.ReducePriceRatio.IsZero() || req.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) >= 0) { | ||||
| 		return errors.New("主单减仓价格百分比错误") | ||||
| 	} | ||||
|  | ||||
| @ -447,7 +447,7 @@ func (req LineBatchAddPreOrderReq) CheckParams() error { | ||||
| 		return errors.New("主单减仓数量百分比不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if req.ReducePriceRatio.Cmp(decimal.Zero) <= 0 || req.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) >= 0 { | ||||
| 	if req.PricePattern != "mixture" && (req.ReducePriceRatio.Cmp(decimal.Zero) <= 0 || req.ReducePriceRatio.Cmp(decimal.NewFromInt(100)) >= 0) { | ||||
| 		return errors.New("主单减仓价格百分比错误") | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -592,6 +592,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | ||||
|  | ||||
| 		preOrderStatus := models.LinePreOrderStatus{} | ||||
| 		preOrderStatus.OrderSn = AddOrder.OrderSn | ||||
| 		mainPrice := utility.StringToDecimal(AddOrder.Price) | ||||
|  | ||||
| 		//订单配置信息 | ||||
| 		preOrderExts := make([]models.LinePreOrderExt, 0) | ||||
| @ -606,6 +607,12 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | ||||
| 			TpTpPriceRatio:     req.ProfitTpTpPriceRatio, | ||||
| 			TpSlPriceRatio:     req.ProfitTpSlPriceRatio, | ||||
| 		} | ||||
|  | ||||
| 		if req.PricePattern == "mixture" { | ||||
| 			defultExt.TakeProfitRatio = mainPrice.Div(utility.StrToDecimal(req.Profit)).Sub(decimal.NewFromInt(1)).Abs().Mul(decimal.NewFromInt(100)).Truncate(2) | ||||
| 			defultExt.StopLossRatio = mainPrice.Div(req.StopLoss).Sub(decimal.NewFromInt(1)).Abs().Mul(decimal.NewFromInt(100)).Truncate(2) | ||||
| 		} | ||||
|  | ||||
| 		//减仓单 | ||||
| 		defultExt2 := models.LinePreOrderExt{ | ||||
| 			AddType:            2, | ||||
| @ -617,17 +624,12 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | ||||
| 			TakeProfitNumRatio: decimal.NewFromInt(100), //减仓止盈默认100% | ||||
| 			StopLossRatio:      req.ReduceStopLossRatio, | ||||
| 		} | ||||
| 		mainPrice := utility.StringToDecimal(AddOrder.Price) | ||||
| 		mainAmount := utility.SafeDiv(buyPrice, mainPrice) | ||||
| 		defultExt.TotalAfter = utility.StrToDecimal(AddOrder.Num).Truncate(int32(tradeSet.AmountDigit)) | ||||
| 		defultExt2.TotalBefore = defultExt.TotalAfter | ||||
|  | ||||
| 		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) | ||||
|  | ||||
| 		calculateResp := dto.CalculateBreakEvenRatioResp{} | ||||
| 		mainParam := dto.CalculateBreakEevenRatioReq{ | ||||
| @ -643,15 +645,22 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | ||||
| 			AddPositionVal:   req.ReduceNumRatio, | ||||
| 		} | ||||
|  | ||||
| 		if req.PricePattern == "mixture" { | ||||
| 			mainParam.LossEndPercent = mainPrice.Div(req.ReducePriceRatio).Sub(decimal.NewFromInt(1)).Abs().Mul(decimal.NewFromInt(100)).Truncate(2) | ||||
| 			defultExt2.PriceRatio = mainParam.LossEndPercent | ||||
| 		} | ||||
|  | ||||
| 		//计算减仓后 | ||||
| 		mainParam.LossEndPercent = req.ReducePriceRatio | ||||
| 		defultExt2.ReTakeRatio = utility.SafeDiv(mainParam.LossEndPercent, default2NumPercent).Truncate(2) | ||||
| 		mainParam.RemainingQuantity = mainAmount | ||||
| 		e.CalculateBreakEvenRatio(&mainParam, &calculateResp, tradeSet) | ||||
| 		mainParam.RemainingQuantity = calculateResp.RemainingQuantity //mainAmount.Mul(decimal.NewFromInt(100).Sub(req.ReduceNumRatio).Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit)) | ||||
| 		mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU   //buyPrice.Mul(req.ReducePriceRatio.Div(decimal.NewFromInt(100)).Truncate(4)).Truncate(int32(tradeSet.PriceDigit)) | ||||
| 		req.ReduceReTakeProfitRatio = calculateResp.Ratio | ||||
| 		mainParam.LossBeginPercent = req.ReducePriceRatio | ||||
| 		mainParam.LossBeginPercent = mainParam.LossEndPercent | ||||
| 		// defultExt.ReTakeRatio = calculateResp.Ratio | ||||
| 		preOrderExts = append(preOrderExts, defultExt) | ||||
| 		preOrderExts = append(preOrderExts, defultExt2) | ||||
|  | ||||
| 		for index, addPosition := range req.Ext { | ||||
| 			ext := models.LinePreOrderExt{ | ||||
| @ -1069,6 +1078,8 @@ func makeFuturesTakeAndReduce(preOrder *models.LinePreOrder, ext models.LinePreO | ||||
| 		mainId = preOrder.MainId | ||||
| 	} | ||||
|  | ||||
| 	fmt.Println("take", ext.TakeProfitRatio.String()) | ||||
| 	fmt.Println("boo", ext.TakeProfitRatio.Cmp(decimal.Zero)) | ||||
| 	if ext.TakeProfitRatio.Cmp(decimal.Zero) > 0 { | ||||
| 		// 止盈单 | ||||
| 		profitOrder := models.LinePreOrder{} | ||||
| @ -2237,15 +2248,18 @@ func (e *LinePreOrder) GenerateOrder(req *dto.LineAddPreOrderReq) error { | ||||
| 		AddPositionVal:   req.ReduceNumRatio, | ||||
| 	} | ||||
|  | ||||
| 	if req.PricePattern == "mixture" { | ||||
| 		mainParam.LossEndPercent = price.Div(req.ReducePriceRatio).Sub(decimal.NewFromInt(1)).Abs().Mul(decimal.NewFromInt(100)).Truncate(2) | ||||
| 	} | ||||
|  | ||||
| 	//计算减仓后 | ||||
| 	mainParam.LossEndPercent = req.ReducePriceRatio | ||||
| 	mainParam.RemainingQuantity = mainAmount | ||||
| 	mainParam.AddType = 2 | ||||
| 	e.CalculateBreakEvenRatio(&mainParam, &calculateResp, tradeSet) | ||||
| 	mainParam.RemainingQuantity = calculateResp.RemainingQuantity | ||||
| 	mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU | ||||
| 	req.ReduceReTakeProfitRatio = calculateResp.Ratio | ||||
| 	lossBeginPercent = req.ReducePriceRatio | ||||
| 	lossBeginPercent = mainParam.LossEndPercent | ||||
|  | ||||
| 	//顺序排序 | ||||
| 	sort.Slice(req.Ext, func(i, j int) bool { | ||||
|  | ||||
							
								
								
									
										67
									
								
								app/jobs/account_job.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								app/jobs/account_job.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| package jobs | ||||
|  | ||||
| import ( | ||||
| 	binancedto "go-admin/models/binancedto" | ||||
| 	"go-admin/services/binanceservice" | ||||
|  | ||||
| 	DbModels "go-admin/app/admin/models" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/logger" | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type BinanceSpotAccountJob struct{} | ||||
|  | ||||
| type BinanceFuturesAccountJob struct{} | ||||
|  | ||||
| // 币安账户划转 | ||||
| func (t BinanceSpotAccountJob) Exec(arg interface{}) error { | ||||
| 	db := getDefaultDb() | ||||
| 	req := binancedto.BinanceTransfer{ | ||||
| 		Type:       "MAIN_UMFUTURE", | ||||
| 		Asset:      "USDT", | ||||
| 		Amount:     decimal.NewFromFloat(0.1), | ||||
| 		FromSymbol: "USDT", | ||||
| 		ToSymbol:   "USDT", | ||||
| 	} | ||||
| 	var apis []DbModels.LineApiUser | ||||
|  | ||||
| 	if err := db.Model(&DbModels.LineApiUser{}).Where("open_status = 1").Find(&apis).Error; err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, apiUserInfo := range apis { | ||||
| 		err := binanceservice.TradeAmount(db, &req, apiUserInfo) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			logger.Errorf("现货划转合约失败, err: %s", err) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 币安账户划转 | ||||
| func (t BinanceFuturesAccountJob) Exec(arg interface{}) error { | ||||
| 	db := getDefaultDb() | ||||
| 	req := binancedto.BinanceTransfer{ | ||||
| 		Type:       "UMFUTURE_MAIN", | ||||
| 		Asset:      "USDT", | ||||
| 		Amount:     decimal.NewFromFloat(0.1), | ||||
| 		FromSymbol: "USDT", | ||||
| 		ToSymbol:   "USDT", | ||||
| 	} | ||||
| 	var apis []DbModels.LineApiUser | ||||
| 	if err := db.Model(&DbModels.LineApiUser{}).Where("open_status = 1").Find(&apis).Error; err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, apiUserInfo := range apis { | ||||
| 		err := binanceservice.TradeAmount(db, &req, apiUserInfo) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			logger.Errorf("合约划转现货失败, err: %s", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/jobs/account_job_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/jobs/account_job_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| package jobs | ||||
|  | ||||
| import ( | ||||
| 	"go-admin/common/helper" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk" | ||||
| 	"gorm.io/driver/mysql" | ||||
| 	"gorm.io/gorm" | ||||
| ) | ||||
|  | ||||
| func TestAccountJob(t *testing.T) { | ||||
| 	dsn := "root:123456@tcp(127.0.0.1:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" | ||||
| 	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
| 	sdk.Runtime.SetDb("default", db) | ||||
|  | ||||
| 	helper.InitDefaultRedis("127.0.0.1:6379", "", 2) | ||||
| 	helper.InitLockRedisConn("127.0.0.1:6379", "", "2") | ||||
|  | ||||
| 	accountJob := BinanceSpotAccountJob{} | ||||
| 	accountJob.Exec(nil) | ||||
| } | ||||
|  | ||||
| func TestFutureAccountJob(t *testing.T) { | ||||
| 	dsn := "root:123456@tcp(127.0.0.1:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" | ||||
| 	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
| 	sdk.Runtime.SetDb("default", db) | ||||
|  | ||||
| 	helper.InitDefaultRedis("127.0.0.1:6379", "", 2) | ||||
| 	helper.InitLockRedisConn("127.0.0.1:6379", "", "2") | ||||
|  | ||||
| 	accountJob := BinanceFuturesAccountJob{} | ||||
| 	accountJob.Exec(nil) | ||||
| } | ||||
| @ -39,6 +39,8 @@ func InitJob() { | ||||
| 		"MemberRenwalOrderExpirationJob": MemberRenwalOrderExpirationJob{}, //会员续费订单过期处理 | ||||
| 		"TrxQueryJobs":                   TrxQueryJobs{},                   //订单支付监听 | ||||
| 		"StrategyJob":                    StrategyJob{},                    //下单策略触发 | ||||
| 		"BinanceSpotAccountJob":          BinanceSpotAccountJob{},          //币安现货划转 | ||||
| 		"BinanceFuturesAccountJob":       BinanceFuturesAccountJob{},       //币安合约划转 | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										11
									
								
								models/binancedto/account.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								models/binancedto/account.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| package binancedto | ||||
|  | ||||
| import "github.com/shopspring/decimal" | ||||
|  | ||||
| type BinanceTransfer struct { | ||||
| 	Type       string          `json:"type" content:"枚举 MAIN_UMFUTURE-现货到u合约"` | ||||
| 	Asset      string          `json:"asset" content:"币种"` | ||||
| 	Amount     decimal.Decimal `json:"amount" content:"数量"` | ||||
| 	FromSymbol string          `json:"fromSymbol" content:"转出币种"` | ||||
| 	ToSymbol   string          `json:"toSymbol" content:"转入币种"` | ||||
| } | ||||
| @ -640,3 +640,43 @@ func GetSpotUProperty(apiUserInfo DbModels.LineApiUser, data *dto.LineUserProper | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 万象划转 | ||||
| func TradeAmount(db *gorm.DB, req *binancedto.BinanceTransfer, apiUserInfo DbModels.LineApiUser) error { | ||||
| 	url := "/sapi/v1/asset/transfer" | ||||
|  | ||||
| 	client := GetClient(&apiUserInfo) | ||||
|  | ||||
| 	params := map[string]string{ | ||||
| 		"type":       req.Type, | ||||
| 		"asset":      req.Asset, | ||||
| 		"amount":     req.Amount.String(), | ||||
| 		"fromSymbol": req.FromSymbol, | ||||
| 		"toSymbol":   req.ToSymbol, | ||||
| 		"recvWindow": "10000", | ||||
| 	} | ||||
|  | ||||
| 	_, code, err := client.SendSpotAuth(url, "POST", params) | ||||
| 	if err != nil || code != 200 { | ||||
| 		log.Error("万向划转失败 参数:", params) | ||||
| 		log.Error("万向划转失败 code:", code) | ||||
| 		log.Error("万向划转失败 err:", err) | ||||
| 		dataMap := make(map[string]interface{}) | ||||
| 		if err.Error() != "" { | ||||
| 			if err := sonic.Unmarshal([]byte(err.Error()), &dataMap); err != nil { | ||||
| 				return fmt.Errorf("api_id:%d 万向划转失败:%+v", apiUserInfo.Id, err.Error()) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		code, ok := dataMap["code"] | ||||
| 		if ok { | ||||
| 			return fmt.Errorf("api_id:%d 万向划转失败:%s", apiUserInfo.Id, ErrorMaps[code.(float64)]) | ||||
| 		} | ||||
| 		if strings.Contains(err.Error(), "Unknown order sent.") { | ||||
| 			return fmt.Errorf("api_id:%d 万向划转失败:%+v", apiUserInfo.Id, ErrorMaps[-2011]) | ||||
| 		} | ||||
| 		return fmt.Errorf("api_id:%d 万向划转失败:%+v", apiUserInfo.Id, err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user