Administrator
2026-05-19 7491d19c0412712080f23c389eb2f1bfa2924e09
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -600,6 +600,125 @@
        }
    }
    /**
     * 用户私有成交回调。由 {@link com.xcong.excoin.modules.gateApi.wsHandler.handler.UserTradesChannelHandler}
     * 在收到 {@code futures.usertrades} 推送时调用。
     *
     * @param contract 合约名称
     * @param orderId  订单 ID
     * @param price    成交价格
     * @param size     成交数量
     * @param role     用户角色(maker / taker)
     * @param fee      手续费
     */
    public void onUserTrade(String contract, String orderId, BigDecimal price, String size, String role, BigDecimal fee) {
        if (state == StrategyState.STOPPED) {
            return;
        }
        log.info("[Gate] 成交明细, 合约:{}, 订单ID:{}, 价格:{}, 数量:{}, 角色:{}, 手续费:{}",
                contract, orderId, price, size, role, fee);
    }
    /**
     * 自动订单(条件单)状态变更回调。
     * 由 {@link com.xcong.excoin.modules.gateApi.wsHandler.handler.AutoOrdersChannelHandler}
     * 在收到 {@code futures.autoorders} 推送时调用。
     *
     * @param orderId   条件单 ID
     * @param status    订单状态(open / finished / cancelled)
     * @param reason    变更原因
     * @param orderType 订单类型(plan-close-long-position 等)
     */
    public void onAutoOrder(String orderId, String status, String reason, String orderType) {
        if (state == StrategyState.STOPPED) {
            return;
        }
        log.info("[Gate] 条件单状态变更, id:{}, status:{}, reason:{}, order_type:{}",
                orderId, status, reason, orderType);
        if (!"finished".equals(status)) {
            return;
        }
        /**
         * 匹配止盈单止盈
         */
        GridElement byLongTakeProfitOrderId = GridElement.findByLongTakeProfitOrderId(orderId);
        if (byLongTakeProfitOrderId != null){
            longTakeProfitTraderIdParam(
                    byLongTakeProfitOrderId,
                    null,
                    false
            );
            longEntryTraderIdParam(
                    byLongTakeProfitOrderId,
                    null,
                    false
            );
        }
        GridElement byShortTakeProfitOrderId = GridElement.findByShortTakeProfitOrderId(orderId);
        if (byShortTakeProfitOrderId != null){
            shortTakeProfitTraderIdParam(
                    byShortTakeProfitOrderId,
                    null,
                    false
            );
            shortEntryTraderIdParam(
                    byShortTakeProfitOrderId,
                    null,
                    false
            );
        }
        /**
         * 匹配挂单
         */
        GridElement longGridElement = GridElement.findByLongOrderId(orderId);
        if (longGridElement != null) {
            if (longGridElement.isHasLongOrder()){
                if (longGridElement.getLongTakeProfitOrderId() == null){
                    BigDecimal longTp = longGridElement.getLongTraderParam().getTakeProfitPrice();
                    if (longTp != null) {
                        executor.placeTakeProfit(longTp,
                                FuturesPriceTrigger.RuleEnum.NUMBER_1,
                                ORDER_TYPE_CLOSE_LONG,
                                negate(config.getQuantity()),
                                (profitId) -> {
                                    longTakeProfitTraderIdParam(
                                            longGridElement,
                                            profitId,
                                            true
                                    );
                                });
                        log.info("[Gate] 多单成交匹配止盈, orderId:{}, 止盈价:{}, size:{}", orderId, longTp, negate(config.getQuantity()));
                        return;
                    }
                }
            }
        }
        GridElement shortGridElement = GridElement.findByShortOrderId(orderId);
        if (shortGridElement != null) {
            if (shortGridElement.isHasShortOrder()){
                if (shortGridElement.getShortTakeProfitOrderId() == null){
                    BigDecimal shortTp = shortGridElement.getShortTraderParam().getTakeProfitPrice();
                    if (shortTp != null) {
                        executor.placeTakeProfit(shortTp,
                                FuturesPriceTrigger.RuleEnum.NUMBER_2,
                                ORDER_TYPE_CLOSE_SHORT,
                                config.getQuantity(),
                                (profitId) -> {
                                    shortTakeProfitTraderIdParam(
                                            shortGridElement,
                                            profitId,
                                            true
                                    );
                                });
                        log.info("[Gate] 空单成交匹配止盈, orderId:{}, 止盈价:{}, size:{}", orderId, shortTp, config.getQuantity());
                    }
                }
            }
        }
    }
    // ---- 网格队列处理 ----
    /**
@@ -631,6 +750,7 @@
            GridElement baseGridElement = GridElement.findById(0);
            TraderParam baseLongTraderParam = config.getBaseLongTraderParam();
            baseGridElement.setLongOrderId(baseLongTraderParam.getEntryOrderId());
            baseGridElement.setHasLongOrder(true);
            //0位置的网格的多单止盈
            BigDecimal upTakeProfitPrice = baseGridElement.getLongTraderParam().getTakeProfitPrice();
            executor.placeTakeProfit(
@@ -649,6 +769,7 @@
            //0位置的网格的空单止盈
            TraderParam baseShortTraderParam = config.getBaseShortTraderParam();
            baseGridElement.setShortOrderId(baseShortTraderParam.getEntryOrderId());
            baseGridElement.setHasShortOrder(true);
            BigDecimal downTakeProfitPrice = baseGridElement.getShortTraderParam().getTakeProfitPrice();
            executor.placeTakeProfit(
                    downTakeProfitPrice,