3. 行情数据接口:Ticker、OrderBook、Kline、交易对信息、市场统计

行情数据,说白了就是市场的「心跳」。

做量化交易,你首先要能感知到市场在干什么。价格跳了、深度变了、成交量放大了——这些信号都藏在行情接口里。我个人习惯把行情数据分成五类:Ticker、OrderBook、Kline、交易对信息、市场统计。每一类都有它独特的用途,咱们一个一个说。

核心观点:行情接口是交易系统的「眼睛」。数据质量直接决定策略的成败。接口设计上,延迟、吞吐量、数据一致性是三个绕不开的坎。

3.1 Ticker —— 市场的「快照」

Ticker 是最基础的行情数据。它告诉你当前这个交易对「大概什么价」。我见过不少新手一上来就盯着 Ticker 做高频策略,结果亏得很惨。为什么?因为 Ticker 本质是一个汇总数据,它不保证你能按那个价格成交。

一个标准的 Ticker 接口,通常包含这些字段:

字段 类型 说明
symbol string 交易对,如 BTCUSDT
lastPrice decimal 最新成交价
bidPrice decimal 买一价
askPrice decimal 卖一价
volume decimal 24小时成交量
highPrice decimal 24小时最高价
lowPrice decimal 24小时最低价
openPrice decimal 24小时开盘价
timestamp long 数据生成时间戳(毫秒)

避坑指南:我曾经在对接某二线交易所时,发现它的 Ticker 里的 bidPrice 和 askPrice 居然不是实时更新的,而是每隔 5 秒才刷新一次。结果我的做市策略按这个价格挂单,全被吃掉了。所以,拿到 Ticker 数据后,一定要先压测一下它的更新频率。

接口设计上,我建议 Ticker 走 WebSocket 推送,而不是 REST 轮询。因为 Ticker 变化太快,轮询的延迟和带宽消耗都不划算。推送频率可以控制在 100ms 到 500ms 一次,具体看你的策略需求。

3.2 OrderBook —— 市场的「深度」

OrderBook 就是买卖挂单的集合。它告诉你「现在有多少人想买,多少钱想买;有多少人想卖,多少钱想卖」。做市商、套利策略、大单拆单,都离不开 OrderBook。

一个典型的 OrderBook 数据结构长这样:

{
  "symbol": "BTCUSDT",
  "bids": [
    ["45000.00", "1.5"],
    ["44999.50", "2.3"],
    ...
  ],
  "asks": [
    ["45001.00", "0.8"],
    ["45001.50", "1.2"],
    ...
  ],
  "lastUpdateId": 123456789,
  "timestamp": 1690000000000
}

这里要注意,bids 和 asks 都是二维数组,每个元素是 [价格, 数量]。价格精度和数量精度由交易所决定,你设计接口时一定要预留足够的精度位。

重要提醒:OrderBook 的增量更新(incremental update)比全量推送更高效。但增量更新有个坑——数据顺序不能乱。我曾经在项目中遇到 WebSocket 断线重连后,增量数据丢失了几条,结果整个 OrderBook 就「歪」了。解决方案是:每次重连后,先拉一次全量快照,再切回增量模式。

我个人习惯把 OrderBook 的深度控制在 20 层以内。太深了,数据量大,延迟高;太浅了,信息不够用。20 层是一个比较平衡的点。

3.3 Kline / 蜡烛图 —— 市场的「历史」

Kline 是技术分析的基石。没有 K 线,你连均线都画不出来。Kline 接口的核心参数就两个:时间周期和数量。

常见的周期有:1m、5m、15m、30m、1h、4h、1d、1w、1M。每个周期对应一个时间窗口。

一个 Kline 数据项通常包含:

字段 类型 说明
openTime long 这根 K 线的开盘时间
open decimal 开盘价
high decimal 最高价
low decimal 最低价
close decimal 收盘价
volume decimal 成交量
closeTime long 这根 K 线的收盘时间
quoteVolume decimal 成交额(以报价币种计)
trades int 成交笔数

个人经验:Kline 的 REST 接口通常支持查询最近 500 到 1000 根 K 线。但如果你要回测,需要拉取几个月甚至几年的数据。这时候我建议你写一个数据抓取脚本,分批拉取,然后存到本地数据库里。别每次都从交易所拉,一来慢,二来容易被限流。

另外,Kline 的 WebSocket 推送是「增量」的——每根 K 线在未关闭前会不断更新。比如 1 分钟 K 线,在这一分钟内,价格每变动一次,交易所就会推送一次更新。你收到后,直接覆盖本地缓存里那根 K 线的 close、high、low 就行。

3.4 交易对信息 —— 市场的「规则」

交易对信息,说白了就是告诉你「这个币怎么交易」。每个交易所、每个交易对都有自己的规则。比如最小下单数量、价格精度、数量精度、最小名义价值等等。

这些信息如果不搞清楚,你的订单很可能被交易所拒绝。我见过有人因为精度问题,下单时价格多了一位小数,结果订单直接被拒,错过了行情。

一个标准的交易对信息接口返回:

{
  "symbol": "BTCUSDT",
  "status": "TRADING",
  "baseAsset": "BTC",
  "quoteAsset": "USDT",
  "baseAssetPrecision": 8,
  "quoteAssetPrecision": 8,
  "filters": [
    {
      "filterType": "PRICE_FILTER",
      "minPrice": "0.01",
      "maxPrice": "1000000.00",
      "tickSize": "0.01"
    },
    {
      "filterType": "LOT_SIZE",
      "minQty": "0.000001",
      "maxQty": "100000",
      "stepSize": "0.000001"
    }
  ]
}

这里的关键字段是 filters。它定义了价格和数量的约束。你的下单模块在构造订单前,一定要先校验这些规则。我习惯在系统启动时,一次性拉取所有交易对信息,缓存到本地,然后每小时刷新一次。

注意:交易对信息不是一成不变的。交易所可能会调整精度、最小数量,甚至下架某个交易对。所以,你的系统要能处理「交易对状态变更」的事件。比如,当 status 变成 "BREAK" 或 "PAUSE" 时,你的策略应该自动停止对该交易对的操作。

3.5 市场统计 —— 市场的「体温」

市场统计接口,通常返回一些汇总指标。比如 24 小时涨跌幅、成交量、成交额、最高最低价、换手率等。这些数据对宏观判断很有用。

举个例子,你想知道今天市场整体情绪怎么样。看 BTC 的 24 小时涨跌幅和成交量变化,基本就能判断个大概。

市场统计接口的设计比较简单,通常就是 Ticker 的扩展版。但要注意,不同交易所对「24 小时」的定义可能不同。有的是滚动 24 小时,有的是从 0 点开始算。你设计系统时,最好统一用滚动 24 小时,这样数据更实时。

3.6 知识体系总览

下面这张图,是我对行情数据接口的整体理解。你可以把它当作一个「地图」,方便你快速定位每个接口的位置和作用。

行情数据接口知识体系 行情数据接口 Ticker OrderBook Kline / 蜡烛图 交易对信息 市场统计 核心字段 lastPrice, bidPrice askPrice, volume high, low, open 核心字段 bids, asks lastUpdateId 增量更新 vs 全量 核心字段 open, high, low, close volume, quoteVolume 时间周期 核心字段 status, filters PRICE_FILTER LOT_SIZE 核心字段 24h 涨跌幅 成交量、成交额 换手率 设计原则 低延迟 · 高吞吐 · 数据一致性 · 容错重连

这张图里,五个子节点分别对应我们刚才讲的五类数据。每个子节点下面,我都列出了它的核心字段和关键设计点。你可以把它当作一个「速查表」,在设计接口时对照着看。

3.7 接口设计的一些通用原则

最后,我想聊聊行情接口设计的几个通用原则。这些是我在多个项目中踩坑踩出来的经验。

  • WebSocket 优先,REST 辅助。 行情数据变化快,WebSocket 推送是主流。REST 接口只用来做初始数据拉取和兜底。
  • 数据压缩。 行情数据量很大,尤其是 OrderBook 和 Kline。建议用 gzip 或 snappy 压缩,能省 60% 以上的带宽。
  • 时间戳统一。 所有接口的时间戳都用毫秒级 Unix 时间戳,避免时区问题。我见过有人用字符串格式的时间,结果解析起来各种坑。
  • 限流与熔断。 行情接口也要限流。别以为行情数据是只读的就不需要限流。我曾经在测试环境里忘了加限流,结果把交易所的行情服务器打挂了……嗯,那天的复盘会开得特别长。

一个小技巧:如果你同时对接多个交易所,建议把行情数据统一成自己的内部格式。这样上层策略不用关心底层是哪个交易所,切换起来也方便。我习惯在数据接入层做一个「适配器」,把不同交易所的数据转成统一结构。

好了,行情数据接口就讲到这里。记住,数据是交易系统的血液。接口设计得好,策略跑起来就顺畅;设计得不好,后面全是坑。


专注资料整理