OKX 网格交易策略 — 架构文档
一、模块总览
okxNewPrice/
├── OkxConfig.java # 全局配置(Builder模式)
├── OkxGridTradeService.java # 核心策略引擎
├── OkxTradeExecutor.java # REST API 异步执行器
├── OkxGridElement.java # 网格价格层级 + 8个全局O(1)索引
├── OkxTraderParam.java # 单笔挂单参数
├── OkxGridWsClient.java # WebSocket 客户端(双连接)
├── OkxWebSocketClientManager.java # Spring容器入口 + WS组装
├── ExchangeInfoEnum.java # 账户枚举
│
├── gridWs/
│ ├── OkxGridChannelHandler.java # 频道处理器接口
│ ├── OkxKlineChannelHandler.java # candle1m → onKline()
│ ├── OkxPositionsChannelHandler.java # positions → onPositionUpdate()
│ ├── OkxOrdersChannelHandler.java # orders → onOrderUpdate()(替代orders-algo)
│ └── OkxAlgoOrdersChannelHandler.java # orders-algo(测试网不可用,保留备用)
│
└── okxpi/config/ # OKX API 底层HTTP/签名工具
二、策略生命周期
┌─────────────────────────────────────────────────────────────────┐
│ init() → startGrid() → WAITING_KLINE │
│ ↓ │
│ onKline(首根K线) → OPENING → 市价双开基底 │
│ ├── openLong(baseQuantity张) │
│ └── openShort(baseQuantity张) │
│ ↓ │
│ onPositionUpdate() → 双基底成交 → tryGenerateQueues() │
│ ├── generateShortQueue() 空仓队列(基准价向下步进) │
│ ├── generateLongQueue() 多仓队列(基准价向上步进) │
│ ├── updateGridElements() 构建OkxGridElement双向链表 │
│ ├── 多仓止损 -2~-11: algo(sell+long, slTriggerPx, sz=qty) │
│ └── 空仓止损 2~11: algo(buy+short, slTriggerPx, sz=qty) │
│ ↓ │
│ state = ACTIVE │
└─────────────────────────────────────────────────────────────────┘
状态机
| 状态 |
含义 |
进入条件 |
WAITING_KLINE |
等待首根K线 |
startGrid() |
OPENING |
基底开仓中 |
首根K线到达 |
ACTIVE |
策略运行中 |
网格初始化完成 |
STOPPED |
已停止(等待重启) |
盈亏达标/持仓归零 |
三、WS连接架构
┌──────────────────────────────────────────────────────┐
│ OkxWebSocketClientManager (@PostConstruct) │
│ │
│ ┌─ gridWsClientPublic ───────────────────────────┐ │
│ │ URL: /ws/v5/business (无需登录,直连订阅) │ │
│ │ ├── OkxKlineChannelHandler (candle1m) │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ┌─ gridWsClientPrivate ──────────────────────────┐ │
│ │ URL: /ws/v5/private (先登录再订阅) │ │
│ │ ├── OkxPositionsChannelHandler (positions) │ │
│ │ └── OkxOrdersChannelHandler (orders) │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
| 连接 |
URL |
频道 |
是否登录 |
回调 |
| 业务WS |
/ws/v5/business |
candle1m |
否 |
onKline(closePrice) |
| 私有WS |
/ws/v5/private |
positions |
是 |
onPositionUpdate(instId, posSide, pos, avgPx) |
| 私有WS |
/ws/v5/private |
orders |
是 |
onOrderUpdate(algoId, state, ordType) |
注意:orders-algo 频道在测试网不可用(60018),已替换为 orders 频道。algo触发后生成普通订单,fill数据中带 algoId 字段可匹配回原始条件单。
四、网格ID体系
价格方向: 低 ←────────────────── 基准价 ──────────────────→ 高
ID: -N ... -3 -2 -1 0 1 2 3 ... N
用途: 多仓止损区 基底 空仓止损区
(初始化: -2~-11) (初始化: 2~11)
链表: ... ← -3 ← -2 ← -1 ← 0 → 1 → 2 → 3 → ...
(通过 upId/downId + INDEX 实现 O(1) 遍历)
GridElement 字段
| 类别 |
字段 |
说明 |
| 标识 |
id, gridPrice, upId, downId |
编号、价格、双向链表指针 |
| 多仓订单 |
hasLongOrder, longOrderId, longTraderParam |
多仓条件单状态 |
| 空仓订单 |
hasShortOrder, shortOrderId, shortTraderParam |
空仓条件单状态 |
| 止盈 |
longTakeProfitOrderId, shortTakeProfitOrderId |
止盈algoId |
| 止损 |
longStopLossOrderId, shortStopLossOrderId |
止损algoId |
8个全局O(1)索引
INDEX → findById(int)
PRICE_INDEX → findByPrice(BigDecimal)
LONG_ORDER_ID_INDEX → findByLongOrderId(String)
SHORT_ORDER_ID_INDEX → findByShortOrderId(String)
LONG_TP_ORDER_ID_INDEX → findByLongTakeProfitOrderId(String)
SHORT_TP_ORDER_ID_INDEX→ findByShortTakeProfitOrderId(String)
LONG_SL_ORDER_ID_INDEX → findByLongStopLossOrderId(String)
SHORT_SL_ORDER_ID_INDEX→ findByShortStopLossOrderId(String)
五、事件驱动循环(ACTIVE状态)
5.1 K线回调 onKline(closePrice)
更新 lastKlinePrice → updateUnrealizedPnl()
→ STOPPED: 清条件单+平仓+startGrid()
→ WAITING_KLINE: 市价双开基底
→ ACTIVE: checkProfitAndReset()(每根K线检查盈亏达标)
5.2 仓位推送 onPositionUpdate(instId, posSide, posSize, avgPx)
基底首次成交 → tryGenerateQueues()
后续仓位变化 → 更新 positionSize/entryPrice
仓位归零 → handlePositionZeroAndReset()
5.3 订单成交 onOrderUpdate(algoId, state, ordType)
state == "filled" 时:
┌─ findByLongStopLossOrderId(algoId) → handleLongStopLossTriggered()
│ 清空止损ID → grid -(N-1) 挂 count×qty 张多单
│ → 若 N>2, 取消 grid -(N-2) 旧多单
│
├─ findByShortStopLossOrderId(algoId) → handleShortStopLossTriggered()
│ 清空止损ID → grid N-1 挂 count×qty 张空单
│ → 若 N>2, 取消 grid N-2 旧空单
│
├─ findByShortOrderId(algoId) → extendShortStopLoss(filledQty)
│ 从最远空仓止损向外扩展 stopLossCount 个网格止损
│
└─ findByLongOrderId(algoId) → extendLongStopLoss(filledQty)
从最远多仓止损向外扩展 stopLossCount 个网格止损
5.4 平仓推送 onPositionClose(side, pnl)
cumulativePnl += pnl
→ 总盈亏 ≤ -maxLoss → 钉钉告警(不停止,仅通知)
六、关键公式
6.1 网格步长
step = shortBaseEntryPrice × gridRate (对齐到 priceScale 精度)
6.2 止损触发 → 追单数量
priceDiff = |avgEntryPrice - newEntryGridPrice|.abs()
count = priceDiff / step (DOWN取整, 最小1)
entryQty = count × quantity
6.3 挂单成交 → 追挂止损
stopLossCount = filledQty / quantity
从最远止损ID向外扩展 stopLossCount 个网格,每格挂 1个 quantity张的止损单
6.4 未实现盈亏
多仓Pnl = longPositionSize × ctVal × (lastKlinePrice - longEntryPrice)
空仓Pnl = shortPositionSize × ctVal × (shortEntryPrice - lastKlinePrice)
unrealizedPnl = 多仓Pnl + 空仓Pnl
6.5 盈亏达标检查
upl + availEq > initialPrincipal + expectedProfit → 重置策略
七、REST API 映射
| OkxTradeExecutor方法 |
OKX API |
用途 |
openLong(size) / openShort(size) |
POST /api/v5/trade/order (market) |
市价基底开仓 |
marketClose(side, posSide, sz) |
POST /api/v5/trade/order (market, reduceOnly) |
市价平仓 |
placeConditionalEntryOrder(tp, side, posSide, sz) |
POST /api/v5/trade/order-algo (triggerPx) |
条件开仓单 |
placeTakeProfit(tp, side, posSide, sz) |
POST /api/v5/trade/order-algo (slTriggerPx) |
止损/止盈条件单 |
cancelAlgoOrder(algoId) |
POST /api/v5/trade/cancel-algos |
取消单个条件单 |
getBalance() |
GET /api/v5/account/balance |
查询余额 |
getPositions() |
GET /api/v5/account/positions |
查询持仓 |
setLeverage(lever) |
POST /api/v5/account/set-leverage |
设置杠杆 |
八、配置参数(OkxConfig.Builder默认值)
| 参数 |
默认值 |
说明 |
instId |
ETH-USDT-SWAP |
合约名称 |
leverage |
100 |
杠杆倍数 |
tdMode |
cross |
全仓保证金 |
gridRate |
0.0025 |
网格间距 0.25% |
expectedProfit |
2 |
预期收益 2 USDT |
maxLoss |
15 |
最大亏损 15 USDT |
quantity |
1 |
每格下单张数 |
baseQuantity |
10 |
基底开仓张数 |
priceScale |
2 |
价格精度 |
ctVal |
0.1 |
合约面值 |
gridQueueSize |
300 |
队列容量 |
marginRatioLimit |
0.2 |
保证金占比上限 20% |
九、线程模型
WS回调线程(串行) Executor线程(单线程池)
│ │
├─ onKline() ├─ openLong/openShort
├─ onPositionUpdate() ├─ marketClose
├─ onOrderUpdate() ──下单──→ ├─ placeConditionalEntryOrder
│ ├─ placeTakeProfit
│ └─ cancelAlgoOrder
│
└─ checkProfitAndReset() (REST同步查余额)
- WS回调在
[ctReadThread-XX] 中**串行**执行,避免并发问题
- REST API 提交到
okx-trade-worker 单线程池异步执行,避免阻塞WS线程
closeExistingPositions() 和 handlePositionZeroAndReset() 在WS线程中同步调用REST,需注意耗时
LostConnectionChecker 已关闭(setConnectionLostTimeout(0)),由应用层 ping/pong 心跳接管