2. 案例02:计算反转因子并分析其与未来收益的相关性
任务说明
本案例基于日线收盘价构造 5 日反转因子:rev5 = -(close / close.shift(5) - 1),即过去 5 日累计收益取负。随后计算未来 5 日收益 fwd5 = close.shift(-5) / close - 1,用 Spearman 相关系数检验因子值与未来收益的相关性。反转因子预期与未来收益正相关(过去跌得多,未来反弹概率大)。
环境与依赖
pip install pandas numpy scipy
完整实现
import numpy as np
import pandas as pd
from scipy.stats import spearmanr
# 1. 构造示例日线数据(真实使用时替换为读取行情数据)
np.random.seed(42)
dates = pd.bdate_range("2023-01-02", periods=300)
# 模拟带轻微均值回复的收益率序列
rets = np.random.normal(0, 0.02, len(dates))
for i in range(1, len(rets)):
rets[i] -= 0.05 * rets[i - 1] # 引入反转效应
close = pd.Series(100 * np.cumprod(1 + rets), index=dates, name="close")
# 2. 计算 5 日反转因子
rev5 = -(close / close.shift(5) - 1)
rev5.name = "rev5"
# 3. 计算未来 5 日收益
fwd5 = close.shift(-5) / close - 1
fwd5.name = "fwd5"
# 4. 对齐并剔除缺失值
df = pd.concat([rev5, fwd5], axis=1).dropna()
# 5. Spearman 相关性检验
rho, pval = spearmanr(df["rev5"], df["fwd5"])
print(f"样本数: {len(df)}")
print(f"Spearman rho = {rho:.4f}, p-value = {pval:.4f}")
# 6. 分组验证:按因子值分 5 组,观察各组未来收益均值
df["group"] = pd.qcut(df["rev5"], 5, labels=False)
group_mean = df.groupby("group")["fwd5"].mean()
print("\n分组未来5日收益均值:")
print(group_mean)
运行与验证
- 运行脚本后观察
rho与p-value。若rho > 0且p-value < 0.05,说明反转因子与未来 5 日收益显著正相关,因子方向符合预期。 - 分组均值应呈现单调递增趋势(group 0 最低、group 4 最高),进一步佐证因子单调性。
- 替换
close为真实行情数据(如从 CSV 读取pd.read_csv("xxx.csv", index_col="date", parse_dates=True)["close"])即可复用到实际标的。
关键点
- 因子方向:取负号使"过去跌得多"对应因子值大,与未来收益正相关,便于统一解读。
- Spearman 对异常值不敏感,适合因子与收益这类非线性单调关系的检验。
- 必须用
shift(-5)构造未来收益,避免使用未来信息污染因子计算。