Administrator
2026-05-22 c846827b1024f3b6f5a33663f219827c67489d21
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -794,22 +794,11 @@
                if (!UpGridElement.isHasShortOrder() && shortEntryPrice.compareTo(newLongFirst) > 0) {
                    //挂空仓条件单
                    TraderParam upShortTraderParam = UpGridElement.getShortTraderParam();
                    executor.placeConditionalEntryOrder(
                    placeEntryOrderWithPreFlag(UpGridElement, false,
                            upShortTraderParam.getEntryPrice(),
                            FuturesPriceTrigger.RuleEnum.NUMBER_2,
                            negate(upShortTraderParam.getQuantity()),
                            orderId ->
                            {
                                shortEntryTraderIdParam(
                                        UpGridElement,
                                        orderId,
                                        true
                                );
                            },
                            null
                    );
                            negate(upShortTraderParam.getQuantity()));
                }
                int i = gridElement.getUpId();
                GridElement downGridElement = GridElement.findById(i);
@@ -823,20 +812,10 @@
                                    downGridPrice.compareTo(longEntryPrice) <= 0 &&
                                    downGridPrice.compareTo(shortEntryPrice) >= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, false,
                                downShortTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_1,
                                negate(downShortTraderParam.getQuantity()),
                                orderId ->
                                {
                                    shortEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                negate(downShortTraderParam.getQuantity()));
                    }
@@ -845,20 +824,10 @@
                            !downGridElement.isHasLongOrder() &&
                                    downGridPrice.compareTo(longEntryPrice) <= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, true,
                                downLongTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_1,
                                downLongTraderParam.getQuantity(),
                                orderId ->
                                {
                                    longEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                downLongTraderParam.getQuantity());
                    }
                }
            }
@@ -885,22 +854,11 @@
            if (UpGridElement != null) {
                if (!UpGridElement.isHasLongOrder() && longEntryPrice.compareTo(newLongFirst) < 0) {
                    //挂多仓条件单
                    TraderParam upLongTraderParam = UpGridElement.getLongTraderParam();
                    executor.placeConditionalEntryOrder(
                    placeEntryOrderWithPreFlag(UpGridElement, true,
                            upLongTraderParam.getEntryPrice(),
                            FuturesPriceTrigger.RuleEnum.NUMBER_1,
                            config.getQuantity(),
                            orderId ->
                            {
                                longEntryTraderIdParam(
                                        UpGridElement,
                                        orderId,
                                        true
                                );
                            },
                            null
                    );
                            config.getQuantity());
                }
                int i = gridElement.getDownId();
@@ -915,20 +873,10 @@
                                    downGridPrice.compareTo(shortEntryPrice) >= 0 &&
                                    downGridPrice.compareTo(longEntryPrice) <= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, true,
                                downLongTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_2,
                                config.getQuantity(),
                                orderId ->
                                {
                                    longEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                config.getQuantity());
                    }
@@ -938,20 +886,10 @@
                                    downGridPrice.compareTo(shortEntryPrice) >= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, false,
                                shortTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_2,
                                negate(config.getQuantity()),
                                orderId ->
                                {
                                    shortEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                negate(config.getQuantity()));
                    }
                }
            }
@@ -1031,33 +969,17 @@
            Integer upId = baseGridElement.getUpId();
            GridElement upGridElementOne = GridElement.findById(upId);
            BigDecimal longTp = upGridElementOne.getGridPrice();
            executor.placeConditionalEntryOrder(
            placeEntryOrderWithPreFlag(upGridElementOne, true,
                    longTp,
                    FuturesPriceTrigger.RuleEnum.NUMBER_1,
                    config.getQuantity(),
                    orderId -> {
                        longEntryTraderIdParam(
                                upGridElementOne,
                                orderId,
                                true
                        );
                    },
                    null);
                    config.getQuantity());
            Integer downId = baseGridElement.getDownId();
            GridElement downGridElementOne = GridElement.findById(downId);
            BigDecimal shortTp = downGridElementOne.getGridPrice();
            executor.placeConditionalEntryOrder(
            placeEntryOrderWithPreFlag(downGridElementOne, false,
                    shortTp,
                    FuturesPriceTrigger.RuleEnum.NUMBER_2,
                    negate(config.getQuantity()),
                    orderId -> {
                        shortEntryTraderIdParam(
                                downGridElementOne,
                                orderId,
                                true
                        );
                    },
                    null);
                    negate(config.getQuantity()));
            state = StrategyState.ACTIVE;
        }
@@ -1318,22 +1240,11 @@
                if (!UpGridElement.isHasShortOrder() && shortEntryPrice.compareTo(newLongFirst) > 0) {
                    //挂空仓条件单
                    TraderParam upShortTraderParam = UpGridElement.getShortTraderParam();
                    executor.placeConditionalEntryOrder(
                    placeEntryOrderWithPreFlag(UpGridElement, false,
                            upShortTraderParam.getEntryPrice(),
                            FuturesPriceTrigger.RuleEnum.NUMBER_2,
                            negate(upShortTraderParam.getQuantity()),
                            orderId ->
                            {
                                shortEntryTraderIdParam(
                                        UpGridElement,
                                        orderId,
                                        true
                                );
                            },
                            null
                    );
                            negate(upShortTraderParam.getQuantity()));
                }
                int i = UpGridElement.getId() + 2;
                GridElement downGridElement = GridElement.findById(i);
@@ -1347,20 +1258,10 @@
                                    downGridPrice.compareTo(longEntryPrice) <= 0 &&
                                    downGridPrice.compareTo(shortEntryPrice) >= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, false,
                                downShortTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_1,
                                negate(downShortTraderParam.getQuantity()),
                                orderId ->
                                {
                                    shortEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                negate(downShortTraderParam.getQuantity()));
                    }
@@ -1369,20 +1270,10 @@
                            !downGridElement.isHasLongOrder() &&
                                    downGridPrice.compareTo(longEntryPrice) <= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, true,
                                downLongTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_1,
                                downLongTraderParam.getQuantity(),
                                orderId ->
                                {
                                    longEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                downLongTraderParam.getQuantity());
                    }
                }
            }
@@ -1454,22 +1345,11 @@
            if (UpGridElement != null) {
                if (!UpGridElement.isHasLongOrder() && longEntryPrice.compareTo(newLongFirst) < 0) {
                    //挂多仓条件单
                    TraderParam upLongTraderParam = UpGridElement.getLongTraderParam();
                    executor.placeConditionalEntryOrder(
                    placeEntryOrderWithPreFlag(UpGridElement, true,
                            upLongTraderParam.getEntryPrice(),
                            FuturesPriceTrigger.RuleEnum.NUMBER_1,
                            config.getQuantity(),
                            orderId ->
                            {
                                longEntryTraderIdParam(
                                        UpGridElement,
                                        orderId,
                                        true
                                );
                            },
                            null
                    );
                            config.getQuantity());
                }
                int i = UpGridElement.getId() - 2;
@@ -1484,20 +1364,10 @@
                                    downGridPrice.compareTo(shortEntryPrice) >= 0 &&
                                    downGridPrice.compareTo(longEntryPrice) <= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, true,
                                downLongTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_2,
                                config.getQuantity(),
                                orderId ->
                                {
                                    longEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                config.getQuantity());
                    }
@@ -1507,20 +1377,10 @@
                                    downGridPrice.compareTo(shortEntryPrice) >= 0
                    ){
                        executor.placeConditionalEntryOrder(
                        placeEntryOrderWithPreFlag(downGridElement, false,
                                shortTraderParam.getEntryPrice(),
                                FuturesPriceTrigger.RuleEnum.NUMBER_2,
                                negate(config.getQuantity()),
                                orderId ->
                                {
                                    shortEntryTraderIdParam(
                                            downGridElement,
                                            orderId,
                                            true
                                    );
                                },
                                null
                        );
                                negate(config.getQuantity()));
                    }
                }
            }
@@ -1563,6 +1423,50 @@
    }
    /**
     * 预设标志位后提交条件开仓单,防止异步回调导致的竞态重复挂单。
     *
     * <p>在调用 {@link GateTradeExecutor#placeConditionalEntryOrder} 之前同步设置
     * {@code isHasLongOrder / isHasShortOrder},关闭 WS 线程与 Executor 线程之间的
     * 检查-下单时间窗口。API 失败时自动回滚标志位。
     *
     * @param gridElement 目标网格元素
     * @param isLong      true=多仓下单,false=空仓下单
     * @param triggerPrice 触发价
     * @param rule        触发规则
     * @param size        开仓张数
     */
    private void placeEntryOrderWithPreFlag(GridElement gridElement, boolean isLong,
                                             BigDecimal triggerPrice,
                                             FuturesPriceTrigger.RuleEnum rule,
                                             String size) {
        if (isLong) {
            gridElement.setHasLongOrder(true);
        } else {
            gridElement.setHasShortOrder(true);
        }
        executor.placeConditionalEntryOrder(triggerPrice, rule, size,
                orderId -> {
                    if (isLong) {
                        longEntryTraderIdParam(gridElement, orderId, true);
                    } else {
                        shortEntryTraderIdParam(gridElement, orderId, true);
                    }
                },
                () -> {
                    if (isLong) {
                        gridElement.setHasLongOrder(false);
                        gridElement.setLongOrderId(null);
                    } else {
                        gridElement.setHasShortOrder(false);
                        gridElement.setShortOrderId(null);
                    }
                    GridElement.refreshIndices();
                    log.warn("[Gate] 条件单创建失败,回滚标志位 gridId:{}, isLong:{}", gridElement.getId(), isLong);
                }
        );
    }
    /**
     * 根据持仓和当前价格计算未实现盈亏。
     *
     * <h3>正向合约公式</h3>