1bug修复
This commit is contained in:
		| @ -295,7 +295,7 @@ func (req LineAddPreOrderReq) Valid() error { | |||||||
| 		return errors.New("主单减仓数量百分比不能为空") | 		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("主单减仓价格百分比错误") | 		return errors.New("主单减仓价格百分比错误") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -447,7 +447,7 @@ func (req LineBatchAddPreOrderReq) CheckParams() error { | |||||||
| 		return errors.New("主单减仓数量百分比不能为空") | 		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("主单减仓价格百分比错误") | 		return errors.New("主单减仓价格百分比错误") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -592,6 +592,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | |||||||
|  |  | ||||||
| 		preOrderStatus := models.LinePreOrderStatus{} | 		preOrderStatus := models.LinePreOrderStatus{} | ||||||
| 		preOrderStatus.OrderSn = AddOrder.OrderSn | 		preOrderStatus.OrderSn = AddOrder.OrderSn | ||||||
|  | 		mainPrice := utility.StringToDecimal(AddOrder.Price) | ||||||
|  |  | ||||||
| 		//订单配置信息 | 		//订单配置信息 | ||||||
| 		preOrderExts := make([]models.LinePreOrderExt, 0) | 		preOrderExts := make([]models.LinePreOrderExt, 0) | ||||||
| @ -606,6 +607,12 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | |||||||
| 			TpTpPriceRatio:     req.ProfitTpTpPriceRatio, | 			TpTpPriceRatio:     req.ProfitTpTpPriceRatio, | ||||||
| 			TpSlPriceRatio:     req.ProfitTpSlPriceRatio, | 			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{ | 		defultExt2 := models.LinePreOrderExt{ | ||||||
| 			AddType:            2, | 			AddType:            2, | ||||||
| @ -617,17 +624,12 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | |||||||
| 			TakeProfitNumRatio: decimal.NewFromInt(100), //减仓止盈默认100% | 			TakeProfitNumRatio: decimal.NewFromInt(100), //减仓止盈默认100% | ||||||
| 			StopLossRatio:      req.ReduceStopLossRatio, | 			StopLossRatio:      req.ReduceStopLossRatio, | ||||||
| 		} | 		} | ||||||
| 		mainPrice := utility.StringToDecimal(AddOrder.Price) |  | ||||||
| 		mainAmount := utility.SafeDiv(buyPrice, mainPrice) | 		mainAmount := utility.SafeDiv(buyPrice, mainPrice) | ||||||
| 		defultExt.TotalAfter = utility.StrToDecimal(AddOrder.Num).Truncate(int32(tradeSet.AmountDigit)) | 		defultExt.TotalAfter = utility.StrToDecimal(AddOrder.Num).Truncate(int32(tradeSet.AmountDigit)) | ||||||
| 		defultExt2.TotalBefore = defultExt.TotalAfter | 		defultExt2.TotalBefore = defultExt.TotalAfter | ||||||
|  |  | ||||||
| 		default2NumPercent := utility.SafeDiv(decimal.NewFromInt(100).Sub(req.ReduceNumRatio), decimal.NewFromInt(100)) | 		default2NumPercent := utility.SafeDiv(decimal.NewFromInt(100).Sub(req.ReduceNumRatio), decimal.NewFromInt(100)) | ||||||
| 		defultExt2.TotalAfter = mainAmount.Mul(default2NumPercent).Truncate(int32(tradeSet.AmountDigit)) | 		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{} | 		calculateResp := dto.CalculateBreakEvenRatioResp{} | ||||||
| 		mainParam := dto.CalculateBreakEevenRatioReq{ | 		mainParam := dto.CalculateBreakEevenRatioReq{ | ||||||
| @ -643,15 +645,22 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, apiUserIds []int | |||||||
| 			AddPositionVal:   req.ReduceNumRatio, | 			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 | 		mainParam.RemainingQuantity = mainAmount | ||||||
| 		e.CalculateBreakEvenRatio(&mainParam, &calculateResp, tradeSet) | 		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.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)) | 		mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU   //buyPrice.Mul(req.ReducePriceRatio.Div(decimal.NewFromInt(100)).Truncate(4)).Truncate(int32(tradeSet.PriceDigit)) | ||||||
| 		req.ReduceReTakeProfitRatio = calculateResp.Ratio | 		req.ReduceReTakeProfitRatio = calculateResp.Ratio | ||||||
| 		mainParam.LossBeginPercent = req.ReducePriceRatio | 		mainParam.LossBeginPercent = mainParam.LossEndPercent | ||||||
| 		// defultExt.ReTakeRatio = calculateResp.Ratio | 		// defultExt.ReTakeRatio = calculateResp.Ratio | ||||||
|  | 		preOrderExts = append(preOrderExts, defultExt) | ||||||
|  | 		preOrderExts = append(preOrderExts, defultExt2) | ||||||
|  |  | ||||||
| 		for index, addPosition := range req.Ext { | 		for index, addPosition := range req.Ext { | ||||||
| 			ext := models.LinePreOrderExt{ | 			ext := models.LinePreOrderExt{ | ||||||
| @ -1069,6 +1078,8 @@ func makeFuturesTakeAndReduce(preOrder *models.LinePreOrder, ext models.LinePreO | |||||||
| 		mainId = preOrder.MainId | 		mainId = preOrder.MainId | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Println("take", ext.TakeProfitRatio.String()) | ||||||
|  | 	fmt.Println("boo", ext.TakeProfitRatio.Cmp(decimal.Zero)) | ||||||
| 	if ext.TakeProfitRatio.Cmp(decimal.Zero) > 0 { | 	if ext.TakeProfitRatio.Cmp(decimal.Zero) > 0 { | ||||||
| 		// 止盈单 | 		// 止盈单 | ||||||
| 		profitOrder := models.LinePreOrder{} | 		profitOrder := models.LinePreOrder{} | ||||||
| @ -2237,15 +2248,18 @@ func (e *LinePreOrder) GenerateOrder(req *dto.LineAddPreOrderReq) error { | |||||||
| 		AddPositionVal:   req.ReduceNumRatio, | 		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.RemainingQuantity = mainAmount | ||||||
| 	mainParam.AddType = 2 | 	mainParam.AddType = 2 | ||||||
| 	e.CalculateBreakEvenRatio(&mainParam, &calculateResp, tradeSet) | 	e.CalculateBreakEvenRatio(&mainParam, &calculateResp, tradeSet) | ||||||
| 	mainParam.RemainingQuantity = calculateResp.RemainingQuantity | 	mainParam.RemainingQuantity = calculateResp.RemainingQuantity | ||||||
| 	mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU | 	mainParam.TotalLossAmountU = calculateResp.TotalLossAmountU | ||||||
| 	req.ReduceReTakeProfitRatio = calculateResp.Ratio | 	req.ReduceReTakeProfitRatio = calculateResp.Ratio | ||||||
| 	lossBeginPercent = req.ReducePriceRatio | 	lossBeginPercent = mainParam.LossEndPercent | ||||||
|  |  | ||||||
| 	//顺序排序 | 	//顺序排序 | ||||||
| 	sort.Slice(req.Ext, func(i, j int) bool { | 	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{}, //会员续费订单过期处理 | 		"MemberRenwalOrderExpirationJob": MemberRenwalOrderExpirationJob{}, //会员续费订单过期处理 | ||||||
| 		"TrxQueryJobs":                   TrxQueryJobs{},                   //订单支付监听 | 		"TrxQueryJobs":                   TrxQueryJobs{},                   //订单支付监听 | ||||||
| 		"StrategyJob":                    StrategyJob{},                    //下单策略触发 | 		"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 | 	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