From 5c7fa04ebbe54d7bf5050c7f02d3dfadd0fbaf7d Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 19 May 2026 10:40:14 +0800
Subject: [PATCH] feat(ws): 添加订单更新ID日志记录功能

---
 src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java                       |   19 +++++++++
 src/main/java/com/xcong/excoin/modules/gateApi/GateWebSocketClientManager.java                 |    5 ++
 src/main/java/com/xcong/excoin/modules/gateApi/wsHandler/handler/UserTradesChannelHandler.java |   81 ++++++++++++++++++++++++++++++++++++++++
 src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java                          |    1 
 4 files changed, 105 insertions(+), 1 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 5150891..0206cd3 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -600,6 +600,25 @@
         }
     }
 
+    /**
+     * 用户私有成交回调。由 {@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);
+    }
+
     // ---- 网格队列处理 ----
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java b/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
index da78ba3..991a260 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
@@ -323,6 +323,7 @@
 
                 TriggerOrderResponse response = futuresApi.createPriceTriggeredOrder(SETTLE, order);
                 String orderId = String.valueOf(response.getId());
+                String orderIdStr = response.getIdString();
                 log.info("[TradeExec] 条件开仓单已创建, trigger:{}, rule:{}, size:{}, id:{}",
                         triggerPrice, rule, size, orderId);
                 if (onSuccess != null) {
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/GateWebSocketClientManager.java b/src/main/java/com/xcong/excoin/modules/gateApi/GateWebSocketClientManager.java
index 8292a6a..1f306c3 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateWebSocketClientManager.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateWebSocketClientManager.java
@@ -4,6 +4,7 @@
 import com.xcong.excoin.modules.gateApi.wsHandler.handler.OrdersChannelHandler;
 import com.xcong.excoin.modules.gateApi.wsHandler.handler.PositionClosesChannelHandler;
 import com.xcong.excoin.modules.gateApi.wsHandler.handler.PositionsChannelHandler;
+import com.xcong.excoin.modules.gateApi.wsHandler.handler.UserTradesChannelHandler;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
@@ -98,8 +99,10 @@
                     config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService));
             wsClient.addChannelHandler(new OrdersChannelHandler(
                     config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService));
+            wsClient.addChannelHandler(new UserTradesChannelHandler(
+                    config.getApiKey(), config.getApiSecret(), config.getContract(), gridTradeService));
             wsClient.init();
-            log.info("[管理器] WS已连接, 已注册 4 个频道处理器");
+            log.info("[管理器] WS已连接, 已注册 5 个频道处理器");
 
             // 3. 激活策略,等待首根 K 线触发基底双开
             gridTradeService.startGrid();
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/wsHandler/handler/UserTradesChannelHandler.java b/src/main/java/com/xcong/excoin/modules/gateApi/wsHandler/handler/UserTradesChannelHandler.java
new file mode 100644
index 0000000..282df7a
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/wsHandler/handler/UserTradesChannelHandler.java
@@ -0,0 +1,81 @@
+package com.xcong.excoin.modules.gateApi.wsHandler.handler;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.xcong.excoin.modules.gateApi.GateGridTradeService;
+import com.xcong.excoin.modules.gateApi.wsHandler.AbstractPrivateChannelHandler;
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+
+/**
+ * 用户私有成交频道处理器(futures.usertrades)。
+ *
+ * <h3>数据用途</h3>
+ * 订阅用户私有成交更新推送。当订单成交时,获得真实的成交价格、手续费等信息,
+ * 可用于计算实际盈亏。
+ *
+ * <h3>关键推送字段</h3>
+ * <ul>
+ *   <li>id:交易 ID</li>
+ *   <li>contract:合约名称</li>
+ *   <li>order_id:订单 ID</li>
+ *   <li>size:成交数量</li>
+ *   <li>price:成交价格</li>
+ *   <li>role:用户角色(maker/taker)</li>
+ *   <li>fee:手续费</li>
+ *   <li>point_fee:点卡手续费</li>
+ *   <li>text:订单自定义信息</li>
+ * </ul>
+ *
+ * <h3>回调数据(传给 GateGridTradeService)</h3>
+ * contract (String), orderId (String), price (BigDecimal), size (String), role (String), fee (BigDecimal)
+ *
+ * @author Administrator
+ */
+@Slf4j
+public class UserTradesChannelHandler extends AbstractPrivateChannelHandler {
+
+    private static final String CHANNEL_NAME = "futures.usertrades";
+
+    public UserTradesChannelHandler(String apiKey, String apiSecret,
+                                     String contract,
+                                     GateGridTradeService gridTradeService) {
+        super(CHANNEL_NAME, apiKey, apiSecret, contract, gridTradeService);
+    }
+
+    @Override
+    public boolean handleMessage(JSONObject response) {
+        if (!CHANNEL_NAME.equals(response.getString("channel"))) {
+            return false;
+        }
+        try {
+            JSONArray resultArray = response.getJSONArray("result");
+            if (resultArray == null || resultArray.isEmpty()) {
+                return true;
+            }
+            for (int i = 0; i < resultArray.size(); i++) {
+                JSONObject trade = resultArray.getJSONObject(i);
+                String contract = trade.getString("contract");
+                if (!getContract().equals(contract)) {
+                    continue;
+                }
+                String id = trade.getString("id");
+                String orderId = trade.getString("order_id");
+                String size = trade.getString("size");
+                BigDecimal price = trade.getBigDecimal("price");
+                String role = trade.getString("role");
+                BigDecimal fee = trade.getBigDecimal("fee");
+                String text = trade.getString("text");
+                log.info("[{}] 成交更新, id:{}, order_id:{}, price:{}, size:{}, role:{}, fee:{}, text:{}",
+                        CHANNEL_NAME, id, orderId, price, size, role, fee, text);
+                if (getGridTradeService() != null) {
+                    getGridTradeService().onUserTrade(contract, orderId, price, size, role, fee);
+                }
+            }
+        } catch (Exception e) {
+            log.error("[{}] 处理数据失败", CHANNEL_NAME, e);
+        }
+        return true;
+    }
+}

--
Gitblit v1.9.1