如何用 Python 计算个股的 Beta 和相关性?(以沪深300为基准)
如何用 Python 计算个股的 Beta 和相关性?(以沪深300为基准)
一句话回答: Beta 衡量个股相对大盘的系统性风险(Beta>1 比大盘波动更大),相关性衡量两只标的同涨同跌的程度。用 AlphaFeed 取个股与沪深300(000300.SH)的前复权日线收益率,用 numpy/pandas 几行即可算出 Beta、相关系数和相关性矩阵。
概念速览
- Beta = Cov(个股收益, 基准收益) / Var(基准收益)。Beta≈1 与大盘同步,>1 更激进,<1 更防御,<0 反向。
- 相关系数 ρ ∈ [-1, 1]:接近 1 高度同向,接近 0 不相关,负值反向。组合分散化就是找低相关的资产。
两者都基于收益率序列,所以取数必须用前复权价(避免除权跳空污染)。
第一步:取个股与基准的日线
from alphafeed import AlphaFeed
import pandas as pd
af = AlphaFeed() # 读取 ALPHAFEED_API_KEY
def close_series(symbol, count=250):
df = af.klines.get(symbol, period="1d", count=count, adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date")
return df.set_index("trade_date")["close"].rename(symbol)
stock = close_series("600519.SH") # 贵州茅台
bench = close_series("000300.SH") # 沪深300 指数
000300.SH(沪深300)、399001.SZ(深证成指)等指数均可直接取;也可用510300.SH(沪深300ETF)做基准。
第二步:计算 Beta
按日期对齐后取收益率,套公式:
import numpy as np
def beta(stock_close, bench_close):
df = pd.concat([stock_close, bench_close], axis=1, join="inner").dropna()
r = df.pct_change().dropna()
s, m = r.iloc[:, 0], r.iloc[:, 1]
cov = np.cov(s, m)[0, 1]
var = np.var(m, ddof=1)
return cov / var
b = beta(stock, bench)
print(f"贵州茅台 Beta(相对沪深300): {b:.2f}")
解读:Beta=1.2 → 大盘涨 1%,该股平均涨约 1.2%(也跌得更多)。Beta 用于估计系统性风险敞口、做对冲或控制组合的市场暴露。
第三步:计算与大盘的相关系数
def corr_with_bench(stock_close, bench_close):
df = pd.concat([stock_close, bench_close], axis=1, join="inner").dropna()
r = df.pct_change().dropna()
return r.iloc[:, 0].corr(r.iloc[:, 1])
print(f"与沪深300相关系数: {corr_with_bench(stock, bench):.2f}")
第四步:多只股票的相关性矩阵
组合分散化要挑低相关的股票。批量取数后一步算出矩阵:
symbols = ["600519.SH", "000001.SZ", "601318.SH", "300750.SZ", "600036.SH"]
dfs = af.klines.batch(symbols, period="1d", count=250, adjust="forward",
to_dataframe=True, show_progress=True)
closes = pd.DataFrame({
sym: d.sort_values("trade_date").set_index("trade_date")["close"]
for sym, d in dfs.items()
})
returns = closes.pct_change().dropna()
corr = returns.corr()
print(corr.round(2))
想找分散化候选,看相关系数最低的对:
c = corr.where(~np.eye(len(corr), dtype=bool)) # 去对角线
pair = c.stack().idxmin()
print(f"相关性最低的一对: {pair} = {c.stack().min():.2f}")
第五步:批量算全池 Beta(可选)
给一篮子股票统一算 Beta,挑高/低 Beta 组合:
betas = {}
for sym, d in dfs.items():
s = d.sort_values("trade_date").set_index("trade_date")["close"]
betas[sym] = round(beta(s, bench), 2)
print(dict(sorted(betas.items(), key=lambda kv: kv[1], reverse=True)))
注意事项(诚实提示)
| 坑 | 说明 |
|---|---|
| 不复权 | 会让收益率在除权日跳变,Beta/相关性失真,务必 adjust="forward" |
| 样本长度 | 太短(<60)估计不稳;常用 250 日 |
| 时变性 | Beta 会随时间变化,可用滚动窗口 rolling 观察 |
| 停牌 | 停牌期无收益,join="inner" 对齐可避免错配 |
常见问题(FAQ)
Q:基准用指数还是 ETF?
A:都可以。指数(000300.SH)更纯;ETF(510300.SH)贴近可交易标的。保持一致即可。
Q:为什么用 ddof=1?
A:样本方差用无偏估计(n-1),与 np.cov 默认一致。
Q:Beta 能直接当买卖信号吗? A:不能。它是风险度量,用于对冲、暴露控制、组合构建,需结合其他因子。
小结
Beta 和相关性是组合与风险管理的基石。有了 AlphaFeed 的前复权日线 + 指数基准(000300.SH),Cov/Var 与 corr() 几行就能算出个股 Beta、与大盘相关性以及多标的相关矩阵,为分散化和对冲提供依据。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- K 线数据文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。