diff --git a/app/admin/apis/line_pre_order.go b/app/admin/apis/line_pre_order.go index 1af6d1c..8b68bd1 100644 --- a/app/admin/apis/line_pre_order.go +++ b/app/admin/apis/line_pre_order.go @@ -581,3 +581,24 @@ func (e LinePreOrder) QueryOrder(c *gin.Context) { } e.OK(res, "操作成功") } + +func (e LinePreOrder) QueryAiCoinPrice(c *gin.Context) { + s := service.LinePreOrder{} + req := dto.QueryAiCoinPriceReq{} + 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 + } + res, err := s.QueryAiCoinPrice(&req) + if err != nil { + e.Error(500, err, err.Error()) + return + } + e.OK(res, "操作成功") +} diff --git a/app/admin/router/line_pre_order.go b/app/admin/router/line_pre_order.go index c05884b..adc6a95 100644 --- a/app/admin/router/line_pre_order.go +++ b/app/admin/router/line_pre_order.go @@ -36,6 +36,7 @@ func registerLinePreOrderRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM r.POST("closePosition", actions.PermissionAction(), api.ClosePosition) // 平仓 r.GET("getOrderPage", actions.PermissionAction(), api.GetOrderPage) //订单列表 r.POST("clearUnTriggered", actions.PermissionAction(), api.ClearUnTriggered) // 清除待触发的交易对 + r.POST("aiCoinPrice", actions.PermissionAction(), api.QueryAiCoinPrice) //获取aiCoin买入点 } } diff --git a/app/admin/service/dto/line_pre_order.go b/app/admin/service/dto/line_pre_order.go index 93cf3b6..6264e34 100644 --- a/app/admin/service/dto/line_pre_order.go +++ b/app/admin/service/dto/line_pre_order.go @@ -442,6 +442,10 @@ type QueryOrderReq struct { Symbol string `json:"symbol"` //交易对 } +type QueryAiCoinPriceReq struct { + Symbol string `json:"symbol"` //交易对 +} + type SpotQueryOrderResp struct { Symbol string `json:"symbol"` OrderId int `json:"orderId"` diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index 52e702a..6072b3f 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -1310,3 +1310,9 @@ func (e *LinePreOrder) QueryOrder(req *dto.QueryOrderReq) (res interface{}, err } return nil, err } + +func (e *LinePreOrder) QueryAiCoinPrice(req *dto.QueryAiCoinPriceReq) (models.LineDirection, error) { + var info models.LineDirection + err := e.Orm.Model(&models.LineDirection{}).Where("symbol = ?", req.Symbol).Find(&info).Error + return info, err +} 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 +}