一、高频交易数据基础
做高频交易这些年,我最大的感触就是:数据是命根子。你策略再牛,模型再花哨,数据不行,一切都是白扯。今天咱们就来聊聊高频交易里最基础、也最容易被忽视的东西——数据本身。
1.1 Tick数据:最原始的脉搏
Tick数据,说白了就是交易所每一笔成交的原始记录。它不像K线那样被加工过,是赤裸裸的真相。
一个标准的Tick数据长什么样?我直接贴个结构出来:
{
"symbol": "BTC-USDT", // 交易对
"timestamp": 1704067200123, // 毫秒级时间戳
"price": 42850.12, // 成交价
"volume": 0.0234, // 成交量
"side": "buy", // 主动成交方向
"trade_id": "123456789" // 唯一成交ID
}
嗯,这里要注意一个坑:时间戳。不同交易所给的时间戳精度不一样,有的到毫秒,有的到微秒,甚至纳秒。我早期做回测时,就因为没注意这个精度差异,导致策略信号和实际成交差了十几毫秒——这在高频里可是致命的。
1.2 Order Book数据:市场的深度与博弈
如果说Tick是成交的结果,那Order Book就是成交前的博弈过程。它告诉你:现在有多少人在买,多少人在卖,价格挂在哪里。
一个典型的Order Book快照结构:
{
"symbol": "BTC-USDT",
"timestamp": 1704067200123,
"bids": [ // 买单,按价格从高到低
[42850.00, 1.2345], // [价格, 数量]
[42849.50, 5.6789],
...
],
"asks": [ // 卖单,按价格从低到高
[42851.00, 0.9876],
[42851.50, 3.4567],
...
]
}
我个人习惯把Order Book数据分成两类:
- 快照型:每隔固定时间(比如100ms)拍一张全量快照。优点是完整,缺点是数据量大,而且两次快照之间的变化你完全不知道。
- 增量型:只记录每次挂单、撤单、成交的变化。优点是数据量小,能还原完整过程,缺点是你得自己维护一个本地的Order Book状态。
你想想看,如果你做的是高频做市策略,增量型数据几乎是必须的。因为你需要知道每一笔挂单的来龙去脉,才能判断市场情绪的变化。
1.3 交易数据:成交的最终记录
交易数据,其实就是你账户里实际发生的成交记录。它和Tick数据很像,但多了一些账户相关的字段:
{
"account": "sub_account_01",
"symbol": "BTC-USDT",
"trade_time": 1704067200123,
"side": "sell",
"price": 42850.12,
"volume": 0.5,
"fee": 0.0005, // 手续费
"fee_asset": "BNB", // 手续费币种
"order_id": "ord_98765" // 关联的订单ID
}
这里有个细节:手续费。别小看这零点几的手续费,高频交易一天几千上万笔,手续费累积起来可能比你的利润还高。我见过不少团队,策略回测时跑得飞起,实盘一跑就亏,查来查去发现是手续费没算对。
1.4 数据频率:Tick级、秒级、分钟级
数据频率的选择,直接决定了你的策略能做什么、不能做什么。我画了一张图,帮你理清思路:
说白了,你选什么频率,取决于你的策略周期。做高频做市的,必须用Tick级数据,毫秒级的延迟都不能忍。做日内趋势的,秒级数据就够用了。做中长线的,分钟级甚至小时级都行。
1.5 数据质量与清洗:被低估的关键
这一节,我想重点聊聊。因为数据质量这个问题,我吃过太多亏了。
你以为交易所给的数据就是干净的?太天真了。我遇到过的情况包括但不限于:
- 重复数据:同一笔成交被推送了两次
- 缺失数据:某几秒的数据突然断了
- 乱序数据:后发生的成交先到了
- 异常值:价格突然跳到一个离谱的数字
- 精度问题:小数点后位数不一致
为什么会这样?交易所的架构再牛逼,也架不住网络抖动、系统故障、数据同步延迟。你想想看,如果数据本身就有问题,你的策略回测结果能信吗?
我分享一个我自己的清洗流程:
def clean_tick_data(df):
# 1. 去重:按trade_id去重
df = df.drop_duplicates(subset=['trade_id'])
# 2. 排序:按时间戳排序
df = df.sort_values('timestamp')
# 3. 检查缺失:看时间戳是否连续
time_gaps = df['timestamp'].diff().dt.total_seconds()
if (time_gaps > 1).any():
print(f"发现时间缺口,最大缺口:{time_gaps.max()}秒")
# 4. 异常值过滤:价格超出3个标准差
mean_price = df['price'].mean()
std_price = df['price'].std()
df = df[(df['price'] > mean_price - 3*std_price) &
(df['price'] < mean_price + 3*std_price)]
# 5. 精度统一:保留4位小数
df['price'] = df['price'].round(4)
df['volume'] = df['volume'].round(4)
return df
1.6 本章小结
这一章我们聊了高频交易数据的几个核心概念:
- Tick数据:最原始的成交记录,精度要求极高
- Order Book数据:市场的深度信息,分快照型和增量型
- 交易数据:账户维度的成交记录,手续费不能忽略
- 数据频率:Tick级、秒级、分钟级,各有适用场景
- 数据清洗:去重、排序、异常值处理,一步都不能少
嗯,这些都是最基础的东西。但基础往往是最重要的。就像盖房子,地基没打好,上面盖得再漂亮也没用。下一章,我们会深入聊聊如何高效地存储这些数据——毕竟,数据量大了以后,怎么存、怎么查,都是大问题。