From cb855452d1e8c990e00b30ae9b6e4e875e63b3f5 Mon Sep 17 00:00:00 2001 From: daichao <1078638034@qq.com> Date: Tue, 11 Feb 2025 09:39:15 +0800 Subject: [PATCH] code --- app/jobs/examples.go | 13 ++-- app/jobs/jobs.go | 157 +++++++++++++++++++++++++++++++------------ 2 files changed, 121 insertions(+), 49 deletions(-) diff --git a/app/jobs/examples.go b/app/jobs/examples.go index 73c03dc..5a7ed06 100644 --- a/app/jobs/examples.go +++ b/app/jobs/examples.go @@ -23,12 +23,13 @@ func InitJob() { jobList = map[string]JobExec{ "ExamplesOne": ExamplesOne{}, // ... - "DeleteExpireOrder": DeleteExpireOrder{}, //定时删除过期数据 - "UpRange": UpRange{}, //更新涨跌幅 - "InitFuturesSymbol": InitFuturesSymbol{}, //定时更新合约交易对 - "InitSpotSymbol": InitSpotSymbol{}, //定时更新现货交易对 - "ClearLogJob": ClearLogJob{}, //定时清理日志 - "AutoPlaceOrder": AutoPlaceOrder{}, //定时下单 + "DeleteExpireOrder": DeleteExpireOrder{}, //定时删除过期数据 + "UpRange": UpRange{}, //更新涨跌幅 + "InitFuturesSymbol": InitFuturesSymbol{}, //定时更新合约交易对 + "InitSpotSymbol": InitSpotSymbol{}, //定时更新现货交易对 + "ClearLogJob": ClearLogJob{}, //定时清理日志 + "AutoPlaceOrder": AutoPlaceOrder{}, //定时下单 + "LimitOrderTimeoutDuration": LimitOrderTimeoutDuration{}, //定时取消限价单改下市价单 } } diff --git a/app/jobs/jobs.go b/app/jobs/jobs.go index 741207d..2b21de9 100644 --- a/app/jobs/jobs.go +++ b/app/jobs/jobs.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/jinzhu/copier" + "github.com/shopspring/decimal" "go-admin/app/admin/models" "go-admin/app/admin/service" "go-admin/app/admin/service/dto" @@ -34,7 +35,7 @@ type ClearLogJob struct { type AutoPlaceOrder struct { } -type CancelOrderByTime struct { +type LimitOrderTimeoutDuration struct { } // 初始化合约交易对 @@ -133,7 +134,7 @@ func (t AutoPlaceOrder) Exec(arg interface{}) error { return nil } -func (t CancelOrderByTime) Exec(arg interface{}) error { +func (t LimitOrderTimeoutDuration) Exec(arg interface{}) error { str := time.Now().Format(timeFormat) + " [INFO] JobCore ClearLogJob exec success" defer logger.Info(str) @@ -161,54 +162,16 @@ func (t CancelOrderByTime) Exec(arg interface{}) error { return err } spotApi := binanceservice.SpotRestApi{} + futApi := binanceservice.FutRestApi{} for _, order := range orders { var apiUserinfo models.LineApiUser db.Model(&models.LineApiUser{}).Where("id = ?", order.ApiId).Find(&apiUserinfo) //现货 if order.SymbolType == global.SYMBOL_SPOT { if order.ExchangeType == global.EXCHANGE_BINANCE { - for i := 0; i < 3; i++ { - err := spotApi.CancelOpenOrderByOrderSn(apiUserinfo, order.Symbol, order.OrderSn) - if err == nil || strings.Contains(err.Error(), "该交易对没有订单") { - break - } - } + err := t.ReSpotOrderPlace(db, order, apiUserinfo, spotApi) if err != nil { - logger.Error(fmt.Sprintf("取消现货委托失败:order_sn:%s err:%+v", order.OrderSn, err)) continue - } else { - newClientOrderId := snowflakehelper.GetOrderId() - - var newOrder models.LinePreOrder - copier.Copy(&newOrder, order) - newOrder.Id = 0 - newOrder.OrderSn = utility.Int64ToString(newClientOrderId) - newOrder.CreatedAt = time.Now() - newOrder.MainOrderType = "MARKET" - err = db.Model(&models.LinePreOrder{}).Create(&newOrder).Error - if err != nil { - logger.Error(fmt.Sprintf("生成新市价单失败 err:%+v", err)) - continue - } - params := binanceservice.OrderPlacementService{ - ApiId: order.ApiId, - Symbol: order.Symbol, - Side: order.Site, - Type: "MARKET", - TimeInForce: "GTC", - Price: utility.StringToDecimal(order.Price), - Quantity: utility.StringToDecimal(order.Num), - NewClientOrderId: utility.Int64ToString(newClientOrderId), - } - if err := spotApi.OrderPlace(db, params); err != nil { - logger.Error(fmt.Sprintf("重新下市价单失败 err:%+v", err)) - err := db.Model(&models.LinePreOrder{}).Where("id = ? AND status = 0", newOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error - - if err != nil { - logger.Error("下单失败后修改订单失败") - continue - } - } } } @@ -216,9 +179,117 @@ func (t CancelOrderByTime) Exec(arg interface{}) error { //合约 if order.SymbolType == global.SYMBOL_FUTURES { - + if order.ExchangeType == global.EXCHANGE_BINANCE { + err := t.ReFutOrderPlace(db, order, apiUserinfo, futApi) + if err != nil { + continue + } + } } } return nil } + +// ReSpotOrderPlace 重下现货市价单 +func (t LimitOrderTimeoutDuration) ReSpotOrderPlace(db *gorm.DB, order models.LinePreOrder, apiUserinfo models.LineApiUser, spotApi binanceservice.SpotRestApi) error { + var err error + for i := 0; i < 3; i++ { + err := spotApi.CancelOpenOrderByOrderSn(apiUserinfo, order.Symbol, order.OrderSn) + if err == nil || strings.Contains(err.Error(), "该交易对没有订单") { + break + } + } + if err != nil { + logger.Error(fmt.Sprintf("取消现货委托失败:order_sn:%s err:%+v", order.OrderSn, err)) + return err + } else { + newClientOrderId := snowflakehelper.GetOrderId() + + var newOrder models.LinePreOrder + copier.Copy(&newOrder, order) + newOrder.Id = 0 + newOrder.OrderSn = utility.Int64ToString(newClientOrderId) + newOrder.CreatedAt = time.Now() + newOrder.MainOrderType = "MARKET" + err = db.Model(&models.LinePreOrder{}).Create(&newOrder).Error + if err != nil { + logger.Error(fmt.Sprintf("生成新市价单失败 err:%+v", err)) + return err + } + params := binanceservice.OrderPlacementService{ + ApiId: order.ApiId, + Symbol: order.Symbol, + Side: order.Site, + Type: "MARKET", + TimeInForce: "GTC", + Price: utility.StringToDecimal(order.Price), + Quantity: utility.StringToDecimal(order.Num), + NewClientOrderId: utility.Int64ToString(newClientOrderId), + } + if err := spotApi.OrderPlace(db, params); err != nil { + logger.Error(fmt.Sprintf("重新下市价单失败 err:%+v", err)) + err := db.Model(&models.LinePreOrder{}).Where("id = ? AND status = 0", newOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error + + if err != nil { + logger.Error("下单失败后修改订单失败") + return err + } + } + } + + return nil +} + +// ReFutOrderPlace 重下合约市价单 +func (t LimitOrderTimeoutDuration) ReFutOrderPlace(db *gorm.DB, order models.LinePreOrder, apiUserinfo models.LineApiUser, futApi binanceservice.FutRestApi) error { + var err error + for i := 0; i < 3; i++ { + err := futApi.CancelFutOrder(apiUserinfo, order.Symbol, order.OrderSn) + if err == nil || strings.Contains(err.Error(), "该交易对没有订单") { + break + } + } + if err != nil { + logger.Error(fmt.Sprintf("取消现货委托失败:order_sn:%s err:%+v", order.OrderSn, err)) + return err + } else { + newClientOrderId := snowflakehelper.GetOrderId() + + var newOrder models.LinePreOrder + copier.Copy(&newOrder, order) + newOrder.Id = 0 + newOrder.OrderSn = utility.Int64ToString(newClientOrderId) + newOrder.CreatedAt = time.Now() + newOrder.MainOrderType = "MARKET" + err = db.Model(&models.LinePreOrder{}).Create(&newOrder).Error + if err != nil { + logger.Error(fmt.Sprintf("生成合约新市价单失败 err:%+v", err)) + return err + } + + params := binanceservice.FutOrderPlace{ + ApiId: order.ApiId, + Symbol: order.Symbol, + Side: order.Site, + Quantity: utility.StringToDecimal(order.Num), + Price: utility.StringToDecimal(order.Price), + SideType: "MARKET", + OpenOrder: 0, + Profit: decimal.Decimal{}, + StopPrice: decimal.Decimal{}, + OrderType: "MARKET", + NewClientOrderId: utility.Int64ToString(newClientOrderId), + } + + if err := futApi.OrderPlace(db, params); err != nil { + logger.Error(fmt.Sprintf("重新下合约市价单失败 err:%+v", err)) + err := db.Model(&models.LinePreOrder{}).Where("id = ? AND status = 0", newOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error + if err != nil { + logger.Error("下单失败后修改订单失败") + return err + } + } + } + return err +}