2. 金融数据获取:使用yfinance和pandas-datareader获取股票行情数据

做量化策略,第一步就是搞数据。没有数据,再牛的因子也是空中楼阁。

我个人习惯用 yfinancepandas-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 数据清洗与预处理

拿到原始数据后,别急着用。先做三件事:

  1. 检查缺失值:用 isnull().sum() 看看哪些列有NaN。
  2. 处理异常值:比如某天涨幅超过20%,很可能是数据错误。用 quantile() 或标准差法剔除。
  3. 对齐时间索引:多只股票的交易日期可能不一致。用 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 本章知识体系

下面这张图总结了本章的核心逻辑:

金融数据获取流程 数据源 雅虎财经 / FRED 获取工具 yfinance / pandas-datareader 数据格式 OHLCV / 时间序列 缺失值处理 异常值剔除 时间对齐 干净可用的行情数据

2.8 避坑指南

最后,分享几个我踩过的坑:

  • 股票代码格式:A股代码要加后缀,上海是.SS,深圳是.SZ。港股是.HK,美股直接写代码就行。我曾经把腾讯的代码写成"0700",结果一直报错,后来才发现要写成"0700.HK"。
  • 数据延迟:yfinance的数据通常有15-20分钟延迟。做实时交易不行,但做回测和策略研究完全OK。
  • 网络超时:批量下载时,如果股票数量太多,可能会超时。建议分批次下载,每次不超过50只。或者用 yf.download(..., threads=True) 开启多线程。

我的习惯:每次拿到新数据,我都会先画个K线图看一眼。如果发现某只股票的价格曲线有异常跳空,那八成是数据源的问题。别偷懒,多检查一遍。

好了,数据获取这块就聊到这儿。下一节我们开始处理ESG因子数据,那才是真正有意思的部分。

专注资料整理