Administrator
15 hours ago cd6a9821d0e9e4f7f13d7b5dab00f22b267cc222
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -2325,14 +2325,17 @@
        int baseQty = Integer.parseInt(config.getBaseQuantity());
        int gridCount = baseQty / qty;
        GridElement entryElem = GridElement.findById(gridId);
        if (gridCount <= 0 || filledQty < qty) {
        if (gridCount <= 0 || filledQty <= 0) {
            // 早期返回需重置防重入标记
            if (entryElem != null) { entryElem.setExtendStopLossInProgress(false); }
            return;
        }
        // [Gate] 止损只针对初始开仓仓位(baseQuantity),加仓部分只做止盈
        int totalOrders = filledQty / qty;
        // [Gate] 止损只针对初始开仓仓位(baseQuantity),加仓部分只做止盈;
        // 持仓不足一个网格量时也按剩余张数挂一张止损(手动重建场景,避免裸奔)
        int slSize = Math.min(filledQty, baseQty);
        int totalOrders = slSize / qty;
        int remainder = slSize % qty;
        int[] orders = new int[gridCount];
        if (gridCount == 1) {
@@ -2356,6 +2359,7 @@
        for (int i = 0; i < gridCount; i++) {
            if (orders[i] > 0) { totalOrdersToPlace += orders[i]; }
        }
        if (remainder > 0) { totalOrdersToPlace += 1; }
        if (totalOrdersToPlace == 0) {
            if (entryElem != null) { entryElem.setExtendStopLossInProgress(false); }
            return;
@@ -2366,13 +2370,23 @@
        for (int i = 0; i < gridCount; i++) {
            if (orders[i] > 0) {
                int sgId = gridId - 2 - i;
                placeStopLossOrders(sgId, orders[i], qty, FuturesPriceTrigger.RuleEnum.NUMBER_2,
                placeStopLossOrders(sgId, orders[i], String.valueOf(qty), FuturesPriceTrigger.RuleEnum.NUMBER_2,
                        ORDER_TYPE_CLOSE_LONG, true, remainCount, entryElem);
                if (detail.length() > 0) {
                    detail.append("  ");
                }
                detail.append(sgId).append("x").append(orders[i]);
            }
        }
        // 不足一个网格量的余数:单独挂一张止损
        if (remainder > 0) {
            int sgId = gridId - 2 - totalOrders;
            placeStopLossOrders(sgId, 1, String.valueOf(remainder), FuturesPriceTrigger.RuleEnum.NUMBER_2,
                    ORDER_TYPE_CLOSE_LONG, true, remainCount, entryElem);
            if (detail.length() > 0) {
                detail.append("  ");
            }
            detail.append(sgId).append("x").append(remainder);
        }
        log.info("[Gate] 多仓追挂止损, 成交{}张, gridId:{}, 网格数:{}, 分配:{}",
@@ -2388,14 +2402,17 @@
        int baseQty = Integer.parseInt(config.getBaseQuantity());
        int gridCount = baseQty / qty;
        GridElement entryElem = GridElement.findById(gridId);
        if (gridCount <= 0 || filledQty < qty) {
        if (gridCount <= 0 || filledQty <= 0) {
            // 早期返回需重置防重入标记
            if (entryElem != null) { entryElem.setExtendStopLossInProgress(false); }
            return;
        }
        // [Gate] 止损只针对初始开仓仓位(baseQuantity),加仓部分只做止盈
        int totalOrders = filledQty / qty;
        // [Gate] 止损只针对初始开仓仓位(baseQuantity),加仓部分只做止盈;
        // 持仓不足一个网格量时也按剩余张数挂一张止损(手动重建场景,避免裸奔)
        int slSize = Math.min(filledQty, baseQty);
        int totalOrders = slSize / qty;
        int remainder = slSize % qty;
        int[] orders = new int[gridCount];
        if (gridCount == 1) {
@@ -2419,6 +2436,7 @@
        for (int i = 0; i < gridCount; i++) {
            if (orders[i] > 0) { totalOrdersToPlace += orders[i]; }
        }
        if (remainder > 0) { totalOrdersToPlace += 1; }
        if (totalOrdersToPlace == 0) {
            if (entryElem != null) { entryElem.setExtendStopLossInProgress(false); }
            return;
@@ -2429,13 +2447,23 @@
        for (int i = 0; i < gridCount; i++) {
            if (orders[i] > 0) {
                int sgId = gridId + 2 + i;
                placeStopLossOrders(sgId, orders[i], qty, FuturesPriceTrigger.RuleEnum.NUMBER_1,
                placeStopLossOrders(sgId, orders[i], String.valueOf(qty), FuturesPriceTrigger.RuleEnum.NUMBER_1,
                        ORDER_TYPE_CLOSE_SHORT, false, remainCount, entryElem);
                if (detail.length() > 0) {
                    detail.append("  ");
                }
                detail.append(sgId).append("x").append(orders[i]);
            }
        }
        // 不足一个网格量的余数:单独挂一张止损
        if (remainder > 0) {
            int sgId = gridId + 2 + totalOrders;
            placeStopLossOrders(sgId, 1, String.valueOf(remainder), FuturesPriceTrigger.RuleEnum.NUMBER_1,
                    ORDER_TYPE_CLOSE_SHORT, false, remainCount, entryElem);
            if (detail.length() > 0) {
                detail.append("  ");
            }
            detail.append(sgId).append("x").append(remainder);
        }
        log.info("[Gate] 空仓追挂止损, 成交{}张, gridId:{}, 网格数:{}, 分配:{}",
@@ -2473,7 +2501,7 @@
    /**
     * 在指定网格位置挂 count 个独立止损单,每个 size 张。
     */
    private void placeStopLossOrders(int gridId, int count, int qty,
    private void placeStopLossOrders(int gridId, int count, String qtyStr,
                                      FuturesPriceTrigger.RuleEnum rule,
                                      String orderType, boolean isLong,
                                      AtomicInteger remainCount,
@@ -2506,8 +2534,8 @@
            return;
        }
        BigDecimal triggerPrice = elem.getGridPrice();
        String size = isLong ? negate(qtyStr) : qtyStr;
        for (int i = 0; i < count; i++) {
            String size = isLong ? negate(String.valueOf(qty)) : String.valueOf(qty);
            int finalGridId = gridId;
            int finalI = i;
            executor.placeTakeProfit(