3、Tick数据结构解析:时间戳、价格、成交量、买卖盘口等字段详解
做量化交易的朋友都知道,Tick数据是市场的“原子”记录。每一笔成交、每一次报价变动,都被忠实地记录下来。但说实话,我刚入行那会儿,面对一堆密密麻麻的字段,也是一头雾水。
今天我就带你把这层窗户纸捅破。咱们把Tick数据里最核心的几个字段——时间戳、价格、成交量、买卖盘口——一个一个拆开来看。搞懂了这些,后面的清洗和特征工程才能玩得转。
3.1 时间戳:市场的“心跳”
时间戳是Tick数据的灵魂。没有它,所有数据都是死的。
我见过不少新手,拿到数据第一件事就是看价格,结果分析半天发现时间对不上。嗯,这里要特别注意:时间戳的精度和时区,是第一个坑。
核心要点:
- 精度:国内A股通常是毫秒级(3位小数),期货可能是微秒级(6位小数)。高频策略对精度要求极高,差1毫秒可能就是天壤之别。
- 时区:国内数据一般是北京时间(UTC+8)。但有些数据商可能给你的是UTC时间,不转换直接分析,结果全乱套。
- 格式:常见的有Unix时间戳(整数或浮点数)和字符串格式(如"2024-01-15 09:30:00.123")。
我的习惯:拿到数据后,第一件事就是把时间戳统一转换成datetime64[ns]类型,并强制设定时区。这样后续所有操作都基于同一个时间基准,不会出幺蛾子。
举个例子,看看Python里怎么处理:
import pandas as pd
# 假设原始时间戳是Unix毫秒
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
# 强制设定为北京时间
df['timestamp'] = df['timestamp'].dt.tz_localize('UTC').dt.tz_convert('Asia/Shanghai')
# 去掉时区信息,方便计算
df['timestamp'] = df['timestamp'].dt.tz_localize(None)
为什么会这样?因为很多计算库(比如numpy)对带时区的datetime支持不好,容易报错。去掉时区后,我们心里清楚它代表的是北京时间就行。
3.2 价格:成交的“锚点”
价格字段看起来简单,但里面门道不少。我遇到过最离谱的一次,是某个数据源把“昨收价”和“最新价”搞混了,导致我回测的夏普比率直接翻倍……还好发现得早。
常见的价格字段有这几个:
| 字段名 | 含义 | 注意事项 |
|---|---|---|
| LastPrice | 最新成交价 | 这是最常用的价格,但要注意它可能不是连续的 |
| BidPrice1 | 买一价 | 最高买入申报价 |
| AskPrice1 | 卖一价 | 最低卖出申报价 |
| OpenPrice | 开盘价 | 集合竞价后的第一笔成交价 |
| HighPrice / LowPrice | 当日最高/最低价 | 注意是当日累计,不是当前Tick的 |
避坑指南:我曾经在清洗期货数据时,发现某天的最高价比涨停板还高。查了半天,原来是数据商把下一交易日的预埋单价格也录进来了。所以,价格字段一定要做上下限校验,比如对照涨跌停板、昨收价等。
价格清洗的一个常用技巧是“价格跳变检测”。如果相邻两个Tick的价格差超过了某个阈值(比如1%),那很可能是数据错误,需要标记出来人工复核。
# 价格跳变检测
threshold = 0.01 # 1%的阈值
price_diff = df['LastPrice'].pct_change()
suspicious = price_diff.abs() > threshold
print(f"发现 {suspicious.sum()} 个可疑价格跳变点")
3.3 成交量:市场的“呼吸”
成交量反映了市场的活跃程度。但Tick级别的成交量,和日线级别的成交量,理解起来不太一样。
在Tick数据里,成交量通常有两种:
- Volume:当前Tick的成交量(即这一笔成交了多少手/股)
- TotalVolume:从开盘到现在的累计成交量
我个人习惯用Volume,因为它能直接反映每一笔交易的“力度”。比如,同样是价格上涨1个tick,如果成交量是100手和1000手,背后的含义完全不同。
一个实用的特征:计算“每笔成交量”的均值。如果某笔成交量突然放大到均值的5倍以上,往往意味着有大资金在行动。这个特征在捕捉“主力异动”时非常有用。
成交量清洗时要注意:
- 成交量不能为负数(废话,但真的有人遇到过)
- 累计成交量应该是单调递增的,如果出现下降,说明数据有重复或乱序
- 对于期货,要注意合约换月时成交量的“断崖”变化
3.4 买卖盘口:市场的“情绪”
买卖盘口,也就是我们常说的“十档行情”或“五档行情”。它展示了当前市场上所有未成交的买单和卖单。
常见的字段包括:
- BidPrice1~BidPrice5:买一到买五的价格
- BidVolume1~BidVolume5:买一到买五的挂单量
- AskPrice1~AskPrice5:卖一到卖五的价格
- AskVolume1~AskVolume5:卖一到卖五的挂单量
盘口数据里藏着很多信息。比如:
- 买卖价差(Spread) = AskPrice1 - BidPrice1。价差越小,流动性越好。
- 订单簿不平衡(Order Imbalance) = (BidVolume1 - AskVolume1) / (BidVolume1 + AskVolume1)。正值表示买方力量强,负值表示卖方力量强。
- 深度(Depth):某个价格区间内的总挂单量。深度越厚,价格越不容易被操纵。
我常用的一个技巧:计算“盘口压力比”。比如,把买一到买五的总量除以卖一到卖五的总量。如果这个比值突然从1.2掉到0.8,说明卖方压力骤增,可能是下跌的前兆。当然,这只是一个信号,不能单独作为交易依据。
盘口数据清洗的难点在于:
- 价格和数量必须匹配(比如BidPrice1不能比BidPrice2还低)
- 价格必须在合理范围内(不能出现负价格或离谱的高价)
- 挂单量不能为负数(虽然很少见,但数据损坏时可能发生)
3.5 知识体系总览
说了这么多,咱们用一张图来总结一下Tick数据的核心字段和它们之间的关系:
这张图把咱们刚才讲的内容串起来了。你看,Tick数据虽然字段多,但核心就这四大块。每一块都有它的清洗要点和特征提取方法。
说实话,搞懂这些字段只是第一步。真正有价值的是,你能从这些原始字段里“挖”出什么特征来。比如,把时间戳和价格结合起来,可以计算“每笔价格变化的速度”;把成交量和盘口结合起来,可以判断“大单是主动买入还是卖出”。
嗯,这些内容咱们后面的章节会详细展开。今天先把地基打牢,后面的高楼才能盖得稳。
总结一下今天的核心收获:
- 时间戳要注意精度和时区,统一转换成标准格式
- 价格要做上下限校验,防止异常值污染数据
- 成交量要区分单笔和累计,检查单调性
- 盘口数据可以衍生出价差、不平衡度、深度等特征
下次你拿到一份Tick数据,别急着跑策略。先花10分钟,把上面这些字段检查一遍。相信我,这10分钟能帮你省下后面10小时的debug时间。