2. 金融数据获取:使用yfinance和pandas-datareader获取股票行情数据
做量化策略,第一步就是搞数据。没有数据,再牛的因子也是空中楼阁。
我个人习惯用 yfinance 和 pandas-datareader 这两个库。它们免费、轻量,而且直接对接雅虎财经和FRED等数据源。今天我们就来聊聊怎么用它们拿到干净的股票行情数据。
2.1 为什么选这两个库?
市面上获取金融数据的工具不少,但yfinance和pandas-datareader是我用得最顺手的。原因有三:
- 免费:不需要API Key,不需要付费订阅。对于个人研究和策略原型开发,完全够用。
- 简单:几行代码就能拿到日线数据。你想想看,如果每次都要写几十行代码去解析CSV,那多浪费时间。
- 覆盖面广:全球主要交易所的股票、ETF、指数都能拿。我曾在项目中同时拉取A股、港股和美股的数据,一个库搞定。
核心观点:yfinance适合快速获取单只或多只股票的行情数据;pandas-datareader更适合获取宏观经济数据(如利率、汇率)或批量下载。两者结合,基本覆盖了量化策略90%的数据需求。
2.2 安装与导入
先装库。打开终端,执行:
pip install yfinance pandas-datareader pandas numpy
嗯,这里要注意。pandas-datareader依赖pandas和numpy,所以一起装上。我个人习惯用虚拟环境,避免污染全局包。
导入也很简单:
import yfinance as yf
import pandas_datareader.data as web
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
2.3 使用yfinance获取股票数据
yfinance的用法非常直观。我举个例子,获取贵州茅台(600519.SS)最近一年的数据:
# 定义股票代码
ticker = "600519.SS" # 上海交易所的股票代码后缀是.SS
# 获取数据
maotai = yf.download(ticker, start="2023-01-01", end="2024-01-01")
# 查看前5行
print(maotai.head())
输出结果长这样:
Open High Low Close Volume
Date
2023-01-03 1720.0000 1735.0000 1705.0000 1727.0000 3200000
2023-01-04 1728.0000 1742.0000 1718.0000 1735.0000 2800000
...
你看,Open、High、Low、Close、Volume,标准的OHLCV数据,直接拿来用。
小技巧:如果你想要调整后的价格(考虑分红、拆股),可以用 yf.download(..., auto_adjust=True)。我在做回测时一定会用调整后的数据,否则收益率计算会失真。
2.4 批量获取多只股票
做因子策略,通常需要同时处理几十甚至上百只股票。yfinance支持批量下载:
# 定义股票池
tickers = ["600519.SS", "000858.SZ", "601318.SS", "600036.SS"]
# 批量下载,使用多线程加速
data = yf.download(tickers, start="2023-01-01", end="2024-01-01", group_by="ticker")
# 查看贵州茅台的收盘价
print(data["600519.SS"]["Close"])
这里有个坑,我曾经踩过。如果某只股票在某一天停牌,yfinance会返回NaN。你需要用 fillna(method='ffill') 向前填充,或者直接删除缺失值。我个人建议用前向填充,因为停牌期间的信息其实已经反映在复牌后的价格里了。
2.5 使用pandas-datareader获取数据
pandas-datareader的强项是获取宏观经济数据。比如,获取美联储的联邦基金利率:
# 获取FRED数据
start = datetime(2020, 1, 1)
end = datetime(2024, 1, 1)
# 联邦基金利率
fed_funds = web.DataReader("FEDFUNDS", "fred", start, end)
print(fed_funds.head())
输出:
FEDFUNDS
DATE
2020-01-01 1.55
2020-02-01 1.58
...
为什么需要这个?因为动量因子和ESG因子都会受到宏观环境的影响。利率上升时,高估值股票(很多ESG好的公司)往往承压。把这些宏观数据纳入模型,能提升策略的稳健性。
注意:pandas-datareader的FRED数据源需要网络连接。如果你在内网环境,可以考虑提前下载好数据存成CSV。我曾经在客户现场演示时网络断了,场面一度很尴尬。
2.6 数据清洗与预处理
拿到原始数据后,别急着用。先做三件事:
- 检查缺失值:用
isnull().sum()看看哪些列有NaN。 - 处理异常值:比如某天涨幅超过20%,很可能是数据错误。用
quantile()或标准差法剔除。 - 对齐时间索引:多只股票的交易日期可能不一致。用
reindex()统一到同一个交易日历。
我写了一个小函数,专门做这件事:
def clean_stock_data(df):
"""清洗股票数据:填充缺失值,剔除异常值"""
# 前向填充缺失值
df = df.fillna(method='ffill')
# 剔除涨跌幅超过20%的异常日
returns = df['Close'].pct_change()
df = df[returns.abs() < 0.2]
return df
2.7 本章知识体系
下面这张图总结了本章的核心逻辑:
2.8 避坑指南
最后,分享几个我踩过的坑:
- 股票代码格式:A股代码要加后缀,上海是.SS,深圳是.SZ。港股是.HK,美股直接写代码就行。我曾经把腾讯的代码写成"0700",结果一直报错,后来才发现要写成"0700.HK"。
- 数据延迟:yfinance的数据通常有15-20分钟延迟。做实时交易不行,但做回测和策略研究完全OK。
- 网络超时:批量下载时,如果股票数量太多,可能会超时。建议分批次下载,每次不超过50只。或者用
yf.download(..., threads=True)开启多线程。
我的习惯:每次拿到新数据,我都会先画个K线图看一眼。如果发现某只股票的价格曲线有异常跳空,那八成是数据源的问题。别偷懒,多检查一遍。
好了,数据获取这块就聊到这儿。下一节我们开始处理ESG因子数据,那才是真正有意思的部分。