2. 行情数据基础
在实时行情平台中,ClickHouse 承担的是“高吞吐写入 + 低延迟查询”的核心角色,但数据能否发挥价值,首先取决于我们对行情数据本身的理解。不同市场的行情数据在字段结构、更新频率、交易时段和采集协议上差异很大,如果前期没有统一建模,后续写入 ClickHouse 时就会出现字段混乱、时间戳语义不一致、重复数据难以去重等问题。本节从数据格式、字段含义、数据源和采集方式四个角度,建立行情数据的整体认知。
一、核心原理:行情数据的三种基本形态
无论股票、期货还是加密货币,行情数据本质上都可以归入三类形态:快照(Snapshot)、逐笔(Tick/Trade)和盘口(OrderBook/Depth)。快照是某一时刻的截面数据,包含最新价、成交量、买卖五档等;逐笔是每一笔成交的明细,强调时序和唯一性;盘口则是订单簿的深度信息,反映买卖双方的挂单分布。三者的更新频率、数据量和查询模式完全不同,在 ClickHouse 中通常需要分表存储。
二、字段含义:跨市场通用字段对照
虽然各市场字段命名不同,但核心语义高度一致。下面这张对照表是后续建表和采集映射的基础。
| 通用字段 | 股票 | 期货 | 加密货币 | 含义 |
|---|---|---|---|---|
| symbol | 600519.SH | rb2405 | BTC-USDT | 标的唯一标识 |
| timestamp | 交易所时间 | 交易所时间 | 毫秒时间戳 | 行情发生时间 |
| last_price | 最新价 | 最新价 | 最新成交价 | 最近成交价格 |
| volume | 成交量(股) | 成交量(手) | 成交量(币) | 累计或单笔成交量 |
| bid/ask | 买一/卖一 | 买一/卖一 | bid/ask | 最优买卖报价 |
| bid_size/ask_size | 买一量/卖一量 | 买一量/卖一量 | 数量 | 最优档挂单量 |
| open/high/low | 开高低 | 开高低 | 24h 高低 | 区间价格统计 |
需要特别注意的是时间戳语义。股票和期货通常使用交易所本地时间,加密货币多为 UTC 毫秒时间戳。采集时必须统一转换为 UTC 或带时区的时间,否则在 ClickHouse 中做跨市场关联查询时会出现时间错位。
三、数据源与采集方式
不同市场的数据源和采集协议差异明显,选择时需权衡实时性、成本和稳定性。
- 股票:常见数据源包括交易所 Level-1/Level-2 行情、券商柜台接口、第三方数据商(如 Wind、聚宽)。采集方式多为 TCP 私有协议或 HTTP 轮询,Level-2 通常需要授权。
- 期货:国内多通过 CTP 接口采集,支持 Tick 和盘口;外盘常用 FIX 协议或交易所 API。CTP 采集需要处理前置连接、心跳和断线重连。
- 加密货币:以 WebSocket 为主,如 Binance、OKX 提供 trade、depth、kline 等流。优点是免费、实时性高,缺点是消息量大、需要处理限频和断线。
采集层通常采用“采集进程 + 消息队列 + 写入进程”的结构。采集进程负责连接数据源并解析为统一结构,消息队列(如 Kafka)做缓冲,写入进程批量写入 ClickHouse。下面是一个典型的采集配置片段:
source: binance
streams:
- trade
- depth20
symbols:
- BTC-USDT
- ETH-USDT
output:
kafka_topic: market_raw
batch_size: 1000
flush_interval_ms: 200
四、案例与场景:从原始消息到统一结构
以 Binance 的 trade 流为例,原始消息字段为 e、E、s、p、q、T 等,含义分别是事件类型、事件时间、交易对、价格、数量和成交时间。采集时需要将其映射为通用字段:symbol=s,last_price=p,volume=q,timestamp=T。映射完成后写入 Kafka,再由写入进程批量写入 ClickHouse 的 tick 表。
对于股票快照,采集到的往往是包含买卖五档的数组,需要展开为 bid1~bid5、ask1~ask5 等字段。若直接以数组形式存入 ClickHouse,查询时需使用 arrayJoin,性能不如展开列。因此建议在采集层完成展开,保持表结构扁平。
五、误区与复盘
掌握行情数据的格式、字段、数据源和采集方式后,下一步就可以进入 ClickHouse 的表结构设计。只有数据源头清晰、字段统一,后续的实时写入和低延迟查询才有可靠基础。