edit | blame | history | raw

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 心跳接管