This commit is contained in:
2025-02-08 14:05:57 +08:00
parent c0b8749eef
commit 979ef507fe
30 changed files with 660 additions and 431 deletions

View File

@ -111,6 +111,12 @@ func (e LineApiGroup) Insert(c *gin.Context) {
e.Error(500, err, err.Error()) e.Error(500, err, err.Error())
return return
} }
if err := req.Valid(); err != nil {
e.Error(500, err, err.Error())
return
}
// 设置创建人 // 设置创建人
req.SetCreateBy(user.GetUserId(c)) req.SetCreateBy(user.GetUserId(c))

View File

@ -236,7 +236,7 @@ func (e LineApiUser) GetUser(c *gin.Context) {
} }
//p := actions.GetPermissionFromContext(c) //p := actions.GetPermissionFromContext(c)
list := make([]models.LineApiUser, 0) list := make([]models.LineApiUser, 0)
err = s.GetUser(&list) err = s.GetUser(&req, &list)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error()))
return return
@ -247,8 +247,10 @@ func (e LineApiUser) GetUser(c *gin.Context) {
// GetMainUser 获取主账号 // GetMainUser 获取主账号
func (e LineApiUser) GetMainUser(c *gin.Context) { func (e LineApiUser) GetMainUser(c *gin.Context) {
s := service.LineApiUser{} s := service.LineApiUser{}
req := dto.GetMainUserReq{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
@ -258,7 +260,7 @@ func (e LineApiUser) GetMainUser(c *gin.Context) {
} }
//p := actions.GetPermissionFromContext(c) //p := actions.GetPermissionFromContext(c)
list := make([]models.LineApiUser, 0) list := make([]models.LineApiUser, 0)
err = s.GetMainUser(&list) err = s.GetMainUser(&req, &list)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error()))
return return

View File

@ -245,7 +245,7 @@ func (e LineSymbol) SyncSpotSymbol(c *gin.Context) {
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
continue continue
} }
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, symbol) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbol)
//判断是否在黑名单里面 //判断是否在黑名单里面
for _, black := range symbolBlack { for _, black := range symbolBlack {
@ -283,6 +283,7 @@ func (e LineSymbol) SyncSpotSymbol(c *gin.Context) {
} }
} }
if lineSymbol.Id <= 0 { if lineSymbol.Id <= 0 {
lineSymbol.ExchangeType = global.EXCHANGE_BINANCE
lineSymbol.Symbol = symbol lineSymbol.Symbol = symbol
lineSymbol.BaseAsset = tradeSet.Coin lineSymbol.BaseAsset = tradeSet.Coin
lineSymbol.QuoteAsset = tradeSet.Currency lineSymbol.QuoteAsset = tradeSet.Currency
@ -308,7 +309,7 @@ func (e LineSymbol) SyncSpotSymbol(c *gin.Context) {
e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", group.Id).Update("symbol", join) e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", group.Id).Update("symbol", join)
} }
} }
e.Orm.Model(&models.LineSymbol{}).Where("symbol = ? AND type = 1", symbol).Unscoped().Delete(&models.LineSymbol{}) e.Orm.Model(&models.LineSymbol{}).Where("symbol = ? AND type = 1 AND exchange_type =?", symbol, global.EXCHANGE_BINANCE).Unscoped().Delete(&models.LineSymbol{})
} }
} }
@ -406,6 +407,7 @@ func (e LineSymbol) SyncFutSymbol(c *gin.Context) {
} }
if lineSymbol.Id <= 0 { if lineSymbol.Id <= 0 {
lineSymbol.ExchangeType = global.EXCHANGE_BINANCE
lineSymbol.Symbol = symbol lineSymbol.Symbol = symbol
lineSymbol.BaseAsset = tradeSet.Coin lineSymbol.BaseAsset = tradeSet.Coin
lineSymbol.QuoteAsset = tradeSet.Currency lineSymbol.QuoteAsset = tradeSet.Currency
@ -423,8 +425,8 @@ func (e LineSymbol) SyncFutSymbol(c *gin.Context) {
//如果在交易对组里面 //如果在交易对组里面
groups := make([]models.LineSymbolGroup, 0) groups := make([]models.LineSymbolGroup, 0)
//var symbolGroup []models.LineSymbolGroup //var symbolGroup []models.LineSymbolGroup
sql := "SELECT * FROM line_symbol_group WHERE FIND_IN_SET( ? , symbol) AND type = 2 AND deleted_at is NULL;" sql := "SELECT * FROM line_symbol_group WHERE FIND_IN_SET( ? , symbol) AND type = 2 AND exchange_type =? AND deleted_at is NULL;"
e.Orm.Model(&models.LineSymbolGroup{}).Exec(sql, symbol).Find(&groups) e.Orm.Model(&models.LineSymbolGroup{}).Exec(sql, symbol, global.EXCHANGE_BINANCE).Find(&groups)
for _, group := range groups { for _, group := range groups {
if group.Id > 0 { if group.Id > 0 {
split := strings.Split(group.Symbol, ",") split := strings.Split(group.Symbol, ",")
@ -433,7 +435,7 @@ func (e LineSymbol) SyncFutSymbol(c *gin.Context) {
e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", group.Id).Update("symbol", join) e.Orm.Model(&models.LineSymbolGroup{}).Where("id = ?", group.Id).Update("symbol", join)
} }
} }
e.Orm.Model(&models.LineSymbol{}).Where("symbol = ? AND type = 2", symbol).Unscoped().Delete(&models.LineSymbol{}) e.Orm.Model(&models.LineSymbol{}).Where("symbol = ? AND exchange_type =? AND type = 2", symbol, global.EXCHANGE_BINANCE).Unscoped().Delete(&models.LineSymbol{})
} }
} }
@ -450,8 +452,10 @@ func (e LineSymbol) SyncFutSymbol(c *gin.Context) {
// GetSymbol 获取现货和合约都有的交易对 // GetSymbol 获取现货和合约都有的交易对
func (e LineSymbol) GetSymbol(c *gin.Context) { func (e LineSymbol) GetSymbol(c *gin.Context) {
s := service.LineSymbol{} s := service.LineSymbol{}
req := dto.LineSymbolGetListReq{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
@ -460,7 +464,7 @@ func (e LineSymbol) GetSymbol(c *gin.Context) {
return return
} }
data, err := s.GetSymbol() data, err := s.GetSymbol(&req)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("获取失败,\r\n失败信息 %s", err.Error()))
return return

View File

@ -1,7 +1,7 @@
package apis package apis
import ( import (
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk/api" "github.com/go-admin-team/go-admin-core/sdk/api"
@ -29,18 +29,18 @@ type LineSymbolGroup struct {
// @Router /api/v1/line-symbol-group [get] // @Router /api/v1/line-symbol-group [get]
// @Security Bearer // @Security Bearer
func (e LineSymbolGroup) GetPage(c *gin.Context) { func (e LineSymbolGroup) GetPage(c *gin.Context) {
req := dto.LineSymbolGroupGetPageReq{} req := dto.LineSymbolGroupGetPageReq{}
s := service.LineSymbolGroup{} s := service.LineSymbolGroup{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req). Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
e.Logger.Error(err) e.Logger.Error(err)
e.Error(500, err, err.Error()) e.Error(500, err, err.Error())
return return
} }
p := actions.GetPermissionFromContext(c) p := actions.GetPermissionFromContext(c)
list := make([]models.LineSymbolGroup, 0) list := make([]models.LineSymbolGroup, 0)
@ -49,7 +49,7 @@ func (e LineSymbolGroup) GetPage(c *gin.Context) {
err = s.GetPage(&req, p, &list, &count) err = s.GetPage(&req, p, &list, &count)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("获取交易对组列表失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("获取交易对组列表失败,\r\n失败信息 %s", err.Error()))
return return
} }
e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
@ -66,7 +66,7 @@ func (e LineSymbolGroup) GetPage(c *gin.Context) {
func (e LineSymbolGroup) Get(c *gin.Context) { func (e LineSymbolGroup) Get(c *gin.Context) {
req := dto.LineSymbolGroupGetReq{} req := dto.LineSymbolGroupGetReq{}
s := service.LineSymbolGroup{} s := service.LineSymbolGroup{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req). Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
@ -82,10 +82,10 @@ func (e LineSymbolGroup) Get(c *gin.Context) {
err = s.Get(&req, p, &object) err = s.Get(&req, p, &object)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("获取交易对组列表失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("获取交易对组列表失败,\r\n失败信息 %s", err.Error()))
return return
} }
e.OK( object, "查询成功") e.OK(object, "查询成功")
} }
// Insert 创建交易对组列表 // Insert 创建交易对组列表
@ -99,25 +99,25 @@ func (e LineSymbolGroup) Get(c *gin.Context) {
// @Router /api/v1/line-symbol-group [post] // @Router /api/v1/line-symbol-group [post]
// @Security Bearer // @Security Bearer
func (e LineSymbolGroup) Insert(c *gin.Context) { func (e LineSymbolGroup) Insert(c *gin.Context) {
req := dto.LineSymbolGroupInsertReq{} req := dto.LineSymbolGroupInsertReq{}
s := service.LineSymbolGroup{} s := service.LineSymbolGroup{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req). Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
e.Logger.Error(err) e.Logger.Error(err)
e.Error(500, err, err.Error()) e.Error(500, err, err.Error())
return return
} }
// 设置创建人 // 设置创建人
req.SetCreateBy(user.GetUserId(c)) req.SetCreateBy(user.GetUserId(c))
err = s.Insert(&req) err = s.Insert(&req)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("创建交易对组列表失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("创建交易对组列表失败,\r\n失败信息 %s", err.Error()))
return return
} }
e.OK(req.GetId(), "创建成功") e.OK(req.GetId(), "创建成功")
@ -135,27 +135,27 @@ func (e LineSymbolGroup) Insert(c *gin.Context) {
// @Router /api/v1/line-symbol-group/{id} [put] // @Router /api/v1/line-symbol-group/{id} [put]
// @Security Bearer // @Security Bearer
func (e LineSymbolGroup) Update(c *gin.Context) { func (e LineSymbolGroup) Update(c *gin.Context) {
req := dto.LineSymbolGroupUpdateReq{} req := dto.LineSymbolGroupUpdateReq{}
s := service.LineSymbolGroup{} s := service.LineSymbolGroup{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req). Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
e.Logger.Error(err) e.Logger.Error(err)
e.Error(500, err, err.Error()) e.Error(500, err, err.Error())
return return
} }
req.SetUpdateBy(user.GetUserId(c)) req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c) p := actions.GetPermissionFromContext(c)
err = s.Update(&req, p) err = s.Update(&req, p)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("修改交易对组列表失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("修改交易对组列表失败,\r\n失败信息 %s", err.Error()))
return return
} }
e.OK( req.GetId(), "修改成功") e.OK(req.GetId(), "修改成功")
} }
// Delete 删除交易对组列表 // Delete 删除交易对组列表
@ -167,18 +167,18 @@ func (e LineSymbolGroup) Update(c *gin.Context) {
// @Router /api/v1/line-symbol-group [delete] // @Router /api/v1/line-symbol-group [delete]
// @Security Bearer // @Security Bearer
func (e LineSymbolGroup) Delete(c *gin.Context) { func (e LineSymbolGroup) Delete(c *gin.Context) {
s := service.LineSymbolGroup{} s := service.LineSymbolGroup{}
req := dto.LineSymbolGroupDeleteReq{} req := dto.LineSymbolGroupDeleteReq{}
err := e.MakeContext(c). err := e.MakeContext(c).
MakeOrm(). MakeOrm().
Bind(&req). Bind(&req).
MakeService(&s.Service). MakeService(&s.Service).
Errors Errors
if err != nil { if err != nil {
e.Logger.Error(err) e.Logger.Error(err)
e.Error(500, err, err.Error()) e.Error(500, err, err.Error())
return return
} }
// req.SetUpdateBy(user.GetUserId(c)) // req.SetUpdateBy(user.GetUserId(c))
p := actions.GetPermissionFromContext(c) p := actions.GetPermissionFromContext(c)
@ -186,7 +186,7 @@ func (e LineSymbolGroup) Delete(c *gin.Context) {
err = s.Remove(&req, p) err = s.Remove(&req, p)
if err != nil { if err != nil {
e.Error(500, err, fmt.Sprintf("删除交易对组列表失败,\r\n失败信息 %s", err.Error())) e.Error(500, err, fmt.Sprintf("删除交易对组列表失败,\r\n失败信息 %s", err.Error()))
return return
} }
e.OK( req.GetId(), "删除成功") e.OK(req.GetId(), "删除成功")
} }

View File

@ -7,10 +7,11 @@ import (
type LineApiGroup struct { type LineApiGroup struct {
models.Model models.Model
GroupName string `json:"groupName" gorm:"type:varchar(255);comment:用户组名称"` ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所 字典exchange_type"`
ApiUserId string `json:"apiUserId" gorm:"type:varchar(255);comment:绑定的api账户id"` GroupName string `json:"groupName" gorm:"type:varchar(255);comment:用户组名称"`
AApiName string `json:"a_api_name" gorm:"-"` ApiUserId string `json:"apiUserId" gorm:"type:varchar(255);comment:绑定的api账户id"`
BApiName string `json:"b_api_name" gorm:"-"` AApiName string `json:"a_api_name" gorm:"-"`
BApiName string `json:"b_api_name" gorm:"-"`
models.ModelTime models.ModelTime
models.ControlBy models.ControlBy
} }

View File

@ -7,20 +7,21 @@ import (
type LineApiUser struct { type LineApiUser struct {
models.Model models.Model
UserId int64 `json:"userId" gorm:"type:int unsigned;comment:用户id"` ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型(字典 exchange_type)"`
JysId int64 `json:"jysId" gorm:"type:int;comment:关联交易所账号id"` UserId int64 `json:"userId" gorm:"type:int unsigned;comment:用户id"`
ApiName string `json:"apiName" gorm:"type:varchar(255);comment:api用户名"` JysId int64 `json:"jysId" gorm:"type:int;comment:关联交易所账号id"`
ApiKey string `json:"apiKey" gorm:"type:varchar(255);comment:apiKey"` ApiName string `json:"apiName" gorm:"type:varchar(255);comment:api用户名"`
ApiSecret string `json:"apiSecret" gorm:"type:varchar(255);comment:apiSecret"` ApiKey string `json:"apiKey" gorm:"type:varchar(255);comment:apiKey"`
IpAddress string `json:"ipAddress" gorm:"type:varchar(255);comment:代理地址"` ApiSecret string `json:"apiSecret" gorm:"type:varchar(255);comment:apiSecret"`
UserPass string `json:"userPass" gorm:"type:varchar(255);comment:代码账号密码"` IpAddress string `json:"ipAddress" gorm:"type:varchar(255);comment:代理地址"`
AdminId int64 `json:"adminId" gorm:"type:int unsigned;comment:管理员id"` UserPass string `json:"userPass" gorm:"type:varchar(255);comment:代码账号密码"`
Affiliation int64 `json:"affiliation" gorm:"type:int;comment:归属:1=现货,2=合约,3=现货合约"` AdminId int64 `json:"adminId" gorm:"type:int unsigned;comment:管理员id"`
AdminShow int64 `json:"adminShow" gorm:"type:int;comment:是否超管可见:1=是,0=否"` Affiliation int64 `json:"affiliation" gorm:"type:int;comment:归属:1=现货,2=合约,3=现货合约"`
Site string `json:"site" gorm:"type:enum('1','2','3');comment:允许下单的方向:1=多;2=空;3=多空"` AdminShow int64 `json:"adminShow" gorm:"type:int;comment:是否超管可见:1=是,0=否"`
Subordinate string `json:"subordinate" gorm:"type:enum('0','1','2');comment:从属关系:0=未绑定关系;1=主账号;2=副帐号"` Site string `json:"site" gorm:"type:enum('1','2','3');comment:允许下单的方向:1=多;2=空;3=多空"`
GroupId int64 `json:"groupId" gorm:"type:int unsigned;comment:所属组id"` Subordinate string `json:"subordinate" gorm:"type:enum('0','1','2');comment:从属关系:0=未绑定关系;1=主账号;2=副帐号"`
OpenStatus int64 `json:"openStatus" gorm:"type:int unsigned;comment:开启状态 0=关闭 1=开启"` GroupId int64 `json:"groupId" gorm:"type:int unsigned;comment:所属组id"`
OpenStatus int64 `json:"openStatus" gorm:"type:int unsigned;comment:开启状态 0=关闭 1=开启"`
SpotLastTime string `json:"spotLastTime" gorm:"-"` //现货websocket最后通信时间 SpotLastTime string `json:"spotLastTime" gorm:"-"` //现货websocket最后通信时间
FuturesLastTime string `json:"futuresLastTime" gorm:"-"` //合约websocket最后通信时间 FuturesLastTime string `json:"futuresLastTime" gorm:"-"` //合约websocket最后通信时间

View File

@ -34,7 +34,8 @@ type LinePreOrder struct {
CoverType int `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"` CoverType int `json:"coverType" gorm:"type:int unsigned;omitempty;comment:对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货"`
ExpireTime time.Time `json:"expireTime" gorm:"comment:过期时间"` ExpireTime time.Time `json:"expireTime" gorm:"comment:过期时间"`
MainOrderType string `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价LIMIT市价(MARKET)"` MainOrderType string `json:"mainOrderType" gorm:"type:enum;comment:第一笔(主单类型) 限价LIMIT市价(MARKET)"`
HedgeBuyTotal decimal.Decimal `json:"hedgeBuyTotal" gorm:"type:decimal(10,2);comment:对冲买总金额U"` HedgeBuyType int `json:"hedge_buy_type" gorm:"type:int;comment:对冲单购买类型 1-百分比 2-实际金额"`
HedgeBuyTotal decimal.Decimal `json:"hedgeBuyTotal" gorm:"type:decimal(10,2);comment:对冲买总金额"`
HedgeOrderType string `json:"hedgeOrderType" gorm:"type:enum;comment:第二笔类型 限价LIMIT市价(MARKET)"` HedgeOrderType string `json:"hedgeOrderType" gorm:"type:enum;comment:第二笔类型 限价LIMIT市价(MARKET)"`
HedgeTakeProfit decimal.Decimal `json:"hedgeTakeProfit" gorm:"type:decimal(10,2);comment:对冲止盈百分比"` HedgeTakeProfit decimal.Decimal `json:"hedgeTakeProfit" gorm:"type:decimal(10,2);comment:对冲止盈百分比"`
HedgeStopLoss decimal.Decimal `json:"hedgeStopLoss" gorm:"type:decimal(10,2);comment:对冲止损百分比"` HedgeStopLoss decimal.Decimal `json:"hedgeStopLoss" gorm:"type:decimal(10,2);comment:对冲止损百分比"`

View File

@ -7,13 +7,14 @@ import (
type LineSymbol struct { type LineSymbol struct {
models.Model models.Model
ApiId string `json:"apiId" gorm:"type:int;comment:api账户id"` ExchangeType string `json:"exchangeType" gorm:"type:varchar(20);comment:交易所类型 字典 exchange_type"`
Symbol string `json:"symbol" gorm:"type:varchar(32);comment:交易对"` ApiId string `json:"apiId" gorm:"type:int;comment:api账户id"`
BaseAsset string `json:"baseAsset" gorm:"type:varchar(255);comment:基础货币"` Symbol string `json:"symbol" gorm:"type:varchar(32);comment:交易对"`
QuoteAsset string `json:"quoteAsset" gorm:"type:varchar(255);comment:计价货币"` BaseAsset string `json:"baseAsset" gorm:"type:varchar(255);comment:基础货币"`
Switch string `json:"switch" gorm:"type:enum('0','1');comment:状态"` QuoteAsset string `json:"quoteAsset" gorm:"type:varchar(255);comment:计价货币"`
Type string `json:"type" gorm:"type:enum('1','2');comment:交易对类型"` Switch string `json:"switch" gorm:"type:enum('0','1');comment:状态"`
Number int `json:"number" gorm:"->"` Type string `json:"type" gorm:"type:enum('1','2');comment:交易对类型"`
Number int `json:"number" gorm:"->"`
models.ModelTime models.ModelTime
models.ControlBy models.ControlBy
} }

View File

@ -6,12 +6,12 @@ import (
type LineSymbolGroup struct { type LineSymbolGroup struct {
models.Model models.Model
ExchangeType string `json:"exchangeType" gorm:"type:varchar(50);comment:交易所类型"`
GroupName string `json:"groupName" gorm:"type:varchar(255);comment:交易对组名称"` GroupName string `json:"groupName" gorm:"type:varchar(255);comment:交易对组名称"`
Symbol string `json:"symbol" gorm:"type:text;comment:交易对"` Symbol string `json:"symbol" gorm:"type:text;comment:交易对"`
GroupType string `json:"groupType" gorm:"type:enum('1','2');comment:分组类型:1=普通类型"` GroupType string `json:"groupType" gorm:"type:enum('1','2');comment:分组类型:1=普通类型"`
Type string `json:"type" gorm:"type:enum('1','2');comment:类型:1=现货,2=合约"` Type string `json:"type" gorm:"type:enum('1','2');comment:类型:1=现货,2=合约"`
Count int `json:"count" gorm:"->"` Count int `json:"count" gorm:"->"`
models.ModelTime models.ModelTime
models.ControlBy models.ControlBy
} }

View File

@ -1,28 +1,28 @@
package dto package dto
import ( import (
"errors"
"go-admin/app/admin/models" "go-admin/app/admin/models"
"go-admin/common/dto" "go-admin/common/dto"
common "go-admin/common/models" common "go-admin/common/models"
) )
type LineApiGroupGetPageReq struct { type LineApiGroupGetPageReq struct {
dto.Pagination `search:"-"` dto.Pagination `search:"-"`
GroupName string `form:"groupName" search:"type:exact;column:group_name;table:line_api_group" comment:"用户组名称"` ExchangeType string `form:"exchangeType" search:"-"`
LineApiGroupOrder GroupName string `form:"groupName" search:"type:exact;column:group_name;table:line_api_group" comment:"用户组名称"`
LineApiGroupOrder
} }
type LineApiGroupOrder struct { type LineApiGroupOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:line_api_group"` Id string `form:"idOrder" search:"type:order;column:id;table:line_api_group"`
GroupName string `form:"groupNameOrder" search:"type:order;column:group_name;table:line_api_group"` GroupName string `form:"groupNameOrder" search:"type:order;column:group_name;table:line_api_group"`
ApiUserId string `form:"apiUserIdOrder" search:"type:order;column:api_user_id;table:line_api_group"` ApiUserId string `form:"apiUserIdOrder" search:"type:order;column:api_user_id;table:line_api_group"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_api_group"` CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_api_group"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_api_group"` UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_api_group"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_api_group"` DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_api_group"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_api_group"` CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_api_group"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_api_group"` UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_api_group"`
} }
func (m *LineApiGroupGetPageReq) GetNeedSearch() interface{} { func (m *LineApiGroupGetPageReq) GetNeedSearch() interface{} {
@ -30,19 +30,28 @@ func (m *LineApiGroupGetPageReq) GetNeedSearch() interface{} {
} }
type LineApiGroupInsertReq struct { type LineApiGroupInsertReq struct {
Id int `json:"-" comment:""` // Id int `json:"-" comment:""` //
GroupName string `json:"groupName" comment:"用户组名称"` ExchangeType string `json:"exchangeType" comment:"交易所编码"`
ApiUserId string `json:"apiUserId" comment:"绑定的api账户id"` GroupName string `json:"groupName" comment:"用户组名称"`
common.ControlBy ApiUserId string `json:"apiUserId" comment:"绑定的api账户id"`
common.ControlBy
} }
func (s *LineApiGroupInsertReq) Generate(model *models.LineApiGroup) { func (req *LineApiGroupInsertReq) Valid() error {
if s.Id == 0 { if req.ExchangeType == "" {
model.Model = common.Model{ Id: s.Id } return errors.New("交易所不能为空")
} }
model.GroupName = s.GroupName return nil
model.ApiUserId = s.ApiUserId }
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
func (s *LineApiGroupInsertReq) Generate(model *models.LineApiGroup) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.ExchangeType = s.ExchangeType
model.GroupName = s.GroupName
model.ApiUserId = s.ApiUserId
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
} }
func (s *LineApiGroupInsertReq) GetId() interface{} { func (s *LineApiGroupInsertReq) GetId() interface{} {
@ -50,19 +59,21 @@ func (s *LineApiGroupInsertReq) GetId() interface{} {
} }
type LineApiGroupUpdateReq struct { type LineApiGroupUpdateReq struct {
Id int `uri:"id" comment:""` // Id int `uri:"id" comment:""` //
GroupName string `json:"groupName" comment:"用户组名称"` ExchangeType string `json:"exchangeType" comment:"交易所编码"`
ApiUserId string `json:"apiUserId" comment:"绑定的api账户id"` GroupName string `json:"groupName" comment:"用户组名称"`
common.ControlBy ApiUserId string `json:"apiUserId" comment:"绑定的api账户id"`
common.ControlBy
} }
func (s *LineApiGroupUpdateReq) Generate(model *models.LineApiGroup) { func (s *LineApiGroupUpdateReq) Generate(model *models.LineApiGroup) {
if s.Id == 0 { if s.Id == 0 {
model.Model = common.Model{ Id: s.Id } model.Model = common.Model{Id: s.Id}
} }
model.GroupName = s.GroupName model.ExchangeType = s.ExchangeType
model.ApiUserId = s.ApiUserId model.GroupName = s.GroupName
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 model.ApiUserId = s.ApiUserId
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
} }
func (s *LineApiGroupUpdateReq) GetId() interface{} { func (s *LineApiGroupUpdateReq) GetId() interface{} {
@ -71,8 +82,9 @@ func (s *LineApiGroupUpdateReq) GetId() interface{} {
// LineApiGroupGetReq 功能获取请求参数 // LineApiGroupGetReq 功能获取请求参数
type LineApiGroupGetReq struct { type LineApiGroupGetReq struct {
Id int `uri:"id"` Id int `uri:"id"`
} }
func (s *LineApiGroupGetReq) GetId() interface{} { func (s *LineApiGroupGetReq) GetId() interface{} {
return s.Id return s.Id
} }

View File

@ -8,6 +8,7 @@ import (
type LineApiUserGetPageReq struct { type LineApiUserGetPageReq struct {
dto.Pagination `search:"-"` dto.Pagination `search:"-"`
ExchangeType string `form:"exchangeType" search:"-"`
LineApiUserOrder LineApiUserOrder
} }
@ -39,21 +40,22 @@ func (m *LineApiUserGetPageReq) GetNeedSearch() interface{} {
} }
type LineApiUserInsertReq struct { type LineApiUserInsertReq struct {
Id int `json:"-" comment:"id"` // id Id int `json:"-" comment:"id"` // id
UserId int64 `json:"userId" comment:"用户id"` ExchangeType string `json:"exchangeType" comment:"交易所code"`
JysId int64 `json:"jysId" comment:"关联交易所账号id"` UserId int64 `json:"userId" comment:"用户id"`
ApiName string `json:"apiName" comment:"api用户名"` JysId int64 `json:"jysId" comment:"关联交易所账号id"`
ApiKey string `json:"apiKey" comment:"apiKey"` ApiName string `json:"apiName" comment:"api用户名"`
ApiSecret string `json:"apiSecret" comment:"apiSecret"` ApiKey string `json:"apiKey" comment:"apiKey"`
IpAddress string `json:"ipAddress" comment:"代理地址"` ApiSecret string `json:"apiSecret" comment:"apiSecret"`
UserPass string `json:"userPass" comment:"代码账号密码"` IpAddress string `json:"ipAddress" comment:"代理地址"`
AdminId int64 `json:"adminId" comment:"管理员id"` UserPass string `json:"userPass" comment:"代码账号密码"`
Affiliation int64 `json:"affiliation" comment:"归属:1=现货,2=合约,3=现货合约"` AdminId int64 `json:"adminId" comment:"管理员id"`
AdminShow int64 `json:"adminShow" comment:"是否超管可见:1=是,0=否"` Affiliation int64 `json:"affiliation" comment:"归属:1=现货,2=合约,3=现货合约"`
Site string `json:"site" comment:"允许下单的方向:1=多;2=空;3=多空"` AdminShow int64 `json:"adminShow" comment:"是否超管可见:1=是,0=否"`
Subordinate string `json:"subordinate" comment:"从属关系:0=未绑定关系;1=主账号;2=副帐号"` Site string `json:"site" comment:"允许下单的方向:1=多;2=空;3=多空"`
GroupId int64 `json:"groupId" comment:"所属组id"` Subordinate string `json:"subordinate" comment:"从属关系:0=未绑定关系;1=主账号;2=副帐号"`
OpenStatus int64 `json:"openStatus" comment:"开启状态 0=关闭 1=开启"` GroupId int64 `json:"groupId" comment:"所属组id"`
OpenStatus int64 `json:"openStatus" comment:"开启状态 0=关闭 1=开启"`
common.ControlBy common.ControlBy
} }
@ -61,6 +63,7 @@ func (s *LineApiUserInsertReq) Generate(model *models.LineApiUser) {
if s.Id == 0 { if s.Id == 0 {
model.Model = common.Model{Id: s.Id} model.Model = common.Model{Id: s.Id}
} }
model.ExchangeType = s.ExchangeType
model.UserId = s.UserId model.UserId = s.UserId
model.JysId = s.JysId model.JysId = s.JysId
model.ApiName = s.ApiName model.ApiName = s.ApiName
@ -83,21 +86,22 @@ func (s *LineApiUserInsertReq) GetId() interface{} {
} }
type LineApiUserUpdateReq struct { type LineApiUserUpdateReq struct {
Id int `uri:"id" comment:"id"` // id Id int `uri:"id" comment:"id"` // id
UserId int64 `json:"userId" comment:"用户id"` ExchangeType string `json:"exchangeType" comment:"交易所code"`
JysId int64 `json:"jysId" comment:"关联交易所账号id"` UserId int64 `json:"userId" comment:"用户id"`
ApiName string `json:"apiName" comment:"api用户名"` JysId int64 `json:"jysId" comment:"关联交易所账号id"`
ApiKey string `json:"apiKey" comment:"apiKey"` ApiName string `json:"apiName" comment:"api用户名"`
ApiSecret string `json:"apiSecret" comment:"apiSecret"` ApiKey string `json:"apiKey" comment:"apiKey"`
IpAddress string `json:"ipAddress" comment:"代理地址"` ApiSecret string `json:"apiSecret" comment:"apiSecret"`
UserPass string `json:"userPass" comment:"代码账号密码"` IpAddress string `json:"ipAddress" comment:"代理地址"`
AdminId int64 `json:"adminId" comment:"管理员id"` UserPass string `json:"userPass" comment:"代码账号密码"`
Affiliation int64 `json:"affiliation" comment:"归属:1=现货,2=合约,3=现货合约"` AdminId int64 `json:"adminId" comment:"管理员id"`
AdminShow int64 `json:"adminShow" comment:"是否超管可见:1=是,0=否"` Affiliation int64 `json:"affiliation" comment:"归属:1=现货,2=合约,3=现货合约"`
Site string `json:"site" comment:"允许下单的方向:1=多;2=空;3=多空"` AdminShow int64 `json:"adminShow" comment:"是否超管可见:1=是,0=否"`
Subordinate string `json:"subordinate" comment:"从属关系:0=未绑定关系;1=主账号;2=副帐号"` Site string `json:"site" comment:"允许下单的方向:1=多;2=空;3=多空"`
GroupId int64 `json:"groupId" comment:"所属组id"` Subordinate string `json:"subordinate" comment:"从属关系:0=未绑定关系;1=主账号;2=副帐号"`
OpenStatus int64 `json:"openStatus" comment:"开启状态 0=关闭 1=开启"` GroupId int64 `json:"groupId" comment:"所属组id"`
OpenStatus int64 `json:"openStatus" comment:"开启状态 0=关闭 1=开启"`
common.ControlBy common.ControlBy
} }
@ -105,6 +109,7 @@ func (s *LineApiUserUpdateReq) Generate(model *models.LineApiUser) {
if s.Id == 0 { if s.Id == 0 {
model.Model = common.Model{Id: s.Id} model.Model = common.Model{Id: s.Id}
} }
model.ExchangeType = s.ExchangeType
model.UserId = s.UserId model.UserId = s.UserId
model.JysId = s.JysId model.JysId = s.JysId
model.ApiName = s.ApiName model.ApiName = s.ApiName
@ -145,6 +150,11 @@ func (s *LineApiUserDeleteReq) GetId() interface{} {
} }
type LineApiUserBindSubordinateReq struct { type LineApiUserBindSubordinateReq struct {
UserIdStr string `json:"user_id_str"` ExchangeType string `json:"exchangeType"`
GroupName string `json:"group_name"` UserIdStr string `json:"user_id_str"`
GroupName string `json:"group_name"`
}
type GetMainUserReq struct {
ExchangeType string `json:"exchangeType"`
} }

View File

@ -197,24 +197,28 @@ func (s *LinePreOrderDeleteReq) GetId() interface{} {
} }
type LineAddPreOrderReq struct { type LineAddPreOrderReq struct {
ExchangeType string `json:"exchange_type"` //交易所类型 ExchangeType string `json:"exchange_type"` //交易所类型
OrderType int `json:"order_type"` //订单类型 OrderType int `json:"order_type"` //订单类型
Symbol string `json:"symbol"` //交易对 Symbol string `json:"symbol"` //交易对
ApiUserId string `json:"api_id"` //下单用户 ApiUserId string `json:"api_id"` //下单用户
Site string `json:"site"` //购买方向 Site string `json:"site"` //购买方向
BuyPrice string `json:"buy_price"` //购买金额 U BuyPrice string `json:"buy_price"` //购买金额 U
PricePattern string `json:"price_pattern"` //价格模式 PricePattern string `json:"price_pattern"` //价格模式
Price string `json:"price"` //下单价百分比 Price string `json:"price"` //下单价百分比
Profit string `json:"profit"` //止盈价 Profit string `json:"profit"` //止盈价
StopPrice string `json:"stop_price"` //止损价 StopPrice string `json:"stop_price"` //止损价
PriceType string `json:"price_type"` //价格类型 PriceType string `json:"price_type"` //价格类型
SaveTemplate string `json:"save_template"` //是否保存模板 SaveTemplate string `json:"save_template"` //是否保存模板
TemplateName string `json:"template_name"` //模板名字 TemplateName string `json:"template_name"` //模板名字
SymbolType int `json:"symbol_type"` //交易对类型 1-现货 2-合约 SymbolType int `json:"symbol_type"` //交易对类型 1-现货 2-合约
CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货 CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货
ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 ExpireHour int `json:"expire_hour"` // 过期时间 单位小时
MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET)
HedgeOrderType string `json:"hedge_order_type"` //第二笔(对冲单)类型:限价(LIMIT)或市价(MARKET) HedgeOrderType string `json:"hedge_order_type"` //第二笔(对冲单)类型:限价(LIMIT)或市价(MARKET)
HedgeBuyType int `json:"hedge_buy_type"` //对冲单购买类型 1-百分比 2-实际金额
HedgeBuyTotal decimal.Decimal `json:"hedge_buy_total"` //对冲购买金额
HedgeTakeProfit decimal.Decimal `json:"hedge_take_profit"` //对冲止盈
HedgeStopLoss decimal.Decimal `json:"hedge_stop_loss"` //对冲止损
} }
func (req LineAddPreOrderReq) CheckParams() error { func (req LineAddPreOrderReq) CheckParams() error {
@ -237,32 +241,40 @@ func (req LineAddPreOrderReq) CheckParams() error {
return errors.New("请选择价格类型") return errors.New("请选择价格类型")
} }
if req.ExchangeType == "" {
return errors.New("请选择交易所")
}
return nil return nil
} }
// LineBatchAddPreOrderReq 批量添加订单请求参数 // LineBatchAddPreOrderReq 批量添加订单请求参数
type LineBatchAddPreOrderReq struct { type LineBatchAddPreOrderReq struct {
ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type ExchangeType string `json:"exchange_type"` //交易所类型 字典exchange_type
SymbolType int `json:"symbolType"` //主单交易对类型 0-现货 1-合约 SymbolType int `json:"symbolType"` //主单交易对类型 0-现货 1-合约
OrderType int `json:"order_type"` //订单类型 OrderType int `json:"order_type"` //订单类型
SymbolGroupId string `json:"symbol_group_id"` //交易对组id SymbolGroupId string `json:"symbol_group_id"` //交易对组id
Symbol string `json:"symbol"` //交易对 Symbol string `json:"symbol"` //交易对
ApiUserId string `json:"api_id"` //下单用户 ApiUserId string `json:"api_id"` //下单用户
Site string `json:"site"` //购买方向 Site string `json:"site"` //购买方向
BuyPrice string `json:"buy_price"` //购买金额 U BuyPrice string `json:"buy_price"` //购买金额 U
PricePattern string `json:"price_pattern"` //价格模式 PricePattern string `json:"price_pattern"` //价格模式
Price string `json:"price"` //下单价百分比 Price string `json:"price"` //下单价百分比
Profit string `json:"profit"` //止盈价 Profit string `json:"profit"` //止盈价
StopPrice string `json:"stop_price"` //止损价 StopPrice string `json:"stop_price"` //止损价
PriceType string `json:"price_type"` //价格类型 PriceType string `json:"price_type"` //价格类型
SaveTemplate string `json:"save_template"` //是否保存模板 SaveTemplate string `json:"save_template"` //是否保存模板
TemplateName string `json:"template_name"` //模板名字 TemplateName string `json:"template_name"` //模板名字
OrderNum int `json:"order_num"` //脚本运行次数 OrderNum int `json:"order_num"` //脚本运行次数
Script string `json:"script"` //是否是脚本运行 1 = 是 0= 否 Script string `json:"script"` //是否是脚本运行 1 = 是 0= 否
CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货 CoverType int `json:"cover_type"` //对冲类型 1= 现货对合约 2=合约对合约 3 合约对现货
ExpireHour int `json:"expire_hour"` // 过期时间 单位小时 ExpireHour int `json:"expire_hour"` // 过期时间 单位小时
MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET) MainOrderType string `json:"main_order_type"` //主单类型:限价(LIMIT)或市价(MARKET)
HedgeOrderType string `json:"hedge_order_type"` //第二笔(对冲单)类型:限价(LIMIT)或市价(MARKET) HedgeOrderType string `json:"hedge_order_type"` //第二笔(对冲单)类型:限价(LIMIT)或市价(MARKET)
HedgeBuyType int `json:"hedge_buy_type"` //对冲单购买类型 1-百分比 2-实际金额
HedgeBuyTotal decimal.Decimal `json:"hedge_buy_total"` //对冲购买金额
HedgeTakeProfit decimal.Decimal `json:"hedge_take_profit"` //对冲止盈
HedgeStopLoss decimal.Decimal `json:"hedge_stop_loss"` //对冲止损
} }
func (req LineBatchAddPreOrderReq) CheckParams() error { func (req LineBatchAddPreOrderReq) CheckParams() error {
@ -285,6 +297,10 @@ func (req LineBatchAddPreOrderReq) CheckParams() error {
return errors.New("请选择价格类型") return errors.New("请选择价格类型")
} }
if req.ExchangeType == "" {
return errors.New("请选择交易所")
}
return nil return nil
} }

View File

@ -1,6 +1,7 @@
package dto package dto
import ( import (
"errors"
"go-admin/app/admin/models" "go-admin/app/admin/models"
"go-admin/common/dto" "go-admin/common/dto"
common "go-admin/common/models" common "go-admin/common/models"
@ -8,6 +9,7 @@ import (
type LineSymbolGetPageReq struct { type LineSymbolGetPageReq struct {
dto.Pagination `search:"-"` dto.Pagination `search:"-"`
ExchangeType string `form:"exchangeType" search:"type:exact;column:exchange_type;table:line_symbol"`
Symbol string `form:"symbol" search:"type:contains;column:symbol;table:line_symbol" comment:"交易对"` Symbol string `form:"symbol" search:"type:contains;column:symbol;table:line_symbol" comment:"交易对"`
BaseAsset string `form:"baseAsset" search:"type:contains;column:base_asset;table:line_symbol" comment:"基础货币"` BaseAsset string `form:"baseAsset" search:"type:contains;column:base_asset;table:line_symbol" comment:"基础货币"`
QuoteAsset string `form:"quoteAsset" search:"type:exact;column:quote_asset;table:line_symbol" comment:"计价货币"` QuoteAsset string `form:"quoteAsset" search:"type:exact;column:quote_asset;table:line_symbol" comment:"计价货币"`
@ -30,6 +32,18 @@ type LineSymbolOrder struct {
Type string `form:"typeOrder" search:"type:order;column:type;table:line_symbol"` Type string `form:"typeOrder" search:"type:order;column:type;table:line_symbol"`
} }
type LineSymbolGetListReq struct {
ExchangeType string `json:"exchangeType" form:"exchangeType"`
}
func (req *LineSymbolGetListReq) Valid() error {
if req.ExchangeType == "" {
return errors.New("交易所不能为空")
}
return nil
}
func (m *LineSymbolGetPageReq) GetNeedSearch() interface{} { func (m *LineSymbolGetPageReq) GetNeedSearch() interface{} {
return *m return *m
} }

View File

@ -1,30 +1,30 @@
package dto package dto
import ( import (
"go-admin/app/admin/models" "go-admin/app/admin/models"
"go-admin/common/dto" "go-admin/common/dto"
common "go-admin/common/models" common "go-admin/common/models"
) )
type LineSymbolGroupGetPageReq struct { type LineSymbolGroupGetPageReq struct {
dto.Pagination `search:"-"` dto.Pagination `search:"-"`
Type string `form:"type" search:"type:exact;column:type;table:line_symbol_group" comment:"类型:1=现货,2=合约"` ExchangeType string `form:"exchangeType" search:"-"`
LineSymbolGroupOrder Type string `form:"type" search:"type:exact;column:type;table:line_symbol_group" comment:"类型:1=现货,2=合约"`
LineSymbolGroupOrder
} }
type LineSymbolGroupOrder struct { type LineSymbolGroupOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:line_symbol_group"` Id string `form:"idOrder" search:"type:order;column:id;table:line_symbol_group"`
GroupName string `form:"groupNameOrder" search:"type:order;column:group_name;table:line_symbol_group"` // Exchange string `form:"exchangeOrder" `
Symbol string `form:"symbolOrder" search:"type:order;column:symbol;table:line_symbol_group"` GroupName string `form:"groupNameOrder" search:"type:order;column:group_name;table:line_symbol_group"`
GroupType string `form:"groupTypeOrder" search:"type:order;column:groupType;table:line_symbol_group"` Symbol string `form:"symbolOrder" search:"type:order;column:symbol;table:line_symbol_group"`
Type string `form:"typeOrder" search:"type:order;column:type;table:line_symbol_group"` GroupType string `form:"groupTypeOrder" search:"type:order;column:groupType;table:line_symbol_group"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_symbol_group"` Type string `form:"typeOrder" search:"type:order;column:type;table:line_symbol_group"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_symbol_group"` CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_symbol_group"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_symbol_group"` UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_symbol_group"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_symbol_group"` DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_symbol_group"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_symbol_group"` CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_symbol_group"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_symbol_group"`
} }
func (m *LineSymbolGroupGetPageReq) GetNeedSearch() interface{} { func (m *LineSymbolGroupGetPageReq) GetNeedSearch() interface{} {
@ -32,23 +32,25 @@ func (m *LineSymbolGroupGetPageReq) GetNeedSearch() interface{} {
} }
type LineSymbolGroupInsertReq struct { type LineSymbolGroupInsertReq struct {
Id int `json:"-" comment:""` // Id int `json:"-" comment:""` //
GroupName string `json:"groupName" comment:"交易对组名称"` ExchangeType string `json:"exchangeType"`
Symbol string `json:"symbol" comment:"交易对"` GroupName string `json:"groupName" comment:"交易对组名称"`
GroupType string `json:"groupType" comment:"分组类型:1=普通类型"` Symbol string `json:"symbol" comment:"交易对"`
Type string `json:"type" comment:"类型:1=现货,2=合约"` GroupType string `json:"groupType" comment:"分组类型:1=普通类型"`
common.ControlBy Type string `json:"type" comment:"类型:1=现货,2=合约"`
common.ControlBy
} }
func (s *LineSymbolGroupInsertReq) Generate(model *models.LineSymbolGroup) { func (s *LineSymbolGroupInsertReq) Generate(model *models.LineSymbolGroup) {
if s.Id == 0 { if s.Id == 0 {
model.Model = common.Model{ Id: s.Id } model.Model = common.Model{Id: s.Id}
} }
model.GroupName = s.GroupName // model.ExchangeType = s.ExchangeType
model.Symbol = s.Symbol model.GroupName = s.GroupName
model.GroupType = s.GroupType model.Symbol = s.Symbol
model.Type = s.Type model.GroupType = s.GroupType
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 model.Type = s.Type
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
} }
func (s *LineSymbolGroupInsertReq) GetId() interface{} { func (s *LineSymbolGroupInsertReq) GetId() interface{} {
@ -56,23 +58,25 @@ func (s *LineSymbolGroupInsertReq) GetId() interface{} {
} }
type LineSymbolGroupUpdateReq struct { type LineSymbolGroupUpdateReq struct {
Id int `uri:"id" comment:""` // Id int `uri:"id" comment:""` //
GroupName string `json:"groupName" comment:"交易对组名称"` ExchangeType string `json:"exchangeType"`
Symbol string `json:"symbol" comment:"交易对"` GroupName string `json:"groupName" comment:"交易对组名称"`
GroupType string `json:"groupType" comment:"分组类型:1=普通类型"` Symbol string `json:"symbol" comment:"交易对"`
Type string `json:"type" comment:"类型:1=现货,2=合约"` GroupType string `json:"groupType" comment:"分组类型:1=普通类型"`
common.ControlBy Type string `json:"type" comment:"类型:1=现货,2=合约"`
common.ControlBy
} }
func (s *LineSymbolGroupUpdateReq) Generate(model *models.LineSymbolGroup) { func (s *LineSymbolGroupUpdateReq) Generate(model *models.LineSymbolGroup) {
if s.Id == 0 { if s.Id == 0 {
model.Model = common.Model{ Id: s.Id } model.Model = common.Model{Id: s.Id}
} }
model.GroupName = s.GroupName // model.ExchangeType = s.ExchangeType
model.Symbol = s.Symbol model.GroupName = s.GroupName
model.GroupType = s.GroupType model.Symbol = s.Symbol
model.Type = s.Type model.GroupType = s.GroupType
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 model.Type = s.Type
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
} }
func (s *LineSymbolGroupUpdateReq) GetId() interface{} { func (s *LineSymbolGroupUpdateReq) GetId() interface{} {
@ -81,8 +85,9 @@ func (s *LineSymbolGroupUpdateReq) GetId() interface{} {
// LineSymbolGroupGetReq 功能获取请求参数 // LineSymbolGroupGetReq 功能获取请求参数
type LineSymbolGroupGetReq struct { type LineSymbolGroupGetReq struct {
Id int `uri:"id"` Id int `uri:"id"`
} }
func (s *LineSymbolGroupGetReq) GetId() interface{} { func (s *LineSymbolGroupGetReq) GetId() interface{} {
return s.Id return s.Id
} }

View File

@ -14,22 +14,16 @@ type LineSystemSettingGetPageReq struct {
} }
type LineSystemSettingOrder struct { type LineSystemSettingOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:line_system_setting"` Id string `form:"idOrder" search:"type:order;column:id;table:line_system_setting"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_system_setting"` CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:line_system_setting"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_system_setting"` UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:line_system_setting"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_system_setting"` DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:line_system_setting"`
Time string `form:"timeOrder" search:"type:order;column:time;table:line_system_setting"` Time string `form:"timeOrder" search:"type:order;column:time;table:line_system_setting"`
BatchTime string `form:"batchTimeOrder" search:"type:order;column:batch_time;table:line_system_setting"` BatchTime string `form:"batchTimeOrder" search:"type:order;column:batch_time;table:line_system_setting"`
ProfitRate string `form:"profitRateOrder" search:"type:order;column:profit_rate;table:line_system_setting"` ProfitRate string `form:"profitRateOrder" search:"type:order;column:profit_rate;table:line_system_setting"`
CoverOrderTypeBRate string `form:"coverOrderTypeBRateOrder" search:"type:order;column:cover_order_type_b_rate;table:line_system_setting"` CoverOrderTypeBRate string `form:"coverOrderTypeBRateOrder" search:"type:order;column:cover_order_type_b_rate;table:line_system_setting"`
ScaleOrderTypeARate string `form:"scaleOrderTypeARateOrder" search:"type:order;column:scale_order_type_a_rate;table:line_system_setting"` CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_system_setting"`
ScaleOrderTypeBRate string `form:"scaleOrderTypeBRateOrder" search:"type:order;column:scale_order_type_b_rate;table:line_system_setting"` UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_system_setting"`
ScaleUnRealizedProfitRate string `form:"scaleUnRealizedProfitRateOrder" search:"type:order;column:scale_unRealizedProfitRate;table:line_system_setting"`
ScaleNum string `form:"scaleNumOrder" search:"type:order;column:scale_num;table:line_system_setting"`
ScaleSubordinate string `form:"scaleSubordinateOrder" search:"type:order;column:scale_subordinate;table:line_system_setting"`
AutoScaleTimes string `form:"autoScaleTimesOrder" search:"type:order;column:auto_scale_times;table:line_system_setting"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:line_system_setting"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:line_system_setting"`
} }
func (m *LineSystemSettingGetPageReq) GetNeedSearch() interface{} { func (m *LineSystemSettingGetPageReq) GetNeedSearch() interface{} {
@ -37,18 +31,12 @@ func (m *LineSystemSettingGetPageReq) GetNeedSearch() interface{} {
} }
type LineSystemSettingInsertReq struct { type LineSystemSettingInsertReq struct {
Id int `json:"-" comment:"id"` // id Id int `json:"-" comment:"id"` // id
Time int64 `json:"time" comment:"导入:挂单时长达到时间后失效"` Time int64 `json:"time" comment:"导入:挂单时长达到时间后失效"`
BatchTime int64 `json:"batchTime" comment:"批量:挂单时长达到时间后失效"` BatchTime int64 `json:"batchTime" comment:"批量:挂单时长达到时间后失效"`
ProfitRate string `json:"profitRate" comment:"平仓盈利比例"` ProfitRate string `json:"profitRate" comment:"平仓盈利比例"`
CoverOrderTypeBRate string `json:"coverOrderTypeBRate" comment:"b账户限价补单的买入百分比"` CoverOrderTypeBRate string `json:"coverOrderTypeBRate" comment:"b账户限价补单的买入百分比"`
ScaleOrderTypeARate string `json:"scaleOrderTypeARate" comment:"a账户限价加仓买入百分比"` StopLossPremium decimal.Decimal `json:"stopLossPremium" comment:"限价止损溢价"`
ScaleOrderTypeBRate string `json:"scaleOrderTypeBRate" comment:"b账户限价加仓买入百分比"`
ScaleUnRealizedProfitRate string `json:"scaleUnRealizedProfitRate" comment:"亏损百分比加仓"`
ScaleNum string `json:"scaleNum" comment:"加仓数值"`
ScaleSubordinate int64 `json:"scaleSubordinate" comment:"加仓账户:1=A账户;2=副账户;3=都加"`
AutoScaleTimes int64 `json:"autoScaleTimes" comment:"自动加仓次数"`
ProtectHedgeEnable int `json:"protectHedgeEnable" comment:"是否只开启保险对冲 0-否 1-是"`
common.ControlBy common.ControlBy
} }
@ -60,12 +48,7 @@ func (s *LineSystemSettingInsertReq) Generate(model *models.LineSystemSetting) {
model.BatchTime = s.BatchTime model.BatchTime = s.BatchTime
model.ProfitRate = s.ProfitRate model.ProfitRate = s.ProfitRate
model.CoverOrderTypeBRate = s.CoverOrderTypeBRate model.CoverOrderTypeBRate = s.CoverOrderTypeBRate
model.ScaleOrderTypeARate = s.ScaleOrderTypeARate model.StopLossPremium = s.StopLossPremium
model.ScaleOrderTypeBRate = s.ScaleOrderTypeBRate
model.ScaleUnrealizedProfitRate = s.ScaleUnRealizedProfitRate
model.ScaleNum = s.ScaleNum
model.ScaleSubordinate = s.ScaleSubordinate
model.AutoScaleTimes = s.AutoScaleTimes
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
} }
@ -74,20 +57,12 @@ func (s *LineSystemSettingInsertReq) GetId() interface{} {
} }
type LineSystemSettingUpdateReq struct { type LineSystemSettingUpdateReq struct {
Id int `uri:"id" comment:"id"` // id Id int `uri:"id" comment:"id"` // id
Time int64 `json:"time" comment:"导入:挂单时长达到时间后失效"` Time int64 `json:"time" comment:"导入:挂单时长达到时间后失效"`
BatchTime int64 `json:"batchTime" comment:"批量:挂单时长达到时间后失效"` BatchTime int64 `json:"batchTime" comment:"批量:挂单时长达到时间后失效"`
ProfitRate string `json:"profitRate" comment:"平仓盈利比例"` ProfitRate string `json:"profitRate" comment:"平仓盈利比例"`
CoverOrderTypeBRate string `json:"coverOrderTypeBRate" comment:"b账户限价补单的买入百分比"` CoverOrderTypeBRate string `json:"coverOrderTypeBRate" comment:"b账户限价补单的买入百分比"`
ScaleOrderTypeARate string `json:"scaleOrderTypeARate" comment:"a账户限价加仓买入百分比"` StopLossPremium decimal.Decimal `json:"stopLossPremium" comment:"限价止损溢价"`
ScaleOrderTypeBRate string `json:"scaleOrderTypeBRate" comment:"b账户限价加仓买入百分比"`
ScaleUnrealizedProfitRate string `json:"scaleUnRealizedProfitRate" comment:"亏损百分比加仓"`
ScaleNum string `json:"scaleNum" comment:"加仓数值"`
ScaleSubordinate int64 `json:"scaleSubordinate" comment:"加仓账户:1=A账户;2=副账户;3=都加"`
AutoScaleTimes int64 `json:"autoScaleTimes" comment:"自动加仓次数"`
HedgePerformance decimal.Decimal `json:"hedgePerformance" comment:"对冲平仓涨跌幅"`
ProtectHedgeRate decimal.Decimal `json:"protectHedgeRate" comment:"对冲市价亏损百分比"`
ProtectHedgeEnable int `json:"protectHedgeEnable" comment:"是否只开启保险对冲 0-否 1-是"`
common.ControlBy common.ControlBy
} }
@ -99,15 +74,7 @@ func (s *LineSystemSettingUpdateReq) Generate(model *models.LineSystemSetting) {
model.BatchTime = s.BatchTime model.BatchTime = s.BatchTime
model.ProfitRate = s.ProfitRate model.ProfitRate = s.ProfitRate
model.CoverOrderTypeBRate = s.CoverOrderTypeBRate model.CoverOrderTypeBRate = s.CoverOrderTypeBRate
model.ScaleOrderTypeARate = s.ScaleOrderTypeARate model.StopLossPremium = s.StopLossPremium
model.ScaleOrderTypeBRate = s.ScaleOrderTypeBRate
model.ScaleUnrealizedProfitRate = s.ScaleUnrealizedProfitRate
model.ScaleNum = s.ScaleNum
model.ScaleSubordinate = s.ScaleSubordinate
model.AutoScaleTimes = s.AutoScaleTimes
model.HedgePerformance = s.HedgePerformance
model.ProtectHedgeRate = s.ProtectHedgeRate
model.ProtectHedgeEnable = s.ProtectHedgeEnable
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
} }

View File

@ -29,7 +29,13 @@ func (e *LineApiGroup) GetPage(c *dto.LineApiGroupGetPageReq, p *actions.DataPer
var err error var err error
var data models.LineApiGroup var data models.LineApiGroup
err = e.Orm.Model(&data). query := e.Orm.Model(&data)
if c.ExchangeType != "" {
query.Where("exchange_type = ?", c.ExchangeType)
}
err = query.
Scopes( Scopes(
cDto.MakeCondition(c.GetNeedSearch()), cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),

View File

@ -29,13 +29,18 @@ type LineApiUser struct {
func (e *LineApiUser) GetPage(c *dto.LineApiUserGetPageReq, p *actions.DataPermission, list *[]models.LineApiUser, count *int64) error { func (e *LineApiUser) GetPage(c *dto.LineApiUserGetPageReq, p *actions.DataPermission, list *[]models.LineApiUser, count *int64) error {
var err error var err error
var data models.LineApiUser var data models.LineApiUser
query := e.Orm.Model(&data).
err = e.Orm.Model(&data).
Scopes( Scopes(
cDto.MakeCondition(c.GetNeedSearch()), cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p), actions.Permission(data.TableName(), p),
). )
if c.ExchangeType != "" {
query.Where("exchange_type = ?", c.ExchangeType)
}
err = query.
Find(list).Limit(-1).Offset(-1). Find(list).Limit(-1).Offset(-1).
Count(count).Error Count(count).Error
if err != nil { if err != nil {
@ -309,11 +314,16 @@ func (e *LineApiUser) Bind(req *dto.LineApiUserBindSubordinateReq, p *actions.Da
} }
// GetUser 获取未绑定的用户列表 // GetUser 获取未绑定的用户列表
func (e *LineApiUser) GetUser(list *[]models.LineApiUser) error { func (e *LineApiUser) GetUser(req *dto.LineApiUserBindSubordinateReq, list *[]models.LineApiUser) error {
var err error var err error
var data models.LineApiUser var data models.LineApiUser
query := e.Orm.Model(&data).Where("subordinate = '0'")
err = e.Orm.Model(&data).Where("subordinate = '0'").Find(list).Error if req.ExchangeType != "" {
query = query.Where("exchange_type = ?", req.ExchangeType)
}
err = query.Find(list).Error
if err != nil { if err != nil {
e.Log.Errorf("LineApiUserService error:%s \r\n", err) e.Log.Errorf("LineApiUserService error:%s \r\n", err)
return err return err
@ -322,11 +332,15 @@ func (e *LineApiUser) GetUser(list *[]models.LineApiUser) error {
} }
// GetMainUser 获取主账号 // GetMainUser 获取主账号
func (e *LineApiUser) GetMainUser(list *[]models.LineApiUser) error { func (e *LineApiUser) GetMainUser(req *dto.GetMainUserReq, list *[]models.LineApiUser) error {
var err error var err error
var data models.LineApiUser var data models.LineApiUser
query := e.Orm.Model(&data).Where("subordinate = '1' AND group_id > 0")
err = e.Orm.Model(&data).Where("subordinate = '1' AND group_id > 0").Find(list).Error if req.ExchangeType != "" {
query = query.Where("exchange_type =?", req.ExchangeType)
}
err = query.Find(list).Error
if err != nil { if err != nil {
e.Log.Errorf("LineApiUserService error:%s \r\n", err) e.Log.Errorf("LineApiUserService error:%s \r\n", err)
return err return err

View File

@ -13,6 +13,7 @@ import (
"go-admin/app/admin/service/dto" "go-admin/app/admin/service/dto"
"go-admin/common/actions" "go-admin/common/actions"
cDto "go-admin/common/dto" cDto "go-admin/common/dto"
"go-admin/common/global"
) )
type LineDirection struct { type LineDirection struct {
@ -183,10 +184,11 @@ func (e *LineDirection) ReloadGroup() error {
groupName := fmt.Sprintf("现货-%s", key) groupName := fmt.Sprintf("现货-%s", key)
group := models.LineSymbolGroup{ group := models.LineSymbolGroup{
GroupName: groupName, ExchangeType: global.EXCHANGE_BINANCE,
Type: "1", GroupName: groupName,
GroupType: "1", Type: "1",
Symbol: strings.Join(item, ","), GroupType: "1",
Symbol: strings.Join(item, ","),
} }
groupNames = append(groupNames, groupName) groupNames = append(groupNames, groupName)
@ -197,10 +199,11 @@ func (e *LineDirection) ReloadGroup() error {
groupName := fmt.Sprintf("合约-%s", key) groupName := fmt.Sprintf("合约-%s", key)
group := models.LineSymbolGroup{ group := models.LineSymbolGroup{
GroupName: groupName, ExchangeType: global.EXCHANGE_BINANCE,
Type: "2", GroupName: groupName,
GroupType: "1", Type: "2",
Symbol: strings.Join(item, ","), GroupType: "1",
Symbol: strings.Join(item, ","),
} }
groupNames = append(groupNames, groupName) groupNames = append(groupNames, groupName)

View File

@ -241,13 +241,15 @@ func (e *LinePreOrder) Remove(d *dto.LinePreOrderDeleteReq, p *actions.DataPermi
apiIds = append(apiIds, order.ApiId) apiIds = append(apiIds, order.ApiId)
} }
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf("%s:%s", global.TICKER_SPOT, order.Symbol)) tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf(global.TICKER_SPOT, order.ExchangeType, order.Symbol))
redisList.Price = utility.StringToDecimal(redisList.Price).Truncate(int32(tradeSet.PriceDigit)).String() redisList.Price = utility.StringToDecimal(redisList.Price).Truncate(int32(tradeSet.PriceDigit)).String()
marshal, _ := sonic.Marshal(redisList) marshal, _ := sonic.Marshal(redisList)
if order.SymbolType == 1 { if order.SymbolType == 1 {
helper.DefaultRedis.LRem(rediskey.PreFutOrderList, string(marshal)) listKey := fmt.Sprintf(rediskey.PreSpotOrderList, order.ExchangeType)
helper.DefaultRedis.LRem(listKey, string(marshal))
} else { } else {
helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, string(marshal)) listKey := fmt.Sprintf(rediskey.PreFutOrderList, order.ExchangeType)
helper.DefaultRedis.LRem(listKey, string(marshal))
} }
binanceservice.MainClosePositionClearCache(order.Id, order.CoverType) binanceservice.MainClosePositionClearCache(order.Id, order.CoverType)
@ -340,9 +342,9 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
} }
var key string var key string
if req.SymbolType == global.SYMBOL_SPOT { if req.SymbolType == global.SYMBOL_SPOT {
key = fmt.Sprintf("%s:%s", global.TICKER_SPOT, req.Symbol) key = fmt.Sprintf(global.TICKER_SPOT, req.ExchangeType, req.Symbol)
} else { } else {
key = fmt.Sprintf("%s:%s", global.TICKER_FUTURES, req.Symbol) key = fmt.Sprintf(global.TICKER_FUTURES, req.ExchangeType, req.Symbol)
} }
for _, id := range apiUserIds { for _, id := range apiUserIds {
@ -361,32 +363,14 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
*errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 该交易对已存在,请勿重复下单", id, req.Symbol)) *errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 该交易对已存在,请勿重复下单", id, req.Symbol))
continue continue
} }
var tickerPrice decimal.Decimal tickerPrice := utility.StrToDecimal(tradeSet.LastPrice)
ticker := models2.TradeSet{}
tickerVal := ""
if req.SymbolType == 1 {
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, req.Symbol))
}
if tickerVal == "" {
logger.Error("获取交易对:%s 现货ticker失败", req.Symbol)
continue
}
err := sonic.Unmarshal([]byte(tickerVal), &ticker)
if ticker.LastPrice == "" {
logger.Error("获取交易对:%s 现货ticker失败,err:%v", req.Symbol, err)
continue
}
if tickerPrice.Equal(decimal.Zero) { //redis 没有这个值 if tickerPrice.Equal(decimal.Zero) { //redis 没有这个值
*errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 交易行情出错", id, req.Symbol)) *errs = append(*errs, fmt.Errorf("api_id:%s 获取交易对:%s 交易行情出错", id, req.Symbol))
continue continue
} }
AddOrder.HedgeBuyType = req.HedgeBuyType
AddOrder.ExchangeType = req.ExchangeType
AddOrder.OrderCategory = 1 AddOrder.OrderCategory = 1
AddOrder.SignPriceType = "new" AddOrder.SignPriceType = "new"
AddOrder.BuyPrice = req.BuyPrice //购买多少U AddOrder.BuyPrice = req.BuyPrice //购买多少U
@ -434,7 +418,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
continue continue
} }
err = sonic.Unmarshal([]byte(tickerVal), &ticker2) err := sonic.Unmarshal([]byte(tickerVal), &ticker2)
if ticker2.LastPrice == "" { if ticker2.LastPrice == "" {
logger.Errorf("查询行情失败 %s err:%v", strings.ToUpper(symbolInfo.QuoteAsset+"USDT"), err) logger.Errorf("查询行情失败 %s err:%v", strings.ToUpper(symbolInfo.QuoteAsset+"USDT"), err)
@ -465,10 +449,13 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
AddOrder.GroupId = "0" AddOrder.GroupId = "0"
AddOrder.AdminId = "0" AddOrder.AdminId = "0"
AddOrder.Status = 0 AddOrder.Status = 0
AddOrder.HedgeBuyTotal = req.HedgeBuyTotal
AddOrder.HedgeStopLoss = req.HedgeStopLoss
AddOrder.HedgeTakeProfit = req.HedgeTakeProfit
copier.Copy(&profitOrder, &AddOrder) copier.Copy(&profitOrder, &AddOrder)
copier.Copy(&stopOrder, &AddOrder) copier.Copy(&stopOrder, &AddOrder)
err = e.Orm.Model(&models.LinePreOrder{}).Omit("id", "save_template", "template_name").Create(&AddOrder).Error err := e.Orm.Model(&models.LinePreOrder{}).Omit("id", "save_template", "template_name").Create(&AddOrder).Error
if err != nil { if err != nil {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%s 获取交易对:%s 生成订单失败", id, req.Symbol))) *errs = append(*errs, errors.New(fmt.Sprintf("api_id:%s 获取交易对:%s 生成订单失败", id, req.Symbol)))
continue continue
@ -491,10 +478,10 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
} }
marshal, _ := sonic.Marshal(&list) marshal, _ := sonic.Marshal(&list)
var preKey string var preKey string
if AddOrder.OrderType == global.SYMBOL_SPOT { if AddOrder.SymbolType == global.SYMBOL_SPOT {
preKey = rediskey.PreSpotOrderList preKey = fmt.Sprintf(rediskey.PreSpotOrderList, AddOrder.ExchangeType)
} else { } else {
preKey = rediskey.PreFutOrderList preKey = fmt.Sprintf(rediskey.PreFutOrderList, AddOrder.ExchangeType)
} }
helper.DefaultRedis.LPushList(preKey, string(marshal)) helper.DefaultRedis.LPushList(preKey, string(marshal))
@ -540,7 +527,7 @@ func (e *LinePreOrder) AddPreOrder(req *dto.LineAddPreOrderReq, p *actions.DataP
// CheckRepeatOrder 检查重复下单 检查基础货币 // CheckRepeatOrder 检查重复下单 检查基础货币
func (e *LinePreOrder) CheckRepeatOrder(orderType int, apiUserId, site, baseCoin string) int64 { func (e *LinePreOrder) CheckRepeatOrder(orderType int, apiUserId, site, baseCoin string) int64 {
var count int64 var count int64
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol like ? AND order_type = ? AND site = ? AND `status` != '2' AND `status`!='4' AND `status` != '0' AND `status` != '6'", 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)", apiUserId, baseCoin+"%", orderType, site).Count(&count)
return count return count
} }
@ -884,6 +871,8 @@ func (e *LinePreOrder) ClearAll() error {
"holde_a", "holde_a",
"holde_b", "holde_b",
"stop_loss_markt", "stop_loss_markt",
"_PreSpotOrderList_",
"_PreFutOrderList_",
} }
err = helper.DefaultRedis.DeleteKeysByPrefix(prefixs...) err = helper.DefaultRedis.DeleteKeysByPrefix(prefixs...)
if err != nil { if err != nil {
@ -1014,9 +1003,9 @@ func (e *LinePreOrder) SpotClosePosition(position *dto.ClosePosition, errs *[]er
//查询已经开仓的现货交易对 //查询已经开仓的现货交易对
var spotList []models.LinePreOrder var spotList []models.LinePreOrder
if position.Symbol == "" { //全平 if position.Symbol == "" { //全平
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = '9' AND pid = 0 AND order_type = '1'", position.ApiId).Find(&spotList) e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = 6 AND pid = 0 AND order_type = 0", position.ApiId).Find(&spotList)
} else { } else {
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol = ? AND status = '9' AND pid = 0 AND order_type = '1'", position.ApiId, position.Symbol).Find(&spotList) e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol = ? AND status = 6 AND pid = 0 AND order_type = 0", position.ApiId, position.Symbol).Find(&spotList)
} }
if len(spotList) <= 0 { if len(spotList) <= 0 {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 没有可平仓的交易对", position.ApiId))) *errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 没有可平仓的交易对", position.ApiId)))
@ -1034,7 +1023,7 @@ func (e *LinePreOrder) SpotClosePosition(position *dto.ClosePosition, errs *[]er
"symbol": list.Symbol, "symbol": list.Symbol,
}) })
} }
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, list.Symbol) key := fmt.Sprintf(global.TICKER_SPOT, list.ExchangeType, list.Symbol)
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key) tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key)
total := utility.StringToDecimal(balance.Free).Add(utility.StringToDecimal(balance.Locked)).Truncate(int32(tradeSet.AmountDigit)) total := utility.StringToDecimal(balance.Free).Add(utility.StringToDecimal(balance.Locked)).Truncate(int32(tradeSet.AmountDigit))
lastPrice := api.GetSpotSymbolLastPrice(list.Symbol) lastPrice := api.GetSpotSymbolLastPrice(list.Symbol)
@ -1108,12 +1097,12 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err
//查询已经开仓的合约交易对 //查询已经开仓的合约交易对
var futList []models.LinePreOrder var futList []models.LinePreOrder
if position.Symbol == "" { if position.Symbol == "" {
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = '13' AND pid = 0 AND order_type = '2'", position.ApiId).Find(&futList) e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND status = 6 AND order_category=2 AND order_type =0", position.ApiId).Find(&futList)
} else { } else {
e.Orm.Model(&models.LinePreOrder{}).Where("api_id = ? AND symbol = ? AND status = '13' AND pid = 0 AND order_type = '2'", position.ApiId, position.Symbol).Find(&futList) 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)
} }
if len(futList) <= 0 { if len(futList) <= 0 {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 没有可平仓的交易对", position.ApiId))) *errs = append(*errs, fmt.Errorf("api_id:%d 没有可平仓的交易对", position.ApiId))
return return
} }
@ -1122,15 +1111,22 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err
for _, list := range futList { for _, list := range futList {
risks, err := api.GetPositionV3(&apiUserInfo, list.Symbol) risks, err := api.GetPositionV3(&apiUserInfo, list.Symbol)
if err != nil { if err != nil {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 获取仓位信息时 没有可平仓的交易对 err: %s", position.ApiId, err))) *errs = append(*errs, fmt.Errorf("api_id:%d 获取仓位信息时 没有可平仓的交易对 err: %s", position.ApiId, err))
continue continue
} }
key := fmt.Sprintf(global.TICKER_FUTURES, list.SymbolType, list.Symbol) key := fmt.Sprintf(global.TICKER_FUTURES, list.ExchangeType, list.Symbol)
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key) tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, key)
lastPrice := api.GetFutSymbolLastPrice(list.Symbol) lastPrice := api.GetFutSymbolLastPrice(list.Symbol)
parentId := list.Id
if list.Pid > 0 {
parentId = list.Pid
}
for _, risk := range risks { for _, risk := range risks {
positionAmt := utility.StringToDecimal(risk.PositionAmt) positionAmt := utility.StringToDecimal(risk.PositionAmt)
var riskSide string var riskSide string
var orderSide string var orderSide string
if positionAmt.GreaterThan(decimal.Zero) { if positionAmt.GreaterThan(decimal.Zero) {
@ -1154,12 +1150,12 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err
} }
if positionAmt.Abs().LessThanOrEqual(decimal.NewFromFloat(tradeSet.MinQty)) { if positionAmt.Abs().LessThanOrEqual(decimal.NewFromFloat(tradeSet.MinQty)) {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 下单数量小于最小下单数量", position.ApiId))) *errs = append(*errs, fmt.Errorf("api_id:%d 下单数量小于最小下单数量", position.ApiId))
continue continue
} }
order := models.LinePreOrder{ order := models.LinePreOrder{
Pid: list.Id, Pid: parentId,
ApiId: list.ApiId, ApiId: list.ApiId,
GroupId: "0", GroupId: "0",
Symbol: list.Symbol, Symbol: list.Symbol,
@ -1185,7 +1181,7 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err
} }
err = e.Orm.Model(&models.LinePreOrder{}).Create(&order).Error err = e.Orm.Model(&models.LinePreOrder{}).Create(&order).Error
if err != nil { if err != nil {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 生成平仓单错误:%s", position.ApiId, err))) *errs = append(*errs, fmt.Errorf("api_id:%d 生成平仓单错误:%s", position.ApiId, err))
continue continue
} }
@ -1202,7 +1198,7 @@ func (e *LinePreOrder) FutClosePosition(position *dto.ClosePosition, errs *[]err
err = api.ClosePosition(list.Symbol, order.OrderSn, utility.StringToDecimal(order.Num), "SELL", "LONG", apiUserInfo, "LIMIT", "0", price) err = api.ClosePosition(list.Symbol, order.OrderSn, utility.StringToDecimal(order.Num), "SELL", "LONG", apiUserInfo, "LIMIT", "0", price)
} }
if err != nil { if err != nil {
*errs = append(*errs, errors.New(fmt.Sprintf("api_id:%d 币安平仓单错误:%s", position.ApiId, err))) *errs = append(*errs, fmt.Errorf("api_id:%d 币安平仓单错误:%s", position.ApiId, err))
continue continue
} }
// 主单平仓删除缓存 // 主单平仓删除缓存
@ -1229,13 +1225,15 @@ func (e *LinePreOrder) ClearUnTriggered() error {
OrderSn: order.OrderSn, OrderSn: order.OrderSn,
QuoteSymbol: order.QuoteSymbol, QuoteSymbol: order.QuoteSymbol,
} }
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf("%s:%s", global.TICKER_SPOT, order.Symbol)) tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf(global.TICKER_SPOT, order.ExchangeType, order.Symbol))
redisList.Price = utility.StringToDecimal(redisList.Price).Truncate(int32(tradeSet.PriceDigit)).String() redisList.Price = utility.StringToDecimal(redisList.Price).Truncate(int32(tradeSet.PriceDigit)).String()
marshal, _ := sonic.Marshal(redisList) marshal, _ := sonic.Marshal(redisList)
if order.SymbolType == 1 { if order.SymbolType == 1 {
helper.DefaultRedis.LRem(rediskey.PreFutOrderList, string(marshal)) key := fmt.Sprintf(rediskey.PreFutOrderList, order.ExchangeType)
helper.DefaultRedis.LRem(key, string(marshal))
} else { } else {
helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, string(marshal)) 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("pid = ?", order.Id).Unscoped().Delete(&models.LinePreOrder{})
} }

View File

@ -148,7 +148,7 @@ func (e *LinePriceLimit) UpRange() error {
} }
for _, hr := range spotTicker24HrAll { for _, hr := range spotTicker24HrAll {
tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf("%s:%s", global.TICKER_SPOT, hr.Symbol)) tradeSet, _ := helper.GetObjString[models2.TradeSet](helper.DefaultRedis, fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, hr.Symbol))
if tradeSet.Currency != "" && tradeSet.Coin != "" { if tradeSet.Currency != "" && tradeSet.Coin != "" {
spotTicker24Hr = append(spotTicker24Hr, hr) spotTicker24Hr = append(spotTicker24Hr, hr)
} }

View File

@ -61,6 +61,11 @@ func (e *LineSymbol) GetSamePage(c *dto.LineSymbolGetPageReq, p *actions.DataPer
Scopes( Scopes(
actions.Permission(data.TableName(), p), actions.Permission(data.TableName(), p),
) )
if c.ExchangeType != "" {
tx.Where("exchange_type = ?", c.ExchangeType)
scopes.Where("exchange_type = ?", c.ExchangeType)
}
if c.Symbol != "" { if c.Symbol != "" {
tx.Where("symbol = ?", c.Symbol) tx.Where("symbol = ?", c.Symbol)
scopes.Where("symbol = ?", c.Symbol) scopes.Where("symbol = ?", c.Symbol)
@ -153,16 +158,16 @@ func (e *LineSymbol) Remove(d *dto.LineSymbolDeleteReq, p *actions.DataPermissio
return nil return nil
} }
func (e *LineSymbol) GetSymbol() (data []models.LineSymbol, err error) { func (e *LineSymbol) GetSymbol(req *dto.LineSymbolGetListReq) (data []models.LineSymbol, err error) {
var ( var (
spotSymbol, futSymbol []models.LineSymbol spotSymbol, futSymbol []models.LineSymbol
) )
err = e.Orm.Model(&models.LineSymbol{}).Where("type = '1' AND switch = 1").Find(&spotSymbol).Error err = e.Orm.Model(&models.LineSymbol{}).Where("type = '1' AND switch = 1 AND exchange_type =?", req.ExchangeType).Find(&spotSymbol).Error
if err != nil { if err != nil {
e.Log.Errorf("Service GetSpotSymbol error:%s \r\n", err) e.Log.Errorf("Service GetSpotSymbol error:%s \r\n", err)
return data, err return data, err
} }
err = e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = 1").Find(&futSymbol).Error err = e.Orm.Model(&models.LineSymbol{}).Where("type = '2' AND switch = 1 AND exchange_type =?", req.ExchangeType).Find(&futSymbol).Error
if err != nil { if err != nil {
e.Log.Errorf("Service GetFutSymbol error:%s \r\n", err) e.Log.Errorf("Service GetFutSymbol error:%s \r\n", err)
return data, err return data, err
@ -224,7 +229,7 @@ func (e *LineSymbol) ResetSpotSymbol() error {
for symbol, tradeSet := range tradeSets { for symbol, tradeSet := range tradeSets {
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, symbol) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbol)
//判断是否在黑名单里面 //判断是否在黑名单里面
for _, black := range symbolBlack { for _, black := range symbolBlack {
@ -265,6 +270,7 @@ func (e *LineSymbol) ResetSpotSymbol() error {
lineSymbol, _ := oldMapSymbols[symbol] lineSymbol, _ := oldMapSymbols[symbol]
if lineSymbol.Id <= 0 { if lineSymbol.Id <= 0 {
lineSymbol.ExchangeType = global.EXCHANGE_BINANCE
lineSymbol.Symbol = symbol lineSymbol.Symbol = symbol
lineSymbol.BaseAsset = tradeSet.Coin lineSymbol.BaseAsset = tradeSet.Coin
lineSymbol.QuoteAsset = tradeSet.Currency lineSymbol.QuoteAsset = tradeSet.Currency
@ -380,7 +386,7 @@ func (e *LineSymbol) ResetFuturesSymbol() error {
e.Orm.Model(&models.LineSymbolBlack{}).Where("type = 2").Find(&symbolBlack) e.Orm.Model(&models.LineSymbolBlack{}).Where("type = 2").Find(&symbolBlack)
for symbol, tradeSet := range tradeSets { for symbol, tradeSet := range tradeSets {
key := fmt.Sprintf("%s:%s", global.TICKER_FUTURES, symbol) key := fmt.Sprintf(global.TICKER_FUTURES, global.EXCHANGE_BINANCE, symbol)
//判断是否在黑名单里面 //判断是否在黑名单里面
for _, black := range symbolBlack { for _, black := range symbolBlack {
@ -419,6 +425,7 @@ func (e *LineSymbol) ResetFuturesSymbol() error {
lineSymbol, _ := oldMapSymbols[symbol] lineSymbol, _ := oldMapSymbols[symbol]
if lineSymbol.Id <= 0 { if lineSymbol.Id <= 0 {
lineSymbol.ExchangeType = global.EXCHANGE_BINANCE
lineSymbol.Symbol = symbol lineSymbol.Symbol = symbol
lineSymbol.BaseAsset = tradeSet.Coin lineSymbol.BaseAsset = tradeSet.Coin
lineSymbol.QuoteAsset = tradeSet.Currency lineSymbol.QuoteAsset = tradeSet.Currency

View File

@ -21,13 +21,17 @@ type LineSymbolGroup struct {
func (e *LineSymbolGroup) GetPage(c *dto.LineSymbolGroupGetPageReq, p *actions.DataPermission, list *[]models.LineSymbolGroup, count *int64) error { func (e *LineSymbolGroup) GetPage(c *dto.LineSymbolGroupGetPageReq, p *actions.DataPermission, list *[]models.LineSymbolGroup, count *int64) error {
var err error var err error
var data models.LineSymbolGroup var data models.LineSymbolGroup
query := e.Orm.Model(&data).
err = e.Orm.Model(&data).
Scopes( Scopes(
cDto.MakeCondition(c.GetNeedSearch()), cDto.MakeCondition(c.GetNeedSearch()),
cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
actions.Permission(data.TableName(), p), actions.Permission(data.TableName(), p),
). )
if c.ExchangeType != "" {
query = query.Where("exchange_type = ?", c.ExchangeType)
}
err = query.
Find(list).Limit(-1).Offset(-1). Find(list).Limit(-1).Offset(-1).
Count(count).Error Count(count).Error
if err != nil { if err != nil {

View File

@ -63,7 +63,7 @@ const (
const ( const (
//交易对-现货 //交易对-现货
SYMBOL_SPOT = 0 SYMBOL_SPOT = 1
//交易对-合约 //交易对-合约
SYMBOL_FUTURES = 1 SYMBOL_FUTURES = 2
) )

View File

@ -5,6 +5,7 @@ import (
"go-admin/app/admin/models" "go-admin/app/admin/models"
"go-admin/app/admin/service" "go-admin/app/admin/service"
"go-admin/common/const/rediskey" "go-admin/common/const/rediskey"
"go-admin/common/global"
"go-admin/common/helper" "go-admin/common/helper"
"go-admin/pkg/utility" "go-admin/pkg/utility"
"go-admin/services/excservice" "go-admin/services/excservice"
@ -20,7 +21,7 @@ import (
func UserSubscribeInit(orm *gorm.DB, ctx context.Context) { func UserSubscribeInit(orm *gorm.DB, ctx context.Context) {
var list []models.LineApiUser var list []models.LineApiUser
err := orm.Model(&models.LineApiUser{}).Where("open_status=1 ").Find(&list).Error err := orm.Model(&models.LineApiUser{}).Where("open_status=1 AND exchange_type =?", global.EXCHANGE_BINANCE).Find(&list).Error
if err != nil { if err != nil {
log.Error("获取用户api失败", err) log.Error("获取用户api失败", err)

View File

@ -5,7 +5,7 @@ settings:
# 服务器ip默认使用 0.0.0.0 # 服务器ip默认使用 0.0.0.0
host: 0.0.0.0 host: 0.0.0.0
# 服务名称 # 服务名称
name: testApp name: exchange_go
# 端口号 # 端口号
port: 6789 # 服务端口号 port: 6789 # 服务端口号
readtimeout: 1 readtimeout: 1
@ -31,7 +31,7 @@ settings:
# sqlserver: sqlserver://用户名:密码@地址?database=数据库名 # sqlserver: sqlserver://用户名:密码@地址?database=数据库名
driver: mysql driver: mysql
# 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms
source: root:root@tcp(192.168.1.12:3306)/gp-bian?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms source: root:root@tcp(192.168.1.12:3306)/go_exchange?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms
# databases: # databases:
# 'locaohost:8000': # 'locaohost:8000':
# driver: mysql # driver: mysql
@ -53,7 +53,7 @@ settings:
redis: redis:
addr: "192.168.1.12:6379" addr: "192.168.1.12:6379"
password: "" password: ""
db: 0 db: 1
# 雪花算法设备id # 雪花算法设备id
serviceId: 1 serviceId: 1

View File

@ -93,7 +93,7 @@ func (e SpotRestApi) GetSpotTicker24h(tradeSet *map[string]models.TradeSet) (del
} }
for _, item := range tickers { for _, item := range tickers {
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, item.Symbol) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, item.Symbol)
symbol, exits := (*tradeSet)[item.Symbol] symbol, exits := (*tradeSet)[item.Symbol]
if !exits { if !exits {
@ -138,7 +138,7 @@ func (e SpotRestApi) GetSpotTicker24h(tradeSet *map[string]models.TradeSet) (del
- @data 结果 - @data 结果
*/ */
func (e SpotRestApi) GetSpotTicker24(symbol string, data *models.Ticker24, tradeSet *models.TradeSet) error { func (e SpotRestApi) GetSpotTicker24(symbol string, data *models.Ticker24, tradeSet *models.TradeSet) error {
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, symbol) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbol)
val, err := helper.DefaultRedis.GetString(key) val, err := helper.DefaultRedis.GetString(key)
if err != nil { if err != nil {
@ -304,7 +304,7 @@ func (e SpotRestApi) CancelOpenOrderByOrderSn(apiUserInfo DbModels.LineApiUser,
} else { } else {
client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress) client, _ = helper.NewBinanceClient(apiUserInfo.ApiKey, apiUserInfo.ApiSecret, "socks5", apiUserInfo.UserPass+"@"+apiUserInfo.IpAddress)
} }
_, code, err := client.SendSpotAuth("/api/v3/order ", "DELETE", params) _, code, err := client.SendSpotAuth("/api/v3/order", "DELETE", params)
if err != nil || code != 200 { if err != nil || code != 200 {
log.Error("取消现货委托失败 参数:", params) log.Error("取消现货委托失败 参数:", params)
log.Error("取消现货委托失败 code:", code) log.Error("取消现货委托失败 code:", code)
@ -352,7 +352,7 @@ func (e SpotRestApi) ClosePosition(symbol string, orderSn string, quantity decim
} }
if orderType == "LIMIT" { if orderType == "LIMIT" {
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, symbol) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbol)
tradeSet, _ := helper.GetObjString[models.TradeSet](helper.DefaultRedis, key) tradeSet, _ := helper.GetObjString[models.TradeSet](helper.DefaultRedis, key)
rateFloat, _ := decimal.NewFromString(rate) rateFloat, _ := decimal.NewFromString(rate)
if rateFloat.GreaterThan(decimal.Zero) { if rateFloat.GreaterThan(decimal.Zero) {
@ -515,6 +515,117 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
} }
} }
// 判断是否触发止损
func JudgeSpotStopLoss(trade models.TradeSet) {
key := fmt.Sprintf(rediskey.SpotStopLossList, global.EXCHANGE_BINANCE)
stopLossVal, _ := helper.DefaultRedis.GetAllList(key)
if len(stopLossVal) == 0 {
return
}
db := GetDBConnection()
spotApi := SpotRestApi{}
setting, err := GetSystemSetting(db)
if err != nil {
log.Error("获取系统设置失败")
return
}
tradeSet, err := GetTradeSet(trade.Coin+trade.Currency, 0)
if err != nil {
log.Error("获取交易设置失败")
return
}
for _, item := range stopLossVal {
stopOrder := dto.StopLossRedisList{}
if err := sonic.Unmarshal([]byte(item), &stopOrder); err != nil {
log.Error("反序列化失败")
continue
}
if stopOrder.Symbol == trade.Coin+trade.Currency {
orderPrice := stopOrder.Price
tradePrice, _ := decimal.NewFromString(trade.LastPrice)
//买入
if strings.ToUpper(stopOrder.Site) == "SELL" &&
orderPrice.Cmp(tradePrice) >= 0 &&
orderPrice.Cmp(decimal.Zero) > 0 &&
tradePrice.Cmp(decimal.Zero) > 0 {
SpotStopLossTrigger(db, stopOrder, spotApi, setting, tradeSet, key, item)
}
}
}
}
// 触发现货止损
func SpotStopLossTrigger(db *gorm.DB, stopOrder dto.StopLossRedisList, spotApi SpotRestApi, setting DbModels.LineSystemSetting, tradeSet models.TradeSet, key string, item string) {
lock := helper.NewRedisLock(fmt.Sprintf(rediskey.SpotTrigger, stopOrder.ApiId, stopOrder.Symbol), 20, 5, 100*time.Millisecond)
if ok, err := lock.AcquireWait(context.Background()); err != nil {
log.Error("获取锁失败", err)
return
} else if ok {
defer lock.Release()
takeOrder := DbModels.LinePreOrder{}
if err := db.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type =1", stopOrder.PId).Find(&takeOrder).Error; err != nil {
log.Error("查询止盈单失败")
return
}
apiInfo, _ := GetApiInfo(takeOrder.ApiId)
if apiInfo.Id == 0 {
log.Error("现货止损 查询api用户不存在")
return
}
var err error
for x := 1; x <= 4; x++ {
err = spotApi.CancelOpenOrderByOrderSn(apiInfo, takeOrder.Symbol, takeOrder.OrderSn)
if err == nil {
break
}
}
if err != nil {
log.Error("现货止损撤单失败", err)
return
}
stopPreOrder, _ := GetOrderById(db, stopOrder.Id)
price := stopOrder.Price.Mul(decimal.NewFromInt(1).Sub(setting.StopLossPremium.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.PriceDigit))
num := utility.StrToDecimal(takeOrder.Num).Truncate(int32(tradeSet.AmountDigit))
params := OrderPlacementService{
ApiId: takeOrder.ApiId,
Side: takeOrder.Site,
Type: "LIMIT",
TimeInForce: "GTC",
Symbol: takeOrder.Symbol,
Price: price,
Quantity: num,
NewClientOrderId: stopPreOrder.OrderSn,
}
if err := spotApi.OrderPlace(db, params); err != nil {
log.Errorf("现货止损挂单失败 id%s err:%v", stopOrder.Id, err)
}
if _, err := helper.DefaultRedis.LRem(key, item); err != nil {
log.Errorf("现货止损 删除缓存失败 id:%v err:%v", stopOrder.Id, err)
}
} else {
log.Error("获取锁失败")
}
}
/* /*
获取api用户信息 获取api用户信息
*/ */

View File

@ -319,7 +319,7 @@ func InitSymbolsTicker24h(maps *map[string]models.TradeSet) (deletes []string, e
symbol.QuoteVolume = item.QuoteVolume symbol.QuoteVolume = item.QuoteVolume
symbol.LastPrice = item.LastPrice symbol.LastPrice = item.LastPrice
key := fmt.Sprintf("%s:%s", global.TICKER_FUTURES, item.Symbol) key := fmt.Sprintf(global.TICKER_FUTURES, global.EXCHANGE_BINANCE, item.Symbol)
if !strings.HasSuffix(item.Symbol, symbol.Currency) || item.Count <= 0 || utility.StringToFloat64(item.QuoteVolume) <= 0 { if !strings.HasSuffix(item.Symbol, symbol.Currency) || item.Count <= 0 || utility.StringToFloat64(item.QuoteVolume) <= 0 {
helper.DefaultRedis.DeleteString(key) helper.DefaultRedis.DeleteString(key)
deleteSymbol = append(deleteSymbol, item.Symbol) deleteSymbol = append(deleteSymbol, item.Symbol)
@ -332,7 +332,7 @@ func InitSymbolsTicker24h(maps *map[string]models.TradeSet) (deletes []string, e
log.Error("设置行情序列化报错", err) log.Error("设置行情序列化报错", err)
} }
tcKey := fmt.Sprintf("%s:%s", global.TICKER_FUTURES, item.Symbol) tcKey := fmt.Sprintf(global.TICKER_FUTURES, global.EXCHANGE_BINANCE, item.Symbol)
caches[tcKey] = string(val) caches[tcKey] = string(val)
priceChange = append(priceChange, &redis.Z{ priceChange = append(priceChange, &redis.Z{
Score: symbol.PriceChange, Score: symbol.PriceChange,

View File

@ -2,11 +2,9 @@ package binanceservice
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"go-admin/app/admin/models" "go-admin/app/admin/models"
DbModels "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/const/rediskey"
"go-admin/common/global" "go-admin/common/global"
"go-admin/common/helper" "go-admin/common/helper"
@ -28,11 +26,17 @@ import (
func ChangeFutureOrder(mapData map[string]interface{}) { func ChangeFutureOrder(mapData map[string]interface{}) {
// 检查订单号是否存在 // 检查订单号是否存在
orderSn, ok := mapData["c"] orderSn, ok := mapData["c"]
originOrderSn := mapData["C"] //取消操作 代表原始订单号
if !ok { if !ok {
logger.Error("合约订单回调失败,没有订单号") logger.Error("合约订单回调失败,没有订单号")
return return
} }
if originOrderSn != "" {
orderSn = originOrderSn
}
// 获取数据库连接 // 获取数据库连接
db := GetDBConnection() db := GetDBConnection()
if db == nil { if db == nil {
@ -134,42 +138,47 @@ func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
return return
} }
// 获取交易对配置 triggerHedgeOrder(order, db, preOrder)
}
// 下合约对冲单
func triggerHedgeOrder(order DbModels.LinePreOrder, db *gorm.DB, preOrder *DbModels.LinePreOrder) bool {
symbolName := utility.ReplaceSuffix(order.Symbol, order.QuoteSymbol, "USDT") symbolName := utility.ReplaceSuffix(order.Symbol, order.QuoteSymbol, "USDT")
// 获取交易对配置
tradeSet, err := GetTradeSet(symbolName, 1) tradeSet, err := GetTradeSet(symbolName, 1)
if tradeSet.Coin == "" || err != nil { if tradeSet.Coin == "" || err != nil {
logger.Errorf("止损单成交 获取交易对配置失败 交易对:%s 订单号:%s err:%v", symbolName, order.OrderSn, err) logger.Errorf("止损单成交 获取交易对配置失败 交易对:%s 订单号:%s err:%v", symbolName, order.OrderSn, err)
return return true
} }
// 检查对冲单购买金额 // 检查对冲单购买金额
if order.HedgeBuyTotal.Cmp(decimal.Zero) <= 0 { if order.HedgeBuyTotal.Cmp(decimal.Zero) <= 0 {
logger.Errorf("止损单成交 对冲单购买金额为0 订单号:%s", order.OrderSn) logger.Errorf("止损单成交 对冲单购买金额为0 订单号:%s", order.OrderSn)
return return true
} }
// 获取系统设置 // 获取系统设置
setting, err := GetSystemSetting(db) setting, err := GetSystemSetting(db)
if err != nil { if err != nil {
logger.Errorf("止损单成交 获取系统设置失败 订单号:%s err:%v", order.OrderSn, err) logger.Errorf("止损单成交 获取系统设置失败 订单号:%s err:%v", order.OrderSn, err)
return return true
} }
// 获取API信息 // 获取API信息
apiInfo, err := GetChildApiInfo(order.ApiId) apiInfo, err := GetChildApiInfo(order.ApiId)
if err != nil { if err != nil {
logger.Errorf("止损单成交 获取api信息失败 订单号:%s err:%v", order.OrderSn, err) logger.Errorf("止损单成交 获取api信息失败 订单号:%s err:%v", order.OrderSn, err)
return return true
} }
// 计算价格 // 计算价格
price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit)) price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit))
if order.CoverType == 2 { if order.CoverType == 1 {
price = utility.StrToDecimal(tradeSet.LastPrice).Truncate(int32(tradeSet.PriceDigit)) price = utility.StrToDecimal(tradeSet.LastPrice).Truncate(int32(tradeSet.PriceDigit))
} }
if price.Cmp(decimal.Zero) <= 0 { if price.Cmp(decimal.Zero) <= 0 {
logger.Errorf("单价异常 price:%v 止损单编号:%s 行情:%v", price, order.OrderSn, tradeSet) logger.Errorf("单价异常 price:%v 止损单编号:%s 行情:%v", price, order.OrderSn, tradeSet)
return return true
} }
// 创建对冲订单 // 创建对冲订单
@ -179,17 +188,25 @@ func handleStopLoss(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
// 批量插入订单 // 批量插入订单
if err := db.Model(&DbModels.LinePreOrder{}).CreateInBatches(orders, 1).Error; err != nil { if err := db.Model(&DbModels.LinePreOrder{}).CreateInBatches(orders, 1).Error; err != nil {
logger.Errorf("主单止损 重下对冲失败止损单id%s err:%v", order.OrderSn, err) logger.Errorf("主单止损 重下对冲失败止损单id%s err:%v", order.OrderSn, err)
return return true
} }
// 调用API下单 // 调用API下单
if err := placeFutOrder(db, hedgeOrder, price, &apiInfo); err != nil { if err := placeFutOrder(db, hedgeOrder, price, &apiInfo); err != nil {
logger.Errorf("主单止损 重下对冲失败,止损单号:%s err:%v", order.OrderSn, err) logger.Errorf("主单止损 重下对冲失败,止损单号:%s err:%v", order.OrderSn, err)
} }
return false
} }
// 创建对冲订单 // 创建对冲订单
func createHedgeOrders(order DbModels.LinePreOrder, price decimal.Decimal, tradeSet *models2.TradeSet, apiInfo *DbModels.LineApiUser, setting *DbModels.LineSystemSetting) (DbModels.LinePreOrder, DbModels.LinePreOrder, DbModels.LinePreOrder) { func createHedgeOrders(order DbModels.LinePreOrder, price decimal.Decimal, tradeSet *models2.TradeSet, apiInfo *DbModels.LineApiUser, setting *DbModels.LineSystemSetting) (DbModels.LinePreOrder, DbModels.LinePreOrder, DbModels.LinePreOrder) {
buyPrice := order.HedgeBuyTotal.String()
if order.HedgeBuyType == 1 {
mainTotal := utility.StrToDecimal(order.BuyPrice)
buyPrice = mainTotal.Mul(order.HedgeBuyTotal).Truncate(int32(tradeSet.PriceDigit)).String()
}
hedgeOrder := DbModels.LinePreOrder{ hedgeOrder := DbModels.LinePreOrder{
ApiId: apiInfo.Id, ApiId: apiInfo.Id,
ExchangeType: order.ExchangeType, ExchangeType: order.ExchangeType,
@ -199,7 +216,7 @@ func createHedgeOrders(order DbModels.LinePreOrder, price decimal.Decimal, trade
SignPrice: order.Price, SignPrice: order.Price,
SignPriceType: "new", SignPriceType: "new",
Rate: "0", Rate: "0",
BuyPrice: order.HedgeBuyTotal.String(), BuyPrice: buyPrice,
OrderCategory: 2, OrderCategory: 2,
OrderSn: utility.Int64ToString(snowflakehelper.GetOrderId()), OrderSn: utility.Int64ToString(snowflakehelper.GetOrderId()),
OrderType: 0, OrderType: 0,
@ -302,7 +319,9 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) {
if i >= 2 { // 最多处理 2 个订单 if i >= 2 { // 最多处理 2 个订单
break break
} }
price := utility.StrToDecimal(order.Price).Truncate(int32(tradeSet.PriceDigit))
num = num.Truncate(int32(tradeSet.AmountDigit)) num = num.Truncate(int32(tradeSet.AmountDigit))
order.Price = price.String()
if err := db.Model(&order).Update("num", num).Error; err != nil { if err := db.Model(&order).Update("num", num).Error; err != nil {
logger.Errorf("修改止盈止损数量失败 订单号:%s err:%v", order.OrderSn, err) logger.Errorf("修改止盈止损数量失败 订单号:%s err:%v", order.OrderSn, err)
@ -312,7 +331,7 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder) {
case 1: // 止盈 case 1: // 止盈
processFutTakeProfitOrder(db, futApi, order, num) processFutTakeProfitOrder(db, futApi, order, num)
case 2: // 止损 case 2: // 止损
processFutStopLossOrder(order) processFutStopLossOrder(db, order, price, num)
} }
} }
} }
@ -345,6 +364,8 @@ func processFutTakeProfitOrder(db *gorm.DB, futApi FutRestApi, order models.Line
if err == nil { if err == nil {
break break
} }
time.Sleep(time.Millisecond * 250)
} }
} }
@ -364,29 +385,39 @@ func processFutTakeProfitOrder(db *gorm.DB, futApi FutRestApi, order models.Line
// 处理止损订单 // 处理止损订单
// order 止损单 // order 止损单
func processFutStopLossOrder(order models.LinePreOrder) error { func processFutStopLossOrder(db *gorm.DB, order models.LinePreOrder, price, num decimal.Decimal) error {
price := utility.StrToDecimal(order.Price) params := FutOrderPlace{
stopLoss := dto.StopLossRedisList{ ApiId: order.ApiId,
Id: order.Id, Symbol: order.Symbol,
PId: order.Pid, Side: order.Site,
ApiId: order.ApiId, Price: price,
OrderTye: order.OrderType, Quantity: num,
OrderCategory: order.OrderCategory, OrderType: "STOP_MARKET",
Price: price, StopPrice: price,
SymbolType: order.SymbolType, NewClientOrderId: order.OrderSn,
Symbol: order.Symbol, }
Site: order.Site, futApi := FutRestApi{}
var err error
for x := 1; x < 4; x++ {
err = futApi.OrderPlace(db, params)
if err == nil {
break
}
time.Sleep(time.Millisecond * 200)
} }
stoplossVal, _ := sonic.MarshalString(&stopLoss) if err != nil {
stoplossKey := fmt.Sprintf(rediskey.FuturesStopLossList, global.EXCHANGE_BINANCE) if err2 := db.Model(&order).Updates(map[string]interface{}{"status": 2, "desc": err.Error()}).Error; err2 != nil {
logger.Error("合约止损下单失败,更新状态失败:", order.OrderSn, " err:", err2)
if stoplossVal == "" { }
return errors.New("stoplossVal is empty") } else {
} if err := db.Model(&order).Where("status =0").
Updates(map[string]interface{}{"status": "1"}).Error; err != nil {
if err := helper.DefaultRedis.RPushList(stoplossKey, stoplossVal); err != nil { logger.Error("合约止损下单成功,更新状态失败:", order.OrderSn, " err:", err)
return err }
} }
return nil return nil

View File

@ -27,11 +27,17 @@ import (
func ChangeSpotOrder(mapData map[string]interface{}) { func ChangeSpotOrder(mapData map[string]interface{}) {
// 检查订单号是否存在 // 检查订单号是否存在
orderSn, ok := mapData["c"] orderSn, ok := mapData["c"]
originOrderSn := mapData["C"] //取消操作 代表原始订单号
if !ok { if !ok {
logger.Error("订单回调失败, 没有订单号", mapData) logger.Error("订单回调失败, 没有订单号", mapData)
return return
} }
if originOrderSn != "" {
orderSn = originOrderSn
}
// 获取数据库连接 // 获取数据库连接
db := GetDBConnection() db := GetDBConnection()
if db == nil { if db == nil {
@ -123,6 +129,13 @@ func handleOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderStatus
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =?", preOrder.Pid).Update("status", 9).Error; err != nil { if err := db.Model(&DbModels.LinePreOrder{}).Where("id =?", preOrder.Pid).Update("status", 9).Error; err != nil {
logger.Errorf("主单止损回调 订单号:%s 修改主单状态失败:%v", preOrder.OrderSn, err) logger.Errorf("主单止损回调 订单号:%s 修改主单状态失败:%v", preOrder.OrderSn, err)
} }
} else {
order, err := GetOrderById(db, preOrder.Pid)
if err != nil {
logger.Errorf("主单止损回调 获取主单失败 订单号:%s err:%v", preOrder.OrderSn, err)
return
}
triggerHedgeOrder(order, db, preOrder)
} }
} }
} }
@ -178,7 +191,7 @@ func handleSpotTakeProfitFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
for _, v := range stoplossVal { for _, v := range stoplossVal {
sonic.Unmarshal([]byte(v), &stoploss) sonic.Unmarshal([]byte(v), &stoploss)
if stoploss.Pid == preOrder.Id { if stoploss.Pid == preOrder.Pid {
_, err := helper.DefaultRedis.LRem(stoplossKey, v) _, err := helper.DefaultRedis.LRem(stoplossKey, v)
if err != nil { if err != nil {
@ -235,7 +248,7 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r
params["num"] = num params["num"] = num
params["price"] = total.Div(totalAmount) params["price"] = total.Div(totalAmount)
preOrder.Num = num.String() preOrder.Num = num.String()
preOrder.Price = params["price"].(string) preOrder.Price = total.Div(totalAmount).String()
} }
case false: case false:
status, _ := mapData["X"].(string) status, _ := mapData["X"].(string)
@ -243,10 +256,11 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r
if status == "FILLED" { if status == "FILLED" {
num, _ := decimal.NewFromString(mapData["z"].(string)) num, _ := decimal.NewFromString(mapData["z"].(string))
params["num"] = num.Mul(decimal.NewFromFloat(0.998)).String() params["num"] = num.Mul(decimal.NewFromFloat(0.998)).String()
params["price"], _ = mapData["ap"].(string) price, _ := mapData["ap"].(string)
params["price"] = price
preOrder.Num = num.String() preOrder.Num = num.String()
preOrder.Price = params["price"].(string) preOrder.Price = price
} }
} }

View File

@ -203,7 +203,7 @@ func handleTickerMessage(msg []byte) {
continue continue
} }
key := fmt.Sprintf("%s:%s", global.TICKER_SPOT, symbolName) key := fmt.Sprintf(global.TICKER_SPOT, global.EXCHANGE_BINANCE, symbolName)
tcVal, _ := helper.DefaultRedis.GetString(key) tcVal, _ := helper.DefaultRedis.GetString(key)
tradeSet := models.TradeSet{} tradeSet := models.TradeSet{}
if err := sonic.UnmarshalString(tcVal, &tradeSet); err != nil { if err := sonic.UnmarshalString(tcVal, &tradeSet); err != nil {
@ -245,7 +245,7 @@ func handleTickerMessage(msg []byte) {
utility.SafeGoParam(binanceservice.JudgeSpotPrice, trades[index]) utility.SafeGoParam(binanceservice.JudgeSpotPrice, trades[index])
// 止损单 // 止损单
// utility.SafeGoParam(binanceservice.JudgeSpotStopLoss, trades[index]) utility.SafeGoParam(binanceservice.JudgeSpotStopLoss, trades[index])
} }
} }
} }