第二章 数据获取与清洗:数据源选择、数据清洗、数据对齐与重采样
各位同学,欢迎来到第二章。上一章我们聊了量化交易的整体框架,今天咱们来点实在的——数据。
做量化交易,说白了就是跟数据打交道。你策略再牛,模型再花哨,数据是脏的、乱的、缺的,那结果就是垃圾进垃圾出。我见过太多人,策略回测曲线漂亮得不行,一上实盘就崩,查到最后,往往是数据对齐出了问题。
嗯,今天我们就来把这几个硬骨头啃下来。
2.1 数据源选择:你的原材料从哪来?
数据源的选择,决定了你后续工作的基础。我个人习惯,会根据不同场景选不同的数据源。
2.1.1 Yahoo Finance
Yahoo Finance 是很多入门者的首选。免费、覆盖广、接口简单。用 yfinance 库几行代码就能拉数据。
import yfinance as yf
# 获取苹果股票数据
aapl = yf.download('AAPL', start='2020-01-01', end='2023-12-31')
print(aapl.head())
但我要提醒你:Yahoo Finance 的数据质量,说实话,不太稳定。我在项目中遇到过几次,某天的数据突然跳空,或者复权数据算错了。你想想看,这种错误要是没发现,回测结果能信吗?
2.1.2 Binance
做加密货币交易,Binance 几乎是标配。它的 API 文档清晰,数据粒度细到毫秒级。
from binance.client import Client
client = Client(api_key='你的API_KEY', api_secret='你的API_SECRET')
klines = client.get_klines(symbol='BTCUSDT', interval=Client.KLINE_INTERVAL_1HOUR)
Binance 的数据有个好处——它是交易所直接出来的,没有中间商赚差价。但问题也有:不同交易所之间,同一时刻的价格可能差好几个点。你如果做套利策略,这个价差就是利润来源,但也可能是坑。
2.1.3 其他数据源
| 数据源 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Quandl | 宏观经济数据、期货 | 数据质量高,清洗过 | 收费,贵 |
| Alpha Vantage | 美股、外汇 | 免费额度够用 | API 限制多,速度慢 |
| 本地数据库 | 生产环境 | 完全可控,速度快 | 维护成本高 |
我的建议是:开发阶段用免费源,生产阶段一定要上付费或自建数据源。别问为什么,问就是吃过亏。
2.2 数据清洗:把脏数据洗干净
数据拿到手,第一件事不是分析,是洗。就像买菜回来,你得先摘菜、洗菜,才能下锅。
2.2.1 去重
重复数据是常见问题。原因很多:API 重试、数据源推送重复、自己代码写错了。去重很简单,但容易被忽略。
# 去除完全重复的行
df = df.drop_duplicates()
# 按时间戳去重,保留最后一条
df = df[~df.index.duplicated(keep='last')]
你可能会问:「重复就重复呗,影响不大吧?」 我告诉你,影响大了去了。重复数据会导致你的统计指标失真,比如计算日均成交量,重复一天的数据,结果就偏了。
2.2.2 缺失值处理
缺失值,是量化数据里最头疼的问题之一。非交易日、数据推送失败、停牌,都会产生缺失值。
处理方式有三种:
- 直接删除:简单粗暴,但会丢失信息。适合缺失比例很小的情况。
- 向前填充:用上一个有效值填充。适合价格数据,因为价格在短时间内不会突变。
- 插值:用前后值做线性插值。适合成交量、持仓量等。
# 向前填充
df['close'] = df['close'].fillna(method='ffill')
# 线性插值
df['volume'] = df['volume'].interpolate(method='linear')
2.2.3 异常值检测
异常值,比如某天价格突然涨了 1000%,或者成交量突然是前一天的 100 倍。这种数据,要么是数据源错了,要么是发生了极端事件。
我常用的方法是 Z-score 法:
from scipy import stats
z_scores = stats.zscore(df['close'])
abs_z_scores = np.abs(z_scores)
filtered_entries = (abs_z_scores < 3)
df_clean = df[filtered_entries]
但注意:Z-score 假设数据是正态分布,金融数据往往不是。所以我会结合业务逻辑来判断。比如,某只股票一天涨 20%,在 A 股是涨停,正常;但在美股,一天涨 20% 就很少见,需要人工确认。
2.3 数据对齐与重采样:让不同频率的数据「对上话」
这是很多新手容易翻车的地方。你拿日线数据做策略,但你的信号是小时级别的,怎么办?或者你有多个股票,它们的交易时间不完全重合,怎么处理?
2.3.1 时间对齐
不同股票的交易时间不同。比如 A 股和港股,开盘时间差半小时。如果你同时交易这两个市场,必须把数据对齐到同一个时间轴上。
# 对齐到北京时间 15:00(收盘价)
aligned = pd.concat([df_a_share['close'], df_hk_share['close']], axis=1, join='inner')
aligned.columns = ['A股', '港股']
join='inner' 表示只保留两个数据都有的时间点。这样能避免因为时间错位导致的「未来函数」问题。
2.3.2 重采样
重采样,就是把高频数据转成低频,或者反过来。最常见的是把分钟线转成日线。
# 1分钟数据转成日线
daily = df_minute.resample('1D').agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
})
这里要注意:重采样时,OHLC 的聚合方式不同。开盘价取第一个,收盘价取最后一个,最高价取最大值,最低价取最小值,成交量求和。这个逻辑看起来简单,但很多人会搞混。
反过来,把日线转成分钟线,就需要插值了。但说实话,我不建议这么做。因为低频转高频,本质上是在「无中生有」,会引入大量噪声。
2.3.3 多频率数据融合
实际项目中,你经常需要把不同频率的数据融合在一起。比如,用日线数据计算均线,用分钟线数据生成交易信号。
# 计算日线均线
daily_ma = daily['close'].rolling(20).mean()
# 将日线均线对齐到分钟线
minute_ma = daily_ma.reindex(df_minute.index, method='ffill')
这里用 reindex 配合 method='ffill',把日线的均线值填充到每一分钟。这样,你的分钟级策略就能用到日线级别的信息了。
2.4 实战:一个完整的数据处理流程
说了这么多,我们来走一遍完整的流程。假设我要做 BTC/USDT 的 1 小时级别策略。
import pandas as pd
import numpy as np
from binance.client import Client
# 1. 获取数据
client = Client()
klines = client.get_klines(symbol='BTCUSDT', interval=Client.KLINE_INTERVAL_1HOUR)
df = pd.DataFrame(klines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume',
'close_time', 'quote_asset_volume', 'number_of_trades',
'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('timestamp', inplace=True)
# 2. 数据清洗
# 去重
df = df[~df.index.duplicated(keep='last')]
# 缺失值处理
df['close'] = df['close'].fillna(method='ffill')
# 异常值处理(Z-score)
z_scores = np.abs((df['close'] - df['close'].mean()) / df['close'].std())
df = df[z_scores < 3]
# 3. 数据对齐(如果有多个币种,这里做对齐)
# 4. 重采样(如果需要,比如转成4小时线)
df_4h = df.resample('4H').agg({
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
})
print(f"原始数据量: {len(klines)}")
print(f"清洗后数据量: {len(df)}")
print(f"重采样后数据量: {len(df_4h)}")
你看,整个流程下来,数据从原始状态变成了可用的状态。这个过程,我建议你每次拿到新数据都走一遍,形成肌肉记忆。
2.5 本章小结
数据获取与清洗,听起来枯燥,但它是量化交易的基石。我见过太多人,策略写得花里胡哨,结果数据没处理好,回测结果全是假的。
记住三个要点:
- 数据源选对:开发用免费,生产用付费
- 数据洗得干净:去重、补缺、去异常,一步不能少
- 对齐和重采样要谨慎:别让时间错位毁了你的策略
下一章,我们会聊技术指标的计算。但如果你这章的数据没处理好,后面再好的指标也是白搭。所以,好好练,别偷懒。
嗯,今天就到这里。有问题欢迎在课程群里讨论。