diff --git a/app/admin/apis/line_pre_order.go b/app/admin/apis/line_pre_order.go index 95bbacc..1af6d1c 100644 --- a/app/admin/apis/line_pre_order.go +++ b/app/admin/apis/line_pre_order.go @@ -464,7 +464,9 @@ func (e LinePreOrder) CancelOpenOrder(c *gin.Context) { } errs := make([]error, 0) errStr := make([]string, 0) - s.CancelOpenOrder(&req, &errs) + if req.ExchangeType == global.EXCHANGE_BINANCE { + s.CancelOpenOrder(&req, &errs) + } if len(errs) > 0 { for _, err2 := range errs { errStr = append(errStr, err2.Error()) @@ -520,10 +522,13 @@ func (e LinePreOrder) ClosePosition(c *gin.Context) { } errs := make([]error, 0) errStr := make([]string, 0) - if req.CloseType == 1 { - s.SpotClosePosition(&req, &errs) - } else { - s.FutClosePosition(&req, &errs) + + if req.ExchangeType == global.EXCHANGE_BINANCE { + if req.CloseType == 1 { + s.SpotClosePosition(&req, &errs) + } else { + s.FutClosePosition(&req, &errs) + } } if len(errs) > 0 { for _, err2 := range errs { diff --git a/app/admin/service/dto/line_pre_order.go b/app/admin/service/dto/line_pre_order.go index f4acc99..6b4e24a 100644 --- a/app/admin/service/dto/line_pre_order.go +++ b/app/admin/service/dto/line_pre_order.go @@ -198,7 +198,6 @@ type LineAddPreOrderReq struct { CoverType int `json:"cover_type"` //对冲类型 0=无对冲 1= 现货对合约 2=合约对合约 3 合约对现货 ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) - TakeProfitRatio decimal.Decimal `json:"take_profit"` //主单止盈比例 ReducePriceRatio decimal.Decimal `json:"reduce_price"` //主单减仓价格百分比 ReduceNumRatio decimal.Decimal `json:"reduce_num"` //主单减仓数量百分比 ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比 @@ -255,7 +254,6 @@ type LineBatchAddPreOrderReq struct { CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货 ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) - TakeProfitRatio decimal.Decimal `json:"take_profit"` //主单止盈比例 ReducePriceRatio decimal.Decimal `json:"reduce_price"` //主单减仓价格百分比 ReduceNumRatio decimal.Decimal `json:"reduce_num"` //主单减仓数量百分比 ReduceTakeProfitRatio decimal.Decimal `json:"reduce_take_profit"` //主单减仓后止盈价百分比 @@ -300,11 +298,12 @@ type QuickAddPreOrderReq struct { // LeverReq 设置杠杆请求 type LeverReq struct { - ApiUserIds string `json:"api_user_ids"` - Symbol string `json:"symbol"` - Leverage int `json:"leverage"` - GroupId int `json:"group_id"` - IsAll int `json:"is_all"` // 1= 全部 0=不是全部 + ApiUserIds string `json:"api_user_ids"` + Symbol string `json:"symbol"` + Leverage int `json:"leverage"` + GroupId int `json:"group_id"` + IsAll int `json:"is_all"` // 1= 全部 0=不是全部 + ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type } func (c LeverReq) CheckParams() error { @@ -318,18 +317,20 @@ func (c LeverReq) CheckParams() error { } type MarginTypeReq struct { - ApiUserIds string `json:"api_user_ids"` - Symbol string `json:"symbol"` // 交易对 - MarginType string `json:"margin_type"` //全仓 CROSSED 逐仓 ISOLATED - GroupId int `json:"group_id"` // 交易对组id - IsAll int `json:"is_all"` // 1= 全部 0=不是全部 + ApiUserIds string `json:"api_user_ids"` + Symbol string `json:"symbol"` // 交易对 + MarginType string `json:"margin_type"` //全仓 CROSSED 逐仓 ISOLATED + GroupId int `json:"group_id"` // 交易对组id + IsAll int `json:"is_all"` // 1= 全部 0=不是全部 + ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type } type CancelOpenOrderReq struct { - ApiId int `json:"api_id"` - Symbol string `json:"symbol"` - OrderSn string `json:"order_sn"` - OrderType int `json:"order_type"` + ApiId int `json:"api_id"` + Symbol string `json:"symbol"` + OrderSn string `json:"order_sn"` + OrderType int `json:"order_type"` + ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type } type GetChildOrderReq struct { @@ -410,10 +411,11 @@ func (m *ManuallyCover) CheckParams() error { // ClosePosition 平仓请求 type ClosePosition struct { - ApiId int `json:"api_id"` //api-user 用户id - Symbol string `json:"symbol"` // 交易对 - Rate string `json:"rate"` //限价平仓百分比 - CloseType int `json:"close_type"` //现货平仓=1 合约平仓=2 + ApiId int `json:"api_id"` //api-user 用户id + Symbol string `json:"symbol"` // 交易对 + Rate string `json:"rate"` //限价平仓百分比 + CloseType int `json:"close_type"` //现货平仓=1 合约平仓=2 + ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type } func (m *ClosePosition) CheckParams() error { diff --git a/app/admin/service/line_pre_order.go b/app/admin/service/line_pre_order.go index 6fa8576..3b8a6f1 100644 --- a/app/admin/service/line_pre_order.go +++ b/app/admin/service/line_pre_order.go @@ -255,7 +255,7 @@ func (e *LinePreOrder) Remove(d *dto.LinePreOrderDeleteReq, p *actions.DataPermi } if len(ints) > 0 { - e.Orm.Model(&models.LinePreOrder{}).Where("pid >0 AND pid in ?", ints).Unscoped().Delete(&models.LinePreOrder{}) + e.Orm.Model(&models.LinePreOrder{}).Where("main_id >0 AND main_id in ?", ints).Unscoped().Delete(&models.LinePreOrder{}) } return nil } @@ -397,7 +397,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP //订单配置信息 preOrderExts := make([]models.LinePreOrderExt, 0) defultExt := models.LinePreOrderExt{ - TakeProfitRatio: req.TakeProfitRatio, + TakeProfitRatio: utility.StringToDecimal(req.Profit), ReducePriceRatio: req.ReducePriceRatio, ReduceNumRatio: req.ReduceNumRatio, ReduceTakeProfitRatio: req.ReduceTakeProfitRatio, @@ -441,6 +441,10 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP preOrderExts[index].MainOrderId = AddOrder.Id } + err = tx.Model(&models.LinePreOrderExt{}).Create(&preOrderExts).Error + if err != nil { + return err + } list := dto.PreOrderRedisList{ Id: AddOrder.Id, Symbol: AddOrder.Symbol, @@ -506,7 +510,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP // CheckRepeatOrder 检查重复下单 检查基础货币 func (e *LinePreOrder) CheckRepeatOrder(orderType int, apiUserId, site, baseCoin string) int64 { var count int64 - e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol like ? AND order_type = ? AND site = ? AND `status` IN (1,5)", apiUserId, baseCoin+"%", orderType, site).Count(&count) + e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol like ? AND order_type = ? AND site = ? AND `status` IN (1,5,6)", apiUserId, baseCoin+"%", orderType, site).Count(&count) return count } @@ -650,7 +654,7 @@ func (e *LinePreOrder) QuickAddPreOrder(quickReq *dto.QuickAddPreOrderReq, p *ac // Lever 设置杠杆 func (e *LinePreOrder) Lever(req *dto.LeverReq, p *actions.DataPermission, errs *[]error) { users := make([]models.LineApiUser, 0) - err := e.Orm.Model(&models.LineApiUser{}).Where("id in ? ", strings.Split(req.ApiUserIds, ",")).Find(&users).Error + err := e.Orm.Model(&models.LineApiUser{}).Where("id in ? AND exchange_type = ?", strings.Split(req.ApiUserIds, ","), req.ExchangeType).Find(&users).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { *errs = append(*errs, errors.New(fmt.Sprintf("设置杠杆失败:%+v", err.Error()))) return @@ -660,14 +664,14 @@ func (e *LinePreOrder) Lever(req *dto.LeverReq, p *actions.DataPermission, errs symbols = req.Symbol } else { var symbolGroupInfo models.LineSymbolGroup - e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", req.GroupId).Find(&symbolGroupInfo) + e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ? AND exchange_type = ?", req.GroupId, req.ExchangeType).Find(&symbolGroupInfo) symbols = symbolGroupInfo.Symbol } if req.IsAll == 1 { lineSymbols := make([]models.LineSymbol, 0) futSymbols := make([]string, 0) - e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = '1'").Find(&lineSymbols) + e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = '1' AND exchange_type = ?", req.ExchangeType).Find(&lineSymbols) for _, symbol := range lineSymbols { futSymbols = append(futSymbols, symbol.Symbol) } @@ -676,6 +680,15 @@ func (e *LinePreOrder) Lever(req *dto.LeverReq, p *actions.DataPermission, errs } } + if req.ExchangeType == global.EXCHANGE_BINANCE { + e.SetBinanceLever(req, users, symbols, errs) + } + + return +} + +// SetBinanceLever 设置币安杠杆 +func (e *LinePreOrder) SetBinanceLever(req *dto.LeverReq, users []models.LineApiUser, symbols string, errs *[]error) { for _, user := range users { var client *helper.BinanceClient if user.UserPass == "" { @@ -707,38 +720,10 @@ func (e *LinePreOrder) Lever(req *dto.LeverReq, p *actions.DataPermission, errs } } } - return } -// MarginType 设置仓位模式 -func (e *LinePreOrder) MarginType(req *dto.MarginTypeReq, p *actions.DataPermission, errs *[]error) { - users := make([]models.LineApiUser, 0) - err := e.Orm.Model(&models.LineApiUser{}).Where("id in ? ", strings.Split(req.ApiUserIds, ",")).Find(&users).Error - if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - *errs = append(*errs, errors.New(fmt.Sprintf("设置杠杆失败:%+v", err.Error()))) - return - } - var symbols string - if req.Symbol != "" { - symbols = req.Symbol - } else { - var symbolGroupInfo models.LineSymbolGroup - e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", req.GroupId).Find(&symbolGroupInfo) - symbols = symbolGroupInfo.Symbol - } - - if req.IsAll == 1 { - lineSymbols := make([]models.LineSymbol, 0) - futSymbols := make([]string, 0) - e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = '1'").Find(&lineSymbols) - for _, symbol := range lineSymbols { - futSymbols = append(futSymbols, symbol.Symbol) - } - if len(futSymbols) != 0 { - symbols = strings.Join(futSymbols, ",") - } - } - +// SetBinanceMarginType 设置币安保证金模式 +func (e *LinePreOrder) SetBinanceMarginType(req *dto.MarginTypeReq, users []models.LineApiUser, symbols string, errs *[]error) { for _, user := range users { var client *helper.BinanceClient if user.UserPass == "" { @@ -776,6 +761,40 @@ func (e *LinePreOrder) MarginType(req *dto.MarginTypeReq, p *actions.DataPermiss } } +// MarginType 设置仓位模式 +func (e *LinePreOrder) MarginType(req *dto.MarginTypeReq, p *actions.DataPermission, errs *[]error) { + users := make([]models.LineApiUser, 0) + err := e.Orm.Model(&models.LineApiUser{}).Where("id in ? ", strings.Split(req.ApiUserIds, ",")).Find(&users).Error + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + *errs = append(*errs, errors.New(fmt.Sprintf("设置杠杆失败:%+v", err.Error()))) + return + } + var symbols string + if req.Symbol != "" { + symbols = req.Symbol + } else { + var symbolGroupInfo models.LineSymbolGroup + e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", req.GroupId).Find(&symbolGroupInfo) + symbols = symbolGroupInfo.Symbol + } + + if req.IsAll == 1 { + lineSymbols := make([]models.LineSymbol, 0) + futSymbols := make([]string, 0) + e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = '1'").Find(&lineSymbols) + for _, symbol := range lineSymbols { + futSymbols = append(futSymbols, symbol.Symbol) + } + if len(futSymbols) != 0 { + symbols = strings.Join(futSymbols, ",") + } + } + + if req.ExchangeType == global.EXCHANGE_BINANCE { + e.SetBinanceMarginType(req, users, symbols, errs) + } +} + // CancelOpenOrder 取消委托 func (e *LinePreOrder) CancelOpenOrder(req *dto.CancelOpenOrderReq, errs *[]error) { newClientOrderIdList := make([]string, 0) @@ -805,14 +824,14 @@ func (e *LinePreOrder) CancelOpenOrder(req *dto.CancelOpenOrderReq, errs *[]erro } } else { var orderList []models.LinePreOrder - e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND pid = 0 status = '5' AND order_type = ?", req.ApiId, strconv.Itoa(req.OrderType)).Find(&orderList) + e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND main_id = 0 status = '5'", req.ApiId).Find(&orderList) if len(orderList) <= 0 { *errs = append(*errs, fmt.Errorf("没有可撤销的委托")) return } for _, order := range orderList { - if order.OrderType == global.SYMBOL_SPOT { + if order.SymbolType == global.SYMBOL_SPOT { err := spotApi.CancelOpenOrderByOrderSn(apiUserInfo, req.Symbol, req.OrderSn) if err != nil { *errs = append(*errs, fmt.Errorf("取消委托失败:%+v", err.Error())) @@ -1033,6 +1052,7 @@ func (e *LinePreOrder) SpotClosePosition(position *dto.ClosePosition, errs *[]er order := models.LinePreOrder{ ExchangeType: global.EXCHANGE_BINANCE, Pid: list.Id, + MainId: list.Id, ApiId: list.ApiId, GroupId: "0", Symbol: list.Symbol, @@ -1052,6 +1072,7 @@ func (e *LinePreOrder) SpotClosePosition(position *dto.ClosePosition, errs *[]er ExpireTime: time.Now().Add(time.Hour * 24 * 30), MainOrderType: list.MainOrderType, Child: nil, + OrderCategory: 1, } err := e.Orm.Model(&models.LinePreOrder{}).Create(&order).Error if err != nil { @@ -1080,9 +1101,9 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err //查询已经开仓的合约交易对 var futList []models.LinePreOrder if position.Symbol == "" { - e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = 6 AND order_category=2 AND order_type =0", position.ApiId).Find(&futList) + e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = 6 AND order_type =0 AND main_id = 0", position.ApiId).Find(&futList) } else { - e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol = ? AND status = 6 AND order_category=2 AND order_type = 0", position.ApiId, position.Symbol).Find(&futList) + e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol = ? AND status = 6 AND order_type = 0 AND main_id = 0", position.ApiId, position.Symbol).Find(&futList) } if len(futList) <= 0 { *errs = append(*errs, fmt.Errorf("api_id:%d 没有可平仓的交易对", position.ApiId)) @@ -1140,6 +1161,7 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err order := models.LinePreOrder{ Pid: parentId, ApiId: list.ApiId, + MainId: list.Id, GroupId: "0", Symbol: list.Symbol, QuoteSymbol: list.QuoteSymbol, @@ -1158,6 +1180,7 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err ExpireTime: time.Now().Add(24 * 30 * time.Hour), MainOrderType: list.MainOrderType, Child: nil, + OrderCategory: 1, } err = e.Orm.Model(&models.LinePreOrder{}).Create(&order).Error if err != nil { @@ -1193,7 +1216,7 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err // ClearUnTriggered 清除待触发的交易对 func (e *LinePreOrder) ClearUnTriggered() error { var orderLists []models.LinePreOrder - e.Orm.Model(&models.LinePreOrder{}).Where("pid = 0 AND status = '0'").Find(&orderLists).Unscoped().Delete(&models.LinePreOrder{}) + e.Orm.Model(&models.LinePreOrder{}).Where("main_id = 0 AND pid = 0 AND status = '0'").Find(&orderLists).Unscoped().Delete(&models.LinePreOrder{}) for _, order := range orderLists { redisList := dto.PreOrderRedisList{ @@ -1215,7 +1238,7 @@ func (e *LinePreOrder) ClearUnTriggered() error { key := fmt.Sprintf(rediskey.PreSpotOrderList, order.ExchangeType) helper.DefaultRedis.LRem(key, string(marshal)) } - e.Orm.Model(&models.LinePreOrder{}).Where("pid = ?", order.Id).Unscoped().Delete(&models.LinePreOrder{}) + e.Orm.Model(&models.LinePreOrder{}).Where("main_id = ?", order.Id).Unscoped().Delete(&models.LinePreOrder{}) } return nil } diff --git a/app/jobs/jobs.go b/app/jobs/jobs.go index 06603b2..e1f1760 100644 --- a/app/jobs/jobs.go +++ b/app/jobs/jobs.go @@ -2,9 +2,15 @@ package jobs import ( "errors" + "fmt" + "github.com/jinzhu/copier" "go-admin/app/admin/models" "go-admin/app/admin/service" "go-admin/app/admin/service/dto" + "go-admin/common/global" + "go-admin/pkg/utility" + "go-admin/pkg/utility/snowflakehelper" + "go-admin/services/binanceservice" "go-admin/services/fileservice" "strconv" "strings" @@ -28,6 +34,9 @@ type ClearLogJob struct { type AutoPlaceOrder struct { } +type CancelOrderByTime struct { +} + // 初始化合约交易对 func (t InitFuturesSymbol) Exec(arg interface{}) error { str := time.Now().Format(timeFormat) + " [INFO] JobCore InitFuturesSymbol exec success" @@ -123,3 +132,90 @@ func (t AutoPlaceOrder) Exec(arg interface{}) error { } return nil } + +func (t CancelOrderByTime) Exec(arg interface{}) error { + + str := time.Now().Format(timeFormat) + " [INFO] JobCore ClearLogJob exec success" + defer logger.Info(str) + var db *gorm.DB + + for _, item := range sdk.Runtime.GetDb() { + db = item + break + } + + var req = new(dto.SysConfigByKeyReq) + var resp = new(dto.GetSysConfigByKEYForServiceResp) + req.ConfigKey = "limitOrderTimeoutDuration" + serviceConfig := service.SysConfig{} + serviceConfig.Orm = db + serviceConfig.GetWithKey(req, resp) + + if resp.ConfigValue == "" { + return nil + } + limitOrderTimeoutDuration := utility.StringAsInt64(resp.ConfigValue) + orders := make([]models.LinePreOrder, 0) + err := db.Model(&models.LinePreOrder{}).Where("status = '5' AND main_order_type = 'LIMIT' AND updated_at < ?", time.Now().Add(-time.Duration(limitOrderTimeoutDuration)*time.Second)).Find(&orders).Error + if err != nil { + return err + } + spotApi := binanceservice.SpotRestApi{} + for _, order := range orders { + //现货 + if order.SymbolType == global.SYMBOL_SPOT { + var apiUserinfo models.LineApiUser + db.Model(&models.LineApiUser{}).Where("id = ?", order.ApiId).Find(&apiUserinfo) + 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 + } + } + 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 + } + err = spotApi.OrderPlace(db, 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 != nil { + logger.Error(fmt.Sprintf("重新下市价单失败 err:%+v", err)) + continue + } + } + } + + } + + //合约 + if order.SymbolType == global.SYMBOL_FUTURES { + + } + + } + return nil +} diff --git a/go.mod b/go.mod index 5e7b47b..7a05999 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/qiniu/go-sdk/v7 v7.18.2 - github.com/redis/go-redis/v9 v9.3.0 github.com/robfig/cron/v3 v3.0.1 github.com/rs/xid v1.2.1 github.com/shirou/gopsutil/v3 v3.23.10 @@ -143,6 +142,7 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/redis/go-redis/v9 v9.3.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shamsher31/goimgext v1.0.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect diff --git a/services/binanceservice/binanceservice_test.go b/services/binanceservice/binanceservice_test.go index 5c3f609..b3db562 100644 --- a/services/binanceservice/binanceservice_test.go +++ b/services/binanceservice/binanceservice_test.go @@ -108,11 +108,11 @@ func TestFutOrderPalce(t *testing.T) { func TestCancelOpenOrderByOrderSn(t *testing.T) { api := SpotRestApi{} - dsn := "root:root@tcp(192.168.1.12:3306)/gp-bian?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" + dsn := "root:root@tcp(192.168.1.12:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) var apiUserInfo models.LineApiUser - db.Model(&models.LineApiUser{}).Where("id = ?", 10).Find(&apiUserInfo) - err := api.CancelOpenOrderByOrderSn(apiUserInfo, "DOGEUSDT", "367836524202426368") + db.Model(&models.LineApiUser{}).Where("id = ?", 50).Find(&apiUserInfo) + err := api.CancelOpenOrderByOrderSn(apiUserInfo, "TRUMPUSDT", "1698362708") if err != nil { t.Log("err:", err) } else { @@ -194,3 +194,24 @@ func TestClosePosition(t *testing.T) { fmt.Println("err:", err) } + +func TestFutOrderPlace(t *testing.T) { + futureApi := FutRestApi{} + dsn := "root:root@tcp(192.168.1.12:3306)/go_exchange_single?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" + db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + err := futureApi.OrderPlace(db, FutOrderPlace{ + ApiId: 50, + Symbol: "ADAUSDT", + Side: "SELL", + Quantity: decimal.NewFromFloat(8), + Price: decimal.NewFromFloat(0.697), + SideType: "LIMIT", + OpenOrder: 0, + Profit: decimal.NewFromFloat(0.698), + StopPrice: decimal.NewFromFloat(0.698), + OrderType: "STOP", + NewClientOrderId: "5465465784222554477", + }) + fmt.Println("err:", err) + +} diff --git a/services/binanceservice/futuresbinancerest.go b/services/binanceservice/futuresbinancerest.go index c0d581c..af5fd4e 100644 --- a/services/binanceservice/futuresbinancerest.go +++ b/services/binanceservice/futuresbinancerest.go @@ -449,8 +449,15 @@ func (e FutRestApi) OrderPlace(orm *gorm.DB, params FutOrderPlace) error { paramsMaps["workingType"] = "MARK_PRICE" paramsMaps["timeInForce"] = "GTC" } + + if strings.ToUpper(params.OrderType) == "STOP" { + paramsMaps["price"] = params.Price.String() + paramsMaps["stopprice"] = params.StopPrice.String() + paramsMaps["workingType"] = "MARK_PRICE" + paramsMaps["timeInForce"] = "GTC" + } } - if strings.ToUpper(params.OrderType) != "STOP_MARKET" && strings.ToUpper(params.OrderType) != "TAKE_PROFIT_MARKET" { + if strings.ToUpper(params.OrderType) != "STOP_MARKET" && strings.ToUpper(params.OrderType) != "TAKE_PROFIT_MARKET" && strings.ToUpper(params.OrderType) != "STOP" && strings.ToUpper(params.OrderType) != "TAKE_PROFIT" { if strings.ToUpper(params.Side) == "BUY" { paramsMaps["positionSide"] = "LONG" } else {