From d8bff1cf946b36f6eeb00c8ecafb47e55b96cedb Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 07 Jul 2026 10:21:10 +0800
Subject: [PATCH] refactor(gateApi): 止盈单挂单流程,统一使用固定的gridId为0进行操作
---
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java | 517 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 341 insertions(+), 176 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
index 10916de..ccacbc0 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -364,6 +364,7 @@
* @param closePrice K 线收盘价(即当前最新成交价)
*/
public void onKline(BigDecimal closePrice) {
+
lastKlinePrice = closePrice;
//初始化0位置的开仓,并且用空的开仓价格,作为价格基准来划分网格
@@ -391,46 +392,37 @@
return;
}
+ checkProfitAndReset();
-// checkProfitAndReset();
-
-
- if (state == StrategyState.ACTIVE &&
- longActive == false &&
- longPositionSize.compareTo(BigDecimal.ZERO) == 0){
- processShortGrid(closePrice);
- }
-
-
- if (state == StrategyState.ACTIVE &&
- shortActive == false &&
- shortPositionSize.compareTo(BigDecimal.ZERO) == 0){
- processLongGrid(closePrice);
- }
+// if (state == StrategyState.ACTIVE &&
+// longActive == false &&
+// longPositionSize.compareTo(BigDecimal.ZERO) == 0){
+// processShortGrid(closePrice);
+// }
+//
+//
+// if (state == StrategyState.ACTIVE &&
+// shortActive == false &&
+// shortPositionSize.compareTo(BigDecimal.ZERO) == 0){
+// processLongGrid(closePrice);
+// }
}
/** Gate 永续合约 taker 费率 0.05% */
private static final BigDecimal TAKER_FEE_RATE = new BigDecimal("0.0005");
private void checkProfitAndReset() {
+ if (state == StrategyState.STOPPED || state == StrategyState.WAITING_KLINE) {
+ return;
+ }
try {
BigDecimal target = initialPrincipal.add(config.getExpectedProfit());
FuturesAccount account = futuresApi.listFuturesAccounts(SETTLE);
- BigDecimal unrealisedPnl = new BigDecimal(account.getCrossUnrealisedPnl());
- BigDecimal available = new BigDecimal(account.getCrossAvailable());
- BigDecimal totalEquity = unrealisedPnl.add(available);
+ BigDecimal totalEquity = new BigDecimal(account.getTotal()).add(new BigDecimal(account.getUnrealisedPnl()));
- // 估算平仓手续费:(多仓张数+空仓张数) × 合约面值 × 当前价 × taker费率
- BigDecimal totalSize = longPositionSize.abs().add(shortPositionSize.abs());
- BigDecimal closeContractValue =
- totalSize.multiply(config.getContractMultiplier()).multiply(lastKlinePrice != null ? lastKlinePrice : BigDecimal.ZERO);
- BigDecimal estimatedFee = closeContractValue.multiply(TAKER_FEE_RATE);
- BigDecimal netEquity = totalEquity.subtract(estimatedFee);
- log.info("[Gate] 盈亏检查,总张数:{}, upl:{}, avail:{}, 合计:{}, 估手续费:{}, 净权益:{}, 目标:{}",
- totalSize,unrealisedPnl, available, totalEquity, estimatedFee, netEquity, target);
- if (netEquity.compareTo(target) > 0) {
- log.info("[Gate] 盈亏达标(净权益{}>目标{}),重置策略", netEquity, target);
+ if (totalEquity.compareTo(target) > 0) {
+ log.info("[Gate] 盈亏达标(净权益{}>目标{}),重置策略", totalEquity, target);
state = StrategyState.STOPPED;
try {
futuresApi.cancelPriceTriggeredOrderList(SETTLE, config.getContract());
@@ -641,52 +633,75 @@
// REST 查询可能因交易所延迟返回旧值,与 WS 本地缓存取最大值兜底
int posSize = Math.max(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue());
extendShortStopLoss(posSize, shortGridElement.getId());
- accumulatedShortLossCount = 0; // 加仓订单成交,重置止损累计
log.info("[Gate] 空单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize);
- // 空仓持仓超过baseQuantity时,先找多仓第一个止损位置,从该位置向下挂止盈(间隔=1)
- BigDecimal shortBaseQty = new BigDecimal(config.getBaseQuantity());
- BigDecimal shortGridQty = new BigDecimal(config.getQuantity());
- if (BigDecimal.valueOf(posSize).compareTo(shortBaseQty) > 0) {
- BigDecimal shortExcess = BigDecimal.valueOf(posSize).subtract(shortBaseQty);
- int shortExcessCount = shortExcess.divide(shortGridQty, 0, RoundingMode.DOWN).intValue();
-
- // 找多仓第一个(最近的)止损位置
- int firstLongSlId = 0;
- for (GridElement e : config.getGridElements()) {
- if (e.getLongStopLossOrderId() != null) {
- if (firstLongSlId == 0 || e.getId() > firstLongSlId) {
- firstLongSlId = e.getId();
- }
- }
- }
-
- for (int i = 0; i < shortExcessCount; i++) {
- int tpGridId;
- if (firstLongSlId != 0) {
- tpGridId = firstLongSlId - i; // 从多仓第一个止损位置开始,向下挂,间隔=1
- } else {
- tpGridId = shortGridElement.getId() - 2 * (i + 1); // 无多仓止损时回退原逻辑
- }
- GridElement tpElem = GridElement.findById(tpGridId);
- if (tpElem == null || tpElem.getShortTakeProfitOrderId() != null) {
- continue;
- }
- BigDecimal tpPrice = tpElem.getGridPrice();
- int finalTpGridId = tpGridId;
- executor.placeTakeProfit(
- tpPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_2,
- ORDER_TYPE_CLOSE_SHORT,
- config.getQuantity(),
- profitId -> {
- shortTakeProfitTraderIdParam(tpElem, profitId, true);
- log.info("[Gate] 空仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
- finalTpGridId, tpPrice, profitId);
- }
- );
- }
+ int tpGridId = 0;
+ GridElement tpElem = GridElement.findById(tpGridId);
+ // 已有止盈单先取消再重挂
+ String existingShortTpId = tpElem.getShortTakeProfitOrderId();
+ if (existingShortTpId != null) {
+ executor.cancelConditionalOrder(existingShortTpId, oid -> {
+ shortTakeProfitTraderIdParam(tpElem, null, false);
+ log.info("[Gate] 空仓止盈取消(gridId:{}),准备重挂", tpGridId);
+ });
}
+ BigDecimal tpPrice = tpElem.getGridPrice();
+ int finalTpGridId = tpGridId;
+ executor.placeTakeProfit(
+ tpPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_2,
+ ORDER_TYPE_CLOSE_SHORT,
+ config.getQuantity(),
+ profitId -> {
+ shortTakeProfitTraderIdParam(tpElem, profitId, true);
+ log.info("[Gate] 空仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
+ finalTpGridId, tpPrice, profitId);
+ }
+ );
+
+// // 空仓持仓超过baseQuantity时,先找多仓第一个止损位置,从该位置向下挂止盈(间隔=1)
+// BigDecimal shortBaseQty = new BigDecimal(config.getBaseQuantity());
+// BigDecimal shortGridQty = new BigDecimal(config.getQuantity());
+// if (BigDecimal.valueOf(posSize).compareTo(shortBaseQty) > 0) {
+// BigDecimal shortExcess = BigDecimal.valueOf(posSize).subtract(shortBaseQty);
+// int shortExcessCount = shortExcess.divide(shortGridQty, 0, RoundingMode.DOWN).intValue();
+//
+// // 找多仓第一个(最近的)止损位置
+// int firstLongSlId = 0;
+// for (GridElement e : config.getGridElements()) {
+// if (e.getLongStopLossOrderId() != null) {
+// if (firstLongSlId == 0 || e.getId() > firstLongSlId) {
+// firstLongSlId = e.getId();
+// }
+// }
+// }
+//
+// for (int i = 0; i < shortExcessCount; i++) {
+// int tpGridId;
+// if (firstLongSlId != 0) {
+// tpGridId = firstLongSlId - i; // 从多仓第一个止损位置开始,向下挂,间隔=1
+// } else {
+// tpGridId = shortGridElement.getId() - 2 * (i + 1); // 无多仓止损时回退原逻辑
+// }
+// GridElement tpElem = GridElement.findById(tpGridId);
+// if (tpElem == null || tpElem.getShortTakeProfitOrderId() != null) {
+// continue;
+// }
+// BigDecimal tpPrice = tpElem.getGridPrice();
+// int finalTpGridId = tpGridId;
+// executor.placeTakeProfit(
+// tpPrice,
+// FuturesPriceTrigger.RuleEnum.NUMBER_2,
+// ORDER_TYPE_CLOSE_SHORT,
+// config.getQuantity(),
+// profitId -> {
+// shortTakeProfitTraderIdParam(tpElem, profitId, true);
+// log.info("[Gate] 空仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
+// finalTpGridId, tpPrice, profitId);
+// }
+// );
+// }
+// }
}
}
GridElement longGridElement = GridElement.findByLongOrderId(orderId);
@@ -700,52 +715,75 @@
// REST 查询可能因交易所延迟返回旧值,与 WS 本地缓存取最大值兜底
int posSize = Math.max(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue());
extendLongStopLoss(posSize, longGridElement.getId());
- accumulatedLongLossCount = 0; // 加仓订单成交,重置止损累计
log.info("[Gate] 多单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize);
- // 多仓持仓超过baseQuantity时,先找空仓第一个止损位置,从该位置向上挂止盈(间隔=1)
- BigDecimal longBaseQty = new BigDecimal(config.getBaseQuantity());
- BigDecimal longGridQty = new BigDecimal(config.getQuantity());
- if (BigDecimal.valueOf(posSize).compareTo(longBaseQty) > 0) {
- BigDecimal longExcess = BigDecimal.valueOf(posSize).subtract(longBaseQty);
- int longExcessCount = longExcess.divide(longGridQty, 0, RoundingMode.DOWN).intValue();
-
- // 找空仓第一个(最近的)止损位置
- int firstShortSlId = 0;
- for (GridElement e : config.getGridElements()) {
- if (e.getShortStopLossOrderId() != null) {
- if (firstShortSlId == 0 || e.getId() < firstShortSlId) {
- firstShortSlId = e.getId();
- }
- }
- }
-
- for (int i = 0; i < longExcessCount; i++) {
- int tpGridId;
- if (firstShortSlId != 0) {
- tpGridId = firstShortSlId + i; // 从空仓第一个止损位置开始,向上挂,间隔=1
- } else {
- tpGridId = longGridElement.getId() + 2 * (i + 1); // 无空仓止损时回退原逻辑
- }
- GridElement tpElem = GridElement.findById(tpGridId);
- if (tpElem == null || tpElem.getLongTakeProfitOrderId() != null) {
- continue;
- }
- BigDecimal tpPrice = tpElem.getGridPrice();
- int finalTpGridId = tpGridId;
- executor.placeTakeProfit(
- tpPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_1,
- ORDER_TYPE_CLOSE_LONG,
- negate(config.getQuantity()),
- profitId -> {
- longTakeProfitTraderIdParam(tpElem, profitId, true);
- log.info("[Gate] 多仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
- finalTpGridId, tpPrice, profitId);
- }
- );
- }
+ int tpGridId = 0;
+ GridElement tpElem = GridElement.findById(tpGridId);
+ // 已有止盈单先取消再重挂
+ String existingLongTpId = tpElem.getLongTakeProfitOrderId();
+ if (existingLongTpId != null) {
+ executor.cancelConditionalOrder(existingLongTpId, oid -> {
+ longTakeProfitTraderIdParam(tpElem, null, false);
+ log.info("[Gate] 多仓止盈取消(gridId:{}),准备重挂", tpGridId);
+ });
}
+ BigDecimal tpPrice = tpElem.getGridPrice();
+ int finalTpGridId = tpGridId;
+ executor.placeTakeProfit(
+ tpPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_1,
+ ORDER_TYPE_CLOSE_LONG,
+ negate(config.getQuantity()),
+ profitId -> {
+ longTakeProfitTraderIdParam(tpElem, profitId, true);
+ log.info("[Gate] 多仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
+ finalTpGridId, tpPrice, profitId);
+ }
+ );
+
+// // 多仓持仓超过baseQuantity时,先找空仓第一个止损位置,从该位置向上挂止盈(间隔=1)
+// BigDecimal longBaseQty = new BigDecimal(config.getBaseQuantity());
+// BigDecimal longGridQty = new BigDecimal(config.getQuantity());
+// if (BigDecimal.valueOf(posSize).compareTo(longBaseQty) > 0) {
+// BigDecimal longExcess = BigDecimal.valueOf(posSize).subtract(longBaseQty);
+// int longExcessCount = longExcess.divide(longGridQty, 0, RoundingMode.DOWN).intValue();
+//
+// // 找空仓第一个(最近的)止损位置
+// int firstShortSlId = 0;
+// for (GridElement e : config.getGridElements()) {
+// if (e.getShortStopLossOrderId() != null) {
+// if (firstShortSlId == 0 || e.getId() < firstShortSlId) {
+// firstShortSlId = e.getId();
+// }
+// }
+// }
+//
+// for (int i = 0; i < longExcessCount; i++) {
+// int tpGridId;
+// if (firstShortSlId != 0) {
+// tpGridId = firstShortSlId + i; // 从空仓第一个止损位置开始,向上挂,间隔=1
+// } else {
+// tpGridId = longGridElement.getId() + 2 * (i + 1); // 无空仓止损时回退原逻辑
+// }
+// GridElement tpElem = GridElement.findById(tpGridId);
+// if (tpElem == null || tpElem.getLongTakeProfitOrderId() != null) {
+// continue;
+// }
+// BigDecimal tpPrice = tpElem.getGridPrice();
+// int finalTpGridId = tpGridId;
+// executor.placeTakeProfit(
+// tpPrice,
+// FuturesPriceTrigger.RuleEnum.NUMBER_1,
+// ORDER_TYPE_CLOSE_LONG,
+// negate(config.getQuantity()),
+// profitId -> {
+// longTakeProfitTraderIdParam(tpElem, profitId, true);
+// log.info("[Gate] 多仓止盈挂单, gridId:{}, 触发价:{}, takeProfitId:{}",
+// finalTpGridId, tpPrice, profitId);
+// }
+// );
+// }
+// }
}
}
}
@@ -826,6 +864,43 @@
baseGridElement.setShortOrderId(baseShortTraderParam.getEntryOrderId());
baseGridElement.setHasShortOrder(true);
+ // 空仓止损对应的多仓止盈:多仓止盈挂在ID=3
+ int tpGridIdLong = 3;
+ GridElement tpElemLong = GridElement.findById(tpGridIdLong);
+ BigDecimal triggerPriceLong = tpElemLong.getGridPrice();
+ String sizeLong = config.getQuantity();
+ executor.placeTakeProfit(
+ triggerPriceLong,
+ FuturesPriceTrigger.RuleEnum.NUMBER_1,
+ ORDER_TYPE_CLOSE_LONG,
+ negate(sizeLong),
+ profitId -> {
+ tpElemLong.setLongTakeProfitOrderId(profitId);
+ GridElement.refreshIndices();
+ log.info("[Gate] 多仓止盈已挂(gridId:{}多止盈), 触发价:{}, takeProfitId:{}",
+ tpGridIdLong, triggerPriceLong, profitId);
+ }
+ );
+
+
+ // 多仓止损对应的空仓止盈:空仓止盈挂在ID=-3
+ int tpGridIdShort = -3;
+ GridElement tpElemShort = GridElement.findById(tpGridIdShort);
+ BigDecimal triggerPriceShort = tpElemShort.getGridPrice();
+ String sizeShort = config.getQuantity();
+ executor.placeTakeProfit(
+ triggerPriceShort,
+ FuturesPriceTrigger.RuleEnum.NUMBER_2,
+ ORDER_TYPE_CLOSE_SHORT,
+ sizeShort,
+ profitId -> {
+ tpElemShort.setShortTakeProfitOrderId(profitId);
+ GridElement.refreshIndices();
+ log.info("[Gate] 空仓止盈已挂(gridId:{}空止盈), 触发价:{}, takeProfitId:{}",
+ tpGridIdShort, triggerPriceShort, profitId);
+ }
+ );
+
// int shortTime = 2;
// GridElement elemShort = GridElement.findById(shortTime);
// if (elemShort != null) {
@@ -886,6 +961,7 @@
}
+
int longTime = Integer.parseInt(config.getBaseQuantity()) / Integer.parseInt(config.getQuantity()) + 1;
for (int id = -2; id >= -longTime; id--) {
GridElement elem = GridElement.findById(id);
@@ -908,7 +984,7 @@
);
}
- log.info("[Gate] 止损单已全部挂完, 空仓止损: 2~{}, 多仓止损: -2~-{}", shortTime, longTime);
+ log.info("[Gate] 止损止盈单已全部挂完, 空仓止损:2~{}, 多仓止损:-2~-{}", shortTime, longTime);
state = StrategyState.ACTIVE;
}
@@ -1227,8 +1303,9 @@
private void handleLongStopLossTriggered(GridElement gridElement) {
gridElement.setLongStopLossOrderId(null);
+ accumulatedLongLossCount++;
int gridId = gridElement.getId();
- log.info("[Gate] 多仓止损触发 gridId:{}, 开始追单", gridId);
+ log.info("[Gate] 多仓止损触发 gridId:{}, 止损次数:{}, 开始追单", gridId, accumulatedLongLossCount);
int newEntryGridId = gridId + 1;
GridElement newEntryGrid = GridElement.findById(newEntryGridId);
@@ -1242,15 +1319,37 @@
if (!newEntryGrid.isHasLongOrder()) {
BigDecimal triggerPrice = newEntryGrid.getGridPrice();
- // 累计止损张数 + 当前止损量作为追单size,不再依赖positionSize(避免WS竞态)
- accumulatedLongLossCount += Integer.parseInt(config.getQuantity());
- String size = String.valueOf(accumulatedLongLossCount + Integer.parseInt(config.getQuantity()));
- log.info("[Gate] 多仓止损触发 gridId:{}, 在gridId:{}挂{}基础张多单",
- gridId, newEntryGridId, size);
-
- newEntryGrid.getLongTraderParam().setQuantity(size);
- placeEntryOrderWithPreFlag(newEntryGrid, true, triggerPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_1, size);
+ // 止损触发后持仓在减少,取REST和WS缓存中较小值更准确
+ int posSize = Math.min(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue());
+ int maxPos = config.getMaxPositionSize();
+ // 止损阶梯:止损次数≤阈值时挂单量=单笔数量,超过后恢复默认逻辑(quantity*2)
+ int targetAmount;
+ if (config.getStopLossCount() > 0 && accumulatedLongLossCount <= config.getStopLossCount()) {
+ targetAmount = Integer.parseInt(config.getQuantity());
+ } else {
+ targetAmount = Integer.parseInt(config.getQuantity()) * 2; // quantity + 本次止损量
+ }
+ int addSize;
+ if (maxPos > 0) {
+ int remainingRoom = maxPos - posSize;
+ if (remainingRoom <= 0) {
+ log.warn("[Gate] 多仓止损触发 gridId:{}, 当前持仓{}/{}已达上限,跳过追单",
+ gridId, posSize, maxPos);
+ addSize = 0;
+ } else {
+ addSize = Math.min(remainingRoom, targetAmount);
+ }
+ } else {
+ addSize = targetAmount;
+ }
+ if (addSize > 0) {
+ String size = String.valueOf(addSize);
+ log.info("[Gate] 多仓止损触发 gridId:{}, 止损次数:{}, 在gridId:{}补{}张多单(当前{}/上限{})",
+ gridId, accumulatedLongLossCount, newEntryGridId, size, posSize, maxPos > 0 ? maxPos : "无");
+ newEntryGrid.getLongTraderParam().setQuantity(size);
+ placeEntryOrderWithPreFlag(newEntryGrid, true, triggerPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_1, size);
+ }
}else{
log.warn("[Gate] 多仓止损触发 gridId:{}, 目标gridId:{}已有挂单,跳过重复下单", gridId, newEntryGridId);
}
@@ -1286,8 +1385,9 @@
private void handleShortStopLossTriggered(GridElement gridElement) {
gridElement.setShortStopLossOrderId(null);
+ accumulatedShortLossCount++;
int gridId = gridElement.getId();
- log.info("[Gate] 空仓止损触发 gridId:{}, 开始追单", gridId);
+ log.info("[Gate] 空仓止损触发 gridId:{}, 止损次数:{}, 开始追单", gridId, accumulatedShortLossCount);
int newEntryGridId = gridId - 1;
GridElement newEntryGrid = GridElement.findById(newEntryGridId);
@@ -1301,14 +1401,37 @@
if (!newEntryGrid.isHasShortOrder()) {
BigDecimal triggerPrice = newEntryGrid.getGridPrice();
- // 累计止损张数 + 当前止损量作为追单size,不再依赖positionSize(避免WS竞态)
- accumulatedShortLossCount += Integer.parseInt(config.getQuantity());
- String size = String.valueOf(accumulatedShortLossCount + Integer.parseInt(config.getQuantity()));
- log.info("[Gate] 空仓止损触发 gridId:{}, 在gridId:{}挂{}基础张空单",
- gridId, newEntryGridId, size);
- newEntryGrid.getShortTraderParam().setQuantity(size);
- placeEntryOrderWithPreFlag(newEntryGrid, false, triggerPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_2, negate(size));
+ // 止损触发后持仓在减少,取REST和WS缓存中较小值更准确
+ int posSize = Math.min(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue());
+ int maxPos = config.getMaxPositionSize();
+ // 止损阶梯:止损次数≤阈值时挂单量=单笔数量,超过后恢复默认逻辑(quantity*2)
+ int targetAmount;
+ if (config.getStopLossCount() > 0 && accumulatedShortLossCount <= config.getStopLossCount()) {
+ targetAmount = Integer.parseInt(config.getQuantity());
+ } else {
+ targetAmount = Integer.parseInt(config.getQuantity()) * 2; // quantity + 本次止损量
+ }
+ int addSize;
+ if (maxPos > 0) {
+ int remainingRoom = maxPos - posSize;
+ if (remainingRoom <= 0) {
+ log.warn("[Gate] 空仓止损触发 gridId:{}, 当前持仓{}/{}已达上限,跳过追单",
+ gridId, posSize, maxPos);
+ addSize = 0;
+ } else {
+ addSize = Math.min(remainingRoom, targetAmount);
+ }
+ } else {
+ addSize = targetAmount;
+ }
+ if (addSize > 0) {
+ String size = String.valueOf(addSize);
+ log.info("[Gate] 空仓止损触发 gridId:{}, 止损次数:{}, 在gridId:{}补{}张空单(当前{}/上限{})",
+ gridId, accumulatedShortLossCount, newEntryGridId, size, posSize, maxPos > 0 ? maxPos : "无");
+ newEntryGrid.getShortTraderParam().setQuantity(size);
+ placeEntryOrderWithPreFlag(newEntryGrid, false, triggerPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_2, negate(size));
+ }
}else{
log.warn("[Gate] 空仓止损触发 gridId:{}, 目标gridId:{}已有挂单,跳过重复下单", gridId, newEntryGridId);
}
@@ -1540,28 +1663,49 @@
furthestSlId = gridId;
interval = 2;
}
- int stopLossCount = filledQty / Integer.parseInt(config.getQuantity());
- log.info("[Gate] 多仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}个止损单", furthestSlId, filledQty, stopLossCount);
- for (int i = 0; i < stopLossCount; i++) {
- int newSlId = furthestSlId - i - interval;
- GridElement elem = GridElement.findById(newSlId);
- if (elem == null) {
- continue;
- }
- BigDecimal triggerPrice = elem.getGridPrice();
- int finalSlId = newSlId;
- executor.placeTakeProfit(
- triggerPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_2,
- ORDER_TYPE_CLOSE_LONG,
- negate(config.getQuantity()),
- profitId -> {
- elem.setLongStopLossOrderId(profitId);
- GridElement.refreshIndices();
- log.info("[Gate] 多仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
- }
- );
+ int stopLossCount = filledQty;
+ log.info("[Gate] 多仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}张止损单", furthestSlId, filledQty, stopLossCount);
+ int newSlId = furthestSlId - interval;
+ GridElement elem = GridElement.findById(newSlId);
+ if (elem == null) {
+ return;
}
+ BigDecimal triggerPrice = elem.getGridPrice();
+ int finalSlId = newSlId;
+ executor.placeTakeProfit(
+ triggerPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_2,
+ ORDER_TYPE_CLOSE_LONG,
+ negate(String.valueOf(stopLossCount)),
+ profitId -> {
+ elem.setLongStopLossOrderId(profitId);
+ GridElement.refreshIndices();
+ log.info("[Gate] 多仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
+ }
+ );
+
+// int stopLossCount = filledQty / Integer.parseInt(config.getQuantity());
+// log.info("[Gate] 多仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}个止损单", furthestSlId, filledQty, stopLossCount);
+// for (int i = 0; i < stopLossCount; i++) {
+// int newSlId = furthestSlId - i - interval;
+// GridElement elem = GridElement.findById(newSlId);
+// if (elem == null) {
+// continue;
+// }
+// BigDecimal triggerPrice = elem.getGridPrice();
+// int finalSlId = newSlId;
+// executor.placeTakeProfit(
+// triggerPrice,
+// FuturesPriceTrigger.RuleEnum.NUMBER_2,
+// ORDER_TYPE_CLOSE_LONG,
+// negate(config.getQuantity()),
+// profitId -> {
+// elem.setLongStopLossOrderId(profitId);
+// GridElement.refreshIndices();
+// log.info("[Gate] 多仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
+// }
+// );
+// }
}
private void extendShortStopLoss(int filledQty, int gridId) {
@@ -1577,28 +1721,49 @@
furthestSlId = gridId;
interval = 2;
}
- int stopLossCount = filledQty / Integer.parseInt(config.getQuantity());
- log.info("[Gate] 空仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}个止损单", furthestSlId, filledQty, stopLossCount);
- for (int i = 0; i < stopLossCount; i++) {
- int newSlId = furthestSlId + i + interval;
- GridElement elem = GridElement.findById(newSlId);
- if (elem == null) {
- continue;
- }
- BigDecimal triggerPrice = elem.getGridPrice();
- int finalSlId = newSlId;
- executor.placeTakeProfit(
- triggerPrice,
- FuturesPriceTrigger.RuleEnum.NUMBER_1,
- ORDER_TYPE_CLOSE_SHORT,
- config.getQuantity(),
- profitId -> {
- elem.setShortStopLossOrderId(profitId);
- GridElement.refreshIndices();
- log.info("[Gate] 空仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
- }
- );
+ int stopLossCount = filledQty ;
+ log.info("[Gate] 空仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}张止损单", furthestSlId, filledQty, stopLossCount);
+ int newSlId = furthestSlId + interval;
+ GridElement elem = GridElement.findById(newSlId);
+ if (elem == null) {
+ return;
}
+ BigDecimal triggerPrice = elem.getGridPrice();
+ int finalSlId = newSlId;
+ executor.placeTakeProfit(
+ triggerPrice,
+ FuturesPriceTrigger.RuleEnum.NUMBER_1,
+ ORDER_TYPE_CLOSE_SHORT,
+ String.valueOf(stopLossCount),
+ profitId -> {
+ elem.setShortStopLossOrderId(profitId);
+ GridElement.refreshIndices();
+ log.info("[Gate] 空仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
+ }
+ );
+
+// int stopLossCount = filledQty / Integer.parseInt(config.getQuantity());
+// log.info("[Gate] 空仓追挂止损, 当前最远止损gridId:{}, 成交{}张, 追加{}个止损单", furthestSlId, filledQty, stopLossCount);
+// for (int i = 0; i < stopLossCount; i++) {
+// int newSlId = furthestSlId + i + interval;
+// GridElement elem = GridElement.findById(newSlId);
+// if (elem == null) {
+// continue;
+// }
+// BigDecimal triggerPrice = elem.getGridPrice();
+// int finalSlId = newSlId;
+// executor.placeTakeProfit(
+// triggerPrice,
+// FuturesPriceTrigger.RuleEnum.NUMBER_1,
+// ORDER_TYPE_CLOSE_SHORT,
+// config.getQuantity(),
+// profitId -> {
+// elem.setShortStopLossOrderId(profitId);
+// GridElement.refreshIndices();
+// log.info("[Gate] 空仓止损追加, gridId:{}, 触发价:{}, stopLossId:{}", finalSlId, triggerPrice, profitId);
+// }
+// );
+// }
}
// ---- 工具 ----
--
Gitblit v1.9.1