From bb272e1e2c0d4637d6d9ebfefb635662b804b459 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Wed, 13 May 2026 17:52:48 +0800
Subject: [PATCH] refactor(okxNewPrice): 账户配置

---
 src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java                                  |    4 ++
 src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java                        |    2 
 src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java |    9 ++--
 src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java                              |   55 +++++++++++++++++++++++++++
 src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java                           |   16 +++++---
 src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java                  |   11 ++++-
 6 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java
index b9c4f7f..cdcd8de 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java
@@ -60,6 +60,7 @@
     private final PnLPriceMode unrealizedPnlPriceMode;
     private final BigDecimal maxPosSize;
     private BigDecimal step;
+    private String instIdCode;
 
     private OkxConfig(Builder builder) {
         this.apiKey = builder.apiKey;
@@ -140,6 +141,9 @@
     public BigDecimal getStep() { return step; }
     public void setStep(BigDecimal step) { this.step = step; }
 
+    public String getInstIdCode() { return instIdCode; }
+    public void setInstIdCode(String instIdCode) { this.instIdCode = instIdCode; }
+
     // ==================== 环境 ====================
 
     public boolean isProduction() { return isProduction; }
diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
index 9655c89..f4f6692 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
@@ -47,7 +47,7 @@
     public OkxGridTradeService(OkxConfig config, String accountName) {
         this.config = config;
         this.accountName = accountName;
-        this.executor = new OkxTradeExecutor(config.getContract(), config.getMarginMode(), accountName);
+        this.executor = new OkxTradeExecutor(config.getContract(), config.getMarginMode(), accountName, config.getInstIdCode());
     }
 
     public void setWebSocketClient(WebSocketClient wsClient) {
diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java
index 5c04970..43bdecf 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java
@@ -44,6 +44,61 @@
         return isSuccess(result, "设置杠杆");
     }
 
+    public String fetchInstIdCode(String instType, String instId) {
+        String path = "/api/v5/account/instruments?instType=" + instType + "&instId=" + instId;
+        JSONObject result = get(path);
+        if (result == null || !"0".equals(result.getString("code"))) {
+            log.error("[REST] 获取instIdCode失败, code:{}, msg:{}",
+                    result != null ? result.getString("code") : "null",
+                    result != null ? result.getString("msg") : "no response");
+            return null;
+        }
+        com.alibaba.fastjson.JSONArray data = result.getJSONArray("data");
+        if (data == null || data.isEmpty()) {
+            log.error("[REST] 获取instIdCode失败: data为空");
+            return null;
+        }
+        JSONObject first = data.getJSONObject(0);
+        String instIdCode = first.getString("instIdCode");
+        log.info("[REST] 获取instIdCode成功, instId:{}, instIdCode:{}", instId, instIdCode);
+        return instIdCode;
+    }
+
+    private JSONObject get(String path) {
+        HttpURLConnection conn = null;
+        try {
+            String timestamp = OkxWsUtil.getIso8601Timestamp();
+            String sign = OkxWsUtil.signRest(timestamp, "GET", path, "", secretKey);
+
+            URL url = new URL(baseUrl + path);
+            conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestMethod("GET");
+            conn.setConnectTimeout(15000);
+            conn.setReadTimeout(15000);
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.setRequestProperty("OK-ACCESS-KEY", apiKey);
+            conn.setRequestProperty("OK-ACCESS-SIGN", sign);
+            conn.setRequestProperty("OK-ACCESS-TIMESTAMP", timestamp);
+            conn.setRequestProperty("OK-ACCESS-PASSPHRASE", passphrase);
+            if (isSimulate) {
+                conn.setRequestProperty("x-simulated-trading", "1");
+            }
+
+            int code = conn.getResponseCode();
+            String response = readResponse(conn);
+            log.info("[REST] GET {} → HTTP {} body:{}", path, code, response);
+
+            return JSON.parseObject(response);
+        } catch (Exception e) {
+            log.error("[REST] GET {} 失败: {}", path, e.getMessage());
+            return null;
+        } finally {
+            if (conn != null) {
+                conn.disconnect();
+            }
+        }
+    }
+
     private JSONObject post(String path, JSONObject body) {
         HttpURLConnection conn = null;
         try {
diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java
index 789fe2a..875c01e 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java
@@ -48,15 +48,17 @@
     private final String contract;
     private final String marginMode;
     private final String accountName;
+    private final String instIdCode;
 
     private volatile WebSocketClient wsClient;
 
     private final ExecutorService executor;
 
-    public OkxTradeExecutor(String contract, String marginMode, String accountName) {
+    public OkxTradeExecutor(String contract, String marginMode, String accountName, String instIdCode) {
         this.contract = contract;
         this.marginMode = marginMode;
         this.accountName = accountName;
+        this.instIdCode = instIdCode;
         this.executor = new ThreadPoolExecutor(
                 1, 1,
                 60L, TimeUnit.SECONDS,
@@ -171,7 +173,7 @@
 
                 JSONArray argsArray = new JSONArray();
                 JSONObject args = new JSONObject();
-                args.put("instId", contract);
+                args.put("instIdCode", instIdCode);
                 args.put("tdMode", marginMode);
                 args.put("side", side);
                 args.put("posSide", posSide);
@@ -218,7 +220,7 @@
                 }
                 JSONArray argsArray = new JSONArray();
                 JSONObject args = new JSONObject();
-                args.put("instId", contract);
+                args.put("instIdCode", instIdCode);
                 args.put("algoOrdType", "conditional");
                 argsArray.add(args);
 
@@ -248,7 +250,7 @@
 
     private JSONObject buildOrderArgs(TradeRequestParam param) {
         JSONObject args = new JSONObject();
-        args.put("instId", param.getInstId());
+        args.put("instIdCode", instIdCode);
         args.put("tdMode", param.getTdMode());
         args.put("clOrdId", param.getClOrdId());
         args.put("side", param.getSide());
@@ -273,8 +275,10 @@
 
         String connId = OkxWsUtil.getOrderNum("order");
         JSONObject msg = OkxWsUtil.buildJsonObject(connId, "order", argsArray);
-        wsClient.send(msg.toJSONString());
-        log.info("[TradeExec] 发送下单: side={}, sz={}", param.getSide(), param.getSz());
+        String msgStr = msg.toJSONString();
+        log.info("[TradeExec] 发送下单: {}", msgStr);
+        wsClient.send(msgStr);
+        log.info("[TradeExec] 下单已发送: side={}, sz={}, instId={}", param.getSide(), param.getSz(), param.getInstId());
     }
 
     private void sendBatchOrders(List<TradeRequestParam> params) {
diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java
index 510fb0c..bee8c45 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java
@@ -115,8 +115,15 @@
             log.error("[管理器] 设置杠杆倍数失败,策略可能无法正常运作");
         }
 
-        log.info("[管理器] 账户配置完成, posMode:{}, leverage:{}, marginMode:{}",
-                config.getPosMode(), config.getLeverage(), config.getMarginMode());
+        String instIdCode = restClient.fetchInstIdCode("SWAP", config.getContract());
+        if (instIdCode != null) {
+            config.setInstIdCode(instIdCode);
+        } else {
+            log.error("[管理器] 获取instIdCode失败,WS下单将无法正常工作");
+        }
+
+        log.info("[管理器] 账户配置完成, posMode:{}, leverage:{}, marginMode:{}, instIdCode:{}",
+                config.getPosMode(), config.getLeverage(), config.getMarginMode(), config.getInstIdCode());
     }
 
     public OkxKlineWebSocketClient getKlineWebSocketClient() { return wsKlineClient; }
diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java b/src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java
index 285394c..9db7b25 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java
@@ -85,10 +85,11 @@
                 if (details != null) {
                     for (int j = 0; j < details.size(); j++) {
                         JSONObject detail = details.getJSONObject(j);
-                        log.info("[{}] 币种:{}, 可用余额:{}, 现金余额:{}, 权益:{}",
-                                CHANNEL_NAME,
-                                detail.get("ccy"), detail.get("availBal"),
-                                detail.get("cashBal"), detail.get("eq"));
+                        if ("USDT".equals(detail.getString("ccy"))) {
+                            log.info("[{}] USDT可用余额:{}, 权益:{}",
+                                    CHANNEL_NAME,
+                                    detail.get("availBal"), detail.get("eq"));
+                        }
                     }
                 }
             }

--
Gitblit v1.9.1