拆分加仓、减仓
This commit is contained in:
@ -100,6 +100,9 @@ func handleFutOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderSta
|
||||
//减仓回调
|
||||
case preOrder.OrderType == 4 && orderStatus == 6:
|
||||
handleReduceFilled(db, preOrder)
|
||||
//主单取消
|
||||
case preOrder.OrderType == 0 && preOrder.Pid == 0 && orderStatus == 4:
|
||||
handleMainOrderCancel(db, preOrder, 2)
|
||||
//止损成交
|
||||
case preOrder.OrderType == 2 && orderStatus == 6:
|
||||
handleStopLoss(db, preOrder)
|
||||
@ -154,6 +157,12 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
totalNum = totalNum.Truncate(int32(tradeSet.AmountDigit))
|
||||
price := utility.StrToDecimal(preOrder.Price).Truncate(int32(tradeSet.PriceDigit))
|
||||
futApi := FutRestApi{}
|
||||
mainId := preOrder.Id
|
||||
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
db.Model(&orderExt).Where("order_id =?", preOrder.Pid).First(&orderExt)
|
||||
|
||||
for _, v := range orders {
|
||||
@ -177,39 +186,46 @@ func handleReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
processFutStopLossOrder(db, v, utility.StrToDecimal(v.Price), totalNum)
|
||||
}
|
||||
}
|
||||
nextFuturesReduceTrigger(db, mainId, totalNum, tradeSet)
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrder := DbModels.LinePreOrder{}
|
||||
// 下一个合约待触发
|
||||
func nextFuturesReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, tradeSet models2.TradeSet) {
|
||||
nextOrder := DbModels.LinePreOrder{}
|
||||
nextExt := DbModels.LinePreOrderExt{}
|
||||
|
||||
if err := db.Model(&addPositionOrder).Where("main_id =? AND order_category=3 AND status=0", preOrder.MainId).First(&addPositionOrder).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
if err := db.Model(&models.LinePreOrder{}).Where("main_id =? AND order_type =4 AND status=0", mainId).Order("rate asc").First(&nextOrder).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
keyFutAddpositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE)
|
||||
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
if err := db.Model(&models.LinePreOrderExt{}).Where("id =?", nextOrder.Id).First(&nextExt).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
num := totalNum
|
||||
//移除缓存
|
||||
key := fmt.Sprintf(rediskey.FuturesReduceList, global.EXCHANGE_BINANCE)
|
||||
vals, _ := helper.DefaultRedis.GetAllList(key)
|
||||
item := ReduceListItem{}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
for _, val := range vals {
|
||||
sonic.Unmarshal([]byte(val), &item)
|
||||
if item.MainId == mainId {
|
||||
if _, err := helper.DefaultRedis.LRem(key, val); err != nil {
|
||||
logger.Errorf("减仓单 redis删除失败 main_id:%v err:%v", mainId, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keyFutAddpositionKey, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
//
|
||||
if nextExt.AddPositionVal.Cmp(decimal.Zero) > 0 && nextExt.AddPositionVal.Cmp(decimal.Zero) < 100 {
|
||||
// 计算减仓数量
|
||||
num = totalNum.Mul(nextExt.AddPositionVal.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
nextOrder.Num = num.String()
|
||||
}
|
||||
|
||||
processFutReduceOrder(nextOrder, utility.StrToDecimal(nextOrder.Price).Truncate(int32(tradeSet.PriceDigit)), num)
|
||||
}
|
||||
|
||||
// 获取合约可用数量
|
||||
@ -407,6 +423,7 @@ func removeFutLossAndAddPosition(mainId int, orderSn string) {
|
||||
func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrderId int, first bool) {
|
||||
// 获取交易对配置和API信息
|
||||
tradeSet, err := GetTradeSet(preOrder.Symbol, 1)
|
||||
mainId := preOrder.Id
|
||||
if err != nil || tradeSet.Coin == "" {
|
||||
logger.Errorf("获取交易对配置失败, 回调订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
@ -418,6 +435,10 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd
|
||||
return
|
||||
}
|
||||
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
// 处理主单加仓
|
||||
if preOrder.OrderCategory == 3 {
|
||||
if err := handleMainOrderAddPosition(db, preOrder); err != nil {
|
||||
@ -430,6 +451,39 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd
|
||||
logger.Errorf("取消主单相关订单失败, 订单号:%s, 错误信息: %v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrders := make([]DbModels.LinePreOrder, 0)
|
||||
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_category=3 AND order_type=0 AND status=0", preOrder.Id).Order("rate asc").Find(&addPositionOrders).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
keyFutAddpositionKey := fmt.Sprintf(rediskey.FuturesAddPositionList, global.EXCHANGE_BINANCE)
|
||||
|
||||
for _, addPositionOrder := range addPositionOrders {
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keyFutAddpositionKey, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取止盈止损订单
|
||||
@ -493,10 +547,12 @@ func handleFutMainOrderFilled(db *gorm.DB, preOrder *models.LinePreOrder, extOrd
|
||||
}
|
||||
|
||||
processFutStopLossOrder(db, order, price, num)
|
||||
case 4: // 减仓
|
||||
processFutReduceOrder(order, price, num)
|
||||
// case 4: // 减仓
|
||||
// processFutReduceOrder(order, price, num)
|
||||
}
|
||||
}
|
||||
|
||||
nextFuturesReduceTrigger(db, mainId, num, tradeSet)
|
||||
}
|
||||
|
||||
// 处理主单加仓
|
||||
|
||||
@ -119,7 +119,7 @@ func handleOrderByType(db *gorm.DB, preOrder *DbModels.LinePreOrder, orderStatus
|
||||
handleMainReduceFilled(db, preOrder)
|
||||
//主单取消
|
||||
case preOrder.OrderType == 0 && preOrder.Pid == 0 && orderStatus == 4:
|
||||
handleMainOrderCancel(preOrder)
|
||||
handleMainOrderCancel(db, preOrder, 1)
|
||||
// 止盈成交
|
||||
case preOrder.OrderType == 1 && orderStatus == 6:
|
||||
handleSpotTakeProfitFilled(db, preOrder)
|
||||
@ -224,38 +224,57 @@ func handleMainReduceFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
}
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrder := DbModels.LinePreOrder{}
|
||||
mainId := preOrder.Id
|
||||
|
||||
if err := db.Model(&addPositionOrder).Where("main_id =? AND order_category=3 AND order_type=0 AND status=0", preOrder.MainId).First(&addPositionOrder).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
keySpotAddPosition := fmt.Sprintf(rediskey.SpotAddPositionList, global.EXCHANGE_BINANCE)
|
||||
nextSpotReduceTrigger(db, mainId, totalNum, tradeSet)
|
||||
}
|
||||
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
// 缓存下一个减仓单
|
||||
func nextSpotReduceTrigger(db *gorm.DB, mainId int, totalNum decimal.Decimal, tradeSet models2.TradeSet) bool {
|
||||
nextOrder := DbModels.LinePreOrder{}
|
||||
nextExt := DbModels.LinePreOrderExt{}
|
||||
// var percentag decimal.Decimal
|
||||
|
||||
if err := db.Model(&models.LinePreOrder{}).Where("main_id =? AND order_type =4 AND status=0", mainId).Order("rate asc").First(&nextOrder).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
return true
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
if err := db.Model(&models.LinePreOrderExt{}).Where("id =?", nextOrder.Id).First(&nextExt).Error; err != nil {
|
||||
logger.Errorf("获取下一个单失败 err:%v", err)
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keySpotAddPosition, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
//移除缓存
|
||||
key := fmt.Sprintf(rediskey.SpotReduceList, global.EXCHANGE_BINANCE)
|
||||
vals, _ := helper.DefaultRedis.GetAllList(key)
|
||||
item := ReduceListItem{}
|
||||
|
||||
for _, val := range vals {
|
||||
sonic.Unmarshal([]byte(val), &item)
|
||||
if item.MainId == mainId {
|
||||
if _, err := helper.DefaultRedis.LRem(key, val); err != nil {
|
||||
logger.Errorf("减仓单 redis删除失败 main_id:%v err:%v", mainId, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//减仓配置 且减仓比例大于0小于100
|
||||
if nextExt.Id > 0 && nextExt.AddType == 2 && nextExt.AddPositionVal.Cmp(decimal.Zero) > 0 && nextExt.AddPositionVal.Cmp(decimal.Zero) < 100 {
|
||||
num := totalNum.Mul(nextExt.AddPositionVal.Div(decimal.NewFromInt(100))).Truncate(int32(tradeSet.AmountDigit))
|
||||
// percentag = positionData.TotalLoss.Div(num).Div(price).Mul(decimal.NewFromInt(100)).Truncate(2)
|
||||
nextOrder.Num = num.String()
|
||||
}
|
||||
// percentag = nextExt.PriceRatio.Add(percentag)
|
||||
// nextOrder.Rate = percentag.String()
|
||||
// nextOrder.Price = price.Mul(decimal.NewFromInt(1).Add(percentag.Div(decimal.NewFromInt(100)))).Truncate(int32(tradeSet.AmountDigit)).String()
|
||||
|
||||
//减仓待触发
|
||||
processSpotReduceOrder(nextOrder)
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取主单可用数量
|
||||
@ -344,8 +363,16 @@ func getSpotPositionNum(apiUserInfo DbModels.LineApiUser, preOrder *DbModels.Lin
|
||||
}
|
||||
|
||||
// 主单取消
|
||||
func handleMainOrderCancel(preOrder *DbModels.LinePreOrder) {
|
||||
preOrderKey := fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE)
|
||||
// symbolType 1:现货 2:合约
|
||||
func handleMainOrderCancel(db *gorm.DB, preOrder *DbModels.LinePreOrder, symboType int) {
|
||||
var preOrderKey string
|
||||
|
||||
if symboType == 1 {
|
||||
preOrderKey = fmt.Sprintf(rediskey.PreSpotOrderList, global.EXCHANGE_BINANCE)
|
||||
} else {
|
||||
preOrderKey = fmt.Sprintf(rediskey.PreFutOrderList, global.EXCHANGE_BINANCE)
|
||||
}
|
||||
|
||||
preSpotOrders, _ := helper.DefaultRedis.GetAllList(preOrderKey)
|
||||
preOrderCache := DbModels.LinePreOrder{}
|
||||
|
||||
@ -356,10 +383,17 @@ func handleMainOrderCancel(preOrder *DbModels.LinePreOrder) {
|
||||
|
||||
sonic.Unmarshal([]byte(v), &preOrderCache)
|
||||
if preOrderCache.Pid == preOrder.Id {
|
||||
_, err := helper.DefaultRedis.LRem(preOrderKey, v)
|
||||
var count int64
|
||||
db.Model(&models.LinePreOrder{}).
|
||||
Where("api_id =? AND site=? AND symbol=? AND symbol_type =? AND exchange_type =? AND status =6",
|
||||
preOrder.ApiId, preOrder.Site, preOrder.Symbol, preOrder.SymbolType, preOrder.ExchangeType).Count(&count)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除缓存失败:%v", preOrder.OrderSn, err)
|
||||
if count == 0 {
|
||||
_, err := helper.DefaultRedis.LRem(preOrderKey, v)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("订单回调失败, 回调订单号:%s 删除缓存失败:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -549,9 +583,45 @@ func handleMainOrderFilled(db *gorm.DB, preOrder *DbModels.LinePreOrder) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//加仓待触发
|
||||
addPositionOrders := make([]DbModels.LinePreOrder, 0)
|
||||
|
||||
if err := db.Model(&DbModels.LinePreOrder{}).Where("main_id =? AND order_category=3 AND order_type=0 AND status=0", preOrder.Id).Order("rate asc").Find(&addPositionOrders).Error; err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 获取加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
|
||||
keySpotAddPosition := fmt.Sprintf(rediskey.SpotAddPositionList, global.EXCHANGE_BINANCE)
|
||||
|
||||
for _, addPositionOrder := range addPositionOrders {
|
||||
addPositionData := AddPositionList{
|
||||
Id: addPositionOrder.Id,
|
||||
OrderSn: addPositionOrder.OrderSn,
|
||||
MainId: addPositionOrder.MainId,
|
||||
Pid: addPositionOrder.Pid,
|
||||
Price: utility.StrToDecimal(addPositionOrder.Price),
|
||||
ApiId: addPositionOrder.ApiId,
|
||||
Symbol: addPositionOrder.Symbol,
|
||||
Side: addPositionOrder.Site,
|
||||
SymbolType: addPositionOrder.SymbolType,
|
||||
}
|
||||
|
||||
addVal, err := sonic.MarshalString(addPositionData)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 序列化加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := helper.DefaultRedis.RPushList(keySpotAddPosition, addVal); err != nil {
|
||||
logger.Errorf("handleMainReduceFilled 添加加仓单失败,订单号:%s err:%v", preOrder.OrderSn, err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
processTakeProfitAndStopLossOrders(db, preOrder, &positionData, preOrder.Id, true)
|
||||
|
||||
}
|
||||
|
||||
// 解析订单状态
|
||||
@ -623,6 +693,11 @@ func updateOrderStatus(db *gorm.DB, preOrder *models.LinePreOrder, status int, r
|
||||
func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrder, positionData *positiondto.PositionDto, extOrderId int, fist bool) {
|
||||
orders := []models.LinePreOrder{}
|
||||
tradeSet, _ := GetTradeSet(preOrder.Symbol, 0)
|
||||
mainId := preOrder.Id
|
||||
|
||||
if preOrder.MainId > 0 {
|
||||
mainId = preOrder.MainId
|
||||
}
|
||||
|
||||
if tradeSet.Coin == "" {
|
||||
logger.Error("获取交易对失败")
|
||||
@ -654,9 +729,11 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd
|
||||
spotApi := SpotRestApi{}
|
||||
orderExt := models.LinePreOrderExt{}
|
||||
db.Model(&orderExt).Where("order_id =?", extOrderId).First(&orderExt)
|
||||
num = num.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit))
|
||||
|
||||
//止盈止损
|
||||
for _, order := range orders {
|
||||
order.Num = num.Mul(decimal.NewFromFloat(0.998)).Truncate(int32(tradeSet.AmountDigit)).String()
|
||||
order.Num = num.String()
|
||||
|
||||
if fist && order.OrderCategory == 1 && orderExt.TakeProfitNumRatio.Cmp(decimal.Zero) > 0 && orderExt.TakeProfitNumRatio.Cmp(decimal.NewFromInt(100)) != 0 {
|
||||
//主单第一次且止盈数量不是100% 止盈数量
|
||||
@ -694,10 +771,13 @@ func processTakeProfitAndStopLossOrders(db *gorm.DB, preOrder *models.LinePreOrd
|
||||
}
|
||||
|
||||
processStopLossOrder(order)
|
||||
case 4: //减仓
|
||||
processSpotReduceOrder(order)
|
||||
// case 4: //减仓
|
||||
// processSpotReduceOrder(order)
|
||||
}
|
||||
}
|
||||
|
||||
//待触发减仓单
|
||||
nextSpotReduceTrigger(db, mainId, num, tradeSet)
|
||||
}
|
||||
|
||||
// 根据下单百分比计算价格
|
||||
|
||||
Reference in New Issue
Block a user