第三章:数据获取——用 yfinance 搞定美股历史数据
做量化交易,数据就是你的石油。没有数据,再牛的模型也是空中楼阁。
这一章,我们来聊聊怎么用 Python 把美股数据拉下来。我用的工具是 yfinance,一个非常轻量的库。说实话,我刚开始做美股回测时,也试过各种付费数据源,后来发现 yfinance 对于大多数策略研究来说,完全够用。
3.1 安装与基本用法
先装库,一行命令搞定:
pip install yfinance
然后拉取单只股票的历史数据。比如苹果:
import yfinance as yf
# 下载 AAPL 从 2020-01-01 到 2023-12-31 的日线数据
aapl = yf.download("AAPL", start="2020-01-01", end="2023-12-31")
print(aapl.head())
返回的是一个 DataFrame,包含 Open、High、Low、Close、Volume、Adj Close 六列。嗯,这里要注意:Adj Close 是复权收盘价,做回测时一定要用它,否则分红拆股会把你坑惨。
💡 我的习惯: 每次下载数据后,先检查一下数据长度。有时候节假日或者停牌会导致数据缺失,提前发现比跑完策略才发现要好得多。
3.2 多股票数据获取
单只股票太孤单,我们通常要处理一篮子股票。比如标普500的成份股。
yfinance 支持一次性传入多个 ticker:
tickers = ["AAPL", "MSFT", "GOOGL", "AMZN", "META"]
data = yf.download(tickers, start="2020-01-01", end="2023-12-31")
print(data.head())
返回的数据结构是 MultiIndex DataFrame。列名变成了两层:第一层是价格类型(Open、Close...),第二层是股票代码。
我个人习惯把它整理成更易用的格式。比如只取收盘价:
close_prices = data["Close"]
print(close_prices.head())
这样每列就是一只股票的收盘价序列,做相关性分析、协整检验都方便多了。
⚠️ 我曾经踩过的坑: 有些 ticker 可能已经退市或者改名了。比如 FB 改成了 META。如果你用旧 ticker 去拉数据,yfinance 会返回空 DataFrame。建议先验证一下 ticker 的有效性。
3.3 数据频率选择:日线 vs 分钟线
yfinance 默认返回日线数据。但如果你想做高频策略,就需要分钟线。
获取分钟线数据,加一个 interval 参数:
# 获取 1 分钟线数据
aapl_1min = yf.download("AAPL", period="5d", interval="1m")
print(aapl_1min.head())
# 获取 5 分钟线数据
aapl_5min = yf.download("AAPL", period="1mo", interval="5m")
print(aapl_5min.head())
这里有个限制:yfinance 的分钟线数据最多只能拉取过去 60 天。而且数据量很大,1 分钟线一天就有 390 根 K 线(美股交易时间 6.5 小时)。
| 频率 | interval 参数 | 最大可获取周期 | 适用场景 |
|---|---|---|---|
| 日线 | "1d" | 无限制 | 中长线策略、基本面分析 |
| 周线 | "1wk" | 无限制 | 趋势跟踪、宏观分析 |
| 月线 | "1mo" | 无限制 | 长期投资、资产配置 |
| 1 分钟 | "1m" | 过去 7 天 | 日内高频交易 |
| 5 分钟 | "5m" | 过去 60 天 | 日内短线策略 |
| 15 分钟 | "15m" | 过去 60 天 | 日内波段交易 |
| 30 分钟 | "30m" | 过去 60 天 | 日内趋势跟踪 |
| 60 分钟 | "60m" | 过去 730 天 | 短线至中线策略 |
🔑 核心建议: 做策略研究时,先用日线验证逻辑。日线跑通了,再考虑用分钟线做精细化回测。别一上来就搞分钟线,数据量大、噪音多,容易过度拟合。
3.4 数据清洗与预处理
数据拉下来之后,别急着用。先做三件事:
- 检查缺失值:用
isnull().sum()看看哪些列有空值 - 处理停牌日:美股没有涨跌停,但有停牌。停牌日的价格会保持不变,或者直接缺失
- 对齐时间戳:不同股票的交易时间可能略有差异,尤其是盘前盘后数据
我常用的清洗代码:
# 检查缺失值
print(close_prices.isnull().sum())
# 向前填充(停牌日沿用前一日价格)
close_prices_filled = close_prices.fillna(method='ffill')
# 删除仍然缺失的行(比如某只股票刚上市)
close_prices_clean = close_prices_filled.dropna(axis=1, how='any')
💡 避坑指南: 我曾经用未清洗的数据跑回测,结果某只股票因为停牌三天,策略在那三天里疯狂交易,回测收益高得离谱。后来发现是数据问题。所以,数据清洗是回测的第一道防线。
3.5 本章知识体系
下面这张图,帮你理清数据获取的完整流程:
从安装到清洗,每一步都有坑。但只要你按照这个流程走,数据质量就有保障。
3.6 实战小贴士
- 缓存数据:每次跑策略都重新下载数据太慢了。我习惯把数据存成 CSV 或 Parquet 格式,下次直接读取。
- 注意时区:yfinance 返回的时间是 UTC 时间。美股交易时间对应的是美东时间。做分钟线策略时,一定要转换时区。
- 限流问题:yfinance 没有官方 API Key,但频繁请求会被限流。我一般每次请求间隔 0.5 秒,批量下载时分批处理。
📌 总结一下: yfinance 是入门美股数据获取的最佳选择。它免费、轻量、支持多股票和多频率。但要注意数据清洗和频率限制。下一章,我们会用这些数据来构建第一个预测模型。