package com.xcong.excoin.modules.okxApi.wsHandler.handler; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.xcong.excoin.modules.okxApi.OkxConfig; import com.xcong.excoin.modules.okxApi.OkxGridTradeService; import com.xcong.excoin.modules.okxApi.wsHandler.OkxChannelHandler; import lombok.extern.slf4j.Slf4j; import org.java_websocket.client.WebSocketClient; import java.math.BigDecimal; /** * OKX 订单信息频道处理器(orders)。 * *

数据用途

* 监控订单成交(filled)状态,跟踪已实现盈亏(fillPnl)。 * 成交后通过 batch-orders 频道设置止盈止损限价单。 * *

推送字段

* instId, ordId, clOrdId, side, posSide, state, accFillSz, avgPx, fillPnl, fillFee * *

数据处理

* state=filled 且 accFillSz>0 → 成交 → 调用 gridTradeService.onOrderFilled() 跟踪盈亏 * * @author Administrator */ @Slf4j public class OkxOrderInfoChannelHandler implements OkxChannelHandler { private static final String CHANNEL_NAME = "orders"; private static final String CHANNEL = "orders"; private final String instId; private final OkxGridTradeService gridTradeService; private final OkxConfig config; public OkxOrderInfoChannelHandler(String instId, OkxGridTradeService gridTradeService, OkxConfig config) { this.instId = instId; this.gridTradeService = gridTradeService; this.config = config; } @Override public String getChannelName() { return CHANNEL_NAME; } @Override public void subscribe(WebSocketClient ws) { JSONObject msg = new JSONObject(); msg.put("op", "subscribe"); JSONArray args = new JSONArray(); JSONObject arg = new JSONObject(); arg.put("channel", CHANNEL); arg.put("instType", "SWAP"); arg.put("instId", instId); args.add(arg); msg.put("args", args); ws.send(msg.toJSONString()); log.info("[{}] 订阅成功, 合约:{}", CHANNEL_NAME, instId); } @Override public void unsubscribe(WebSocketClient ws) { JSONObject msg = new JSONObject(); msg.put("op", "unsubscribe"); JSONArray args = new JSONArray(); JSONObject arg = new JSONObject(); arg.put("channel", CHANNEL); arg.put("instType", "SWAP"); arg.put("instId", instId); args.add(arg); msg.put("args", args); ws.send(msg.toJSONString()); log.info("[{}] 取消订阅成功", CHANNEL_NAME); } @Override public boolean handleMessage(JSONObject response) { JSONObject argObj = response.getJSONObject("arg"); if (argObj == null) { return false; } String channel = argObj.getString("channel"); if (!CHANNEL.equals(channel)) { return false; } try { JSONArray dataArray = response.getJSONArray("data"); if (dataArray == null || dataArray.isEmpty()) { return true; } for (int i = 0; i < dataArray.size(); i++) { JSONObject detail = dataArray.getJSONObject(i); if (!instId.equals(detail.getString("instId"))) { continue; } String state = detail.getString("state"); String accFillSz = detail.getString("accFillSz"); String fillPnl = detail.getString("fillPnl"); String posSide = detail.getString("posSide"); String avgPx = detail.getString("avgPx"); String clOrdId = detail.getString("clOrdId"); log.info("[{}] 订单, 方向:{}, 状态:{}, 成交量:{}, 均价:{}, 盈亏:{}, 编号:{}", CHANNEL_NAME, posSide, state, accFillSz, avgPx, fillPnl, clOrdId); if ("filled".equals(state) && accFillSz != null && new BigDecimal(accFillSz).compareTo(BigDecimal.ZERO) > 0) { if (gridTradeService != null) { BigDecimal pnl = fillPnl != null ? new BigDecimal(fillPnl) : BigDecimal.ZERO; gridTradeService.onOrderFilled(posSide, new BigDecimal(accFillSz), pnl); } } } } catch (Exception e) { log.error("[{}] 处理数据失败", CHANNEL_NAME, e); } return true; } }