1、重写

This commit is contained in:
2025-02-06 18:03:09 +08:00
parent 07847a2d9e
commit c0b8749eef
15 changed files with 546 additions and 720 deletions

View File

@ -14,13 +14,9 @@ import (
"go-admin/models/spot"
"go-admin/pkg/httputils"
"go-admin/pkg/utility"
"go-admin/pkg/utility/snowflakehelper"
"strconv"
"strings"
"time"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/copier"
"github.com/shopspring/decimal"
"gorm.io/gorm"
@ -244,14 +240,6 @@ func (e SpotRestApi) OrderPlace(orm *gorm.DB, params OrderPlacementService) erro
if err := sonic.Unmarshal(resp, &dataMap); err != nil {
return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%+v", apiUserInfo.Id, params.Symbol, err.Error())
}
//code, ok := dataMap["code"]
//if !ok {
// return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, params.Symbol, dataMap["message"])
//
//}
//if code.(float64) != 200 {
// return fmt.Errorf("api_id:%d 交易对:%s 下单失败:%s", apiUserInfo.Id, params.Symbol, dataMap["message"])
//}
return nil
}
@ -341,48 +329,6 @@ func (e SpotRestApi) CancelOpenOrderByOrderSn(apiUserInfo DbModels.LineApiUser,
return nil
}
// CalcEntryCashPriceByOrder 计算现货主单均价
func CalcEntryCashPriceByOrder(orderInfo *DbModels.LinePreOrder, orm *gorm.DB) (EntryPriceResult, error) {
//找到主单成交的记录
var id int
if orderInfo.Pid > 0 {
id = orderInfo.Pid
} else {
id = orderInfo.Id
}
orderLists := make([]DbModels.LinePreOrder, 0)
orm.Model(&DbModels.LinePreOrder{}).Where(" symbol = ? AND site = 'BUY' AND order_type in ('1','8') AND status ='9' AND (id = ? OR pid = ?)", orderInfo.Symbol, id, id).Find(&orderLists)
var (
totalNum decimal.Decimal //总成交数量
totalMoney decimal.Decimal //总金额
entryPrice decimal.Decimal //均价
initPrice decimal.Decimal //主单下单价格
firstId int //主单id
)
for _, list := range orderLists {
num, _ := decimal.NewFromString(list.Num)
totalNum = totalNum.Add(num)
price, _ := decimal.NewFromString(list.Price)
totalMoney = totalMoney.Add(num.Mul(price))
if list.OrderType == "1" {
firstId = list.Id
initPrice, _ = decimal.NewFromString(list.Price)
}
}
if totalNum.GreaterThan(decimal.Zero) {
entryPrice = totalMoney.Div(totalNum)
}
return EntryPriceResult{
TotalNum: totalNum,
EntryPrice: entryPrice,
FirstPrice: initPrice,
FirstId: firstId,
TotalMoney: totalMoney,
}, nil
}
// ClosePosition 平仓
// symbol 交易对
// orderSn 平仓单号
@ -459,135 +405,15 @@ func GetClient(apiUserInfo *DbModels.LineApiUser) *helper.BinanceClient {
return client
}
/*
重下止盈单
*/
func (e SpotRestApi) reTakeOrder(parentOrderInfo DbModels.LinePreOrder, orm *gorm.DB) {
price, _ := decimal.NewFromString(parentOrderInfo.Price)
num, _ := decimal.NewFromString(parentOrderInfo.Num)
parentId := parentOrderInfo.Id
if parentOrderInfo.Pid > 0 {
parentId = parentOrderInfo.Pid
}
var takePrice decimal.Decimal
holdeAKey := fmt.Sprintf(rediskey.HoldeA, parentId)
holdeAVal, _ := helper.DefaultRedis.GetString(holdeAKey)
holdeA := HoldeData{}
if holdeAVal != "" {
sonic.Unmarshal([]byte(holdeAVal), &holdeA)
}
//查询持仓失败
if holdeA.Id == 0 {
log.Error("查询A账号持仓失败")
return
}
//加仓次数大于0 就需要使用均价
if holdeA.PositionIncrementCount > 0 {
price = holdeA.AveragePrice
num = holdeA.TotalQuantity
}
if parentOrderInfo.Site == "BUY" {
takePrice = price.Mul(decimal.NewFromInt(100).Add(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100))
} else {
takePrice = price.Mul(decimal.NewFromInt(100).Sub(parentOrderInfo.ProfitRate)).Div(decimal.NewFromInt(100))
}
var takeOrder, oldTakeOrder DbModels.LinePreOrder
if err := orm.Model(&oldTakeOrder).Where("pid= ? AND order_type ='5'", parentId).First(&oldTakeOrder).Error; err != nil {
log.Error("查询止盈单失败")
return
}
tradeset, _ := GetTradeSet(oldTakeOrder.Symbol, 0)
if tradeset.Coin == "" {
log.Error("查询交易对失败")
return
}
copier.Copy(&takeOrder, &oldTakeOrder)
takeOrder.OrderSn = strconv.FormatInt(snowflakehelper.GetOrderId(), 10)
takeOrder.Price = takePrice.Truncate(int32(tradeset.PriceDigit)).String()
takeOrder.Num = num.Mul(decimal.NewFromFloat(0.995)).Truncate(int32(tradeset.AmountDigit)).String()
takeOrder.Desc = ""
takeOrder.Status = 0
takeOrder.Id = 0
if err := orm.Create(&takeOrder).Error; err != nil {
log.Error("创建新止盈单失败")
return
}
params := OrderPlacementService{
ApiId: parentOrderInfo.ApiId,
Symbol: parentOrderInfo.Symbol,
Price: utility.StrToDecimal(takeOrder.Price),
Quantity: utility.StringToDecimal(takeOrder.Num),
Side: "SELL",
Type: "TAKE_PROFIT_LIMIT",
TimeInForce: "GTC",
StopPrice: utility.StrToDecimal(takeOrder.Price),
NewClientOrderId: takeOrder.OrderSn,
}
apiUserInfo, _ := GetApiInfo(parentOrderInfo.ApiId)
if apiUserInfo.Id == 0 {
log.Error("获取用户api失败")
return
}
if err := CancelSpotOrder(parentOrderInfo.Symbol, &apiUserInfo, "SELL"); err != nil {
log.Error("取消旧止盈失败 err:", err)
} else {
if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid = ? AND order_type =5 AND status in ('0','1','5') AND order_sn !=?", parentId, takeOrder.OrderSn).Update("status", "4").Error; err != nil {
log.Error("更新旧止盈单取消状态失败 err:", err)
}
}
var err error
for x := 1; x <= 4; x++ {
err = e.OrderPlace(orm, params)
if err == nil {
break
}
log.Error("下止盈单失败 第", utility.IntToString(x), "次", " err:", err)
time.Sleep(2 * time.Second * time.Duration(x))
}
if err != nil {
log.Error("重新下单止盈失败 err:", err)
if err1 := orm.Model(&DbModels.LinePreOrder{}).Where("order_sn =?", takeOrder.OrderSn).
Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error; err1 != nil {
log.Error("重新下单止盈 修改订单失败 pid:", parentId, " takePrice:", takePrice, " err:", err1)
}
}
//修改止盈单信息
if err := orm.Model(&DbModels.LinePreOrder{}).Where("pid =? AND order_type ='5'", parentId).
Updates(map[string]interface{}{"price": takePrice, "rate": parentOrderInfo.ProfitRate}).Error; err != nil {
log.Error("重新下单止盈 修改订单失败 pid:", parentId, " takePrice:", takePrice, " rate:", parentOrderInfo.ProfitRate, " err:", err)
}
}
/*
判断是否触发
*/
func JudgeSpotPrice(trade models.TradeSet) {
preOrderVal, _ := helper.DefaultRedis.GetAllList(rediskey.PreSpotOrderList)
key := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE)
preOrderVal, _ := helper.DefaultRedis.GetAllList(key)
db := GetDBConnection()
if len(preOrderVal) == 0 {
// log.Debug("没有现货预下单")
return
}
@ -622,35 +448,20 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
} else if ok {
defer lock.Release()
key := fmt.Sprintf(rediskey.UserHolding, v.ApiId)
symbols, err := helper.DefaultRedis.GetAllList(key)
if err != nil && err != redis.Nil {
log.Error("获取用户持仓失败", err)
return
}
key := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE)
preOrder := DbModels.LinePreOrder{}
if err := db.Where("id = ?", v.Id).First(&preOrder).Error; err != nil {
log.Error("获取预下单失败", err)
if errors.Is(err, gorm.ErrRecordNotFound) {
log.Error("不存在待触发主单", item)
helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, item)
helper.DefaultRedis.LRem(key, item)
}
return
}
//获取代币 是否已有持仓
coin := utility.ReplaceSuffix(preOrder.Symbol, preOrder.QuoteSymbol, "")
if utility.ContainsStr(symbols, coin) {
log.Debug("已有持仓")
return
}
hasrecord, _ := helper.DefaultRedis.IsElementInList(rediskey.PreSpotOrderList, item)
hasrecord, _ := helper.DefaultRedis.IsElementInList(key, item)
if !hasrecord {
log.Error("不存在待触发主单", item)
@ -673,14 +484,14 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
if err := spotApi.OrderPlace(db, params); err != nil {
log.Error("下单失败", v.Symbol, " err:", err)
err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status ='0'", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status =0", preOrder.Id).Updates(map[string]interface{}{"status": "2", "desc": err.Error()}).Error
if err != nil {
log.Error("下单失败后修改订单失败")
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, preOrderVal); err != nil {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
}
@ -689,31 +500,14 @@ func SpotOrderLock(db *gorm.DB, v *dto.PreOrderRedisList, item string, spotApi S
}
if preOrderVal != "" {
if _, err := helper.DefaultRedis.LRem(rediskey.PreSpotOrderList, preOrderVal); err != nil {
if _, err := helper.DefaultRedis.LRem(key, preOrderVal); err != nil {
log.Error("删除redis 预下单失败:", err)
}
// spotPreOrders, _ := helper.DefaultRedis.GetAllList(rediskey.PreSpotOrderList)
// futuresPreOrders, _ := helper.DefaultRedis.GetAllList(rediskey.PreFutOrderList)
// var order dto.PreOrderRedisList
// for _, item := range spotPreOrders {
// sonic.Unmarshal([]byte(item), &order)
// if order.QuoteSymbol == "" {
// }
// }
}
if err := db.Model(&DbModels.LinePreOrder{}).Where("id =? AND status ='0'", preOrder.Id).Update("status", "1").Error; err != nil {
log.Error("更新预下单状态失败 ordersn:", v.OrderSn, " status:1")
}
if err := helper.DefaultRedis.RPushList(key, coin); err != nil {
log.Error("写入用户持仓失败", v.Symbol)
}
return
} else {
log.Error("获取锁失败")