4. 量化筛选模型搭建:基于Python的初筛指标计算与数据获取(yfinance库)
好,咱们进入正题。这一章,说白了就是教你如何用Python把纳斯达克龙头股的数据“拽”下来,然后算出一堆有用的指标。我个人习惯把这一步叫做“数据基建”——地基打不好,后面什么模型都是空中楼阁。
你可能会问:“为什么要自己写代码?同花顺、东方财富不都能看数据吗?”嗯,这里有个关键区别:那些软件给你的是“结果”,而我们想要的是“过程”。你自己写代码,才能完全控制数据怎么清洗、指标怎么计算、参数怎么调整。说白了,主动权在自己手里。
4.1 为什么选yfinance?
市面上能拿美股数据的库不少,比如pandas-datareader、alpha vantage、quandl。但我为什么推荐yfinance?原因有三:
- 免费且稳定: 不需要API Key,直接pip install就能用。我在项目中遇到过好几次alpha vantage突然改政策、限制调用次数的情况,yfinance至今没出过这种幺蛾子。
- 数据覆盖面广: 历史日线数据、分红、拆股、财务报表,甚至期权链都能拿。对于初筛来说,日线数据完全够用。
- 社区活跃: 遇到问题,Stack Overflow上一搜一大把解决方案。这一点对新手特别友好。
4.2 环境准备与安装
先别急着写代码,把环境搭好。我习惯用Anaconda管理Python环境,但如果你用原生的pip也没问题。
# 安装必要的库
pip install yfinance pandas numpy matplotlib
# 如果你还没装,建议也装上
pip install ta-lib # 技术指标库,后面会用到
嗯,这里要注意:ta-lib在Windows上安装可能有点麻烦,需要下载whl文件。如果你搞不定,可以用纯Python的替代方案,比如用pandas自己算移动平均线,也不复杂。
4.3 数据获取:从单只股票到批量处理
先拿苹果(AAPL)试试手。我个人习惯先跑通单只股票,再扩展到整个股票池。
import yfinance as yf
import pandas as pd
# 获取苹果的历史数据
aapl = yf.download('AAPL', start='2020-01-01', end='2024-12-31')
print(aapl.head())
跑完这段代码,你会看到一个DataFrame,里面有Open、High、Low、Close、Volume、Adj Close这几列。这就是我们最原始的“原材料”。
但问题来了——我们要筛选的是纳斯达克龙头股,少说也有几十只。难道要一只一只手动下载?当然不是。批量处理才是正解。
# 定义股票列表(这里只是示例,实际名单需要你自己筛选)
tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'NVDA', 'META', 'TSLA']
# 批量下载数据
data = yf.download(tickers, start='2020-01-01', end='2024-12-31')
# 提取调整收盘价
adj_close = data['Adj Close']
print(adj_close.head())
你看,一行代码就把7只龙头股的数据全拿下来了。yfinance会自动处理多列索引,返回一个MultiIndex的DataFrame。我个人觉得这个设计很巧妙——既保留了数据结构,又方便后续按股票切片。
yf.download('AAPL', period='100d')。用period参数比用start/end更省事。
4.4 初筛指标计算:从原始数据到决策依据
数据拿到了,接下来就是算指标。我一般把初筛指标分成三类:
| 指标类别 | 具体指标 | 计算逻辑 |
|---|---|---|
| 动量类 | 20日收益率、60日收益率 | (当前收盘价 - N日前收盘价) / N日前收盘价 |
| 波动类 | 20日年化波动率 | std(日收益率) * sqrt(252) |
| 流动性类 | 20日平均成交量 | rolling(20).mean() |
为什么要选这些指标?你想想看,龙头股首先得“涨得动”(动量),其次不能“上蹿下跳”(波动适中),最后还得“有人玩”(流动性好)。这三个维度缺一不可。
下面我写一个完整的计算函数。这个函数我在项目中反复用过,算是比较成熟的模板。
def calculate_indicators(df, window=20):
"""
计算初筛指标
df: 调整收盘价的DataFrame,列名为股票代码
window: 计算窗口,默认20个交易日
"""
# 计算收益率
returns = df.pct_change()
# 动量指标:N日收益率
momentum = df.pct_change(periods=window)
# 波动率指标:N日年化波动率
volatility = returns.rolling(window=window).std() * (252 ** 0.5)
# 流动性指标:N日平均成交量(需要原始成交量数据)
# 这里假设你已经有volume数据
# avg_volume = volume.rolling(window=window).mean()
# 整合结果
result = pd.DataFrame({
'momentum': momentum.iloc[-1],
'volatility': volatility.iloc[-1],
# 'avg_volume': avg_volume.iloc[-1]
})
return result
# 使用示例
indicators = calculate_indicators(adj_close)
print(indicators.sort_values('momentum', ascending=False))
跑完这段代码,你会得到一个表格,里面每只股票都有动量值和波动率值。这时候你就可以开始做初步筛选了——比如只保留动量排名前20%、波动率低于30%的股票。
4.5 知识体系总览
为了让你对整个流程有个直观印象,我画了一张图。这张图把数据获取、指标计算、筛选逻辑串在了一起。
4.6 实战中的坑与对策
代码写完了,图也画了,但实战中总会遇到各种幺蛾子。我把自己踩过的坑列出来,你遇到了直接抄答案就行。
- 数据缺失: 有些股票可能在某段时间停牌,导致数据为空。我的处理方式是:如果缺失值超过20%,直接剔除这只股票;如果只是零星缺失,用前向填充法(ffill)。
- 股票代码变更: 比如FB改成了META。yfinance会自动处理,但如果你用的是旧代码,可能会拿到空数据。建议定期更新股票池。
- 计算速度: 如果你要处理几百只股票,用纯pandas循环会非常慢。我的优化方案是:用numpy向量化计算,或者用numba加速。不过对于初筛阶段,几十只股票完全够用。
4.7 小结
这一章我们干了三件事:用yfinance拿数据、算动量波动率这些初筛指标、把整个流程串成自动化脚本。你可能会觉得这些指标太简单——没错,初筛阶段就是要简单粗暴。复杂的模型留到后面几章再上。
最后提醒一句:代码跑通了只是第一步。真正有价值的是你如何解读这些指标、如何设定筛选阈值。这些经验性的东西,光看书学不来,得自己动手试错。
好了,这一章就到这里。代码拿去跑,有问题随时调试。记住:数据不会骗人,但解读数据的人会。