diff --git a/app/admin/apis/line_pre_order.go b/app/admin/apis/line_pre_order.go index 735983a..95bbacc 100644 --- a/app/admin/apis/line_pre_order.go +++ b/app/admin/apis/line_pre_order.go @@ -498,41 +498,6 @@ func (e LinePreOrder) ClearAll(c *gin.Context) { e.OK(nil, "操作成功") } -// ManuallyCover 手动加仓 -func (e LinePreOrder) ManuallyCover(c *gin.Context) { - s := service.LinePreOrder{} - req := dto.ManuallyCover{} - err := e.MakeContext(c). - MakeOrm(). - Bind(&req). - MakeService(&s.Service). - Errors - if err != nil { - e.Logger.Error(err) - e.Error(500, err, err.Error()) - return - } - err = req.CheckParams() - if err != nil { - e.Logger.Error(err) - e.Error(500, err, err.Error()) - return - } - p := actions.GetPermissionFromContext(c) - errs := make([]error, 0) - errStr := make([]string, 0) - - s.ManuallyCover(req, p, &errs) - if len(errs) > 0 { - for _, err2 := range errs { - errStr = append(errStr, err2.Error()) - } - e.Error(500, nil, strings.Join(errStr, ",")) - return - } - e.OK(nil, "操作成功") -} - // ClosePosition 平仓 func (e LinePreOrder) ClosePosition(c *gin.Context) { s := service.LinePreOrder{} diff --git a/app/admin/models/line_pre_order.go b/app/admin/models/line_pre_order.go index f6bd75a..bc8c082 100644 --- a/app/admin/models/line_pre_order.go +++ b/app/admin/models/line_pre_order.go @@ -9,34 +9,38 @@ import ( type LinePreOrder struct { models.Model - ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 (字典 exchange_type)"` - Pid int `json:"pid" gorm:"type:int unsigned;omitempty;comment:pid"` - ApiId int `json:"apiId" gorm:"type:varchar(255);omitempty;comment:api用户"` - GroupId string `json:"groupId" gorm:"type:int unsigned;omitempty;comment:交易对组id"` - Symbol string `json:"symbol" gorm:"type:varchar(255);omitempty;comment:交易对"` - QuoteSymbol string `json:"quoteSymbol" gorm:"type:varchar(255);omitempty;comment:计较货币"` - SignPrice string `json:"signPrice" gorm:"type:decimal(18,8);omitempty;comment:对标价"` - SignPriceU decimal.Decimal `json:"signPriceU" gorm:"type:decimal(18,8);omitempty;comment:交易对对标U的行情价"` - SignPriceType string `json:"signPriceType" gorm:"type:enum('new','tall','low','mixture','entrust','add');omitempty;comment:对标价类型: new=最新价格;tall=24小时最高;low=24小时最低;mixture=标记价;entrust=委托实价;add=补仓"` - Rate string `json:"rate" gorm:"type:decimal(18,2);omitempty;comment:下单百分比"` - Price string `json:"price" gorm:"type:decimal(18,8);omitempty;comment:触发价格"` - Num string `json:"num" gorm:"type:decimal(18,8);omitempty;comment:购买数量"` - BuyPrice string `json:"buyPrice" gorm:"type:decimal(18,8);omitempty;comment:购买金额"` - SymbolType int `json:"symbolType" gorm:"type:int;comment:交易对类型:1=现货;2=合约"` - Site string `json:"site" gorm:"type:enum('BUY','SELL');omitempty;comment:购买方向:BUY=买;SELL=卖"` - OrderSn string `json:"orderSn" gorm:"type:varchar(255);omitempty;comment:订单号"` - OrderType int `json:"orderType" gorm:"type:int;omitempty;comment:订单类型:0=主单 1=止盈 2=止损 3=平仓"` - Desc string `json:"desc" gorm:"type:text;omitempty;comment:订单描述"` - Status int `json:"status" gorm:"type:int;omitempty;comment:是否被触发:0=待触发;1=已触发;2=下单失败;4=已取消;5=委托中;6=已成交;9=已平仓"` - AdminId string `json:"adminId" gorm:"type:int unsigned;omitempty;comment:操作管理员id"` - CloseType int `json:"closeType" gorm:"type:int unsigned;omitempty;comment:平仓类型 是否为盈利平仓 1= 是 0 =否"` - CoverType int `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"` - ExpireTime time.Time `json:"expireTime" gorm:"comment:过期时间"` - MainOrderType string `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价(LIMIT)市价(MARKET)"` - HedgeOrderType string `json:"hedgeOrderType" gorm:"type:enum;comment:第二笔类型 限价(LIMIT)市价(MARKET)"` - Child []LinePreOrder `json:"child" gorm:"-"` - ApiName string `json:"api_name" gorm:"->"` - ChildNum int64 `json:"child_num" gorm:"->"` + ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 (字典 exchange_type)"` + Pid int `json:"pid" gorm:"type:int unsigned;omitempty;comment:pid"` + ApiId int `json:"apiId" gorm:"type:varchar(255);omitempty;comment:api用户"` + GroupId string `json:"groupId" gorm:"type:int unsigned;omitempty;comment:交易对组id"` + Symbol string `json:"symbol" gorm:"type:varchar(255);omitempty;comment:交易对"` + QuoteSymbol string `json:"quoteSymbol" gorm:"type:varchar(255);omitempty;comment:计较货币"` + SignPrice string `json:"signPrice" gorm:"type:decimal(18,8);omitempty;comment:对标价"` + SignPriceU decimal.Decimal `json:"signPriceU" gorm:"type:decimal(18,8);omitempty;comment:交易对对标U的行情价"` + SignPriceType string `json:"signPriceType" gorm:"type:enum('new','tall','low','mixture','entrust','add');omitempty;comment:对标价类型: new=最新价格;tall=24小时最高;low=24小时最低;mixture=标记价;entrust=委托实价;add=补仓"` + Rate string `json:"rate" gorm:"type:decimal(18,2);omitempty;comment:下单百分比"` + Price string `json:"price" gorm:"type:decimal(18,8);omitempty;comment:触发价格"` + Num string `json:"num" gorm:"type:decimal(18,8);omitempty;comment:购买数量"` + BuyPrice string `json:"buyPrice" gorm:"type:decimal(18,8);omitempty;comment:购买金额"` + SymbolType int `json:"symbolType" gorm:"type:int;comment:交易对类型:1=现货;2=合约"` + OrderCategory int `json:"orderCategory" gorm:"type:int;comment:订单类型: 1=主单 2=对冲单"` + Site string `json:"site" gorm:"type:enum('BUY','SELL');omitempty;comment:购买方向:BUY=买;SELL=卖"` + OrderSn string `json:"orderSn" gorm:"type:varchar(255);omitempty;comment:订单号"` + OrderType int `json:"orderType" gorm:"type:int;omitempty;comment:订单类型:0=主单 1=止盈 2=止损 3=平仓"` + Desc string `json:"desc" gorm:"type:text;omitempty;comment:订单描述"` + Status int `json:"status" gorm:"type:int;omitempty;comment:是否被触发:0=待触发;1=已触发;2=下单失败;4=已取消;5=委托中;6=已成交;9=已平仓"` + AdminId string `json:"adminId" gorm:"type:int unsigned;omitempty;comment:操作管理员id"` + CloseType int `json:"closeType" gorm:"type:int unsigned;omitempty;comment:平仓类型 是否为盈利平仓 1= 是 0 =否"` + CoverType int `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"` + ExpireTime time.Time `json:"expireTime" gorm:"comment:过期时间"` + MainOrderType string `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价(LIMIT)市价(MARKET)"` + HedgeBuyTotal decimal.Decimal `json:"hedgeBuyTotal" gorm:"type:decimal(10,2);comment:对冲买总金额U"` + HedgeOrderType string `json:"hedgeOrderType" gorm:"type:enum;comment:第二笔类型 限价(LIMIT)市价(MARKET)"` + HedgeTakeProfit decimal.Decimal `json:"hedgeTakeProfit" gorm:"type:decimal(10,2);comment:对冲止盈百分比"` + HedgeStopLoss decimal.Decimal `json:"hedgeStopLoss" gorm:"type:decimal(10,2);comment:对冲止损百分比"` + Child []LinePreOrder `json:"child" gorm:"-"` + ApiName string `json:"api_name" gorm:"->"` + ChildNum int64 `json:"child_num" gorm:"->"` // LinePreOrder 线上预埋单\ models.ModelTime models.ControlBy diff --git a/app/admin/models/line_system_setting.go b/app/admin/models/line_system_setting.go index 71133e2..9cc3077 100644 --- a/app/admin/models/line_system_setting.go +++ b/app/admin/models/line_system_setting.go @@ -9,20 +9,11 @@ import ( type LineSystemSetting struct { models.Model - Time int64 `json:"time" gorm:"type:int;comment:导入:挂单时长达到时间后失效"` - BatchTime int64 `json:"batchTime" gorm:"type:int;comment:批量:挂单时长达到时间后失效"` - ProfitRate string `json:"profitRate" gorm:"type:decimal(10,2);comment:平仓盈利比例"` - CoverOrderTypeBRate string `json:"coverOrderTypeBRate" gorm:"type:decimal(10,2);comment:b账户限价补单的买入百分比"` - ScaleOrderTypeARate string `json:"scaleOrderTypeARate" gorm:"type:decimal(10,2);comment:a账户限价加仓买入百分比"` - ScaleOrderTypeBRate string `json:"scaleOrderTypeBRate" gorm:"type:decimal(10,2);comment:b账户限价加仓买入百分比"` - ScaleUnrealizedProfitRate string `json:"scaleUnrealizedProfitRate" gorm:"type:decimal(10,5) unsigned;comment:亏损百分比加仓"` - ScaleType int `json:"scaleType" gorm:"type:int;comment:加仓类型 1-百分比 2-数值"` - ScaleNum string `json:"scaleNum" gorm:"type:decimal(18,2) unsigned;comment:加仓数值"` - ScaleSubordinate int64 `json:"scaleSubordinate" gorm:"type:int unsigned;comment:加仓账户:1=A账户;2=副账户;3=都加"` - AutoScaleTimes int64 `json:"autoScaleTimes" gorm:"type:int unsigned;comment:自动加仓次数"` - HedgePerformance decimal.Decimal `json:"hedgePerformance" gorm:"type:decimal(5,2);comment:对冲平仓涨跌幅"` - ProtectHedgeRate decimal.Decimal `json:"protectHedgeRate" gorm:"type:decimal(5,2);comment:保护对冲触发百分比"` - ProtectHedgeEnable int `json:"protectHedgeEnable" gorm:"type:int;comment:是否只开启保护对冲 1-开启 0-关闭"` + Time int64 `json:"time" gorm:"type:int;comment:导入:挂单时长达到时间后失效"` + BatchTime int64 `json:"batchTime" gorm:"type:int;comment:批量:挂单时长达到时间后失效"` + ProfitRate string `json:"profitRate" gorm:"type:decimal(10,2);comment:平仓盈利比例"` + CoverOrderTypeBRate string `json:"coverOrderTypeBRate" gorm:"type:decimal(10,2);comment:b账户限价补单的买入百分比"` + StopLossPremium decimal.Decimal `json:"stopLossPremium" gorm:"type:decimal(10,2);comment:限价止损溢价百分比"` models.ModelTime models.ControlBy } diff --git a/app/admin/router/line_pre_order.go b/app/admin/router/line_pre_order.go index 5753dcb..c05884b 100644 --- a/app/admin/router/line_pre_order.go +++ b/app/admin/router/line_pre_order.go @@ -33,7 +33,6 @@ func registerLinePreOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM r.POST("cancelOpenOrder", actions.PermissionAction(), api.CancelOpenOrder) //取消委托 r.POST("clearAll", actions.PermissionAction(), api.ClearAll) // 一键清除数据 r.POST("getChildOrder", actions.PermissionAction(), api.GetChildOrderList) // 获取子订单 - r.POST("manuallyCover", actions.PermissionAction(), api.ManuallyCover) // 手动加仓 r.POST("closePosition", actions.PermissionAction(), api.ClosePosition) // 平仓 r.GET("getOrderPage", actions.PermissionAction(), api.GetOrderPage) //订单列表 r.POST("clearUnTriggered", actions.PermissionAction(), api.ClearUnTriggered) // 清除待触发的交易对 diff --git a/app/admin/service/dto/line_pre_order.go b/app/admin/service/dto/line_pre_order.go index f022b4d..cc56698 100644 --- a/app/admin/service/dto/line_pre_order.go +++ b/app/admin/service/dto/line_pre_order.go @@ -358,16 +358,15 @@ type PreOrderRedisList struct { } type StopLossRedisList struct { - // Id int `json:"id"` - PId int `json:"pid"` - OrderTye string `json:"orderType"` - // Num decimal.Decimal `json:"num"` - - Symbol string `json:"symbol"` - Price decimal.Decimal `json:"price"` //触发价(根据主单价格触发) - Site string `json:"site"` - ApiId int `json:"api_id"` - Stoploss decimal.Decimal `json:"stoploss"` //亏损百分比对冲 + Id int `json:"id"` + PId int `json:"pid"` + OrderTye int `json:"orderType"` + SymbolType int `json:"symbolType"` + OrderCategory int `json:"orderCategory"` + Symbol string `json:"symbol"` + Price decimal.Decimal `json:"price"` //触发价(根据主单价格触发) + Site string `json:"site"` + ApiId int `json:"api_id"` } // ManuallyCover 手动加仓请求体 diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index f9b88b8..41ff678 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -13,7 +13,6 @@ import ( "go-admin/services/binanceservice" "strconv" "strings" - "sync" "time" "github.com/bytedance/sonic" @@ -340,18 +339,15 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP return nil } var key string - //var tickerSymbol string - if req.OrderType == global.SYMBOL_SPOT { + if req.SymbolType == global.SYMBOL_SPOT { key = fmt.Sprintf("%s:%s", global.TICKER_SPOT, req.Symbol) - //tickerSymbol = helper.DefaultRedis.Get(rediskey.SpotSymbolTicker).Val() } else { key = fmt.Sprintf("%s:%s", global.TICKER_FUTURES, req.Symbol) - //tickerSymbol = helper.DefaultRedis.Get(rediskey.FutSymbolTicker).Val() } for _, id := range apiUserIds { - if req.Site == "SELL" && req.OrderType == global.SYMBOL_SPOT { - *errs = append(*errs, errors.New(fmt.Sprintf("api_id:%s 获取交易对:%s 现货不支持卖出操作", id, req.Symbol))) + if req.Site == "SELL" && req.SymbolType == global.SYMBOL_SPOT { + *errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 现货不支持卖出操作", id, req.Symbol)) continue } var AddOrder models.LinePreOrder @@ -362,7 +358,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key) orderCount := e.CheckRepeatOrder(req.OrderType, id, req.Site, tradeSet.Coin) if orderCount > 0 { - *errs = append(*errs, errors.New(fmt.Sprintf("api_id:%s 获取交易对:%s 该交易对已存在,请勿重复下单", id, req.Symbol))) + *errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 该交易对已存在,请勿重复下单", id, req.Symbol)) continue } var tickerPrice decimal.Decimal @@ -370,9 +366,9 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP tickerVal := "" if req.SymbolType == 1 { - tickerVal, _ = helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_SPOT, req.ExchangeType)) + tickerVal, _ = helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_SPOT, req.ExchangeType, req.Symbol)) } else { - tickerVal, _ = helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_FUTURES, req.ExchangeType)) + tickerVal, _ = helper.DefaultRedis.GetString(fmt.Sprintf(global.TICKER_FUTURES, req.ExchangeType, req.Symbol)) } if tickerVal == "" { @@ -387,10 +383,11 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP } if tickerPrice.Equal(decimal.Zero) { //redis 没有这个值 - *errs = append(*errs, errors.New(fmt.Sprintf("api_id:%s 获取交易对:%s 交易行情出错", id, req.Symbol))) + *errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 交易行情出错", id, req.Symbol)) continue } + AddOrder.OrderCategory = 1 AddOrder.SignPriceType = "new" AddOrder.BuyPrice = req.BuyPrice //购买多少U AddOrder.SymbolType = req.SymbolType //交易对类型1= 现货 2 = 合约 @@ -512,7 +509,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP } profitOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10) profitOrder.Pid = AddOrder.Id - profitOrder.OrderType = 2 + profitOrder.OrderType = 1 profitOrder.Status = 0 profitOrder.Rate = req.Profit @@ -529,7 +526,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP } stopOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10) stopOrder.Pid = AddOrder.Id - stopOrder.OrderType = 1 + stopOrder.OrderType = 2 stopOrder.Status = 0 stopOrder.Rate = req.StopPrice @@ -898,28 +895,6 @@ func (e *LinePreOrder) ClearAll() error { return err } -func (e *LinePreOrder) ManuallyCover(req dto.ManuallyCover, p *actions.DataPermission, errs *[]error) { - symbols := strings.Split(req.Symbols, ",") - futApi := binanceservice.FutRestApi{} - spotApi := binanceservice.SpotRestApi{} - addPositionService := binanceservice.AddPosition{Db: e.Orm} - - var wg sync.WaitGroup // 用于等待所有协程完成 - var mu sync.Mutex // 用于保护错误切片的并发访问 - for _, symbol := range symbols { - wg.Add(1) // 增加协程计数 - go func(symbol string) { - defer wg.Done() // 协程完成后减少计数 - if err := addPositionService.ProcessSymbol(req, symbol, &futApi, &spotApi, errs); err != nil { - mu.Lock() // 加锁保护错误切片 - *errs = append(*errs, err) - mu.Unlock() // 解锁 - } - }(symbol) - } - wg.Wait() // 等待所有协程完成 -} - // GetTargetSymbol 获取目标交易对信息 func (e *LinePreOrder) GetTargetSymbol(symbol string, symbolType int) (string, bool, models.LineSymbol, error) { var targetSymbol string diff --git a/common/const/rediskey/redis_key.go b/common/const/rediskey/redis_key.go index b0f9251..11524c6 100644 --- a/common/const/rediskey/redis_key.go +++ b/common/const/rediskey/redis_key.go @@ -46,8 +46,8 @@ const ( SpotHedgeClosePosition = "spot_hedge_close_position:%v_%s" //现货对冲平仓 {mainorderid|symbol} FuturesHedgeClosePosition = "futures_hedge_close_position:%v_%s" //合约对冲平仓 {mainorderid|symbol} - SpotStopLossList = "spot_stoploss_list" //现货止损待触发列表 - FuturesStopLossList = "futures_stoploss_list" //合约止损待触发列表 + SpotStopLossList = "spot_stoploss_list:%s" //现货止损待触发列表 {交易所类型code} + FuturesStopLossList = "futures_stoploss_list:%s" //合约止损待触发列表 {交易所类型code} SpotAddPositionList = "spot_add_position_list" //现货加仓待触发 FuturesAddPositionList = "futures_add_position_list" //合约加仓待触发 diff --git a/services/binanceservice/binancerest.go b/services/binanceservice/binancerest.go index cea8dee..338befb 100644 --- a/services/binanceservice/binancerest.go +++ b/services/binanceservice/binancerest.go @@ -14,13 +14,9 @@ import ( "go-admin/models/spot" "go-admin/pkg/httputils" "go-admin/pkg/utility" - "go-admin/pkg/utility/snowflakehelper" - "strconv" "strings" "time" - "github.com/go-redis/redis/v8" - "github.com/jinzhu/copier" "github.com/shopspring/decimal" "gorm.io/gorm" @@ -244,14 +240,6 @@ func (e SpotRestApi) OrderPlace(orm *gorm.DB, params OrderPlacementService) erro if err := sonic.Unmarshal(resp, &dataMap); err != nil { return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%+v", apiUserInfo.Id, params.Symbol, err.Error()) } - //code, ok := dataMap["code"] - //if !ok { - // return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, params.Symbol, dataMap["message"]) - // - //} - //if code.(float64) != 200 { - // return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, params.Symbol, dataMap["message"]) - //} return nil } @@ -341,48 +329,6 @@ func (e SpotRestApi) CancelOpenOrderByOrderSn(apiUserInfo DbModels.LineApiUser, return nil } -// CalcEntryCashPriceByOrder 计算现货主单均价 -func CalcEntryCashPriceByOrder(orderInfo *DbModels.LinePreOrder, orm *gorm.DB) (EntryPriceResult, error) { - //找到主单成交的记录 - var id int - if orderInfo.Pid > 0 { - id = orderInfo.Pid - } else { - id = orderInfo.Id - } - - orderLists := make([]DbModels.LinePreOrder, 0) - orm.Model(&DbModels.LinePreOrder{}).Where(" symbol = ? AND site = 'BUY' AND order_type in ('1','8') AND status ='9' AND (id = ? OR pid = ?)", orderInfo.Symbol, id, id).Find(&orderLists) - - var ( - totalNum decimal.Decimal //总成交数量 - totalMoney decimal.Decimal //总金额 - entryPrice decimal.Decimal //均价 - initPrice decimal.Decimal //主单下单价格 - firstId int //主单id - ) - for _, list := range orderLists { - num, _ := decimal.NewFromString(list.Num) - totalNum = totalNum.Add(num) - price, _ := decimal.NewFromString(list.Price) - totalMoney = totalMoney.Add(num.Mul(price)) - if list.OrderType == "1" { - firstId = list.Id - initPrice, _ = decimal.NewFromString(list.Price) - } - } - if totalNum.GreaterThan(decimal.Zero) { - entryPrice = totalMoney.Div(totalNum) - } - return EntryPriceResult{ - TotalNum: totalNum, - EntryPrice: entryPrice, - FirstPrice: initPrice, - FirstId: firstId, - TotalMoney: totalMoney, - }, nil -} - // ClosePosition 平仓 // symbol 交易对 // orderSn 平仓单号 @@ -459,135 +405,15 @@ func GetClient(apiUserInfo *DbModels.LineApiUser) *helper.BinanceClient { return client } -/* -重下止盈单 -*/ -func (e SpotRestApi) reTakeOrder(parentOrderInfo DbModels.LinePreOrder, orm *gorm.DB) { - price, _ := decimal.NewFromString(parentOrderInfo.Price) - num, _ := decimal.NewFromString(parentOrderInfo.Num) - parentId := parentOrderInfo.Id - - if parentOrderInfo.Pid > 0 { - parentId = parentOrderInfo.Pid - } - - var takePrice decimal.Decimal - holdeAKey := fmt.Sprintf(rediskey.HoldeA, parentId) - holdeAVal, _ := helper.DefaultRedis.GetString(holdeAKey) - holdeA := HoldeData{} - - if holdeAVal != "" { - sonic.Unmarshal([]byte(holdeAVal), &holdeA) - } - - //查询持仓失败 - if holdeA.Id == 0 { - log.Error("查询A账号持仓失败") - return - } - - //加仓次数大于0 就需要使用均价 - if holdeA.PositionIncrementCount > 0 { - price = holdeA.AveragePrice - num = holdeA.TotalQuantity - } - - if parentOrderInfo.Site == "BUY" { - takePrice = price.Mul(decimal.NewFromInt(100).Add(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100)) - } else { - takePrice = price.Mul(decimal.NewFromInt(100).Sub(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100)) - } - var takeOrder, oldTakeOrder DbModels.LinePreOrder - - if err := orm.Model(&oldTakeOrder).Where("pid= ? AND order_type ='5'", parentId).First(&oldTakeOrder).Error; err != nil { - log.Error("查询止盈单失败") - return - } - - tradeset, _ := GetTradeSet(oldTakeOrder.Symbol, 0) - - if tradeset.Coin == "" { - log.Error("查询交易对失败") - return - } - copier.Copy(&takeOrder, &oldTakeOrder) - - takeOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10) - takeOrder.Price = takePrice.Truncate(int32(tradeset.PriceDigit)).String() - takeOrder.Num = num.Mul(decimal.NewFromFloat(0.995)).Truncate(int32(tradeset.AmountDigit)).String() - takeOrder.Desc = "" - takeOrder.Status = 0 - takeOrder.Id = 0 - - if err := orm.Create(&takeOrder).Error; err != nil { - log.Error("创建新止盈单失败") - return - } - - params := OrderPlacementService{ - ApiId: parentOrderInfo.ApiId, - Symbol: parentOrderInfo.Symbol, - Price: utility.StrToDecimal(takeOrder.Price), - Quantity: utility.StringToDecimal(takeOrder.Num), - Side: "SELL", - Type: "TAKE_PROFIT_LIMIT", - TimeInForce: "GTC", - StopPrice: utility.StrToDecimal(takeOrder.Price), - NewClientOrderId: takeOrder.OrderSn, - } - - apiUserInfo, _ := GetApiInfo(parentOrderInfo.ApiId) - - if apiUserInfo.Id == 0 { - log.Error("获取用户api失败") - return - } - - if err := CancelSpotOrder(parentOrderInfo.Symbol, &apiUserInfo, "SELL"); err != nil { - log.Error("取消旧止盈失败 err:", err) - } else { - if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_type =5 AND status in ('0','1','5') AND order_sn !=?", parentId, takeOrder.OrderSn).Update("status", "4").Error; err != nil { - log.Error("更新旧止盈单取消状态失败 err:", err) - } - } - - var err error - for x := 1; x <= 4; x++ { - err = e.OrderPlace(orm, params) - - if err == nil { - break - } - - log.Error("下止盈单失败 第", utility.IntToString(x), "次", " err:", err) - time.Sleep(2 * time.Second * time.Duration(x)) - } - - if err != nil { - log.Error("重新下单止盈失败 err:", err) - - if err1 := orm.Model(&DbModels.LinePreOrder{}).Where("order_sn =?", takeOrder.OrderSn). - Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error; err1 != nil { - log.Error("重新下单止盈 修改订单失败 pid:", parentId, " takePrice:", takePrice, " err:", err1) - } - } - - //修改止盈单信息 - if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type ='5'", parentId). - Updates(map[string]interface{}{"price": takePrice, "rate": parentOrderInfo.ProfitRate}).Error; err != nil { - log.Error("重新下单止盈 修改订单失败 pid:", parentId, " takePrice:", takePrice, " rate:", parentOrderInfo.ProfitRate, " err:", err) - } -} - /* 判断是否触发 */ func JudgeSpotPrice(trade models.TradeSet) { - preOrderVal, _ := helper.DefaultRedis.GetAllList(rediskey.PreSpotOrderList) + key := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE) + preOrderVal, _ := helper.DefaultRedis.GetAllList(key) db := GetDBConnection() if len(preOrderVal) == 0 { - // log.Debug("没有现货预下单") return } @@ -622,35 +448,20 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S } else if ok { defer lock.Release() - key := fmt.Sprintf(rediskey.UserHolding, v.ApiId) - symbols, err := helper.DefaultRedis.GetAllList(key) - - if err != nil && err != redis.Nil { - log.Error("获取用户持仓失败", err) - return - } - + key := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE) preOrder := DbModels.LinePreOrder{} if err := db.Where("id = ?", v.Id).First(&preOrder).Error; err != nil { log.Error("获取预下单失败", err) if errors.Is(err, gorm.ErrRecordNotFound) { log.Error("不存在待触发主单", item) - helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, item) + helper.DefaultRedis.LRem(key, item) } return } - //获取代币 是否已有持仓 - coin := utility.ReplaceSuffix(preOrder.Symbol, preOrder.QuoteSymbol, "") - - if utility.ContainsStr(symbols, coin) { - log.Debug("已有持仓") - return - } - - hasrecord, _ := helper.DefaultRedis.IsElementInList(rediskey.PreSpotOrderList, item) + hasrecord, _ := helper.DefaultRedis.IsElementInList(key, item) if !hasrecord { log.Error("不存在待触发主单", item) @@ -673,14 +484,14 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S if err := spotApi.OrderPlace(db, params); err != nil { log.Error("下单失败", v.Symbol, " err:", err) - err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status ='0'", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error + err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status =0", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error if err != nil { log.Error("下单失败后修改订单失败") } if preOrderVal != "" { - if _, err := helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, preOrderVal); err != nil { + if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil { log.Error("删除redis 预下单失败:", err) } } @@ -689,31 +500,14 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S } if preOrderVal != "" { - if _, err := helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, preOrderVal); err != nil { + if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil { log.Error("删除redis 预下单失败:", err) } - - // spotPreOrders, _ := helper.DefaultRedis.GetAllList(rediskey.PreSpotOrderList) - // futuresPreOrders, _ := helper.DefaultRedis.GetAllList(rediskey.PreFutOrderList) - // var order dto.PreOrderRedisList - - // for _, item := range spotPreOrders { - // sonic.Unmarshal([]byte(item), &order) - - // if order.QuoteSymbol == "" { - - // } - // } } if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status ='0'", preOrder.Id).Update("status", "1").Error; err != nil { log.Error("更新预下单状态失败 ordersn:", v.OrderSn, " status:1") } - - if err := helper.DefaultRedis.RPushList(key, coin); err != nil { - log.Error("写入用户持仓失败", v.Symbol) - } - return } else { log.Error("获取锁失败") diff --git a/services/binanceservice/binanceservice_test.go b/services/binanceservice/binanceservice_test.go index dad8d14..5c3f609 100644 --- a/services/binanceservice/binanceservice_test.go +++ b/services/binanceservice/binanceservice_test.go @@ -2,13 +2,14 @@ package binanceservice import ( "fmt" - "github.com/bytedance/sonic" "go-admin/app/admin/models" "go-admin/common/helper" "go-admin/pkg/utility" "go-admin/pkg/utility/snowflakehelper" "testing" + "github.com/bytedance/sonic" + "github.com/shopspring/decimal" "gorm.io/driver/mysql" "gorm.io/gorm" @@ -53,16 +54,6 @@ func TestPositionV3(t *testing.T) { fmt.Println(v3) } -func TestInsertLog(t *testing.T) { - dsn := "root:root@tcp(192.168.1.12:3306)/gp-bian?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" - db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) - //初始redis 链接 - helper.InitDefaultRedis("192.168.1.12:6379", "", 0) - helper.InitLockRedisConn("192.168.1.12:6379", "", "0") - - InsertProfitLogs(db, "367452130811838464", decimal.NewFromInt(20), decimal.NewFromFloat(0.34078000)) -} - func TestCancelSpotOrder(t *testing.T) { //dsn := "root:root@tcp(192.168.1.12:3306)/gp-bian?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" //db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) diff --git a/services/binanceservice/commonservice.go b/services/binanceservice/commonservice.go index aa048f9..73f591a 100644 --- a/services/binanceservice/commonservice.go +++ b/services/binanceservice/commonservice.go @@ -16,6 +16,7 @@ import ( "github.com/bytedance/sonic" "github.com/go-admin-team/go-admin-core/logger" log "github.com/go-admin-team/go-admin-core/logger" + "github.com/go-admin-team/go-admin-core/sdk" "github.com/shopspring/decimal" "gorm.io/gorm" ) @@ -329,3 +330,21 @@ func MainClosePositionClearCache(mainOrderId int, coverType int) { } } } + +// 获取数据库连接 +func GetDBConnection() *gorm.DB { + dbs := sdk.Runtime.GetDb() + for _, db := range dbs { + return db + } + return nil +} + +// 查询订单 +func getPreOrder(db *gorm.DB, orderSn interface{}) (*DbModels.LinePreOrder, error) { + preOrder := &DbModels.LinePreOrder{} + if err := db.Model(preOrder).Where("order_sn = ?", orderSn).First(preOrder).Error; err != nil { + return nil, err + } + return preOrder, nil +} diff --git a/services/binanceservice/futuresbinancerest.go b/services/binanceservice/futuresbinancerest.go index 6e2e792..0259928 100644 --- a/services/binanceservice/futuresbinancerest.go +++ b/services/binanceservice/futuresbinancerest.go @@ -13,12 +13,10 @@ import ( "go-admin/models/futuresdto" "go-admin/pkg/httputils" "go-admin/pkg/utility" - "go-admin/pkg/utility/snowflakehelper" "strconv" "strings" "time" - "github.com/jinzhu/copier" "github.com/shopspring/decimal" "gorm.io/gorm" @@ -722,11 +720,10 @@ func (e FutRestApi) ClosePosition(symbol string, orderSn string, quantity decima 判断合约触发 */ func JudgeFuturesPrice(tradeSet models.TradeSet) { - preOrderVal, _ := helper.DefaultRedis.GetAllList(rediskey.PreFutOrderList) + preOrderVal, _ := helper.DefaultRedis.GetAllList(fmt.Sprintf(rediskey.PreFutOrderList, global.EXCHANGE_BINANCE)) db := GetDBConnection() if len(preOrderVal) == 0 { - // log.Debug("没有合约预下单") return } futApi := FutRestApi{} @@ -766,32 +763,21 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi return } else if ok { defer lock.Release() + + key := fmt.Sprintf(rediskey.PreFutOrderList, global.EXCHANGE_BINANCE) preOrder := DbModels.LinePreOrder{} - key := fmt.Sprintf(rediskey.UserHolding, v.ApiId) - symbols, err := helper.DefaultRedis.GetAllList(key) - - if err != nil && err != redis.Nil { - log.Error("获取用户持仓失败", err) - return - } - if err := db.Where("id = ?", v.Id).First(&preOrder).Error; err != nil { log.Error("获取预下单失败", err) if errors.Is(err, gorm.ErrRecordNotFound) { log.Error("不存在待触发主单", item) - helper.DefaultRedis.LRem(rediskey.PreFutOrderList, item) + helper.DefaultRedis.LRem(key, item) } return } - coin := utility.ReplaceSuffix(v.Symbol, preOrder.QuoteSymbol, "") - if utility.ContainsStr(symbols, coin) { - log.Info("用户已经持有", coin) - return - } - hasrecord, _ := helper.DefaultRedis.IsElementInList(rediskey.PreFutOrderList, item) + hasrecord, _ := helper.DefaultRedis.IsElementInList(key, item) if !hasrecord { log.Debug("预下单缓存中不存在", item) @@ -827,7 +813,7 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi } if preOrderVal != "" { - if _, err := helper.DefaultRedis.LRem(rediskey.PreFutOrderList, preOrderVal); err != nil { + if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil { log.Error("删除redis 预下单失败:", err) } } @@ -836,7 +822,7 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi } if preOrderVal != "" { - if _, err := helper.DefaultRedis.LRem(rediskey.PreFutOrderList, preOrderVal); err != nil { + if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil { log.Error("删除redis 预下单失败:", err) } } @@ -845,10 +831,6 @@ func futTriggerOrder(db *gorm.DB, v *dto.PreOrderRedisList, item string, futApi log.Error("更新预下单状态失败 ordersn:", v.OrderSn, " status:1") } - if err := helper.DefaultRedis.RPushList(key, coin); err != nil { - log.Error("写入用户持仓失败", v.Symbol) - } - return } else { log.Error("获取锁失败") @@ -1010,125 +992,3 @@ func (e FutRestApi) GetFutSymbolLastPrice(targetSymbol string) (lastPrice decima } return lastPrice } - -/* -重下止盈单 -*/ -func (e FutRestApi) reTakeOrder(parentOrderInfo DbModels.LinePreOrder, orm *gorm.DB) { - parentId := parentOrderInfo.Id - - if parentOrderInfo.Pid > 0 { - parentId = parentOrderInfo.Pid - } - - price, _ := decimal.NewFromString(parentOrderInfo.Price) - num, _ := decimal.NewFromString(parentOrderInfo.Num) - takePrice := decimal.Zero - holdeAKey := fmt.Sprintf(rediskey.HoldeA, parentId) - holdeAVal, _ := helper.DefaultRedis.GetString(holdeAKey) - holdeA := HoldeData{} - - if holdeAVal != "" { - sonic.Unmarshal([]byte(holdeAVal), &holdeA) - } - - //查询持仓失败 - if holdeA.Id == 0 { - log.Error("查询A账号持仓失败") - return - } - - takeOrder := DbModels.LinePreOrder{} - if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type ='3'").First(&takeOrder).Error; err != nil { - log.Error("查询止盈单失败", err) - return - } - - apiUserInfo, _ := GetApiInfo(takeOrder.ApiId) - if apiUserInfo.Id == 0 { - log.Error("重下止盈 查询api信息失败") - return - } - - newTakeOrder := DbModels.LinePreOrder{} - copier.Copy(&newTakeOrder, &takeOrder) - newTakeOrder.Id = 0 - newTakeOrder.OrderType = 1 - newTakeOrder.Status = 0 - newTakeOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10) - - //加仓次数大于0 就需要使用均价 - if holdeA.PositionIncrementCount > 0 { - price = holdeA.AveragePrice - } - - if parentOrderInfo.Site == "BUY" { - takePrice = price.Mul(decimal.NewFromInt(100).Add(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100)) - } else { - takePrice = price.Mul(decimal.NewFromInt(100).Sub(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100)) - } - - tradeset, _ := GetTradeSet(takeOrder.Symbol, 1) - - if tradeset.Coin == "" { - log.Error("查询交易对失败") - return - } - - newTakeOrder.Price = takePrice.Truncate(int32(tradeset.PriceDigit)).String() - newTakeOrder.Num = num.Mul(decimal.NewFromFloat(0.995)).Truncate(int32(tradeset.AmountDigit)).String() - - if err := orm.Create(&newTakeOrder).Error; err != nil { - log.Error("重新止盈单创建失败", err) - return - } - - params := FutOrderPlace{ - ApiId: newTakeOrder.ApiId, - Symbol: newTakeOrder.Symbol, - Price: utility.StringToDecimal(newTakeOrder.Price), - Quantity: utility.StringToDecimal(newTakeOrder.Num), - Side: newTakeOrder.Site, - OrderType: "TAKE_PROFIT_MARKET", - Profit: utility.StringToDecimal(newTakeOrder.Price), - NewClientOrderId: newTakeOrder.OrderSn, - } - - if err := e.CancelFutOrder(apiUserInfo, takeOrder.Symbol, takeOrder.OrderSn); err != nil { - log.Error("取消老止盈单失败:", err) - - orm.Model(&newTakeOrder).Updates(map[string]interface{}{"status": "2", "desc": "取消老止盈单失败," + err.Error()}) - return - } else { - if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_type =5 AND status in ('0','1','5') AND order_sn !=?", parentId, newTakeOrder.OrderSn).Update("status", "4").Error; err != nil { - log.Error("更新旧止盈单取消状态失败 err:", err) - } - } - - var err error - for x := 0; x < 3; x++ { - err = e.OrderPlace(orm, params) - - if err == nil { - break - } - - log.Error("下止盈单失败 第", utility.IntToString(x), "次", " err:", err) - time.Sleep(2 * time.Second * time.Duration(x)) - } - - if err != nil { - log.Error("重新下单止盈失败 err:", err) - - if err1 := orm.Model(&DbModels.LinePreOrder{}).Where("id =?", newTakeOrder.Id). - Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error; err1 != nil { - log.Error("重新下单止盈 修改止盈订单失败 id:", newTakeOrder.Id, " takePrice:", takePrice, " err:", err1) - } - } - - //修改止盈单信息 - if err := orm.Model(&DbModels.LinePreOrder{}).Where("id =?", newTakeOrder.Id). - Updates(map[string]interface{}{"price": takePrice, "rate": parentOrderInfo.ProfitRate}).Error; err != nil { - log.Error("重新下单止盈 修改订单失败 id:", newTakeOrder.Id, " takePrice:", takePrice, " rate:", parentOrderInfo.ProfitRate, " err:", err) - } -} diff --git a/services/binanceservice/futuresrest.go b/services/binanceservice/futuresrest.go index f00b3c7..ed4f5db 100644 --- a/services/binanceservice/futuresrest.go +++ b/services/binanceservice/futuresrest.go @@ -2,13 +2,24 @@ package binanceservice import ( "context" + "errors" "fmt" + "go-admin/app/admin/models" + DbModels "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" "go-admin/common/const/rediskey" + "go-admin/common/global" "go-admin/common/helper" + models2 "go-admin/models" + "go-admin/pkg/utility" + "go-admin/pkg/utility/snowflakehelper" + "strings" "time" "github.com/bytedance/sonic" "github.com/go-admin-team/go-admin-core/logger" + "github.com/shopspring/decimal" + "gorm.io/gorm" ) /* @@ -56,7 +67,327 @@ func ChangeFutureOrder(mapData map[string]interface{}) { logger.Error("订单回调失败,没有状态:", string(mapStr)) return } + // 更新订单状态 + orderStatus, reason := parseOrderStatus(status, mapData) - //todo + 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) +} + +// 合约回调 +func handleFutOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderStatus int) { + switch { + //主单成交 + case preOrder.OrderType == 0 && orderStatus == 6: + handleFutMainOrderFilled(db, preOrder) + //止盈成交 + case preOrder.OrderType == 1 && orderStatus == 6: + handleTakeProfit(db, preOrder) + //止损成交 + case preOrder.OrderType == 2 && orderStatus == 6: + handleStopLoss(db, preOrder) + //平仓成交 + case preOrder.OrderType == 3 && orderStatus == 6: + handleClosePosition(db, preOrder) + } +} + +// 平仓单成交 +func handleClosePosition(db *gorm.DB, preOrder *DbModels.LinePreOrder) { + panic("unimplemented") +} + +// 止损单成交 +func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) { + // 获取主订单 + order, err := GetOrderById(db, preOrder.Pid) + if err != nil { + logger.Errorf("止损单成交 获取主单失败 订单号:%s err:%v", preOrder.OrderSn, err) + return + } + + // 检查订单类型 + if order.OrderCategory != 1 { + if err := db.Model(&order).Where("pid =? AND order_status <9 AND order_type =0", preOrder.Pid).Error; err != nil { + logger.Errorf("对冲止损单成交 修改对冲主单状态失败 订单号:%s err:%v", order.OrderSn, err) + } + return + } + + // 修改主单状态 + if err := db.Model(&order).Where("id =? AND order_status < 9", preOrder.Pid).Error; err != nil { + logger.Errorf("止损单成交 修改主单状态失败 订单号:%s err:%v", order.OrderSn, err) + return + } + + // 检查是否有对冲 + if order.CoverType <= 0 { + return + } + + // 获取交易对配置 + symbolName := utility.ReplaceSuffix(order.Symbol, order.QuoteSymbol, "USDT") + tradeSet, err := GetTradeSet(symbolName, 1) + if tradeSet.Coin == "" || err != nil { + logger.Errorf("止损单成交 获取交易对配置失败 交易对:%s 订单号:%s err:%v", symbolName, order.OrderSn, err) + return + } + + // 检查对冲单购买金额 + if order.HedgeBuyTotal.Cmp(decimal.Zero) <= 0 { + logger.Errorf("止损单成交 对冲单购买金额为0 订单号:%s", order.OrderSn) + return + } + + // 获取系统设置 + setting, err := GetSystemSetting(db) + if err != nil { + logger.Errorf("止损单成交 获取系统设置失败 订单号:%s err:%v", order.OrderSn, err) + return + } + + // 获取API信息 + apiInfo, err := GetChildApiInfo(order.ApiId) + if err != nil { + logger.Errorf("止损单成交 获取api信息失败 订单号:%s err:%v", order.OrderSn, err) + return + } + + // 计算价格 + price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit)) + if order.CoverType == 2 { + price = utility.StrToDecimal(tradeSet.LastPrice).Truncate(int32(tradeSet.PriceDigit)) + } + if price.Cmp(decimal.Zero) <= 0 { + logger.Errorf("单价异常 price:%v 止损单编号:%s 行情:%v", price, order.OrderSn, tradeSet) + return + } + + // 创建对冲订单 + hedgeOrder, hedgeStoplossOrder, hedgeTakeProfitOrder := createHedgeOrders(order, price, &tradeSet, &apiInfo, &setting) + orders := []DbModels.LinePreOrder{hedgeOrder, hedgeStoplossOrder, hedgeTakeProfitOrder} + + // 批量插入订单 + if err := db.Model(&DbModels.LinePreOrder{}).CreateInBatches(orders, 1).Error; err != nil { + logger.Errorf("主单止损 重下对冲失败,止损单id:%s err:%v", order.OrderSn, err) + return + } + + // 调用API下单 + if err := placeFutOrder(db, hedgeOrder, price, &apiInfo); err != nil { + logger.Errorf("主单止损 重下对冲失败,止损单号:%s err:%v", order.OrderSn, err) + } +} + +// 创建对冲订单 +func createHedgeOrders(order DbModels.LinePreOrder, price decimal.Decimal, tradeSet *models2.TradeSet, apiInfo *DbModels.LineApiUser, setting *DbModels.LineSystemSetting) (DbModels.LinePreOrder, DbModels.LinePreOrder, DbModels.LinePreOrder) { + hedgeOrder := DbModels.LinePreOrder{ + ApiId: apiInfo.Id, + ExchangeType: order.ExchangeType, + Pid: order.Pid, + Symbol: order.Symbol, + SymbolType: global.SYMBOL_FUTURES, + SignPrice: order.Price, + SignPriceType: "new", + Rate: "0", + BuyPrice: order.HedgeBuyTotal.String(), + OrderCategory: 2, + OrderSn: utility.Int64ToString(snowflakehelper.GetOrderId()), + OrderType: 0, + CoverType: 0, + MainOrderType: order.HedgeOrderType, + } + + hedgeStoplossOrder := order + hedgeTakeProfitOrder := order + + if order.Site == "BUY" { + hedgeOrder.Site = "SELL" + hedgeStoplossOrder.Site = "BUY" + hedgeTakeProfitOrder.Site = "BUY" + } else { + hedgeOrder.Site = "BUY" + hedgeStoplossOrder.Site = "SELL" + hedgeTakeProfitOrder.Site = "SELL" + } + + // 计算止盈止损价格 + if hedgeOrder.Site == "BUY" { + hedgeTakeProfitOrder.Price = price.Mul(decimal.NewFromInt(1).Add(order.HedgeTakeProfit.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String() + hedgeStoplossOrder.Price = price.Mul(decimal.NewFromInt(1).Sub(order.HedgeStopLoss.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String() + } else { + hedgeTakeProfitOrder.Price = price.Mul(decimal.NewFromInt(1).Sub(order.HedgeTakeProfit.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String() + hedgeStoplossOrder.Price = price.Mul(decimal.NewFromInt(1).Add(order.HedgeStopLoss.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit)).String() + } + + if hedgeOrder.MainOrderType == "LIMIT" { + coverRate := utility.StrToDecimal(setting.CoverOrderTypeBRate) + price = price.Mul(decimal.NewFromInt(1).Add(coverRate)).Truncate(int32(tradeSet.PriceDigit)) + } + + num := order.HedgeBuyTotal.Div(price).Truncate(int32(tradeSet.AmountDigit)) + hedgeOrder.Price = price.String() + hedgeOrder.Num = num.String() + + hedgeStoplossOrder.OrderSn = utility.Int64ToString(snowflakehelper.GetOrderId()) + hedgeStoplossOrder.Rate = order.HedgeStopLoss.String() + hedgeStoplossOrder.Num = num.String() + + hedgeTakeProfitOrder.OrderSn = utility.Int64ToString(snowflakehelper.GetOrderId()) + hedgeTakeProfitOrder.Rate = order.HedgeTakeProfit.String() + hedgeTakeProfitOrder.Num = num.String() + + return hedgeOrder, hedgeStoplossOrder, hedgeTakeProfitOrder +} + +// 调用合约API下单 +func placeFutOrder(db *gorm.DB, hedgeOrder DbModels.LinePreOrder, price decimal.Decimal, apiInfo *DbModels.LineApiUser) error { + futApi := FutRestApi{} + params := FutOrderPlace{ + ApiId: apiInfo.Id, + Symbol: hedgeOrder.Symbol, + Side: hedgeOrder.Site, + Quantity: utility.StrToDecimal(hedgeOrder.Num), + Price: price, + NewClientOrderId: hedgeOrder.OrderSn, + SideType: hedgeOrder.MainOrderType, + OrderType: hedgeOrder.MainOrderType, + } + return futApi.OrderPlace(db, params) +} + +// 止盈单成交 +func handleTakeProfit(db *gorm.DB, preOrder *DbModels.LinePreOrder) { + if preOrder.OrderCategory == 1 { + //主单止盈成交 + if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ?", preOrder.Pid).Update("order_type", 3).Error; err != nil { + logger.Errorf("主单止盈成功修改主单状态失败 订单号:%s:", err) + } + } else { + //对冲单止盈成交 + if err := db.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_category = 2 AND order_type =0 AND status < 9", preOrder.Pid).Update("status", 9).Error; err != nil { + logger.Errorf("对冲止盈成功修改主单状态失败 订单号:%s:", err) + } + } +} + +// 主单成交 处理止盈止损订单 +// preOrder 主单 +func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) { + orders := []models.LinePreOrder{} + if err := db.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_category = 1 AND order_type > 0 AND status = '0' ", preOrder.Id).Find(&orders).Error; err != nil { + logger.Error("订单回调查询止盈止损单失败:", err) + return + } + + futApi := FutRestApi{} + num, _ := decimal.NewFromString(preOrder.Num) + tradeSet, _ := GetTradeSet(preOrder.Symbol, 0) + + if tradeSet.Coin == "" { + logger.Error("获取交易对失败") + return + } + + for i, order := range orders { + if i >= 2 { // 最多处理 2 个订单 + break + } + num = num.Truncate(int32(tradeSet.AmountDigit)) + + if err := db.Model(&order).Update("num", num).Error; err != nil { + logger.Errorf("修改止盈止损数量失败 订单号:%s err:%v", order.OrderSn, err) + } + + switch order.OrderType { + case 1: // 止盈 + processFutTakeProfitOrder(db, futApi, order, num) + case 2: // 止损 + processFutStopLossOrder(order) + } + } +} + +// 处理止盈订单 +func processFutTakeProfitOrder(db *gorm.DB, futApi FutRestApi, order models.LinePreOrder, num decimal.Decimal) { + price, _ := decimal.NewFromString(order.Price) + + params := FutOrderPlace{ + ApiId: order.ApiId, + Symbol: order.Symbol, + Side: order.Site, + Price: price, + Quantity: num, + OrderType: "TAKE_PROFIT_LIMIT", + StopPrice: price, + NewClientOrderId: order.OrderSn, + } + + err := futApi.OrderPlace(db, params) + + if err != nil { + for x := 0; x < 5; x++ { + if strings.Contains(err.Error(), "LOT_SIZE") { + break + } + + err = futApi.OrderPlace(db, params) + + if err == nil { + break + } + } + } + + if err != nil { + logger.Error("合约止盈下单失败:", order.OrderSn, " err:", err) + if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ?", order.Id). + Updates(map[string]interface{}{"status": "2", "desc": err.Error(), "num": params.Quantity}).Error; err != nil { + logger.Error("合约止盈下单失败,更新状态失败:", order.OrderSn, " err:", err) + } + } else { + if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ? and status =0", order.Id). + Updates(map[string]interface{}{"status": "1", "num": num.String()}).Error; err != nil { + logger.Error("合约止盈下单成功,更新状态失败:", order.OrderSn, " err:", err) + } + } +} + +// 处理止损订单 +// order 止损单 +func processFutStopLossOrder(order models.LinePreOrder) error { + price := utility.StrToDecimal(order.Price) + stopLoss := dto.StopLossRedisList{ + Id: order.Id, + PId: order.Pid, + ApiId: order.ApiId, + OrderTye: order.OrderType, + OrderCategory: order.OrderCategory, + Price: price, + SymbolType: order.SymbolType, + Symbol: order.Symbol, + Site: order.Site, + } + + stoplossVal, _ := sonic.MarshalString(&stopLoss) + stoplossKey := fmt.Sprintf(rediskey.FuturesStopLossList, global.EXCHANGE_BINANCE) + + if stoplossVal == "" { + return errors.New("stoplossVal is empty") + } + + if err := helper.DefaultRedis.RPushList(stoplossKey, stoplossVal); err != nil { + return err + } + + return nil } diff --git a/services/binanceservice/spotreset.go b/services/binanceservice/spotreset.go index 6b3bb12..79bbbfd 100644 --- a/services/binanceservice/spotreset.go +++ b/services/binanceservice/spotreset.go @@ -2,10 +2,13 @@ package binanceservice import ( "context" + "errors" "fmt" "go-admin/app/admin/models" DbModels "go-admin/app/admin/models" + "go-admin/app/admin/service/dto" "go-admin/common/const/rediskey" + "go-admin/common/global" "go-admin/common/helper" "go-admin/pkg/utility" "strconv" @@ -59,7 +62,7 @@ func ChangeSpotOrder(mapData map[string]interface{}) { } // 更新订单状态 - orderStatus, reason := parseOrderStatus(preOrder, status, mapData) + orderStatus, reason := parseOrderStatus(status, mapData) if orderStatus == 0 { logger.Error("订单回调失败,状态错误:", orderSn, " status:", status, " reason:", reason) @@ -99,43 +102,100 @@ func logMapData(mapData map[string]interface{}) { func handleOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderStatus int) { switch { // 主单成交 - case preOrder.OrderType == 0 && (orderStatus == 9 || orderStatus == 6): + case preOrder.OrderType == 0 && orderStatus == 6: handleMainOrderFilled(db, preOrder) //主单取消 case preOrder.OrderType == 0 && preOrder.Pid == 0 && orderStatus == 4: - coin := utility.ReplaceSuffix(preOrder.Symbol, preOrder.QuoteSymbol, "") - removeHoldingCache(preOrder.ApiId, coin, preOrder.Id) + handleMainOrderCancel(preOrder) // 止盈成交 - case preOrder.OrderType == 1 && (orderStatus == 9 || orderStatus == 6): + case preOrder.OrderType == 1 && orderStatus == 6: handleSpotTakeProfitFilled(db, preOrder) - //主单平仓 - case preOrder.OrderType == 3 && orderStatus == 9: + //平仓单 + case preOrder.OrderType == 3 && orderStatus == 6: handleMainOrderClosePosition(db, preOrder) + + //主单止损回调 + case preOrder.OrderType == 2 && preOrder.OrderCategory == 1 && orderStatus == 6: + if preOrder.CoverType == 0 { + if err := db.Model(&DbModels.LinePreOrder{}).Where("id =?", preOrder.Pid).Update("status", 9).Error; err != nil { + logger.Errorf("主单止损回调 订单号:%s 修改主单状态失败:%v", preOrder.OrderSn, err) + } + } } } +// 主单取消 +func handleMainOrderCancel(preOrder *DbModels.LinePreOrder) { + preOrderKey := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE) + preSpotOrders, _ := helper.DefaultRedis.GetAllList(preOrderKey) + preOrderCache := DbModels.LinePreOrder{} + + for _, v := range preSpotOrders { + if v == "" { + continue + } + + sonic.Unmarshal([]byte(v), &preOrderCache) + if preOrderCache.Pid == preOrder.Id { + _, err := helper.DefaultRedis.LRem(preOrderKey, v) + + if err != nil { + logger.Errorf("订单回调失败, 回调订单号:%s 删除缓存失败:%v", preOrder.OrderSn, err) + } + } + } +} + +// 平仓单 func handleMainOrderClosePosition(db *gorm.DB, preOrder *DbModels.LinePreOrder) { - panic("unimplemented") + //主单平仓 + if preOrder.OrderCategory == 1 { + if err := db.Model(&DbModels.LinePreOrder{}).Where("id =?", preOrder.Pid).Update("status", 9).Error; err != nil { + logger.Errorf("平仓订单回调失败, 回调订单号:%s 更新主单失败:%v", preOrder.OrderSn, err) + } + } else { + //对冲单回调 + if err := db.Model(&DbModels.LinePreOrder{}). + Where("pid =? AND order_category =? AND order_type =0 AND status <9 ", preOrder.Pid, preOrder.OrderCategory). + Update("status", 9).Error; err != nil { + logger.Errorf("对冲单平仓回调失败, 回调订单号:%s 更新对冲单失败:%v", preOrder.OrderSn, err) + } + } } +// 止盈成交 func handleSpotTakeProfitFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { - panic("unimplemented") -} - -func removeHoldingCache(i1 int, coin string, i2 int) { - panic("unimplemented") + if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND order_category =?", preOrder.Pid, preOrder.OrderCategory).Update("status", 9).Error; err != nil { + logger.Errorf("止盈订单回调失败, 回调订单号:%s 更新主单失败:%v", preOrder.OrderSn, err) + } + + stoplossKey := fmt.Sprintf(rediskey.SpotStopLossList, global.EXCHANGE_BINANCE) + stoplossVal, _ := helper.DefaultRedis.GetAllList(stoplossKey) + stoploss := DbModels.LinePreOrder{} + + for _, v := range stoplossVal { + sonic.Unmarshal([]byte(v), &stoploss) + if stoploss.Pid == preOrder.Id { + _, err := helper.DefaultRedis.LRem(stoplossKey, v) + + if err != nil { + logger.Errorf("订单回调失败, 回调订单号:%s 删除缓存失败:%v", preOrder.OrderSn, err) + } + } + } } +// 主单成交 func handleMainOrderFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) { - panic("unimplemented") + processTakeProfitAndStopLossOrders(db, preOrder) } // 解析订单状态 -// 5:委托中 9:完全成交 4:取消 -func parseOrderStatus(preOrder *DbModels.LinePreOrder, status interface{}, mapData map[string]interface{}) (int, string) { +// 5:委托中 6:完全成交 4:取消 9:已平仓 +func parseOrderStatus(status interface{}, mapData map[string]interface{}) (int, string) { reason, _ := mapData["r"].(string) if strings.ToLower(reason) == "none" { @@ -146,11 +206,7 @@ func parseOrderStatus(preOrder *DbModels.LinePreOrder, status interface{}, mapDa case "NEW": // 未成交 return 5, reason case "FILLED": // 完全成交 - if preOrder.OrderType < 3 { - return 6, reason - } - - return 9, reason + return 6, reason case "CANCELED", "EXPIRED": // 取消 return 4, reason default: @@ -179,6 +235,7 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r params["num"] = num params["price"] = total.Div(totalAmount) preOrder.Num = num.String() + preOrder.Price = params["price"].(string) } case false: status, _ := mapData["X"].(string) @@ -189,6 +246,7 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r params["price"], _ = mapData["ap"].(string) preOrder.Num = num.String() + preOrder.Price = params["price"].(string) } } @@ -197,26 +255,32 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r } // 主单成交 处理止盈止损订单 +// preOrder 主单 func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrder) { orders := []models.LinePreOrder{} - if err := db.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_type >0 AND status = '0' ", preOrder.Id).Find(&orders).Error; err != nil { + if err := db.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_category = 1 AND order_type > 0 AND status = '0' ", preOrder.Id).Find(&orders).Error; err != nil { logger.Error("订单回调查询止盈止损单失败:", err) return } spotApi := SpotRestApi{} num, _ := decimal.NewFromString(preOrder.Num) + num = num.Mul(decimal.NewFromFloat(0.998)) for i, order := range orders { if i >= 2 { // 最多处理 2 个订单 break } + if err := db.Model(&order).Update("num", num).Error; err != nil { + logger.Errorf("修改止盈止损数量失败 订单号:%s err:%v", order.OrderSn, err) + } + switch order.OrderType { case 1: // 止盈 processTakeProfitOrder(db, spotApi, order, num) case 2: // 止损 - processStopLossOrder(db, order) + processStopLossOrder(order) } } } @@ -231,7 +295,6 @@ func processTakeProfitOrder(db *gorm.DB, spotApi SpotRestApi, order models.LineP } price, _ := decimal.NewFromString(order.Price) - // num, _ := decimal.NewFromString(order.Num) params := OrderPlacementService{ ApiId: order.ApiId, @@ -264,7 +327,7 @@ func processTakeProfitOrder(db *gorm.DB, spotApi SpotRestApi, order models.LineP if err != nil { logger.Error("现货止盈下单失败:", order.OrderSn, " err:", err) if err := db.Model(&DbModels.LinePreOrder{}).Where("id = ?", order.Id). - Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error; err != nil { + Updates(map[string]interface{}{"status": "2", "desc": err.Error(), "num": params.Quantity}).Error; err != nil { logger.Error("现货止盈下单失败,更新状态失败:", order.OrderSn, " err:", err) } } else { @@ -277,110 +340,32 @@ func processTakeProfitOrder(db *gorm.DB, spotApi SpotRestApi, order models.LineP // 处理止损订单 // order 止损单 -func processStopLossOrder(db *gorm.DB, order models.LinePreOrder) error { - // var stopOrder models.LinePreOrder - // orderTypes := []string{"4", "6", "9", "12"} - // parentId := order.Id - - // if order.Pid > 0 { - // parentId = order.Pid - // } - - // if utility.ContainsStr(orderTypes, order.OrderType) { - // var err error - // stopOrder, err = GetStopOrder(db, order.Pid) - - // if err != nil { - // logger.Error("查询止损单失败:", err) - // return err - // } - // } - - // price, _ := decimal.NewFromString(stopOrder.Price) - // stoploss, _ := decimal.NewFromString(order.Rate) - - // if holdeB.Id > 0 { - // _, holdeA := GetHoldeA(stopOrder.Pid) - // var percent decimal.Decimal - // lastPercent, _ := GetStopOrderRate(db, stopOrder.Pid) - - // if stopOrder.Site == "BUY" { - // //平仓次数>=最大次数 且余数为0 重新计算触发对冲百分比 - // // if holdeA.Id > 0 && holdeB.HedgeCloseCount >= stopOrder.HedgeCloseCount && (holdeB.HedgeCloseCount%stopOrder.HedgeCloseCount == 0) { - // rand := getRand(stopOrder.HedgeTriggerPercent, stopOrder.HedgeTriggerPercentMax, lastPercent, 1) - - // percent = decimal.NewFromInt(100).Add(rand).Div(decimal.NewFromInt(100)) - // // } else { - // // rate, _ := decimal.NewFromString(stopOrder.Rate) - // // percent = decimal.NewFromInt(100).Add(rate).Div(decimal.NewFromInt(100)) - // // } - // } else { - // // if holdeA.Id > 0 && holdeB.HedgeCloseCount >= stopOrder.HedgeCloseCount { - // rand := getRand(stopOrder.HedgeTriggerPercent, stopOrder.HedgeTriggerPercentMax, lastPercent, 1) - - // percent = decimal.NewFromInt(100).Sub(rand).Div(decimal.NewFromInt(100)) - // // } else { - // // rate, _ := decimal.NewFromString(stopOrder.Rate) - // // percent = decimal.NewFromInt(100).Sub(rate).Div(decimal.NewFromInt(100)) - // // } - // } - // stoploss = decimal.NewFromInt(100).Sub(percent.Mul(decimal.NewFromInt(100))).Truncate(2) - // price = holdeA.AveragePrice.Mul(percent) - // } - - // tradeset, _ := GetTradeSet(stopOrder.Symbol, 1) - // if tradeset.PriceDigit > 0 { - // price = price.Truncate(int32(tradeset.PriceDigit)) - // } - - // cache := dto.StopLossRedisList{ - // PId: stopOrder.Pid, - // ApiId: stopOrder.ApiId, - // Price: price, - // OrderTye: stopOrder.OrderType, - // Site: stopOrder.Site, - // Symbol: stopOrder.Symbol, - // Stoploss: stoploss, - // } - - // stoplossKey := fmt.Sprintf(rediskey.SpotStopLossList) - // cacheVal, _ := sonic.MarshalString(&cache) - - // if stopOrder.OrderType == "4" { - // stoplossKey = rediskey.FuturesStopLossList - // } - - // stopLossVal, _ := helper.DefaultRedis.GetAllList(stoplossKey) - // for _, itemVal := range stopLossVal { - // if strings.Contains(itemVal, fmt.Sprintf("\"pid\":%v,", stopOrder.Pid)) { - // helper.DefaultRedis.LRem(stoplossKey, itemVal) - // break - // } - // } - - // //重新保存待触发对冲单 - // if err := helper.DefaultRedis.RPushList(stoplossKey, cacheVal); err != nil { - // logger.Error("B单平仓回调,redis添加止损单失败", err) - // } - - return nil -} - -// 生成随机数 且不重复 -// lastPercent 上一次的百分比 -// floatNum 小数点后几位 -func getRand(start, end, lastPercent decimal.Decimal, floatNum int) decimal.Decimal { - var rand decimal.Decimal - - for x := 0; x < 10; x++ { - rand = utility.DecimalRandom(start, end, floatNum) - - if rand.Cmp(lastPercent) != 0 { - break - } +func processStopLossOrder(order models.LinePreOrder) error { + price := utility.StrToDecimal(order.Price) + stopLoss := dto.StopLossRedisList{ + Id: order.Id, + PId: order.Pid, + ApiId: order.ApiId, + OrderTye: order.OrderType, + OrderCategory: order.OrderCategory, + Price: price, + SymbolType: order.SymbolType, + Symbol: order.Symbol, + Site: order.Site, } - return rand + stoplossVal, _ := sonic.MarshalString(&stopLoss) + stoplossKey := fmt.Sprintf(rediskey.SpotStopLossList, global.EXCHANGE_BINANCE) + + if stoplossVal == "" { + return errors.New("stoplossVal is empty") + } + + if err := helper.DefaultRedis.RPushList(stoplossKey, stoplossVal); err != nil { + return err + } + + return nil } func GetSystemSetting(db *gorm.DB) (models.LineSystemSetting, error) { diff --git a/services/futureservice/binancemarket.go b/services/futureservice/binancemarket.go index 5b719f1..72ea0e3 100644 --- a/services/futureservice/binancemarket.go +++ b/services/futureservice/binancemarket.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "fmt" - "go-admin/common/const/rediskey" "go-admin/common/global" "go-admin/common/helper" "go-admin/config" @@ -118,16 +117,7 @@ func handleTickerAllMessage(msg []byte) { return } - pairs := make([]map[string]interface{}, 0) trades := make([]models.TradeSet, 0) - pairVal, _ := helper.DefaultRedis.GetString(rediskey.FutSymbolTicker) - - if pairVal != "" { - err := sonic.Unmarshal([]byte(pairVal), &pairs) - if err != nil { - log.Error("获取redis数据失败", zap.Error(err)) - } - } for _, data := range dataAll.Data { symbol := data["s"].(string) @@ -149,7 +139,6 @@ func handleTickerAllMessage(msg []byte) { tradeSet.LowPrice = utility.StringFloat64Cut(data["l"].(string), int32(tradeSet.PriceDigit)) tradeSet.Volume = utility.StringFloat64Cut(data["v"].(string), int32(tradeSet.AmountDigit)) tradeSet.QuoteVolume = utility.StringFloat64Cut(data["q"].(string), 5) - hasData := false trades = append(trades, tradeSet) tradeSetVal, _ := sonic.MarshalString(&tradeSet) @@ -158,56 +147,14 @@ func handleTickerAllMessage(msg []byte) { log.Error(symbol, "ticker@all ws处理失败", err) } } - - for index := range pairs { - if cacheSymbol, ok := pairs[index]["symbol"].(string); ok { - if cacheSymbol == symbol { - pairs[index]["price"] = tradeSet.LastPrice - hasData = true - break - } - } - } - - if !hasData { - pairs = append(pairs, map[string]interface{}{ - "symbol": symbol, - "price": tradeSet.LastPrice, - }) - } } if len(trades) > 0 { - for index := range trades { - if wsBin.WorkType == "normal" { - //主单触发 - utility.SafeGoParam(binanceservice.JudgeFuturesPrice, trades[index]) - //止损信息 - utility.SafeGoParam(binanceservice.JudgeFuturesStoplossPrice, trades[index]) - //加仓信息 - utility.SafeGoParam(binanceservice.JudgeFuturesAddPositionPrice, trades[index]) - //对冲平仓 - utility.SafeGoParam(binanceservice.JudgeFuturesHedgeClosePosition, trades[index]) - //保险对冲 - utility.SafeGoParam(binanceservice.JudgeFuturesProtectHedge, trades[index]) - } else { - //合约对冲主动平仓 - // utility.SafeGoParam(binanceservice.FutureClosePositionTrigger, trades[index]) - binanceservice.FutureClosePositionTrigger(trades[index]) - } - } - } - - if wsBin.WorkType == "normal" { - if len(pairs) > 0 { - pairVal, _ = sonic.MarshalString(&pairs) - - if pairVal != "" { - if err := helper.DefaultRedis.SetString(rediskey.FutSymbolTicker, pairVal); err != nil { - log.Error("pair@all ws处理合约价格失败", err) - } - } + //主单触发 + utility.SafeGoParam(binanceservice.JudgeFuturesPrice, trades[index]) + //止损信息 + // utility.SafeGoParam(binanceservice.JudgeFuturesStoplossPrice, trades[index]) } } } diff --git a/services/spotservice/binancemarket.go b/services/spotservice/binancemarket.go index cccdc25..26f3062 100644 --- a/services/spotservice/binancemarket.go +++ b/services/spotservice/binancemarket.go @@ -218,26 +218,16 @@ func handleTickerMessage(msg []byte) { tradeSet.LowPrice = utility.StringFloat64Cut(dataMap["l"].(string), int32(tradeSet.PriceDigit)) tradeSet.Volume = utility.StringFloat64Cut(dataMap["v"].(string), int32(tradeSet.AmountDigit)) tradeSet.QuoteVolume = utility.StringFloat64Cut(dataMap["q"].(string), 5) - hasData := false for index := range pairs { if symbol, ok := pairs[index]["symbol"].(string); ok { if symbol == symbolName { - hasData = true pairs[index]["price"] = tradeSet.LastPrice break } } } - if !hasData { - pairs = append(pairs, map[string]interface{}{ - "symbol": symbolName, - "price": tradeSet.LastPrice, - }, - ) - } - trades = append(trades, tradeSet) tcVal, _ = sonic.MarshalString(&tradeSet) @@ -251,35 +241,11 @@ func handleTickerMessage(msg []byte) { //判断触发现货下单 if len(trades) > 0 { for index := range trades { - if wsBin.WorkType == "normal" { - // 主单触发 - utility.SafeGoParam(binanceservice.JudgeSpotPrice, trades[index]) + // 主单触发 + utility.SafeGoParam(binanceservice.JudgeSpotPrice, trades[index]) - // 止损单 - utility.SafeGoParam(binanceservice.JudgeSpotStopLoss, trades[index]) - - // 触发加仓 - utility.SafeGoParam(binanceservice.JudgeSpotAddPosition, trades[index]) - - // 对冲平仓 - utility.SafeGoParam(binanceservice.JudgeSpotHedgeClosePosition, trades[index]) - // 保险对冲 - utility.SafeGoParam(binanceservice.JudgeSpotProtectHedge, trades[index]) - } else { - //todo - } - } - } - - if wsBin.WorkType == "normal" { - if len(pairs) > 0 { - pairsVal, _ = sonic.MarshalString(&pairs) - - if pairsVal != "" { - if err := helper.DefaultRedis.SetString(rediskey.SpotSymbolTicker, pairsVal); err != nil { - log.Error("redis保存", rediskey.SpotSymbolTicker, "失败,", pairs) - } - } + // 止损单 + // utility.SafeGoParam(binanceservice.JudgeSpotStopLoss, trades[index]) } } }