Administrator
2026-07-14 09d80f4bfd8d6dcf17a9617c0b6a0589ff7e08aa
fix(gateApi): 修复网格交易止损计数逻辑

- 修改累计止损计数字段注释,明确同一网格多次止损不累加
- 新增最近止损网格ID字段用于判断连续止损情况
- 在清仓和加仓成交后重置最近止损网格ID
- 实现同一网格止损单不重复计数的逻辑
- 简化止损触发后的目标数量计算公式
1 files modified
32 ■■■■■ changed files
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java 32 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -134,10 +134,14 @@
    /** 多头是否活跃(有仓位) */
    private volatile boolean longActive = false;
    /** 多头累计止损张数(加仓订单成交后归零) */
    /** 多头累计止损次数(加仓订单成交后归零),同一网格多次止损不累加 */
    private volatile int accumulatedLongLossCount = 0;
    /** 空头累计止损张数(加仓订单成交后归零) */
    /** 空头累计止损次数(加仓订单成交后归零),同一网格多次止损不累加 */
    private volatile int accumulatedShortLossCount = 0;
    /** 最近触发止损的多头网格ID,用于判断是否是同一网格的连续止损 */
    private volatile int lastLongStopLossGridId = Integer.MAX_VALUE;
    /** 最近触发止损的空头网格ID,用于判断是否是同一网格的连续止损 */
    private volatile int lastShortStopLossGridId = Integer.MAX_VALUE;
    private volatile BigDecimal lastKlinePrice;
    private volatile BigDecimal markPrice = BigDecimal.ZERO;
@@ -307,6 +311,8 @@
        shortActive = false;
        accumulatedLongLossCount = 0;
        accumulatedShortLossCount = 0;
        lastLongStopLossGridId = Integer.MAX_VALUE;
        lastShortStopLossGridId = Integer.MAX_VALUE;
        shortPriceQueue.clear();
        longPriceQueue.clear();
        totalShortPriceQueue.clear();
@@ -628,6 +634,7 @@
                int filledQty = Integer.parseInt(shortGridElement.getShortTraderParam().getQuantity());
                shortEntryTraderIdParam(shortGridElement, orderId, false);
                accumulatedShortLossCount = 0; // 空单成交,重置止损追单计数
                lastShortStopLossGridId = Integer.MAX_VALUE;
                // [Gate-需求2] 加仓后先撤空仓所有止盈+止损,再查交易所持仓后重挂
                cancelAllShortTakeProfitsAndStopLosses();
                // REST 查询可能因交易所延迟返回旧值,与 WS 本地缓存取最大值兜底
@@ -706,6 +713,7 @@
                int filledQty = Integer.parseInt(longGridElement.getLongTraderParam().getQuantity());
                longEntryTraderIdParam(longGridElement, orderId, false);
                accumulatedLongLossCount = 0; // 多单成交,重置止损追单计数
                lastLongStopLossGridId = Integer.MAX_VALUE;
                // [Gate-需求2] 加仓后先撤多仓所有止盈+止损,再查交易所持仓后重挂
                cancelAllLongTakeProfitsAndStopLosses();
                // REST 查询可能因交易所延迟返回旧值,与 WS 本地缓存取最大值兜底
@@ -1308,8 +1316,12 @@
    private void handleLongStopLossTriggered(GridElement gridElement, String orderId) {
        gridElement.removeLongStopLossOrderId(orderId);
        accumulatedLongLossCount++;
        int gridId = gridElement.getId();
        // 同一网格的多个止损单触发不累加计数,视为同一批次
        if (gridId != lastLongStopLossGridId) {
            accumulatedLongLossCount++;
            lastLongStopLossGridId = gridId;
        }
        log.info("[Gate] 多仓止损触发 gridId:{}, 止损次数:{}, 开始追单", gridId, accumulatedLongLossCount);
        int newEntryGridId = gridId + 1;
@@ -1324,9 +1336,7 @@
        BigDecimal triggerPrice = newEntryGrid.getGridPrice();
        int posSize = Math.min(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue());
        int maxPos = config.getMaxPositionSize();
        int baseQty = Integer.parseInt(config.getBaseQuantity());
        int gridQty = Integer.parseInt(config.getQuantity());
        int targetAmount = baseQty + (accumulatedLongLossCount - 1) * gridQty;
        int targetAmount = accumulatedLongLossCount + 1;
        int addSize;
        if (maxPos > 0) {
            int remainingRoom = maxPos - posSize;
@@ -1383,8 +1393,12 @@
    private void handleShortStopLossTriggered(GridElement gridElement, String orderId) {
        gridElement.removeShortStopLossOrderId(orderId);
        accumulatedShortLossCount++;
        int gridId = gridElement.getId();
        // 同一网格的多个止损单触发不累加计数,视为同一批次
        if (gridId != lastShortStopLossGridId) {
            accumulatedShortLossCount++;
            lastShortStopLossGridId = gridId;
        }
        log.info("[Gate] 空仓止损触发 gridId:{}, 止损次数:{}, 开始追单", gridId, accumulatedShortLossCount);
        int newEntryGridId = gridId - 1;
@@ -1399,9 +1413,7 @@
        BigDecimal triggerPrice = newEntryGrid.getGridPrice();
        int posSize = Math.min(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue());
        int maxPos = config.getMaxPositionSize();
        int baseQty = Integer.parseInt(config.getBaseQuantity());
        int gridQty = Integer.parseInt(config.getQuantity());
        int targetAmount = baseQty + (accumulatedShortLossCount - 1) * gridQty;
        int targetAmount = accumulatedShortLossCount + 1;
        int addSize;
        if (maxPos > 0) {
            int remainingRoom = maxPos - posSize;