3. Tick数据与数据清洗:高频交易的基石
做外汇高频交易,第一关就是Tick数据。
很多人觉得策略是核心,其实数据才是命根子。我见过太多人,策略逻辑写得天花乱坠,结果数据源就有问题,回测跑出来漂亮得不行,实盘一上去直接崩盘。说白了,数据不干净,后面全是白费功夫。
3.1 Tick数据获取渠道
Tick数据,就是每笔成交的原始记录。它不像1分钟K线那样是聚合后的,而是市场最微观的切片。
我个人习惯把数据源分成三类:
- 免费渠道:Dukascopy、TrueFX、HistData。适合入门学习和初步验证。
- 商业渠道:TickData、QuantQuote。数据质量高,但价格不菲。我早期做回测时吃过免费数据的亏,后来果断换了商业数据。
- 券商直连:通过MT5/ICMarkets等平台直接拉取。这是最实时的方式,但需要自己写MQL5脚本。
我的建议:刚开始别花冤枉钱。先用Dukascopy的免费数据跑通流程,等策略稳定了再考虑升级。
3.2 数据清洗与对齐
拿到原始Tick数据后,你会发现——嗯,乱得很。
缺失值、重复记录、时间戳错乱……这些我都遇到过。有一次回测一个高频策略,结果发现某天的数据里居然有连续3秒的空白,导致策略在那段时间里完全失效。
清洗的核心步骤:
- 去重:同一毫秒内的重复Tick只保留一条。
- 补全:对于缺失的时间段,用前一个有效值填充。
- 对齐:不同数据源的时间基准可能不同,需要统一到UTC时间。
# 一个简单的Tick数据清洗示例
import pandas as pd
def clean_tick_data(df):
# 去重
df = df.drop_duplicates(subset=['timestamp', 'bid', 'ask'])
# 排序
df = df.sort_values('timestamp')
# 填充缺失值(前向填充)
df = df.fillna(method='ffill')
return df
3.3 时间戳处理
时间戳是Tick数据的灵魂。但不同平台的时间格式五花八门。
MT5用的是Unix毫秒时间戳,Dukascopy用的是带时区的字符串,有些券商甚至用Excel序列号。你想想看,如果不对齐,回测结果能准吗?
我一般这样处理:
- 统一转为UTC时间戳(毫秒级)
- 去除夏令时影响
- 检查时间连续性(比如周末是否有数据)
注意:外汇市场是24小时交易的,但周末休市。有些数据源会在休市期间产生垃圾数据,一定要过滤掉。
3.4 异常值检测与处理
异常值,说白了就是那些离谱的价格。比如EUR/USD突然跳到1.2000,下一秒又回到1.1000。这种数据如果不处理,策略会以为市场发生了剧烈波动,做出错误决策。
我曾经在回测一个剥头皮策略时,发现某天的收益异常高。一查,原来是数据里混入了一个异常Tick,导致策略在那一瞬间开了不该开的仓位。
常用的检测方法:
| 方法 | 原理 | 适用场景 |
|---|---|---|
| Z-score | 基于标准差 | 价格波动平稳时 |
| IQR | 基于四分位距 | 数据分布偏态时 |
| 滚动窗口 | 基于局部均值 | 高频数据 |
# 使用滚动窗口检测异常值
def detect_outliers(df, window=100, threshold=3):
df['ma'] = df['bid'].rolling(window).mean()
df['std'] = df['bid'].rolling(window).std()
df['z_score'] = (df['bid'] - df['ma']) / df['std']
outliers = df[abs(df['z_score']) > threshold]
return outliers
核心原则:宁可漏掉一个异常,也不要误杀一个正常数据。高频交易中,每一个Tick都可能影响最终收益。
3.5 知识体系总览
下面这张图,是我自己总结的Tick数据处理流程。你可以把它当作一个检查清单:
嗯,这张图基本概括了本章的核心。你按照这个流程走一遍,数据质量至少能提升80%。剩下的20%,就得靠经验了。
避坑指南:我曾经在数据清洗时漏掉了周末的垃圾数据,结果回测出来的策略在周一开盘时表现异常。后来我加了一个周末过滤逻辑,问题才解决。
好了,Tick数据这块就聊到这儿。数据干净了,后面的策略设计和回测才有意义。记住一句话:垃圾进,垃圾出。