edit | blame | history | raw

Gate Api 模块 — 网格交易系统

文件列表

文件 类型 说明
GateWebSocketClientManager @Component Spring 启动入口,组装组件 + 生命周期
GateConfig 配置 Builder 模式:API 密钥、合约、策略参数、环境切换
GateKlineWebSocketClient WS 连接管理 连接/心跳/重连/消息路由
GateGridTradeService 策略核心 网格队列 + 条件开仓单 + 订单订阅止盈 + 反向条件单
GateTradeExecutor 异步执行器 独立线程池执行 REST 下单,成功/失败双回调

wsHandler 子包

文件 类型 说明
wsHandler/GateChannelHandler.java 接口 subscribe / unsubscribe / handleMessage / getChannelName
wsHandler/AbstractPrivateChannelHandler.java 抽象类 私有频道基类:HMAC-SHA512 签名 + 认证请求
wsHandler/handler/CandlestickChannelHandler.java 公开频道 K 线解析 → onKline()
wsHandler/handler/PositionsChannelHandler.java 私有频道 仓位推送 → onPositionUpdate(),日志输出全部 20 个推送字段
wsHandler/handler/PositionClosesChannelHandler.java 私有频道 平仓推送 → onPositionClose()
wsHandler/handler/OrdersChannelHandler.java 私有频道 订单推送 → onOrderUpdate()(订单订阅止盈匹配)

架构总览

┌──────────────────────────────────────────────────────────────────┐
│                    GateWebSocketClientManager                    │
│                      (Spring @Component)                         │
│                                                                  │
│  GateConfig.builder()  →  GateGridTradeService  +  WS Client     │
│     │                         │                      │           │
│     │ REST BasePath           │ GateTradeExecutor    │ WS URL    │
│     ▼                         ▼                      ▼           │
│  Gate API (REST)        独立线程池 (async)     Gate WebSocket     │
│                      onSuccess/onFailure双回调  ┌──────────────┐  │
│                                               │Candlestick H  │  │
│                                               │Positions H    │  │
│                                               │PosCloses H    │  │
│                                               │Orders H       │  │
│                                               └──────────────┘  │
└──────────────────────────────────────────────────────────────────┘

WebSocket 频道

频道 类型 作用
futures.candlesticks 公开 K 线推送 → onKline() 驱动网格触发
futures.positions 私有 仓位推送 → onPositionUpdate() 记录入场价/持仓量、处理反向单
futures.position_closes 私有 平仓推送 → onPositionClose() 累加已实现盈亏
futures.orders 私有 订单推送 → onOrderUpdate() 订阅条件单成交,匹配止盈价

数据流

WebSocket → GateKlineWebSocketClient.handleMessage → 路由 dispatch
│
├─ futures.pong → cancelPongTimeout
├─ subscribe / unsubscribe / error → log
│
├─ futures.candlesticks (公开)
│   └─ CandlestickChannelHandler
│       └─ gridTradeService.onKline(closePrice, timestamp)
│           ├─ 更新 unrealizedPnl(浮动盈亏)
│           ├─ state=WAITING_KLINE → 异步双开基底仓位
│           └─ state=ACTIVE → 方向区分: closePrice>longPriceQueue[0]→processLongGrid,
│               closePrice<shortPriceQueue[0]→processShortGrid, 其余跳过(一个K线只触发一个方向)
│
├─ futures.positions (私有, HMAC-SHA512)
│   └─ PositionsChannelHandler
│       ├─ 解析 mode → Position.ModeEnum(DUAL_LONG / DUAL_SHORT)
│       ├─ 日志输出全部 20 个推送字段
│       └─ gridTradeService.onPositionUpdate(contract, mode, size, entryPrice)
│           ├─ 有仓位: 基底首次成交记录入场价 → tryGenerateQueues
│           ├─ 仓位净减少(size < positionSize)→ 检查反向条件单条件 →
│           │   满足则开反向市价单(止盈价 = entryPrice ± step),orderId+止盈价存入 Map
│           ├─ 仓位不变或增加 → 仅更新 positionSize
│           └─ 无仓位(size=0): 清空活跃标记和持仓量
│
├─ futures.position_closes (私有, HMAC-SHA512)
│   └─ PositionClosesChannelHandler
│       └─ gridTradeService.onPositionClose(contract, side, pnl)
│           └─ cumulativePnl += pnl → checkStopConditions()
│
├─ futures.orders (私有, HMAC-SHA512) ← 订单订阅止盈核心
│   └─ OrdersChannelHandler
│       └─ gridTradeService.onOrderUpdate(orderId, status, finishAs)
│           └─ 条件单成交(status=finished, finish_as=filled)→
│               从 Map 中 remove(orderId) 取出止盈价 →
│               executor.placeTakeProfit(止盈价, ...)
│
└─ 所有下单操作
    └─ GateTradeExecutor (单线程 + 64队列 + CallerRunsPolicy)
        ├─ openLong/openShort → 市价 IOC 开仓(基底双开 + 反向开仓)
        ├─ placeConditionalEntryOrder → 条件开仓单(网格触发,服务端监控价格触发后市价 IOC)
        ├─ cancelConditionalOrder → 取消指定条件单
        ├─ placeTakeProfit → 止盈条件单(plan-close-*-position)
        ├─ cancelAllPriceTriggeredOrders → 清除所有条件单(停止时)
        ├─ placeGridLimitOrder → 【遗留】限价 GTC 单(当前策略未使用)
        └─ cancelOrder → 【遗留】取消限价单(当前策略未使用)

策略状态机

WAITING_KLINE ──onKline──→ OPENING ──双基底都成交──→ ACTIVE
     │                        │                         │
     │                    下单异常               ├─ 每根K线: 更新 unrealizedPnl
     │                        │                 ├─ cumPnl ≥ overallTp → STOPPED
     │                        │                 ├─ cumPnl ≤ -maxLoss → STOPPED
     │                        │                 ├─ 保证金超限 → 跳过挂单,队列照常更新
     │                        │                 ├─ 方向区分 → processShortGrid 或 processLongGrid(二者选一)
     │                        │                 ├─ 网格触发 → 匹配队列→本队补充→挂新条件单
     │                        │                 │   (止盈价随 orderId 存入 Map)
     │                        │                 ├─ 订单推送(futures.orders) → 订阅匹配止盈价 →
     │                        │                 │   挂止盈条件单(plan-close-*-position)
     │                        │                 └─ 仓位推送(净减少) → 反向市价单
     ▼                        ▼
   STOPPED  ←──────────────────┘
状态 含义
WAITING_KLINE 等待首次K线价格
OPENING 正在异步开基底多空仓位(已提交到GateTradeExecutor)
ACTIVE 网格队列激活,K线触发网格 → 挂条件单 → 订单订阅匹配止盈
STOPPED 停止(盈利达标 / 亏损超限)

策略核心:网格队列 + 条件单 + 订单订阅止盈

概述

策略采用"基底 + 价格网格队列"模式:先开一对基底多空仓位,然后以基底入场价为基准生成价格队列。每当 K 线穿破队列元素,匹配后更新队列并挂新条件单。条件单成交后通过 futures.orders 推送匹配止盈价并挂止盈条件单。

核心数据结构

字段 类型 说明
shortPriceQueue List<BigDecimal> 同步列表 空仓价格队列,降序(大→小),容量 gridQueueSize
longPriceQueue List<BigDecimal> 同步列表 多仓价格队列,升序(小→大),容量 gridQueueSize
currentLongOrderIds Map<String, BigDecimal> 同步 LinkedHashMap 多仓条件单映射:orderId → 止盈价,超 5 个时截断保留最新
currentShortOrderIds Map<String, BigDecimal> 同步 LinkedHashMap 空仓条件单映射:orderId → 止盈价,超 5 个时截断保留最新
shortBaseEntryPrice BigDecimal 基底空头入场价(仅记录,用于队列生成基准)
longBaseEntryPrice BigDecimal 基底多头入场价(仅记录,当前未被业务逻辑消费)
shortEntryPrice BigDecimal 当前空仓加权均价(推送实时更新)
longEntryPrice BigDecimal 当前多仓加权均价(推送实时更新)
shortPositionSize BigDecimal 当前空仓持仓量(绝对值)
longPositionSize BigDecimal 当前多仓持仓量
cumulativePnl BigDecimal 累计已实现盈亏(平仓推送驱动)
unrealizedPnl BigDecimal 未实现盈亏(每根K线更新)
initialPrincipal BigDecimal 初始本金(启动时账户总资产)

条件单设计

为什么用条件单而不是限价单?

限价单 price=X, tif=GTC 在价格位于挂单价有利侧时**会立即成交**。改用 Gate API FuturesPriceTriggeredOrder(价格触发条件单),由服务端监控价格,**只有当前价格抵达触发价时才执行**,避免提前成交。

条件单结构
FuturesPriceTriggeredOrder ├─ trigger: { price=触发价, rule=NUMBER_1(≥) 或 NUMBER_2(≤), expiration=0(永久有效) } ├─ initial: { contract, size(正=开多/负=开空), price="0", tif=IOC, reduce_only=false } └─ order_type: strategy_type=NUMBER_0(价格触发), price_type=NUMBER_0(最新价)

订单订阅止盈机制(核心)

这是当前版本的止盈流程,替代了旧版的止盈队列消费模式。

挂条件开仓单时 → onSuccess 回调 → currentXxxOrderIds.put(orderId, 止盈价)
                                               ↓
条件单成交 → futures.orders 推送 → onOrderUpdate(orderId, "finished", "filled")
                                               ↓
                  currentXxxOrderIds.remove(orderId) 取出止盈价
                                               ↓
                  executor.placeTakeProfit(止盈价, 方向参数)

止盈价计算:
- 网格触发processShortGrid/processLongGrid):newFirst ± step
- 初始条件单tryGenerateQueues):queue[0] ± step
- 反向市价单onPositionUpdate):entryPrice ± step

Map 截断机制

currentLongOrderIds / currentShortOrderIdsLinkedHashMap(保持插入顺序)。在 onPositionUpdate 中,当 Map size > 5 时,从头部(最旧条目)开始删除,只保留最新 5 条。防止条件单挂单失败导致 Map 无限膨胀。

基底开仓

K线到达 → 双开基底(市价开多 + 市价开空,IOC)
  → 成交回调: baseLongOpened=true, longActive=true
  → 成交回调: baseShortOpened=true, shortActive=true
  → 两者都成交 → generateShortQueue() + generateLongQueue()
    + 挂初始条件开仓单 → state=ACTIVE

初始条件开仓单

队列生成后立即用队列首元素挂两个价格触发条件单:

方向 触发价 rule size 止盈价(存入Map)
多仓条件单 longPriceQueue[0] NUMBER_1 (≥触发价) +quantity 触发价 + step
空仓条件单 shortPriceQueue[0] NUMBER_2 (≤触发价) -quantity 触发价 − step

网格队列生成

以空头基底入场价 shortBaseEntryPrice 为唯一基准,计算绝对步长 step = shortBaseEntryPrice × gridRate(保留1位小数)。

两个队列均从 shortBaseEntryPrice 出发,按 step 绝对偏移生成 N 个价格(N = gridQueueSize,默认 50):

队列 计算方式 排序
空仓队列 shortPriceQueue 首元素 = shortBaseEntryPrice − step,后续依次 −step 降序(大→小)
多仓队列 longPriceQueue 首元素 = shortBaseEntryPrice + step,后续依次 +step 升序(小→大)

K线触发网格

K线到达(ACTIVE状态):
│
├─ closePrice > longPriceQueue[0] → processLongGrid(价格涨超队列首)
│   ├─ 匹配: 收集所有 < closePrice 的多仓队列元素(升序,一旦遇≥即停止)
│   ├─ 多仓队列: 移除 matched,尾部补充(尾价 + step 循环递增)
│   ├─ 空仓队列: 不再更新(队列转移逻辑已移除)
│   ├─ 保证金检查:
│   │   ├─ 安全 → 挂新多仓条件单(触发价=新 long[0], 止盈=新 long[0]+step, orderId→Map)
│   │   │       → 空仓守卫: newShortFirst = newLongFirst − step×2,
│   │   │         若 > shortEntryPrice → 挂新空仓条件单(止盈=新short[0]−step, orderId→Map)
│   │   └─ 超限 → 跳过挂单(队列照常更新)
│   └─ 条件单成交后由 futures.orders 推送 → onOrderUpdate 匹配止盈价 → 挂止盈条件单
│
└─ closePrice < shortPriceQueue[0] → processShortGrid(价格跌穿队列首)
    ├─ 匹配: 收集所有 > closePrice 的空仓队列元素(降序,一旦遇≤即停止)
    ├─ 空仓队列: 移除 matched,尾部补充(尾价 − step 循环递减)
    ├─ 多仓队列: 不再更新(队列转移逻辑已移除)
    ├─ 保证金检查:
    │   ├─ 安全 → 挂新空仓条件单(触发价=新 short[0], 止盈=新short[0]−step, orderId→Map)
    │   │       → 多仓守卫: newLongFirst = newShortFirst + step×2,
    │   │         若 < longEntryPrice → 挂新多仓条件单(止盈=新long[0]+step, orderId→Map)
    │   └─ 超限 → 跳过挂单(队列照常更新)
    └─ 条件单成交后由 futures.orders 推送 → onOrderUpdate 匹配止盈价 → 挂止盈条件单

closePrice 既不 > longPriceQueue[0] 也不 < shortPriceQueue[0] → 跳过本次K线

关键变更:不再有"队列转移"(对方队列不再更新)、不再有"取消旧条件单"(旧单由 Map 自动覆盖或服务端自动取消)、不再有"止盈队列"(改为订单订阅匹配)。
反向条件单不再在 process*Grid 中处理,改为在 onPositionUpdate 仓位净减少时触发。

队列更新示意

ETH_USDT, gridRate=0.0035, shortBaseEntryPrice=2270, step=2270×0.0035≈7.9, gridQueueSize=4:

初始状态:
  空仓队列: [2262.1, 2254.2, 2246.3, 2238.4]  (降序)
  多仓队列: [2277.9, 2285.8, 2293.7, 2301.6]  (升序)
  初始条件单: 多仓触发价=2277.9(止盈=2285.8→currentLongOrderIds),
              空仓触发价=2262.1(止盈=2254.2→currentShortOrderIds)

价格涨到 2290 → processLongGrid 触发:
  匹配: [2277.9, 2285.8](都 < 2290)

  多仓队列: 移除[2277.9,2285.8] → [2293.7,2301.6]
    补充: 2301.6+7.9=2309.5 → 2309.5+7.9=2317.4
    → [2293.7, 2301.6, 2309.5, 2317.4]

  空仓队列: 不变(队列转移已移除)→ [2262.1, 2254.2, 2246.3, 2238.4]

  挂新多仓条件单(触发价=2293.7, 止盈=2301.6→currentLongOrderIds)
  空仓守卫: newShortFirst=2293.7−15.8=2277.9 > 2262.1? → 满足,
    挂新空仓条件单(触发价=2277.9, 止盈=2270.0→currentShortOrderIds)

条件单 2293.7 成交 → futures.orders 推送:
  → onOrderUpdate(orderId, "finished", "filled")
  → currentLongOrderIds.remove(orderId) = 2301.6
  → placeTakeProfit(2301.6, NUMBER_1, plan-close-long-position, -1)

仓位更新逻辑(onPositionUpdate)

仓位推送:
├─ size ≠ 0:
│   ├─ 基底首次成交 → 记录 baseEntryPrice → tryGenerateQueues
│   ├─ 仓位净减少(size.abs() < positionSize):
│   │   ├─ DUAL_LONG 仓位减少且有反向条件单(newShortFirst > shortEntryPrice
│   │   │   且 < longEntryPrice 且 shortPositionSize < 3):
│   │   │   → 市价开空(止盈=longEntryPrice−step→currentShortOrderIds)
│   │   │   → 累加 positionSize 标记(最多3次)
│   │   └─ DUAL_SHORT 仓位减少且有反向条件单(newLongFirst > shortEntryPrice
│   │       且 < longEntryPrice 且 longPositionSize < 3):
│   │       → 市价开多(止盈=shortEntryPrice+step→currentLongOrderIds)
│   │       → 累加 positionSize 标记(最多3次)
│   └─ 仓位不变或增加 → 仅更新 positionSize
└─ size = 0:
    └─ 清空活跃标记,重置持仓量为0

每次更新后: 截断 currentLongOrderIds / currentShortOrderIds 到最多 5 个元素

策略时序

阶段 1:启动与初始化

Spring @PostConstruct
  → GateConfig.builder()...build()
  → GateGridTradeService(config)
    → init():
      1. 查用户ID(用于私有频道订阅)
      2. 查账户 → 记录初始本金 initialPrincipal → 如需要切持仓模式
      3. 清除旧止盈止损条件单
      4. 查当前合约所有仓位 → 逐个市价平仓(reduce_only, IOC)
         - 单向持仓: size=相反数平仓
         - 双向持仓: size=0, close=false, autoSize=LONG/SHORT
      5. 设杠杆
  → GateKlineWebSocketClient(config.getWsUrl())
    → addChannelHandler x4 → init() → connect()
      → onOpen: handlers依次subscribe → sendPing
  → gridTradeService.startGrid() → state=WAITING_KLINE

阶段 2:基底开仓 → 生成网格队列 → 挂条件单

K线推送 → onKline(closePrice) → state=OPENING
  → executor.openLong(qty, onSuccess, onFailure)
    → 成交 → 仓位推送: DUAL_LONG, size>0, entryPrice=X
      → baseLongOpened=true, longBaseEntryPrice=X
      → tryGenerateQueues(): 双基底都成交? → 生成队列+挂初始条件单 → state=ACTIVE
  → executor.openShort(-qty, onSuccess, onFailure)
    → 成交 → 仓位推送: DUAL_SHORT, size<0, entryPrice=Y
      → baseShortOpened=true, shortBaseEntryPrice=Y
      → tryGenerateQueues(): 双基底都成交? → 生成队列+挂初始条件单 → state=ACTIVE

阶段 3:ACTIVE 状态 — K线驱动网格 + 订单订阅止盈

每根K线 → onKline → updateUnrealizedPnl → 方向区分(一个K线只触发一个方向)

processShortGrid / processLongGrid:
  → 匹配 → 本队补充 → 保证金检查
  → 挂新条件单(止盈价随 orderId 存入 Map)
  → 对方守卫:满足条件时挂对方方向新条件单

条件单被触发成交后 → futures.orders 推送:
  → onOrderUpdate(orderId, "finished", "filled")
  → Map.remove(orderId) 取出止盈价
  → executor.placeTakeProfit(止盈价, 方向参数, plan-close-*-position)

仓位净减少时 → onPositionUpdate:
  → 满足反向条件 → 开反向市价单(止盈价 = entryPrice ± step,orderId+止盈价存入 Map)

阶段 4:停止

平仓推送: pnl=+0.6 → cumulativePnl=0.6 ≥ overallTp(0.5) → state=STOPPED
平仓推送: pnl=-8.0 → cumulativePnl=-8.0 ≤ -maxLoss(7.5) → state=STOPPED

GateConfig

角色: 统一配置中心。Builder模式管理所有参数,提供 REST/WS URL 环境自动切换。

核心方法:
- getRestBasePath(): isProduction ? 生产网 : 测试网
- getWsUrl(): 同上

配置项(含默认值):

参数 默认值 说明
contract BTC_USDT 合约
leverage 10 倍数
marginMode cross 全仓
positionMode dual 双向持仓
gridRate 0.0035 网格间距比率 0.35%
step 运行时计算 网格绝对步长 = shortBaseEntryPrice × gridRate(保留1位小数)
overallTp 0.5 USDT 整体止盈
maxLoss 7.5 USDT 最大亏损
quantity 1 下单张数
gridQueueSize 50 网格价格队列容量
marginRatioLimit 0.2 保证金占初始本金比例上限(20%),超限跳过开仓
contractMultiplier 0.001 合约乘数(单张合约代表的基础资产数量)
unrealizedPnlPriceMode LAST_PRICE 未实现盈亏计价模式:LAST_PRICE / MARK_PRICE

GateTradeExecutor

角色: 独立线程池执行 REST API 下单。采用成功/失败双回调模式。

线程模型:
- ThreadPoolExecutor(1, 1, 60s, LinkedBlockingQueue(64), CallerRunsPolicy)
- 单线程保序 + 有界队列防堆积 + CallerRuns背压
- allowCoreThreadTimeOut: 60s 空闲后线程回收

回调设计:
- openLong/openShort/placeTakeProfit/placeConditionalEntryOrder 接受 onSuccessonFailure 两个 Consumer<String>
- REST 调用成功 → 执行 onSuccess(标记基底已开、记录 orderId+止盈价到 Map 等)
- REST 调用失败 → 执行 onFailure(当前版本多为 null,依赖 position 推送修正)

核心方法

方法 说明
openLong(qty, onSuccess, onFailure) 异步 IOC 市价开多,双回调
openShort(qty, onSuccess, onFailure) 异步 IOC 市价开空,双回调
placeConditionalEntryOrder(triggerPrice, rule, size, onSuccess, onFailure) 异步**条件开仓单**。triggerPrice=监控价,rule 决定触发方向,size 正=开多/负=开空。触发后 price="0" + IOC 市价成交
cancelConditionalOrder(orderId) 异步取消指定条件单(orderId 为 null 时跳过)
placeTakeProfit(trigger, rule, orderType, size) 异步**止盈条件单**(plan-close-*-position)。triggerPrice=止盈触发价,触发后 price="0" + IOC 市价平仓,reduce_only=true
cancelAllPriceTriggeredOrders() 清除所有条件单
shutdown() 等待10秒,超时强制关闭

遗留方法(当前策略未使用)

方法 说明
placeGridLimitOrder(price, size, onSuccess, onFailure) 旧版限价 GTC 单,已被条件单替代
cancelOrder(orderId) 旧版取消限价单,已被 cancelConditionalOrder 替代

条件单 order_type 说明

order_type 用途 size 语义
plan-close-long-position 部分/全部平多仓 size<0 表示平多仓张数
plan-close-short-position 部分/全部平空仓 size>0 表示平空仓张数

为何不用 close-*-positionclose-long-positionclose-short-position 仅支持全部平仓(size=0),且双仓模式还需设置 auto_size。网格策略需要指定张数部分平仓,因此必须使用 plan-close-*-position

条件单构建 (buildTriggeredOrder)

FuturesPriceTriggeredOrder 结构:

组件 字段 开仓单值 止盈单值
trigger price 触发价 止盈价
trigger rule NUMBER_1(≥) 或 NUMBER_2(≤) 同左
trigger strategy_type 0 (价格触发) 0 (价格触发)
trigger price_type 0 (最新价) 0 (最新价)
trigger expiration 0 (永久有效) 0 (永久有效)
initial contract 合约名 合约名
initial size +qty(开多)/-qty(开空) -qty(平多)/+qty(平空)
initial price "0" (市价) "0" (市价)
initial tif IOC IOC
initial reduce_only false true
order_type 不设置 plan-close-long-position 或 plan-close-short-position

GateGridTradeService

角色: 策略核心,管理网格队列状态和执行下单。

状态: StrategyState enum: WAITING_KLINE / OPENING / ACTIVE / STOPPED

关键常量:
java // 止盈条件单 order_type:仓位计划止盈止损,支持指定张数部分平仓 private static final String ORDER_TYPE_CLOSE_LONG = "plan-close-long-position"; private static final String ORDER_TYPE_CLOSE_SHORT = "plan-close-short-position";

回调方法:

方法 触发源 逻辑
onKline(closePrice, timestamp) CandlestickChannelHandler 更新 lastKlinePrice → 计算 unrealizedPnl → WAITING_KLINE 时触发基底双开 → ACTIVE 时方向区分,一个K线只触发一个方向
onPositionUpdate(contract, mode, size, entryPrice) PositionsChannelHandler 基底首次成交记录入场价 + tryGenerateQueues → 仓位净减少时触反向市价单 → Map截断(>5)
onPositionClose(contract, side, pnl) PositionClosesChannelHandler 累加已实现盈亏 → 检查停止条件
onOrderUpdate(orderId, status, finishAs) OrdersChannelHandler 条件单成交(finished+filled) → Map.remove 取止盈价 → placeTakeProfit

processShortGrid / processLongGrid 核心逻辑:

步骤 processShortGrid(空仓触发) processLongGrid(多仓触发)
匹配 收集 shortPriceQueue 中 > currentPrice 的元素 收集 longPriceQueue 中 < currentPrice 的元素
本队补充 尾价 − step 循环递减 × matched.size() 次 尾价 + step 循环递增 × matched.size() 次
对方队列 不再更新(队列转移已移除) 不再更新(队列转移已移除)
保证金检查 marginRatio ≥ 20% 则跳过挂单 同左
挂新条件单 空仓条件单(止盈价=新short[0]−step→currentShortOrderIds) 多仓条件单(止盈价=新long[0]+step→currentLongOrderIds)
对方守卫 newLongFirst + step×2 < longEntryPrice → 挂多仓条件单 newShortFirst − step×2 > shortEntryPrice → 挂空仓条件单

未实现盈亏计算 (updateUnrealizedPnl()):

正向合约公式(含合约乘数):

方向 公式
多仓 持仓量 × contractMultiplier × (计价价格 − 开仓均价)
空仓 持仓量(绝对值)× contractMultiplier × (开仓均价 − 计价价格)

计价价格由 unrealizedPnlPriceMode 决定:
- LAST_PRICE:使用最新成交价(lastKlinePrice,每根 K 线更新)
- MARK_PRICE:使用标记价格(通过 setMarkPrice() 外部注入,如未注入则回退到最新成交价)

保证金安全阀 (isMarginSafe()):
- 实时查询 positionInitialMargin / initialPrincipal
- 比例 ≥ marginRatioLimit(默认20%)→ 跳过开仓,队列照常更新
- REST 查询失败 → 默认放行(避免因查询异常阻塞策略)

REST API 调用:

操作 API 方法 说明
获取用户ID GET /account/detail AccountApi.getAccountDetail()
切持仓模式 POST /futures/usdt/set_position_mode FuturesApi.setPositionMode()
查仓位 GET /futures/usdt/positions FuturesApi.listPositions() 遍历所有仓位,按合约过滤
市价平仓 POST /futures/usdt/orders FuturesApi.createFuturesOrder() reduce_only, IOC
设杠杆 POST /futures/usdt/dual_comp/positions/{contract}/leverage FuturesApi.updateDualModePositionLeverageCall() 双向模式专用
查账户 GET /futures/usdt/accounts FuturesApi.listFuturesAccounts() 获取初始本金
查市价 GET /futures/usdt/order_book FuturesApi.listFuturesOrderBook() 获取合约实时市价(用于市价单 price="0" 的参照)

GateChannelHandler 接口体系

GateChannelHandler (接口)
  ├── CandlestickChannelHandler          (公开频道)
  └── AbstractPrivateChannelHandler      (私有频道基类: HMAC-SHA512)
        ├── PositionsChannelHandler
        ├── PositionClosesChannelHandler
        └── OrdersChannelHandler
  • subscribe: 发送订阅请求。私有 Handler 自动附加 auth 字段
  • unsubscribe: 发送取消订阅请求(私有频道也带签名认证)
  • handleMessage: 解析推送数据并回调 GateGridTradeService,返回 true 表示已处理
  • 消息路由: update/all 事件 → 遍历 channelHandlers → handler 内部二次匹配 channel 名 → 匹配成功回调并停止遍历

PositionsChannelHandler 完整推送字段(20个)

字段 类型 描述
contract String 合约名称
mode String 持仓模式:dual_long / dual_short
size String/Integer 合约张数(正=多头,负=空头)
entry_price Float 开仓均价
cross_leverage_limit Float 全仓模式下的杠杆倍数上限
history_pnl Float 已平仓的仓位总盈亏
history_point Float 已平仓的点卡总盈亏
last_close_pnl Float 最近一次平仓的盈亏
leverage Integer 杠杆倍数(0=全仓,正数=逐仓)
leverage_max Integer 当前风险限额下允许的最大杠杆倍数
liq_price Float 爆仓价格
maintenance_rate Float 当前风险限额下维持保证金比例
margin Float 保证金
realised_pnl Float 已实现盈亏
realised_point Float 点卡已实现盈亏
risk_limit Integer 风险限额
time Integer 更新 unix 时间戳(秒)
time_ms Integer 更新 unix 时间戳(毫秒)
user String 用户 ID
update_id Integer 消息序列号,每次推送 order 后自增1

以上 20 个字段在 PositionsChannelHandler.handleMessage() 中通过 SLF4J 日志全部输出。
回调给 GateGridTradeService.onPositionUpdate() 的仅有 mode、size、entryPrice 三个核心字段。