1、临时提交 反向下单
This commit is contained in:
		| @ -1,7 +1,7 @@ | |||||||
| package apis | package apis | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|     "fmt" | 	"fmt" | ||||||
|  |  | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/go-admin-team/go-admin-core/sdk/api" | 	"github.com/go-admin-team/go-admin-core/sdk/api" | ||||||
| @ -33,27 +33,27 @@ type LineReversePosition struct { | |||||||
| // @Router /api/v1/line-reverse-position [get] | // @Router /api/v1/line-reverse-position [get] | ||||||
| // @Security Bearer | // @Security Bearer | ||||||
| func (e LineReversePosition) GetPage(c *gin.Context) { | func (e LineReversePosition) GetPage(c *gin.Context) { | ||||||
|     req := dto.LineReversePositionGetPageReq{} | 	req := dto.LineReversePositionGetPageReq{} | ||||||
|     s := service.LineReversePosition{} | 	s := service.LineReversePosition{} | ||||||
|     err := e.MakeContext(c). | 	err := e.MakeContext(c). | ||||||
|         MakeOrm(). | 		MakeOrm(). | ||||||
|         Bind(&req). | 		Bind(&req). | ||||||
|         MakeService(&s.Service). | 		MakeService(&s.Service). | ||||||
|         Errors | 		Errors | ||||||
|    	if err != nil { | 	if err != nil { | ||||||
|    		e.Logger.Error(err) | 		e.Logger.Error(err) | ||||||
|    		e.Error(500, err, err.Error()) | 		e.Error(500, err, err.Error()) | ||||||
|    		return | 		return | ||||||
|    	} | 	} | ||||||
|  |  | ||||||
| 	p := actions.GetPermissionFromContext(c) | 	p := actions.GetPermissionFromContext(c) | ||||||
| 	list := make([]models.LineReversePosition, 0) | 	list := make([]dto.LineReversePositionListResp, 0) | ||||||
| 	var count int64 | 	var count int64 | ||||||
|  |  | ||||||
| 	err = s.GetPage(&req, p, &list, &count) | 	err = s.GetPage(&req, p, &list, &count) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Error(500, err, fmt.Sprintf("获取反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | 		e.Error(500, err, fmt.Sprintf("获取反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | ||||||
|         return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||||
| @ -70,7 +70,7 @@ func (e LineReversePosition) GetPage(c *gin.Context) { | |||||||
| func (e LineReversePosition) Get(c *gin.Context) { | func (e LineReversePosition) Get(c *gin.Context) { | ||||||
| 	req := dto.LineReversePositionGetReq{} | 	req := dto.LineReversePositionGetReq{} | ||||||
| 	s := service.LineReversePosition{} | 	s := service.LineReversePosition{} | ||||||
|     err := e.MakeContext(c). | 	err := e.MakeContext(c). | ||||||
| 		MakeOrm(). | 		MakeOrm(). | ||||||
| 		Bind(&req). | 		Bind(&req). | ||||||
| 		MakeService(&s.Service). | 		MakeService(&s.Service). | ||||||
| @ -86,10 +86,10 @@ func (e LineReversePosition) Get(c *gin.Context) { | |||||||
| 	err = s.Get(&req, p, &object) | 	err = s.Get(&req, p, &object) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Error(500, err, fmt.Sprintf("获取反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | 		e.Error(500, err, fmt.Sprintf("获取反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | ||||||
|         return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	e.OK( object, "查询成功") | 	e.OK(object, "查询成功") | ||||||
| } | } | ||||||
|  |  | ||||||
| // Insert 创建反单管理-仓位 | // Insert 创建反单管理-仓位 | ||||||
| @ -103,25 +103,25 @@ func (e LineReversePosition) Get(c *gin.Context) { | |||||||
| // @Router /api/v1/line-reverse-position [post] | // @Router /api/v1/line-reverse-position [post] | ||||||
| // @Security Bearer | // @Security Bearer | ||||||
| func (e LineReversePosition) Insert(c *gin.Context) { | func (e LineReversePosition) Insert(c *gin.Context) { | ||||||
|     req := dto.LineReversePositionInsertReq{} | 	req := dto.LineReversePositionInsertReq{} | ||||||
|     s := service.LineReversePosition{} | 	s := service.LineReversePosition{} | ||||||
|     err := e.MakeContext(c). | 	err := e.MakeContext(c). | ||||||
|         MakeOrm(). | 		MakeOrm(). | ||||||
|         Bind(&req). | 		Bind(&req). | ||||||
|         MakeService(&s.Service). | 		MakeService(&s.Service). | ||||||
|         Errors | 		Errors | ||||||
|     if err != nil { | 	if err != nil { | ||||||
|         e.Logger.Error(err) | 		e.Logger.Error(err) | ||||||
|         e.Error(500, err, err.Error()) | 		e.Error(500, err, err.Error()) | ||||||
|         return | 		return | ||||||
|     } | 	} | ||||||
| 	// 设置创建人 | 	// 设置创建人 | ||||||
| 	req.SetCreateBy(user.GetUserId(c)) | 	req.SetCreateBy(user.GetUserId(c)) | ||||||
|  |  | ||||||
| 	err = s.Insert(&req) | 	err = s.Insert(&req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Error(500, err, fmt.Sprintf("创建反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | 		e.Error(500, err, fmt.Sprintf("创建反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | ||||||
|         return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	e.OK(req.GetId(), "创建成功") | 	e.OK(req.GetId(), "创建成功") | ||||||
| @ -139,27 +139,27 @@ func (e LineReversePosition) Insert(c *gin.Context) { | |||||||
| // @Router /api/v1/line-reverse-position/{id} [put] | // @Router /api/v1/line-reverse-position/{id} [put] | ||||||
| // @Security Bearer | // @Security Bearer | ||||||
| func (e LineReversePosition) Update(c *gin.Context) { | func (e LineReversePosition) Update(c *gin.Context) { | ||||||
|     req := dto.LineReversePositionUpdateReq{} | 	req := dto.LineReversePositionUpdateReq{} | ||||||
|     s := service.LineReversePosition{} | 	s := service.LineReversePosition{} | ||||||
|     err := e.MakeContext(c). | 	err := e.MakeContext(c). | ||||||
|         MakeOrm(). | 		MakeOrm(). | ||||||
|         Bind(&req). | 		Bind(&req). | ||||||
|         MakeService(&s.Service). | 		MakeService(&s.Service). | ||||||
|         Errors | 		Errors | ||||||
|     if err != nil { | 	if err != nil { | ||||||
|         e.Logger.Error(err) | 		e.Logger.Error(err) | ||||||
|         e.Error(500, err, err.Error()) | 		e.Error(500, err, err.Error()) | ||||||
|         return | 		return | ||||||
|     } | 	} | ||||||
| 	req.SetUpdateBy(user.GetUserId(c)) | 	req.SetUpdateBy(user.GetUserId(c)) | ||||||
| 	p := actions.GetPermissionFromContext(c) | 	p := actions.GetPermissionFromContext(c) | ||||||
|  |  | ||||||
| 	err = s.Update(&req, p) | 	err = s.Update(&req, p) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Error(500, err, fmt.Sprintf("修改反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | 		e.Error(500, err, fmt.Sprintf("修改反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | ||||||
|         return | 		return | ||||||
| 	} | 	} | ||||||
| 	e.OK( req.GetId(), "修改成功") | 	e.OK(req.GetId(), "修改成功") | ||||||
| } | } | ||||||
|  |  | ||||||
| // Delete 删除反单管理-仓位 | // Delete 删除反单管理-仓位 | ||||||
| @ -171,18 +171,18 @@ func (e LineReversePosition) Update(c *gin.Context) { | |||||||
| // @Router /api/v1/line-reverse-position [delete] | // @Router /api/v1/line-reverse-position [delete] | ||||||
| // @Security Bearer | // @Security Bearer | ||||||
| func (e LineReversePosition) Delete(c *gin.Context) { | func (e LineReversePosition) Delete(c *gin.Context) { | ||||||
|     s := service.LineReversePosition{} | 	s := service.LineReversePosition{} | ||||||
|     req := dto.LineReversePositionDeleteReq{} | 	req := dto.LineReversePositionDeleteReq{} | ||||||
|     err := e.MakeContext(c). | 	err := e.MakeContext(c). | ||||||
|         MakeOrm(). | 		MakeOrm(). | ||||||
|         Bind(&req). | 		Bind(&req). | ||||||
|         MakeService(&s.Service). | 		MakeService(&s.Service). | ||||||
|         Errors | 		Errors | ||||||
|     if err != nil { | 	if err != nil { | ||||||
|         e.Logger.Error(err) | 		e.Logger.Error(err) | ||||||
|         e.Error(500, err, err.Error()) | 		e.Error(500, err, err.Error()) | ||||||
|         return | 		return | ||||||
|     } | 	} | ||||||
|  |  | ||||||
| 	// req.SetUpdateBy(user.GetUserId(c)) | 	// req.SetUpdateBy(user.GetUserId(c)) | ||||||
| 	p := actions.GetPermissionFromContext(c) | 	p := actions.GetPermissionFromContext(c) | ||||||
| @ -190,7 +190,7 @@ func (e LineReversePosition) Delete(c *gin.Context) { | |||||||
| 	err = s.Remove(&req, p) | 	err = s.Remove(&req, p) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Error(500, err, fmt.Sprintf("删除反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | 		e.Error(500, err, fmt.Sprintf("删除反单管理-仓位失败,\r\n失败信息 %s", err.Error())) | ||||||
|         return | 		return | ||||||
| 	} | 	} | ||||||
| 	e.OK( req.GetId(), "删除成功") | 	e.OK(req.GetId(), "删除成功") | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,8 +11,9 @@ import ( | |||||||
| type LineReverseOrder struct { | type LineReverseOrder struct { | ||||||
| 	models.Model | 	models.Model | ||||||
|  |  | ||||||
| 	ApiId    int `json:"apiId" gorm:"type:bigint;comment:api id"` | 	PositionId int `json:"positionId" gorm:"type:bigint;comment:仓位id"` | ||||||
| 	Category int `json:"category" gorm:"type:tinyint;comment:分类 0-原始订单 1-反单"` | 	ApiId      int `json:"apiId" gorm:"type:bigint;comment:api id"` | ||||||
|  | 	Category   int `json:"category" gorm:"type:tinyint;comment:分类 0-原始订单 1-反单"` | ||||||
|  |  | ||||||
| 	OrderSn       string          `json:"orderSn" gorm:"type:varchar(50);comment:订单号 0-主单 1-止盈 2-止损"` | 	OrderSn       string          `json:"orderSn" gorm:"type:varchar(50);comment:订单号 0-主单 1-止盈 2-止损"` | ||||||
| 	OrderId       string          `json:"orderId" gorm:"type:varchar(50);comment:币安订单号"` | 	OrderId       string          `json:"orderId" gorm:"type:varchar(50);comment:币安订单号"` | ||||||
|  | |||||||
| @ -9,18 +9,20 @@ import ( | |||||||
| type LineReversePosition struct { | type LineReversePosition struct { | ||||||
| 	models.Model | 	models.Model | ||||||
|  |  | ||||||
| 	ApiId              int             `json:"apiId" gorm:"type:bigint;comment:api_id"` | 	PositionNo          string          `json:"positionNo" gorm:"type:varchar(18);comment:仓位编号"` | ||||||
| 	TotalAmount        decimal.Decimal `json:"totalAmount" gorm:"type:decimal(18,8);comment:总仓位"` | 	ApiId               int             `json:"apiId" gorm:"type:bigint;comment:api_id"` | ||||||
| 	Amount             decimal.Decimal `json:"amount" gorm:"type:decimal(18,8);comment:仓位"` | 	TotalAmount         decimal.Decimal `json:"totalAmount" gorm:"type:decimal(18,8);comment:总仓位"` | ||||||
| 	ReverseApiId       int             `json:"reverseApiId" gorm:"type:bigint;comment:反单api_id"` | 	Amount              decimal.Decimal `json:"amount" gorm:"type:decimal(18,8);comment:仓位"` | ||||||
| 	TotalReverseAmount decimal.Decimal `json:"totalReverseAmount" gorm:"type:decimal(18,8);comment:总反单仓位"` | 	ReverseApiId        int             `json:"reverseApiId" gorm:"type:bigint;comment:反单api_id"` | ||||||
| 	ReverseAmount      decimal.Decimal `json:"reverseAmount" gorm:"type:decimal(18,8);comment:反单仓位"` | 	TotalReverseAmount  decimal.Decimal `json:"totalReverseAmount" gorm:"type:decimal(18,8);comment:总反单仓位"` | ||||||
| 	Side               string          `json:"side" gorm:"type:varchar(10);comment:买卖方向 BUY SELL"` | 	ReverseAmount       decimal.Decimal `json:"reverseAmount" gorm:"type:decimal(18,8);comment:反单仓位"` | ||||||
| 	PositionSide       string          `json:"positionSide" gorm:"type:varchar(10);comment:持仓方向 LONG SHORT"` | 	Side                string          `json:"side" gorm:"type:varchar(10);comment:买卖方向 BUY SELL"` | ||||||
| 	Symbol             string          `json:"symbol" gorm:"type:varchar(20);comment:交易对"` | 	PositionSide        string          `json:"positionSide" gorm:"type:varchar(10);comment:持仓方向 LONG SHORT"` | ||||||
| 	Status             int             `json:"status" gorm:"type:tinyint;comment:仓位状态 1-已开仓 2-已平仓"` | 	Symbol              string          `json:"symbol" gorm:"type:varchar(20);comment:交易对"` | ||||||
| 	ReverseStatus      int             `json:"reverseStatus" gorm:"type:tinyint;comment:反单仓位状态 1-已开仓 2-已平仓"` | 	Status              int             `json:"status" gorm:"type:tinyint;comment:仓位状态 1-已开仓 2-已平仓"` | ||||||
|  | 	ReverseStatus       int             `json:"reverseStatus" gorm:"type:tinyint;comment:反单仓位状态 1-已开仓 2-已平仓"` | ||||||
|  | 	AveragePrice        decimal.Decimal `json:"averagePrice" gorm:"type:decimal(18,8);comment:主单平均价格"` | ||||||
|  | 	ReverseAveragePrice decimal.Decimal `json:"reverseAveragePrice" gorm:"type:decimal(18,8);comment:反单平均价格"` | ||||||
| 	models.ModelTime | 	models.ModelTime | ||||||
| 	models.ControlBy | 	models.ControlBy | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ type LineReverseOrderGetPageReq struct { | |||||||
| 	PositionSide   string `form:"positionSide"  search:"type:exact;column:position_side;table:line_reverse_order" comment:"持仓方向 LONG-多 SHORT-空"` | 	PositionSide   string `form:"positionSide"  search:"type:exact;column:position_side;table:line_reverse_order" comment:"持仓方向 LONG-多 SHORT-空"` | ||||||
| 	Side           string `form:"side"  search:"type:exact;column:side;table:line_reverse_order" comment:"买卖方向 SELL-卖 BUY-买"` | 	Side           string `form:"side"  search:"type:exact;column:side;table:line_reverse_order" comment:"买卖方向 SELL-卖 BUY-买"` | ||||||
| 	Status         int    `form:"status"  search:"type:exact;column:status;table:line_reverse_order" comment:"状态 1-待下单 2-已下单 3-已成交 4-已平仓 5-已止损"` | 	Status         int    `form:"status"  search:"type:exact;column:status;table:line_reverse_order" comment:"状态 1-待下单 2-已下单 3-已成交 4-已平仓 5-已止损"` | ||||||
|  | 	PositionId     int    `form:"positionId" search:"type:exact;column:position_id;table:line_reverse_order" comment:"持仓id"` | ||||||
| 	LineReverseOrderOrder | 	LineReverseOrderOrder | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -52,7 +53,7 @@ func (m *LineReverseOrderGetPageReq) GetNeedSearch() interface{} { | |||||||
|  |  | ||||||
| type LineReverseOrderInsertReq struct { | type LineReverseOrderInsertReq struct { | ||||||
| 	Id            int             `json:"-" comment:"主键id"` // 主键id | 	Id            int             `json:"-" comment:"主键id"` // 主键id | ||||||
| 	PId           int             `json:"pId" comment:"主单id"` | 	PositionId    int             `json:"positionId" comment:"仓位id"` | ||||||
| 	OrderSn       string          `json:"orderSn" comment:"订单号"` | 	OrderSn       string          `json:"orderSn" comment:"订单号"` | ||||||
| 	OrderId       string          `json:"orderId" comment:"币安订单号"` | 	OrderId       string          `json:"orderId" comment:"币安订单号"` | ||||||
| 	FollowOrderSn string          `json:"followOrderSn" comment:"跟随币安订单号"` | 	FollowOrderSn string          `json:"followOrderSn" comment:"跟随币安订单号"` | ||||||
| @ -86,6 +87,7 @@ func (s *LineReverseOrderInsertReq) Generate(model *models.LineReverseOrder) { | |||||||
| 	model.PositionSide = s.PositionSide | 	model.PositionSide = s.PositionSide | ||||||
| 	model.Side = s.Side | 	model.Side = s.Side | ||||||
| 	model.SignPrice = s.SignPrice | 	model.SignPrice = s.SignPrice | ||||||
|  | 	model.TriggerTime = &s.TriggerTime | ||||||
| 	model.Status = s.Status | 	model.Status = s.Status | ||||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||||
| } | } | ||||||
| @ -96,7 +98,7 @@ func (s *LineReverseOrderInsertReq) GetId() interface{} { | |||||||
|  |  | ||||||
| type LineReverseOrderUpdateReq struct { | type LineReverseOrderUpdateReq struct { | ||||||
| 	Id            int             `uri:"id" comment:"主键id"` // 主键id | 	Id            int             `uri:"id" comment:"主键id"` // 主键id | ||||||
| 	PId           int             `json:"pId" comment:"主单id"` | 	PositionId    int             `json:"positionId" comment:"仓位id"` | ||||||
| 	OrderSn       string          `json:"orderSn" comment:"订单号"` | 	OrderSn       string          `json:"orderSn" comment:"订单号"` | ||||||
| 	OrderId       string          `json:"orderId" comment:"币安订单号"` | 	OrderId       string          `json:"orderId" comment:"币安订单号"` | ||||||
| 	FollowOrderSn string          `json:"followOrderSn" comment:"跟随币安订单号"` | 	FollowOrderSn string          `json:"followOrderSn" comment:"跟随币安订单号"` | ||||||
| @ -118,7 +120,6 @@ func (s *LineReverseOrderUpdateReq) Generate(model *models.LineReverseOrder) { | |||||||
| 	if s.Id == 0 { | 	if s.Id == 0 { | ||||||
| 		model.Model = common.Model{Id: s.Id} | 		model.Model = common.Model{Id: s.Id} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	model.OrderSn = s.OrderSn | 	model.OrderSn = s.OrderSn | ||||||
| 	model.OrderId = s.OrderId | 	model.OrderId = s.OrderId | ||||||
| 	model.FollowOrderSn = s.FollowOrderSn | 	model.FollowOrderSn = s.FollowOrderSn | ||||||
| @ -131,6 +132,7 @@ func (s *LineReverseOrderUpdateReq) Generate(model *models.LineReverseOrder) { | |||||||
| 	model.PositionSide = s.PositionSide | 	model.PositionSide = s.PositionSide | ||||||
| 	model.Side = s.Side | 	model.Side = s.Side | ||||||
| 	model.SignPrice = s.SignPrice | 	model.SignPrice = s.SignPrice | ||||||
|  | 	model.TriggerTime = &s.TriggerTime | ||||||
| 	model.Status = s.Status | 	model.Status = s.Status | ||||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||||
| } | } | ||||||
|  | |||||||
| @ -115,3 +115,21 @@ type LineReversePositionDeleteReq struct { | |||||||
| func (s *LineReversePositionDeleteReq) GetId() interface{} { | func (s *LineReversePositionDeleteReq) GetId() interface{} { | ||||||
| 	return s.Ids | 	return s.Ids | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type LineReversePositionListResp struct { | ||||||
|  | 	Id                  int             `json:"id"` | ||||||
|  | 	ApiName             string          `json:"apiName"` | ||||||
|  | 	ReverseApiName      string          `json:"reverseApiName"` | ||||||
|  | 	Amount              decimal.Decimal `json:"amount"` | ||||||
|  | 	TotalAmount         decimal.Decimal `json:"totalAmount"` | ||||||
|  | 	ReverseAmount       decimal.Decimal `json:"reverseAmount"` | ||||||
|  | 	TotalReverseAmount  decimal.Decimal `json:"totalReverseAmount"` | ||||||
|  | 	Side                string          `json:"side"` | ||||||
|  | 	PositionSide        string          `json:"positionSide"` | ||||||
|  | 	Symbol              string          `json:"symbol"` | ||||||
|  | 	Status              int             `json:"status"` | ||||||
|  | 	ReverseStatus       int             `json:"reverseStatus"` | ||||||
|  | 	AveragePrice        decimal.Decimal `json:"averagePrice"` | ||||||
|  | 	ReverseAveragePrice decimal.Decimal `json:"reverseAveragePrice"` | ||||||
|  | 	CreatedAt           string          `json:"createdAt"` | ||||||
|  | } | ||||||
|  | |||||||
| @ -3,13 +3,15 @@ package service | |||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  |  | ||||||
|     "github.com/go-admin-team/go-admin-core/sdk/service" | 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||||
|  | 	"github.com/jinzhu/copier" | ||||||
| 	"gorm.io/gorm" | 	"gorm.io/gorm" | ||||||
|  |  | ||||||
| 	"go-admin/app/admin/models" | 	"go-admin/app/admin/models" | ||||||
| 	"go-admin/app/admin/service/dto" | 	"go-admin/app/admin/service/dto" | ||||||
| 	"go-admin/common/actions" | 	"go-admin/common/actions" | ||||||
| 	cDto "go-admin/common/dto" | 	cDto "go-admin/common/dto" | ||||||
|  | 	"go-admin/pkg/utility" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type LineReversePosition struct { | type LineReversePosition struct { | ||||||
| @ -17,9 +19,10 @@ type LineReversePosition struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetPage 获取LineReversePosition列表 | // GetPage 获取LineReversePosition列表 | ||||||
| func (e *LineReversePosition) GetPage(c *dto.LineReversePositionGetPageReq, p *actions.DataPermission, list *[]models.LineReversePosition, count *int64) error { | func (e *LineReversePosition) GetPage(c *dto.LineReversePositionGetPageReq, p *actions.DataPermission, list *[]dto.LineReversePositionListResp, count *int64) error { | ||||||
| 	var err error | 	var err error | ||||||
| 	var data models.LineReversePosition | 	var data models.LineReversePosition | ||||||
|  | 	var datas []models.LineReversePosition | ||||||
|  |  | ||||||
| 	err = e.Orm.Model(&data). | 	err = e.Orm.Model(&data). | ||||||
| 		Scopes( | 		Scopes( | ||||||
| @ -27,12 +30,52 @@ func (e *LineReversePosition) GetPage(c *dto.LineReversePositionGetPageReq, p *a | |||||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||||
| 			actions.Permission(data.TableName(), p), | 			actions.Permission(data.TableName(), p), | ||||||
| 		). | 		). | ||||||
| 		Find(list).Limit(-1).Offset(-1). | 		Find(&datas).Limit(-1).Offset(-1). | ||||||
| 		Count(count).Error | 		Count(count).Error | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Log.Errorf("LineReversePositionService GetPage error:%s \r\n", err) | 		e.Log.Errorf("LineReversePositionService GetPage error:%s \r\n", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	userIds := make([]int, 0) | ||||||
|  |  | ||||||
|  | 	for _, item := range datas { | ||||||
|  | 		if !utility.ContainsInt(userIds, item.ApiId) { | ||||||
|  | 			userIds = append(userIds, item.ApiId) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if !utility.ContainsInt(userIds, item.ReverseApiId) { | ||||||
|  | 			userIds = append(userIds, item.ReverseApiId) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	userMap := make(map[int]string, 0) | ||||||
|  |  | ||||||
|  | 	if len(userIds) > 0 { | ||||||
|  | 		var users []models.LineApiUser | ||||||
|  | 		e.Orm.Model(&models.LineApiUser{}). | ||||||
|  | 			Where("id IN (?)", userIds). | ||||||
|  | 			Find(&users) | ||||||
|  |  | ||||||
|  | 		for _, item := range users { | ||||||
|  | 			userMap[int(item.Id)] = item.ApiName | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, item := range datas { | ||||||
|  | 		var resp dto.LineReversePositionListResp | ||||||
|  | 		copier.Copy(&resp, &item) | ||||||
|  |  | ||||||
|  | 		if userName, ok := userMap[item.ApiId]; ok { | ||||||
|  | 			resp.ApiName = userName | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if userName, ok := userMap[item.ReverseApiId]; ok { | ||||||
|  | 			resp.ReverseApiName = userName | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*list = append(*list, resp) | ||||||
|  | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -59,9 +102,9 @@ func (e *LineReversePosition) Get(d *dto.LineReversePositionGetReq, p *actions.D | |||||||
|  |  | ||||||
| // Insert 创建LineReversePosition对象 | // Insert 创建LineReversePosition对象 | ||||||
| func (e *LineReversePosition) Insert(c *dto.LineReversePositionInsertReq) error { | func (e *LineReversePosition) Insert(c *dto.LineReversePositionInsertReq) error { | ||||||
|     var err error | 	var err error | ||||||
|     var data models.LineReversePosition | 	var data models.LineReversePosition | ||||||
|     c.Generate(&data) | 	c.Generate(&data) | ||||||
| 	err = e.Orm.Create(&data).Error | 	err = e.Orm.Create(&data).Error | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Log.Errorf("LineReversePositionService Insert error:%s \r\n", err) | 		e.Log.Errorf("LineReversePositionService Insert error:%s \r\n", err) | ||||||
| @ -72,22 +115,22 @@ func (e *LineReversePosition) Insert(c *dto.LineReversePositionInsertReq) error | |||||||
|  |  | ||||||
| // Update 修改LineReversePosition对象 | // Update 修改LineReversePosition对象 | ||||||
| func (e *LineReversePosition) Update(c *dto.LineReversePositionUpdateReq, p *actions.DataPermission) error { | func (e *LineReversePosition) Update(c *dto.LineReversePositionUpdateReq, p *actions.DataPermission) error { | ||||||
|     var err error | 	var err error | ||||||
|     var data = models.LineReversePosition{} | 	var data = models.LineReversePosition{} | ||||||
|     e.Orm.Scopes( | 	e.Orm.Scopes( | ||||||
|             actions.Permission(data.TableName(), p), | 		actions.Permission(data.TableName(), p), | ||||||
|         ).First(&data, c.GetId()) | 	).First(&data, c.GetId()) | ||||||
|     c.Generate(&data) | 	c.Generate(&data) | ||||||
|  |  | ||||||
|     db := e.Orm.Save(&data) | 	db := e.Orm.Save(&data) | ||||||
|     if err = db.Error; err != nil { | 	if err = db.Error; err != nil { | ||||||
|         e.Log.Errorf("LineReversePositionService Save error:%s \r\n", err) | 		e.Log.Errorf("LineReversePositionService Save error:%s \r\n", err) | ||||||
|         return err | 		return err | ||||||
|     } | 	} | ||||||
|     if db.RowsAffected == 0 { | 	if db.RowsAffected == 0 { | ||||||
|         return errors.New("无权更新该数据") | 		return errors.New("无权更新该数据") | ||||||
|     } | 	} | ||||||
|     return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // Remove 删除LineReversePosition | // Remove 删除LineReversePosition | ||||||
| @ -99,11 +142,11 @@ func (e *LineReversePosition) Remove(d *dto.LineReversePositionDeleteReq, p *act | |||||||
| 			actions.Permission(data.TableName(), p), | 			actions.Permission(data.TableName(), p), | ||||||
| 		).Delete(&data, d.GetId()) | 		).Delete(&data, d.GetId()) | ||||||
| 	if err := db.Error; err != nil { | 	if err := db.Error; err != nil { | ||||||
|         e.Log.Errorf("Service RemoveLineReversePosition error:%s \r\n", err) | 		e.Log.Errorf("Service RemoveLineReversePosition error:%s \r\n", err) | ||||||
|         return err | 		return err | ||||||
|     } | 	} | ||||||
|     if db.RowsAffected == 0 { | 	if db.RowsAffected == 0 { | ||||||
|         return errors.New("无权删除该数据") | 		return errors.New("无权删除该数据") | ||||||
|     } | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -463,22 +463,13 @@ func (r *RedisHelper) SetNX(key string, value interface{}, expiration time.Durat | |||||||
|  |  | ||||||
| // SetHashWithTags 改进版:支持 struct 或 map 输入 | // SetHashWithTags 改进版:支持 struct 或 map 输入 | ||||||
| func (r *RedisHelper) SetHashWithTags(key string, obj interface{}) error { | func (r *RedisHelper) SetHashWithTags(key string, obj interface{}) error { | ||||||
| 	var fields map[string]interface{} | 	fields, err := getFieldsFromStruct(obj) | ||||||
| 	var err error | 	if err != nil { | ||||||
|  | 		return err | ||||||
| 	// 1. 优先检查 obj 是否已经是一个 map[string]interface{} |  | ||||||
| 	if m, ok := obj.(map[string]interface{}); ok { |  | ||||||
| 		fields = m // 如果是,直接使用这个 map |  | ||||||
| 	} else { |  | ||||||
| 		// 2. 如果不是 map,则假设它是一个 struct,并尝试从 struct 中获取字段 |  | ||||||
| 		fields, err = getFieldsFromStruct(obj) // getFieldsFromStruct 现在需要返回 error |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("从结构体获取字段失败: %w", err) |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	cmd := r.client.HSet(r.ctx, key, fields) | 	_, err = r.client.HSet(r.ctx, key, fields).Result() | ||||||
| 	return cmd.Err() | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| // getFieldsFromStruct 改进版:处理指针并进行类型检查,返回 error | // getFieldsFromStruct 改进版:处理指针并进行类型检查,返回 error | ||||||
|  | |||||||
| @ -37,6 +37,10 @@ type TradeSet struct { | |||||||
| 	E            int64   `json:"-"`                            //推送时间 | 	E            int64   `json:"-"`                            //推送时间 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (e *TradeSet) GetSymbol() string { | ||||||
|  | 	return e.Coin + e.Currency | ||||||
|  | } | ||||||
|  |  | ||||||
| //CommissionType  int     `db:"commissiontype"`                 //手续费:1买,2卖,3双向 | //CommissionType  int     `db:"commissiontype"`                 //手续费:1买,2卖,3双向 | ||||||
| //DepositNum      float64 `db:"depositnum" json:"depositnum"`     //保证金规模(手) | //DepositNum      float64 `db:"depositnum" json:"depositnum"`     //保证金规模(手) | ||||||
| //ForceRate       float64 `db:"forcerate" json:"forcerate"`       //维持保证金率1% | //ForceRate       float64 `db:"forcerate" json:"forcerate"`       //维持保证金率1% | ||||||
|  | |||||||
| @ -28,3 +28,7 @@ func init() { | |||||||
| func GetOrderId() int64 { | func GetOrderId() int64 { | ||||||
| 	return snowNode.Generate().Int64() | 	return snowNode.Generate().Int64() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func GetOrderNo() string { | ||||||
|  | 	return fmt.Sprintf("%d", GetOrderId()) | ||||||
|  | } | ||||||
|  | |||||||
| @ -49,7 +49,6 @@ func (e *FuturesResetV2) OrderPlace(apiUserInfo *DbModels.LineApiUser, params Fu | |||||||
| 	paramsMaps := map[string]string{ | 	paramsMaps := map[string]string{ | ||||||
| 		"symbol":           params.Symbol, | 		"symbol":           params.Symbol, | ||||||
| 		"side":             side, | 		"side":             side, | ||||||
| 		"quantity":         params.Quantity.String(), |  | ||||||
| 		"type":             orderType, | 		"type":             orderType, | ||||||
| 		"newClientOrderId": params.NewClientOrderId, | 		"newClientOrderId": params.NewClientOrderId, | ||||||
| 		"positionSide":     params.PositionSide, | 		"positionSide":     params.PositionSide, | ||||||
| @ -64,6 +63,10 @@ func (e *FuturesResetV2) OrderPlace(apiUserInfo *DbModels.LineApiUser, params Fu | |||||||
| 		paramsMaps["timeInForce"] = "GTC" | 		paramsMaps["timeInForce"] = "GTC" | ||||||
| 		paramsMaps["stopprice"] = params.Profit.String() | 		paramsMaps["stopprice"] = params.Profit.String() | ||||||
| 		paramsMaps["workingType"] = "MARK_PRICE" | 		paramsMaps["workingType"] = "MARK_PRICE" | ||||||
|  |  | ||||||
|  | 		if params.ClosePosition { | ||||||
|  | 			paramsMaps["closePosition"] = "true" | ||||||
|  | 		} | ||||||
| 	case "TAKE_PROFIT": | 	case "TAKE_PROFIT": | ||||||
| 		paramsMaps["price"] = params.Price.String() | 		paramsMaps["price"] = params.Price.String() | ||||||
| 		paramsMaps["stopprice"] = params.Profit.String() | 		paramsMaps["stopprice"] = params.Profit.String() | ||||||
| @ -72,6 +75,10 @@ func (e *FuturesResetV2) OrderPlace(apiUserInfo *DbModels.LineApiUser, params Fu | |||||||
| 		paramsMaps["stopprice"] = params.StopPrice.String() | 		paramsMaps["stopprice"] = params.StopPrice.String() | ||||||
| 		paramsMaps["workingType"] = "MARK_PRICE" | 		paramsMaps["workingType"] = "MARK_PRICE" | ||||||
| 		paramsMaps["timeInForce"] = "GTC" | 		paramsMaps["timeInForce"] = "GTC" | ||||||
|  |  | ||||||
|  | 		if params.ClosePosition { | ||||||
|  | 			paramsMaps["closePosition"] = "true" | ||||||
|  | 		} | ||||||
| 	case "STOP": | 	case "STOP": | ||||||
| 		paramsMaps["price"] = params.Price.String() | 		paramsMaps["price"] = params.Price.String() | ||||||
| 		paramsMaps["stopprice"] = params.StopPrice.String() | 		paramsMaps["stopprice"] = params.StopPrice.String() | ||||||
| @ -79,6 +86,10 @@ func (e *FuturesResetV2) OrderPlace(apiUserInfo *DbModels.LineApiUser, params Fu | |||||||
| 		paramsMaps["timeInForce"] = "GTC" | 		paramsMaps["timeInForce"] = "GTC" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	//不是平仓 | ||||||
|  | 	if !params.ClosePosition { | ||||||
|  | 		paramsMaps["quantity"] = params.Quantity.String() | ||||||
|  | 	} | ||||||
| 	// 获取 API 信息和发送下单请求 | 	// 获取 API 信息和发送下单请求 | ||||||
| 	client := GetClient(apiUserInfo) | 	client := GetClient(apiUserInfo) | ||||||
| 	_, statusCode, err := client.SendFuturesRequestAuth("/fapi/v1/order", "POST", paramsMaps) | 	_, statusCode, err := client.SendFuturesRequestAuth("/fapi/v1/order", "POST", paramsMaps) | ||||||
| @ -99,7 +110,7 @@ func parseOrderError(err error, paramsMaps map[string]string, statusCode int, ap | |||||||
| 			log.Error("下单失败 参数:", paramsVal) | 			log.Error("下单失败 参数:", paramsVal) | ||||||
| 			errContent := FutErrorMaps[code.(float64)] | 			errContent := FutErrorMaps[code.(float64)] | ||||||
| 			if errContent == "" { | 			if errContent == "" { | ||||||
| 				errContent = err.Error() | 				errContent, _ = dataMap["msg"].(string) | ||||||
| 			} | 			} | ||||||
| 			return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, paramsMaps["symbol"], errContent) | 			return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, paramsMaps["symbol"], errContent) | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -784,6 +784,27 @@ func (e FutRestApi) CancelAllFutOrder(apiUserInfo DbModels.LineApiUser, symbol s | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 带重试的批量撤销订单 | ||||||
|  | func (e FutRestApi) CancelBatchFutOrderLoop(apiUserInfo DbModels.LineApiUser, symbol string, newClientOrderIdList []string) error { | ||||||
|  | 	opts := retryhelper.DefaultRetryOptions() | ||||||
|  | 	opts.RetryableErrFn = func(err error) bool { | ||||||
|  | 		if strings.Contains(err.Error(), "LOT_SIZE") { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		//重试 | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err := retryhelper.Retry(func() error { | ||||||
|  | 		return e.CancelBatchFutOrder(apiUserInfo, symbol, newClientOrderIdList) | ||||||
|  | 	}, opts) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // CancelBatchFutOrder 批量撤销订单 | // CancelBatchFutOrder 批量撤销订单 | ||||||
| // symbol 交易对 | // symbol 交易对 | ||||||
| // newClientOrderIdList 系统自定义的订单号, 最多支持10个订单 | // newClientOrderIdList 系统自定义的订单号, 最多支持10个订单 | ||||||
|  | |||||||
| @ -70,36 +70,6 @@ func ChangeFutureOrder(mapData map[string]interface{}, apiKey string) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Errorf("合约订单回调失败,反单失败:%v", err) | 		logger.Errorf("合约订单回调失败,反单失败:%v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// 以前的下单逻辑 |  | ||||||
| 	// 查询订单 |  | ||||||
| 	// preOrder, err := getPreOrder(db, orderSn) |  | ||||||
| 	// if err != nil { |  | ||||||
| 	// 	logger.Error("合约订单回调失败,查询订单失败:", orderSn, " err:", err) |  | ||||||
| 	// 	return |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	// // 解析订单状态 |  | ||||||
| 	// status, ok := mapData["X"].(string) |  | ||||||
| 	// if !ok { |  | ||||||
| 	// 	mapStr, _ := sonic.Marshal(&mapData) |  | ||||||
| 	// 	logger.Error("订单回调失败,没有状态:", string(mapStr)) |  | ||||||
| 	// 	return |  | ||||||
| 	// } |  | ||||||
| 	// // 更新订单状态 |  | ||||||
| 	// orderStatus, reason := parseOrderStatus(status, mapData) |  | ||||||
|  |  | ||||||
| 	// if orderStatus == 0 { |  | ||||||
| 	// 	logger.Error("订单回调失败,状态错误:", orderSn, " status:", status, " reason:", reason) |  | ||||||
| 	// 	return |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	// if err := updateOrderStatus(db, preOrder, orderStatus, reason, true, mapData); err != nil { |  | ||||||
| 	// 	logger.Error("修改订单状态失败:", orderSn, " err:", err) |  | ||||||
| 	// 	return |  | ||||||
| 	// } |  | ||||||
|  |  | ||||||
| 	// handleFutOrderByType(db, preOrder, orderStatus) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // 合约回调 | // 合约回调 | ||||||
|  | |||||||
| @ -73,6 +73,7 @@ type FutOrderPlace struct { | |||||||
| 	StopPrice        decimal.Decimal `json:"stopprice"`     //止损价格 | 	StopPrice        decimal.Decimal `json:"stopprice"`     //止损价格 | ||||||
| 	OrderType        string          `json:"order_type"`    //订单类型,市价或限价MARKET(市价单) TAKE_PROFIT_MARKET(市价止盈) TAKE_PROFIT(限价止盈) STOP (限价止损)  STOP_MARKET(市价止损) | 	OrderType        string          `json:"order_type"`    //订单类型,市价或限价MARKET(市价单) TAKE_PROFIT_MARKET(市价止盈) TAKE_PROFIT(限价止盈) STOP (限价止损)  STOP_MARKET(市价止损) | ||||||
| 	NewClientOrderId string          `json:"newClientOrderId"` | 	NewClientOrderId string          `json:"newClientOrderId"` | ||||||
|  | 	ClosePosition    bool            `json:"closePosition"` //是否平仓 | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s FutOrderPlace) CheckParams() error { | func (s FutOrderPlace) CheckParams() error { | ||||||
|  | |||||||
| @ -7,7 +7,9 @@ import ( | |||||||
| 	DbModels "go-admin/app/admin/models" | 	DbModels "go-admin/app/admin/models" | ||||||
| 	"go-admin/common/global" | 	"go-admin/common/global" | ||||||
| 	"go-admin/common/helper" | 	"go-admin/common/helper" | ||||||
|  | 	"go-admin/models" | ||||||
| 	"go-admin/pkg/maphelper" | 	"go-admin/pkg/maphelper" | ||||||
|  | 	"go-admin/pkg/utility/snowflakehelper" | ||||||
| 	"go-admin/services/cacheservice" | 	"go-admin/services/cacheservice" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
| @ -68,10 +70,23 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac | |||||||
| 		result, err := e.handleSimpleStatusChange(status, orderSn, mapData) | 		result, err := e.handleSimpleStatusChange(status, orderSn, mapData) | ||||||
|  |  | ||||||
| 		//如果是 新开止盈止损 需要取消反单的止盈止损之后重下反单止盈止损 | 		//如果是 新开止盈止损 需要取消反单的止盈止损之后重下反单止盈止损 | ||||||
| 		if status == "NEW" && (ot == "TAKE_PROFIT_MARKET" || ot == "STOP_LOSS_MARKET" || ot == "TAKE_PROFIT_LIMIT" || ot == "STOP_LOSS_LIMIT") && | 		if status == "NEW" && (ot == "TAKE_PROFIT_MARKET" || ot == "STOP_MARKET" || ot == "TAKE_PROFIT" || ot == "STOP") && | ||||||
| 			apiInfo.ReverseStatus == 1 && apiInfo.OpenStatus == 1 && apiInfo.ReverseApiId > 0 { | 			apiInfo.ReverseStatus == 1 && apiInfo.OpenStatus == 1 && apiInfo.ReverseApiId > 0 { | ||||||
|  | 			symbolCode, err := maphelper.GetString(mapData, "s") | ||||||
|  |  | ||||||
| 			if err := e.ReTakeOrStopOrder(&mapData, orderSn, &apiInfo); err != nil { | 			if err != nil { | ||||||
|  | 				e.Log.Errorf("获取symbolCode失败 symbol:%s err:%v", symbolCode, err) | ||||||
|  | 				return true, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			symbol, err := cacheservice.GetTradeSet(global.EXCHANGE_BINANCE, symbolCode, 1) | ||||||
|  |  | ||||||
|  | 			if err != nil { | ||||||
|  | 				e.Log.Errorf("获取symbol失败 symbol:%s err:%v", symbolCode, err) | ||||||
|  | 				return true, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if err := e.ReTakeOrStopOrder(&mapData, orderSn, &apiInfo, &symbol); err != nil { | ||||||
| 				return true, err | 				return true, err | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -128,6 +143,7 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac | |||||||
| 				return true, err | 				return true, err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			price := maphelper.GetDecimal(mapData, "ap") | ||||||
| 			totalNum := maphelper.GetDecimal(mapData, "z") | 			totalNum := maphelper.GetDecimal(mapData, "z") | ||||||
|  |  | ||||||
| 			mainOrder := DbModels.LineReverseOrder{ | 			mainOrder := DbModels.LineReverseOrder{ | ||||||
| @ -136,6 +152,7 @@ func (e *ReverseService) ReverseOrder(apiKey string, mapData map[string]interfac | |||||||
| 				PositionSide: positionSide, | 				PositionSide: positionSide, | ||||||
| 				TotalNum:     totalNum, | 				TotalNum:     totalNum, | ||||||
| 				Side:         side, | 				Side:         side, | ||||||
|  | 				Price:        price, | ||||||
| 			} | 			} | ||||||
| 			e.changeOrderStatus(3, orderSn, mapData) | 			e.changeOrderStatus(3, orderSn, mapData) | ||||||
|  |  | ||||||
| @ -175,8 +192,8 @@ func (e *ReverseService) changeOrderStatus(status int, orderSn string, mapData m | |||||||
| 			data["order_id"] = orderId | 			data["order_id"] = orderId | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ap, ok := mapData["ap"].(bool); ok { | 		if ap, ok := mapData["ap"].(string); ok { | ||||||
| 			data["final_price"] = ap | 			data["final_price"], _ = decimal.NewFromString(ap) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if num, ok := mapData["z"].(string); ok { | 		if num, ok := mapData["z"].(string); ok { | ||||||
| @ -184,6 +201,10 @@ func (e *ReverseService) changeOrderStatus(status int, orderSn string, mapData m | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data["trigger_time"] = &now | 		data["trigger_time"] = &now | ||||||
|  | 	} else if status == 2 { | ||||||
|  | 		if orderId, ok := mapData["i"].(float64); ok { | ||||||
|  | 			data["order_id"] = orderId | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	db := e.Orm.Model(&DbModels.LineReverseOrder{}). | 	db := e.Orm.Model(&DbModels.LineReverseOrder{}). | ||||||
| @ -284,6 +305,12 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r | |||||||
| 	side := reverseOrder.Side | 	side := reverseOrder.Side | ||||||
| 	totalNum := reverseOrder.TotalNum | 	totalNum := reverseOrder.TotalNum | ||||||
|  |  | ||||||
|  | 	symbol, err1 := cacheservice.GetTradeSet(global.EXCHANGE_BINANCE, reverseOrder.Symbol, 1) | ||||||
|  |  | ||||||
|  | 	if err1 != nil { | ||||||
|  | 		e.Log.Errorf("获取交易对失败 symbol:%s err:%v", reverseOrder.Symbol, err1) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	var querySql string | 	var querySql string | ||||||
| 	sqlStr := "" | 	sqlStr := "" | ||||||
|  |  | ||||||
| @ -310,6 +337,8 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r | |||||||
| 			position.Status = 1 | 			position.Status = 1 | ||||||
| 			position.ReverseStatus = 0 | 			position.ReverseStatus = 0 | ||||||
| 			position.PositionSide = positionSide | 			position.PositionSide = positionSide | ||||||
|  | 			position.AveragePrice = reverseOrder.FinalPrice | ||||||
|  | 			position.PositionNo = snowflakehelper.GetOrderNo() | ||||||
| 		} | 		} | ||||||
| 		querySql = "api_id =? and position_side =? and symbol =? and status =1" | 		querySql = "api_id =? and position_side =? and symbol =? and status =1" | ||||||
|  |  | ||||||
| @ -319,9 +348,9 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r | |||||||
| 			sqlStr = "UPDATE line_reverse_position set amount=@totalNum,updated_at=now(),status=2 where id =@id and status!=2 " | 			sqlStr = "UPDATE line_reverse_position set amount=@totalNum,updated_at=now(),status=2 where id =@id and status!=2 " | ||||||
| 		} else if reducePosition { | 		} else if reducePosition { | ||||||
| 			//只减仓 | 			//只减仓 | ||||||
| 			sqlStr = "UPDATE line_reverse_position set amount=amount - @totalNum,updated_at=now() where id =@id and status!=2 " | 			sqlStr = "UPDATE line_reverse_position set amount=amount - @totalNum,updated_at=now(),average_price=@averagePrice where id =@id and status!=2 " | ||||||
| 		} else { | 		} else { | ||||||
| 			sqlStr = "UPDATE line_reverse_position set total_amount=total_amount + @totalNum,amount=amount + @totalNum,updated_at=now() where id =@id and status!=2" | 			sqlStr = "UPDATE line_reverse_position set total_amount=total_amount + @totalNum,amount=amount + @totalNum,updated_at=now(),average_price=@averagePrice where id =@id and status!=2" | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		querySql = "reverse_api_id =? and position_side =? and symbol =? and reverse_status in (0,1)" | 		querySql = "reverse_api_id =? and position_side =? and symbol =? and reverse_status in (0,1)" | ||||||
| @ -330,12 +359,14 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r | |||||||
| 			totalNum = decimal.Zero | 			totalNum = decimal.Zero | ||||||
| 			sqlStr = "UPDATE line_reverse_position set reverse_amount=@totalNum,updated_at=now(),reverse_status=2 where id =@id and reverse_status !=2" | 			sqlStr = "UPDATE line_reverse_position set reverse_amount=@totalNum,updated_at=now(),reverse_status=2 where id =@id and reverse_status !=2" | ||||||
| 		} else if reducePosition { | 		} else if reducePosition { | ||||||
| 			sqlStr = "UPDATE line_reverse_position set reverse_amount=reverse_amount - @totalNum,updated_at=now() where id =@id and reverse_status !=2" | 			sqlStr = "UPDATE line_reverse_position set reverse_amount=reverse_amount - @totalNum,updated_at=now(),reverse_average_price=@averagePrice where id =@id and reverse_status !=2" | ||||||
| 		} else { | 		} else { | ||||||
| 			sqlStr = "UPDATE line_reverse_position set total_reverse_amount=total_reverse_amount + @totalNum,reverse_amount=reverse_amount + @totalNum,updated_at=now(),reverse_status =1 where id =@id and reverse_status !=2" | 			sqlStr = "UPDATE line_reverse_position set total_reverse_amount=total_reverse_amount + @totalNum,reverse_amount=reverse_amount + @totalNum,updated_at=now(),reverse_status =1,reverse_average_price=@averagePrice where id =@id and reverse_status !=2" | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	var averagePrice decimal.Decimal | ||||||
|  |  | ||||||
| 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | ||||||
| 		err1 := tx.Model(&position).Where(querySql, | 		err1 := tx.Model(&position).Where(querySql, | ||||||
| 			reverseOrder.ApiId, positionSide, reverseOrder.Symbol).First(&position).Error | 			reverseOrder.ApiId, positionSide, reverseOrder.Symbol).First(&position).Error | ||||||
| @ -347,16 +378,69 @@ func (e *ReverseService) savePosition(reverseOrder *DbModels.LineReverseOrder, r | |||||||
| 				if err2 := tx.Create(&position).Error; err2 != nil { | 				if err2 := tx.Create(&position).Error; err2 != nil { | ||||||
| 					return err2 | 					return err2 | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				averagePrice = position.AveragePrice | ||||||
| 			} else { | 			} else { | ||||||
| 				return err1 | 				return err1 | ||||||
| 			} | 			} | ||||||
|  | 		} else { | ||||||
|  | 			var totalAmount decimal.Decimal | ||||||
|  | 			var totalPrice decimal.Decimal | ||||||
|  | 			if !position.Amount.IsZero() && !position.AveragePrice.IsZero() { | ||||||
|  | 				if isMain { | ||||||
|  | 					totalPrice = position.Amount.Mul(position.AveragePrice) | ||||||
|  | 					totalAmount = position.Amount | ||||||
|  | 				} else { | ||||||
|  | 					totalPrice = position.ReverseAmount.Mul(position.ReverseAveragePrice) | ||||||
|  | 					totalAmount = position.ReverseAmount | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				//加仓 | ||||||
|  | 				if !reducePosition { | ||||||
|  | 					totalPrice = totalPrice.Add(reverseOrder.Price.Mul(reverseOrder.TotalNum)) | ||||||
|  | 					totalAmount = totalAmount.Add(reverseOrder.TotalNum) | ||||||
|  | 				} else if reducePosition && !closePosition { | ||||||
|  | 					//只减仓 | ||||||
|  | 					totalPrice = totalPrice.Sub(reverseOrder.Price.Mul(reverseOrder.TotalNum)) | ||||||
|  | 					totalAmount = totalAmount.Sub(reverseOrder.TotalNum) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if totalAmount.IsZero() || totalPrice.IsZero() { | ||||||
|  | 				if isMain { | ||||||
|  | 					averagePrice = position.AveragePrice | ||||||
|  | 				} else { | ||||||
|  | 					if position.ReverseAveragePrice.IsZero() { | ||||||
|  | 						averagePrice = reverseOrder.Price | ||||||
|  | 					} else { | ||||||
|  | 						averagePrice = position.ReverseAveragePrice | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				//平仓 | ||||||
|  | 				if closePosition { | ||||||
|  | 					if isMain { | ||||||
|  | 						averagePrice = position.AveragePrice | ||||||
|  | 					} else { | ||||||
|  | 						averagePrice = position.ReverseAveragePrice | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					averagePrice = totalPrice.Div(totalAmount).Truncate(int32(symbol.PriceDigit)) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		dbResult := tx.Exec(sqlStr, sql.Named("totalNum", totalNum), sql.Named("id", position.Id)) | 		//关联订单的仓位id | ||||||
|  | 		if err2 := tx.Exec("UPDATE line_reverse_order set position_id=@positionId where id=@orderId and position_id = 0", sql.Named("positionId", position.Id), sql.Named("orderId", reverseOrder.Id)).Error; err2 != nil { | ||||||
|  | 			return err2 | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		dbResult := tx.Exec(sqlStr, sql.Named("totalNum", totalNum), sql.Named("id", position.Id), sql.Named("averagePrice", averagePrice)) | ||||||
| 		if dbResult.Error != nil { | 		if dbResult.Error != nil { | ||||||
| 			return dbResult.Error | 			return dbResult.Error | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		reverseOrder.PositionId = position.Id | ||||||
| 		if dbResult.RowsAffected == 0 { | 		if dbResult.RowsAffected == 0 { | ||||||
| 			e.Log.Errorf("减仓数据 是否平仓单:%v :%v", closePosition, reverseOrder) | 			e.Log.Errorf("减仓数据 是否平仓单:%v :%v", closePosition, reverseOrder) | ||||||
| 			return errors.New("没有找到对应的持仓信息") | 			return errors.New("没有找到对应的持仓信息") | ||||||
| @ -471,8 +555,8 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder, | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//反向下单百分比 | 		//反向下单百分比 | ||||||
| 		proportion = proportion.Div(decimal.NewFromInt(100)).Truncate(2) | 		proportion = proportion.Div(decimal.NewFromInt(100)).Truncate(4) | ||||||
| 		amount = mainOrder.BuyPrice.Mul(proportion).Div(price).Truncate(int32(symbol.AmountDigit)) | 		amount = mainOrder.TotalNum.Mul(proportion).Truncate(int32(symbol.AmountDigit)) | ||||||
|  |  | ||||||
| 		if amount.Cmp(decimal.Zero) <= 0 { | 		if amount.Cmp(decimal.Zero) <= 0 { | ||||||
| 			e.Log.Errorf("计算数量失败 symbol:%s custom:%s 数量小于0", mainOrder.Symbol, mainOrder.OrderSn) | 			e.Log.Errorf("计算数量失败 symbol:%s custom:%s 数量小于0", mainOrder.Symbol, mainOrder.OrderSn) | ||||||
| @ -487,6 +571,7 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder, | |||||||
| 	order.Status = 1 | 	order.Status = 1 | ||||||
| 	order.Type = setting.ReverseOrderType | 	order.Type = setting.ReverseOrderType | ||||||
| 	order.SignPrice = signPrice | 	order.SignPrice = signPrice | ||||||
|  | 	order.PositionId = mainOrder.PositionId | ||||||
|  |  | ||||||
| 	if order.Remark != "" { | 	if order.Remark != "" { | ||||||
| 		order.Status = 8 | 		order.Status = 8 | ||||||
| @ -498,12 +583,64 @@ func (e *ReverseService) DoAddReverseOrder(mainOrder *DbModels.LineReverseOrder, | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if order.Status == 1 { | 	if order.Status == 1 { | ||||||
| 		e.DoBianceOrder(&order, reverseApiInfo, &setting, reducePosition, closePosition) | 		err = e.DoBianceOrder(&order, reverseApiInfo, &setting, reducePosition, closePosition) | ||||||
|  |  | ||||||
|  | 		//Biance下单成共 且为平仓单时 取消止盈止损 | ||||||
|  | 		if err == nil && closePosition { | ||||||
|  | 			e.DoCancelTakeProfitBatch(symbol.GetSymbol(), order.PositionSide, order.Side, -1, reverseApiInfo) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 取消止盈止损订单 | ||||||
|  | // symbol: 交易对 | ||||||
|  | // positionSide: 持仓方向 | ||||||
|  | // side: 订单方向 | ||||||
|  | // orderType: 订单类型 -1-全部 1-止盈 2-止损 | ||||||
|  | // apiInfo: 下单api | ||||||
|  | func (e *ReverseService) DoCancelTakeProfitBatch(symbol, positionSide, side string, orderType int, apiInfo *DbModels.LineApiUser) error { | ||||||
|  | 	orderSns := e.GetTakeProfitBatch(symbol, positionSide, side, apiInfo.Id, orderType) | ||||||
|  |  | ||||||
|  | 	if len(orderSns) == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(orderSns) > 0 { | ||||||
|  | 		futApi := FutRestApi{} | ||||||
|  | 		err := futApi.CancelBatchFutOrderLoop(*apiInfo, symbol, orderSns) | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			e.Log.Errorf("币安撤单失败 symbol:%s custom:%v :%v", symbol, orderSns, err) | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 获取止盈止损订单 | ||||||
|  | // symbol: 交易对 | ||||||
|  | // positionSide: 持仓方向 | ||||||
|  | // side: 订单方向 | ||||||
|  | // apiId: 币安apiId | ||||||
|  | // orderType: 订单类型 -1-全部 1-止盈 2-止损 | ||||||
|  | func (e *ReverseService) GetTakeProfitBatch(symbol, positionSide, side string, apiId int, orderType int) []string { | ||||||
|  | 	var orderSns []string | ||||||
|  | 	orderTypes := []int{1, 2} | ||||||
|  |  | ||||||
|  | 	if orderType == 1 { | ||||||
|  | 		orderTypes = []int{1} | ||||||
|  | 	} else if orderType == 2 { | ||||||
|  | 		orderTypes = []int{2} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	e.Orm.Model(&DbModels.LineReverseOrder{}).Where("symbol =? and position_side =? and side = ? and status =2 and order_type in ?", symbol, positionSide, side, orderTypes).Pluck("order_sn", &orderSns) | ||||||
|  |  | ||||||
|  | 	return orderSns | ||||||
|  | } | ||||||
|  |  | ||||||
| // 处理币安订单 | // 处理币安订单 | ||||||
| // order: 反单信息 | // order: 反单信息 | ||||||
| // apiInfo: 币安api信息 | // apiInfo: 币安api信息 | ||||||
| @ -546,13 +683,8 @@ func (e *ReverseService) DoBianceOrder(order *DbModels.LineReverseOrder, apiInfo | |||||||
|  |  | ||||||
| // 重下止盈止损 | // 重下止盈止损 | ||||||
| // mapData: 主单止盈止损回调 | // mapData: 主单止盈止损回调 | ||||||
| func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orderSn string, mainApiInfo *DbModels.LineApiUser) error { | func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orderSn string, mainApiInfo *DbModels.LineApiUser, symbol *models.TradeSet) error { | ||||||
| 	symbol, err := maphelper.GetString(*mapData, "s") | 	orderType := 0 //订单类型 1-止盈 2-止损 | ||||||
|  |  | ||||||
| 	if err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	side, err := maphelper.GetString(*mapData, "S") | 	side, err := maphelper.GetString(*mapData, "S") | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -584,6 +716,12 @@ func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orde | |||||||
| 		positionSide = "LONG" | 		positionSide = "LONG" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	close := maphelper.GetBool(*mapData, "cp") | ||||||
|  | 	stopPrice := maphelper.GetDecimal(*mapData, "sp") | ||||||
|  | 	if stopPrice.IsZero() { | ||||||
|  | 		e.Log.Errorf("获取止盈止损单触发价失败 symbol:%s custom:%s :%v", symbol, orderSn, err) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
| 	apiInfo, err := GetApiInfo(mainApiInfo.ReverseApiId) | 	apiInfo, err := GetApiInfo(mainApiInfo.ReverseApiId) | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -591,33 +729,96 @@ func (e *ReverseService) ReTakeOrStopOrder(mapData *map[string]interface{}, orde | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var reverseOrder DbModels.LineReverseOrder | 	switch ot { | ||||||
| 	e.Orm.Model(&DbModels.LineReverseOrder{}). | 	case "STOP_MARKET", "STOP": | ||||||
| 		Where("symbol =? and api_id =? and position_side =? and side = ? and status =1", symbol, mainApiInfo.ReverseApiId, positionSide, side). | 		orderType = 2 | ||||||
| 		First(&reverseOrder) | 	case "TAKE_PROFIT_MARKET", "TAKE_PROFIT": | ||||||
|  | 		orderType = 1 | ||||||
| 	//取消旧止盈止损 | 	default: | ||||||
| 	if reverseOrder.OrderSn != "" { | 		return fmt.Errorf("不支持的订单类型 ot:%s", ot) | ||||||
| 		futApi := FutRestApi{} |  | ||||||
| 		err := futApi.CancelFutOrderRetry(apiInfo, symbol, reverseOrder.OrderSn) |  | ||||||
|  |  | ||||||
| 		if err != nil { |  | ||||||
| 			e.Log.Errorf("币安撤单失败 symbol:%s custom:%s :%v", symbol, orderSn, err) |  | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	var reversePosition DbModels.LineReversePosition | ||||||
|  |  | ||||||
|  | 	e.Orm.Model(&reversePosition). | ||||||
|  | 		Where("symbol =? and reverse_api_id =? and position_side =? and reverse_status =1", symbol.GetSymbol(), apiInfo.Id, positionSide). | ||||||
|  | 		First(&reversePosition) | ||||||
|  |  | ||||||
|  | 	if reversePosition.Id == 0 { | ||||||
|  | 		e.Log.Errorf("获取反单持仓失败 symbol:%s custom:%s :%v", symbol, orderSn, err) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mainPercent := decimal.NewFromInt(1) | ||||||
|  |  | ||||||
|  | 	if !stopPrice.IsZero() && !reversePosition.AveragePrice.IsZero() { | ||||||
|  | 		mainPercent = stopPrice.Div(reversePosition.AveragePrice) | ||||||
|  | 		mainPercent = (mainPercent.Sub(decimal.NewFromInt(1))).Abs().Truncate(4) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var percent decimal.Decimal | ||||||
|  | 	switch { | ||||||
|  | 	//做多止损 | ||||||
|  | 	case orderType == 2 && positionSide == "LONG", orderType == 1 && positionSide == "SHORT": | ||||||
|  | 		percent = decimal.NewFromInt(1).Sub(mainPercent) | ||||||
|  | 	case orderType == 2 && positionSide == "SHORT", orderType == 1 && positionSide == "LONG": | ||||||
|  | 		percent = decimal.NewFromInt(1).Add(mainPercent) | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("不支持的订单类型 ot:%s, ps:%s", ot, positionSide) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	now := time.Now() | ||||||
|  | 	price := reversePosition.AveragePrice.Mul(percent).Truncate(int32(symbol.PriceDigit)) | ||||||
|  | 	lastPrice, _ := decimal.NewFromString(symbol.LastPrice) | ||||||
|  | 	newOrder := DbModels.LineReverseOrder{ | ||||||
|  | 		PositionId:    reversePosition.Id, | ||||||
|  | 		OrderSn:       helper.GetOrderNo(), | ||||||
|  | 		OrderType:     orderType, | ||||||
|  | 		Status:        1, | ||||||
|  | 		Price:         price, | ||||||
|  | 		TotalNum:      reversePosition.TotalReverseAmount, | ||||||
|  | 		Symbol:        symbol.GetSymbol(), | ||||||
|  | 		Side:          side, | ||||||
|  | 		PositionSide:  positionSide, | ||||||
|  | 		FollowOrderSn: orderSn, | ||||||
|  | 		Type:          ot, | ||||||
|  | 		SignPrice:     lastPrice, | ||||||
|  | 		Category:      1, | ||||||
|  | 		ApiId:         apiInfo.Id, | ||||||
|  | 		IsAddPosition: 2, | ||||||
|  | 		TriggerTime:   &now, | ||||||
|  | 		BuyPrice:      reversePosition.TotalReverseAmount.Mul(price).Truncate(int32(symbol.PriceDigit)), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err1 := e.Orm.Create(&newOrder).Error; err1 != nil { | ||||||
|  | 		e.Log.Errorf("保存反单止盈止损失败 symbol:%s custom:%s :%v", symbol, orderSn, err1) | ||||||
|  | 		return err1 | ||||||
|  | 	} | ||||||
| 	params := FutOrderPlace{ | 	params := FutOrderPlace{ | ||||||
| 		ApiId:            apiInfo.Id, | 		ApiId:            apiInfo.Id, | ||||||
| 		Symbol:           symbol, | 		Symbol:           symbol.GetSymbol(), | ||||||
| 		PositionSide:     positionSide, | 		PositionSide:     positionSide, | ||||||
| 		Side:             side, | 		Side:             side, | ||||||
| 		OrderType:        ot, | 		OrderType:        ot, | ||||||
| 		Quantity:         reverseOrder.TotalNum, | 		Quantity:         reversePosition.TotalReverseAmount, | ||||||
| 		Price:            reverseOrder.Price, | 		Price:            price, | ||||||
| 		NewClientOrderId: reverseOrder.OrderSn, | 		StopPrice:        price, | ||||||
|  | 		Profit:           price, | ||||||
|  | 		NewClientOrderId: newOrder.OrderSn, | ||||||
|  | 		ClosePosition:    close, | ||||||
| 	} | 	} | ||||||
| 	futApiV2 := FuturesResetV2{Service: e.Service} | 	futApiV2 := FuturesResetV2{Service: e.Service} | ||||||
| 	futApiV2.OrderPlace(&apiInfo, params) | 	err = futApiV2.OrderPlaceLoop(&apiInfo, params) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		e.Log.Errorf("币安下单失败 symbol:%s custom:%s :%v", symbol.GetSymbol(), orderSn, err) | ||||||
|  |  | ||||||
|  | 		if err1 := e.Orm.Model(&newOrder).Updates(map[string]interface{}{"status": 8, "remark": err.Error(), "updated_at": time.Now()}).Error; err1 != nil { | ||||||
|  | 			e.Log.Errorf("更新订单状态失败 symbol:%s custom:%s :%v", newOrder.Symbol, newOrder.OrderSn, err1) | ||||||
|  | 		} | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	e.DoCancelTakeProfitBatch(symbol.GetSymbol(), positionSide, side, orderType, &apiInfo) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -1 +1,34 @@ | |||||||
| package binanceservice | package binanceservice | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"go-admin/common/helper" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/bytedance/sonic" | ||||||
|  | 	"github.com/go-admin-team/go-admin-core/logger" | ||||||
|  | 	"github.com/go-admin-team/go-admin-core/sdk" | ||||||
|  | 	"gorm.io/driver/mysql" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func initConfig() *gorm.DB { | ||||||
|  | 	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") | ||||||
|  |  | ||||||
|  | 	return db | ||||||
|  | } | ||||||
|  | func TestReverseOrder(t *testing.T) { | ||||||
|  | 	db := initConfig() | ||||||
|  | 	mapData := make(map[string]interface{}) | ||||||
|  | 	content := `{"s":"ADAUSDT","c":"439301585084878848","S":"SELL","o":"LIMIT","f":"GTC","q":"8","p":"0.7781","ap":"0.7843","sp":"0","x":"TRADE","X":"FILLED","i":56468022240,"l":"8","z":"8","L":"0.7843","n":"0.0031372","N":"USDT","T":1753950025820,"t":1642816051,"b":"0","a":"0","m":false,"R":false,"wt":"CONTRACT_PRICE","ot":"LIMIT","ps":"SHORT","cp":false,"rp":"0","pP":false,"si":0,"ss":0,"V":"EXPIRE_MAKER","pm":"NONE","gtd":0}` | ||||||
|  | 	sonic.Unmarshal([]byte(content), &mapData) | ||||||
|  |  | ||||||
|  | 	service := ReverseService{} | ||||||
|  | 	service.Orm = db | ||||||
|  | 	service.Log = logger.NewHelper(logger.DefaultLogger) | ||||||
|  |  | ||||||
|  | 	service.ReverseOrder("c8ej2vxXzNUIlCjQCmU1iavK8LG78uZaXY3CIT4kz0PuhnXycg44HsVAbsqupHTw", mapData) | ||||||
|  | } | ||||||
|  | |||||||
| @ -522,7 +522,7 @@ func (wm *BinanceWebSocketManager) Stop() { | |||||||
|  |  | ||||||
| // 重连机制 | // 重连机制 | ||||||
| func (wm *BinanceWebSocketManager) handleReconnect(ctx context.Context) { | func (wm *BinanceWebSocketManager) handleReconnect(ctx context.Context) { | ||||||
| 	maxRetries := 5 // 最大重试次数 | 	maxRetries := 100 // 最大重试次数 | ||||||
| 	retryCount := 0 | 	retryCount := 0 | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user