Administrator
2026-06-02 19ee15d053a2d239abd3ab1c7440fddd12a05af3
refactor(okxNewPrice): 统一WebSocket登录逻辑并优化频道处理器配置

- 修改OkxGridWsClient中连接断开后的处理逻辑,移除公共/私有区分,统一调用wsLogin()
- 将条件单处理器从私有WebSocket迁移到业务WebSocket(/v5/business)
- 更新日志信息以反映新的WebSocket连接配置:业务端包含K线和条件单,私有端仅包含持仓
- 简化WebSocket客户端管理器中的注释描述,明确区分业务和私有通道功能
1 files added
2 files modified
106 ■■■■■ changed files
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridWsClient.java 6 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxOrdersChannelHandler.java 91 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridWsClient.java
@@ -137,7 +137,11 @@
                    isConnecting.set(false);
                    if (sharedExecutor != null && !sharedExecutor.isShutdown()) {
                        resetHeartbeatTimer();
                        wsLogin();
                        if (isPublic) {
                            subscribeAllHandlers();
                        } else {
                            wsLogin();
                        }
                    }
                }
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
@@ -2,6 +2,7 @@
import com.xcong.excoin.modules.okxNewPrice.gridWs.OkxAlgoOrdersChannelHandler;
import com.xcong.excoin.modules.okxNewPrice.gridWs.OkxKlineChannelHandler;
import com.xcong.excoin.modules.okxNewPrice.gridWs.OkxOrdersChannelHandler;
import com.xcong.excoin.modules.okxNewPrice.gridWs.OkxPositionsChannelHandler;
import com.xcong.excoin.modules.okxNewPrice.okxpi.config.OKXAccount;
import com.xcong.excoin.modules.okxNewPrice.okxpi.config.enums.DefaultUrls;
@@ -105,18 +106,18 @@
            gridTradeService.init();
            // 4. 创建 WS 客户端并注册频道处理器
            // 业务 WS(/v5/business):candle1m + orders-algo(K线 + 条件单)
            // 业务 WS(/v5/business):candle1m
            gridWsClientPublic = new OkxGridWsClient(primaryAccount, true);
            gridWsClientPublic.addChannelHandler(new OkxKlineChannelHandler(okxConfig.getInstId(), gridTradeService));
            gridWsClientPublic.addChannelHandler(new OkxAlgoOrdersChannelHandler(okxConfig.getInstId(), gridTradeService));
            gridWsClientPublic.init();
            // 私有 WS(/v5/private):positions(持仓)
            // 私有 WS(/v5/private):positions + orders(algo触发后订单fill带algoId可匹配)
            gridWsClientPrivate = new OkxGridWsClient(primaryAccount, false);
            gridWsClientPrivate.addChannelHandler(new OkxPositionsChannelHandler(okxConfig.getInstId(), gridTradeService));
            gridWsClientPrivate.addChannelHandler(new OkxOrdersChannelHandler(okxConfig.getInstId(), gridTradeService));
            gridWsClientPrivate.init();
            log.info("[OKX-Manager] WS已连接, business: candle1m/orders-algo, private: positions");
            log.info("[OKX-Manager] WS已连接, business: candle1m, private: positions/orders");
            // 5. 激活策略,等待首根 K 线触发基底双开
            gridTradeService.startGrid();
src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxOrdersChannelHandler.java
New file
@@ -0,0 +1,91 @@
package com.xcong.excoin.modules.okxNewPrice.gridWs;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xcong.excoin.modules.okxNewPrice.OkxGridTradeService;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
/**
 * OKX 订单频道处理器 (orders),替代 orders-algo。
 * 当 algo 订单触发后生成普通市价单,其 fill 数据带 algoId,可匹配到原始条件单。
 */
@Slf4j
public class OkxOrdersChannelHandler implements OkxGridChannelHandler {
    private static final String CHANNEL_NAME = "orders";
    private final String instId;
    private final OkxGridTradeService gridTradeService;
    public OkxOrdersChannelHandler(String instId, OkxGridTradeService gridTradeService) {
        this.instId = instId;
        this.gridTradeService = gridTradeService;
    }
    @Override
    public String getChannelName() { return CHANNEL_NAME; }
    @Override
    public void subscribe(WebSocketClient ws) {
        JSONObject msg = new JSONObject();
        JSONObject arg = new JSONObject();
        arg.put("channel", CHANNEL_NAME);
        arg.put("instType", "SWAP");
        msg.put("op", "subscribe");
        JSONArray args = new JSONArray();
        args.add(arg);
        msg.put("args", args);
        ws.send(msg.toJSONString());
        log.info("[OKX-WS] {} 订阅成功", CHANNEL_NAME);
    }
    @Override
    public void unsubscribe(WebSocketClient ws) {
        JSONObject msg = new JSONObject();
        JSONObject arg = new JSONObject();
        arg.put("channel", CHANNEL_NAME);
        arg.put("instType", "SWAP");
        msg.put("op", "unsubscribe");
        JSONArray args = new JSONArray();
        args.add(arg);
        msg.put("args", args);
        ws.send(msg.toJSONString());
        log.info("[OKX-WS] {} 取消订阅成功", CHANNEL_NAME);
    }
    @Override
    public boolean handleMessage(JSONObject response) {
        JSONObject arg = response.getJSONObject("arg");
        if (arg == null || !CHANNEL_NAME.equals(arg.getString("channel"))) {
            return false;
        }
        try {
            JSONArray data = response.getJSONArray("data");
            if (data == null || data.isEmpty()) return true;
            for (int i = 0; i < data.size(); i++) {
                JSONObject order = data.getJSONObject(i);
                if (!instId.equals(order.getString("instId"))) continue;
                String algoId = order.getString("algoId");
                if (algoId == null || algoId.isEmpty()) continue;
                String state = order.getString("state");
                if (!"filled".equals(state)) continue;
                String ordType = order.getString("ordType");
                log.info("[OKX-WS] 订单成交(algo), algoId:{}, ordType:{}, fillPx:{}, fillSz:{}",
                        algoId, ordType,
                        order.getString("fillPx"),
                        order.getString("fillSz"));
                if (gridTradeService != null) {
                    gridTradeService.onOrderUpdate(algoId, state, ordType);
                }
            }
        } catch (Exception e) {
            log.error("[OKX-WS] {} 处理数据失败", CHANNEL_NAME, e);
        }
        return true;
    }
}