Administrator
4 hours ago bb272e1e2c0d4637d6d9ebfefb635662b804b459
refactor(okxNewPrice): 账户配置
6 files modified
97 ■■■■ changed files
src/main/java/com/xcong/excoin/modules/okxApi/OkxConfig.java 4 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxApi/OkxRestClient.java 55 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxApi/OkxTradeExecutor.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxApi/OkxWebSocketClientManager.java 11 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxApi/wsHandler/handler/OkxAccountChannelHandler.java 9 ●●●●● patch | view | raw | blame | history
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; }
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) {
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 {
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) {
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; }
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"));
                        }
                    }
                }
            }