3. 数据模型设计:时间戳、价格、成交量与标识符
做量化系统,数据模型是地基。地基没打好,后面全是坑。
我个人习惯,在设计 Tick 数据模型时,会先问自己三个问题:这数据怎么来?怎么存?怎么查?想清楚这三点,字段定义自然就出来了。
3.1 时间戳:精度与对齐
时间戳是 Tick 数据的灵魂。没有准确的时间,价格和成交量就是一堆废数字。
精度选择
交易所给的时间戳,通常是微秒级甚至纳秒级。但你真的需要存纳秒吗?
我在项目中遇到过,某家期货交易所的行情源,时间戳精度是微秒,但实际跳动频率只有毫秒级。存纳秒纯属浪费空间。我的建议是:
- 股票/期货:微秒级足够。大部分交易所的撮合频率到不了纳秒。
- 数字货币:毫秒级即可。币圈的 Tick 数据,时间戳太细反而容易产生大量重复数据。
- 回测场景:统一对齐到毫秒。不然回测时时间轴对不上,你会疯掉。
时区处理
嗯,这里要注意。所有时间戳,一律存 UTC。展示时再转本地时间。
我曾经接手过一个老系统,时间戳混着存,有的用北京时间,有的用纽约时间。查个跨市场套利的数据,光时区转换就写了 50 行代码。后来我全部统一成 UTC,世界清净了。
// 推荐的时间戳字段设计
{
"exchange_ts": 1700000000123456, // 交易所原始时间戳(微秒)
"local_ts": 1700000000123456, // 网关接收时间戳(微秒)
"seq_no": 1024 // 交易所序列号(用于去重)
}
3.2 价格:整数化存储
价格字段,很多人直接用浮点数。这是个大坑。
浮点数在计算机里是近似值。0.1 + 0.2 不等于 0.3,这个梗大家都知道。Tick 数据里,价格差一个最小变动价位,可能就是几千块的盈亏。
我的做法:
- 整数化:价格乘以最小变动价位的倒数,存成整数。比如 A 股最小变动 0.01 元,那 12.34 元就存成 1234。
- 精度字段:额外存一个 price_scale,记录小数位数。这样恢复时不会出错。
- 避免 double:能用 int64 就别用 double。存储空间省一半,查询速度还快。
3.3 成交量:注意溢出
成交量看起来简单,就是个数字嘛。但你真的见过一天成交几百万手的品种吗?
我记得有一次,某商品期货因为交割日临近,成交量突然放大。我们的系统用的是 int32 存成交量,结果直接溢出了。回测出来的策略曲线,看着像心电图——全是负值。
避坑指南:
- 用 int64:别省那 4 个字节。int64 能存到 9.22e18,够你用到退休。
- 区分累计量与单笔量:Tick 数据里,有的交易所给的是累计成交量,有的是单笔成交量。字段名要写清楚。
- 成交量单位:是手还是股?是张还是枚?存的时候统一成最小单位,展示时再换算。
// 成交量字段设计示例
{
"volume": 12345678, // 累计成交量(股/手/张)
"turnover": 9876543210, // 成交金额(分)
"volume_type": "cumulative" // cumulative 或 single
}
3.4 标识符:唯一且稳定
标识符是数据的身份证。设计不好,数据关联起来就是一场噩梦。
我推荐的结构:
| 字段 | 示例 | 说明 |
|---|---|---|
| symbol | 600519.SH | 交易所代码 + 市场后缀 |
| exchange | SSE | 交易所枚举值 |
| instrument_id | 600519 | 纯代码,不带后缀 |
| data_source | ctp | 数据来源标识 |
为什么这么设计?
你想想看,同一个股票,在不同数据源里可能叫法不一样。有的叫 600519.SH,有的叫 SH600519。如果你只存一个 symbol,后面做数据合并时,光做映射表就能累死你。
3.5 完整数据模型
把上面这些串起来,一个典型的 Tick 数据行大概长这样:
{
"symbol": "600519.SH",
"exchange": "SSE",
"exchange_ts": 1700000000123456,
"local_ts": 1700000000123456,
"seq_no": 1024,
"price": 123400, // 整数化,实际价格 12.34 元
"price_scale": 4, // 4位小数
"volume": 12345678,
"turnover": 9876543210,
"bid_price_1": 123300,
"bid_volume_1": 1000,
"ask_price_1": 123500,
"ask_volume_1": 2000,
// ... 更多买卖盘口
}
这个模型,我在三个不同的量化系统里用过。从单机回测到分布式实盘,都没出过问题。说白了,数据模型这东西,越简单越可靠。
3.6 核心逻辑图
下面这张图,是我做数据模型设计时的思考框架。每次设计新系统,我都会对着这张图过一遍:
这张图里,四个维度是并列关系。时间戳保证时序,价格保证精度,成交量保证完整性,标识符保证可关联。缺一个,数据模型就不完整。