1. 金融数据获取与清洗
任务说明
本案例从 Yahoo Finance 拉取 3 只股票的日线行情(AAPL、MSFT、SPY),合并为统一时间索引的收盘价面板,并完成缺失值前向填充与异常值(单日涨跌幅超过 20%)的识别与修正。最终输出一个干净的 DataFrame,可直接用于后续特征工程。
环境依赖
pip install yfinance pandas numpy
实现代码
import numpy as np
import pandas as pd
import yfinance as yf
TICKERS = ["AAPL", "MSFT", "SPY"]
START, END = "2022-01-01", "2023-12-31"
# 1. 获取多只股票日线数据
raw = yf.download(TICKERS, start=START, end=END, auto_adjust=True, progress=False)
close = raw["Close"].copy() # 只保留收盘价,列为 ticker
close.index = pd.to_datetime(close.index)
close = close.sort_index()
# 2. 统一时间索引:以交易日并集为基准,缺失值前向填充
full_idx = pd.date_range(close.index.min(), close.index.max(), freq="B")
close = close.reindex(full_idx).ffill()
# 3. 异常值处理:单日涨跌幅绝对值 > 20% 视为异常,用前一日值替换
returns = close.pct_change()
mask = returns.abs() > 0.20
close_clean = close.mask(mask).ffill()
# 4. 汇总报告
report = pd.DataFrame({
"缺失值(原始)": raw["Close"].isna().sum(),
"异常值(修正)": mask.sum(),
"最终缺失": close_clean.isna().sum(),
})
print(report)
print(close_clean.tail())
# 5. 保存
close_clean.to_csv("clean_close.csv")
关键点说明
yf.download一次请求多只股票,返回 MultiIndex 列,取"Close"层得到收盘价面板。- 用
reindex到工作日频率再ffill,保证三只股票共享同一时间索引,避免后续对齐错位。 - 异常值判定基于
pct_change,阈值 20% 可按标的波动性调整;mask+ffill用前值替换异常点。
运行与验证
- 执行脚本,观察
report:三只股票原始缺失值应接近 0(Yahoo 日线通常完整),异常值数量为个位数级别。 close_clean.tail()应显示 2023-12-29 附近三只股票的收盘价,且无 NaN。- 检查
clean_close.csv已生成,行数等于 2022-01-03 至 2023-12-29 的工作日数量(约 520 行)。 - 通过条件:
close_clean.isna().sum().sum() == 0且close_clean.pct_change().abs().max().max() <= 0.20。
常见问题
- 若
yf.download返回空,检查网络或 Yahoo 接口限流,可加threads=False重试。 - 若某只股票停牌导致长段缺失,
ffill会延续旧价,建议对停牌超过 5 日的区间单独标记而非直接填充。