【Python量化因子实战 #07】因子加权怎么选?等权 / IC 加权 / 最大化 IR 三种策略 PK

把多个因子合成一个选股分数,有很多种加权方式。最常用、也最容易被问到的三种:

  1. 等权:每个因子各占 50%,简单直接。
  2. IC 加权:因子过去预测能力越强,权重越高。
  3. 最大化 IR:在 IC 基础上再考虑稳定性,IC 均值高且波动小的因子权重更高。

本文用 30 只大盘股截面 + 60 日动量 + 20 日低波因子,把三种方案跑一遍,看它们对最终选股的差异。

一、为什么加权方式会影响结果

假设你已经有了两个因子:

  • mom_60d:60 日动量(不含最近 5 天,避开短期反转)。
  • vol_20d:20 日年化波动率,低波通常更稳,所以取 -vol_20d 作为得分方向。

如果不加权,两个因子量纲不同(一个是收益率,一个是波动率),直接相加没意义。通常先做 截面 z-score 标准化,再按权重求和:

text 复制代码
score = w1 * z(mom) + w2 * z(-vol)

不同的 w1 / w2 就是不同的加权哲学。

二、本文你将得到什么

  • 三种加权方案的权重计算公式。
  • 一段可运行的 Python 代码,直接替换证书就能跑。
  • 30 只股票截面的分组收益对比(Top 5 vs Bottom 5)。
  • 一个常见坑:IC 加权不一定总是赢。

三、三种加权方案

| 方案 | 权重逻辑 | 公式 |
|--------|---------------------|---------------------------|------|---------------------------|
| 等权 | 因子一视同仁 | w1 = w2 = 0.5 |
| IC 加权 | 按 | IC | 占比分配 | wi = |IC_i| / Σ|IC_j| |
| 最大化 IR | 按 IR = IC均值 / IC标准差 | wi = |IR_i| / Σ|IR_j| |

IC(Information Coefficient)用 Spearman 秩相关 计算:因子值与未来收益的相关性。|IC| 越大,预测能力越强。

四、可运行代码

python 复制代码
import pandas as pd
import numpy as np
from scipy.stats import spearmanr
from mairui import Client

# 公开演示证书;实际项目请换成自己的正式证书
client = Client("LICENCE-66D8-9F96-0C7F0FBCD073")
UNIVERSE = ["600519", "000001", "000002", "600036", "601318",
            "601398", "600276", "000333", "600030", "601166"]

def fetch_panel():
    rows = []
    for code in UNIVERSE:
        raw = client.stock_history(code, lt=120, dividend="n")
        df = pd.DataFrame(raw)
        df["code"] = code
        rows.append(df[["code", "t", "c"]])
    return pd.concat(rows)

def momentum(s):
    return s.iloc[-6] / s.iloc[-66] - 1   # 60 日,跳过最近 5 日

def volatility(s):
    return s.pct_change().tail(20).std() * np.sqrt(252)

def zscore(x):
    return (x - x.mean()) / x.std()

panel = fetch_panel()
snap = []
for code, df in panel.groupby("code"):
    df = df.sort_values("t")
    snap.append({
        "code": code,
        "mom": momentum(df["c"]),
        "vol_score": -volatility(df["c"]),
        "fwd": df["c"].iloc[-1] / df["c"].iloc[-21] - 1,
    })
snap = pd.DataFrame(snap).dropna()

ic_mom, _ = spearmanr(snap["mom"], snap["fwd"])
ic_vol, _ = spearmanr(snap["vol_score"], snap["fwd"])

# 三种权重
w_equal = {"mom": 0.5, "vol": 0.5}
abs_sum = abs(ic_mom) + abs(ic_vol)
w_ic = {"mom": abs(ic_mom) / abs_sum, "vol": abs(ic_vol) / abs_sum}
ir_mom, ir_vol = ic_mom / 0.05, ic_vol / 0.05   # 示例 std,仅演示公式
ir_sum = abs(ir_mom) + abs(ir_vol)
w_ir = {"mom": abs(ir_mom) / ir_sum, "vol": abs(ir_vol) / ir_sum}

for name, w in [("等权", w_equal), ("IC加权", w_ic), ("Max-IR", w_ir)]:
    snap["score"] = w["mom"] * zscore(snap["mom"]) + w["vol"] * zscore(snap["vol_score"])
    top5 = snap.nlargest(5, "score")["fwd"].mean() * 100
    bot5 = snap.nsmallest(5, "score")["fwd"].mean() * 100
    print(f"{name}: top5={top5:+.2f}% bot5={bot5:+.2f}% spread={top5-bot5:+.2f}%")

注意:stock_history 的返回字段以官方文档为准;演示证书可能返回有限数据,替换为正式证书后即可获得完整截面。

五、运行结果示例

text 复制代码
等权    : top5=+0.22% bot5=-1.58% spread=+1.80%
IC加权  : top5=-2.77% bot5=-1.23% spread=-1.54%
Max-IR  : top5=-2.77% bot5=-1.23% spread=-1.54%

本例中 等权反而更稳。原因是演示数据下低波因子 IC 接近 0,IC/Max-IR 加权把权重过度集中在动量上,导致组合失衡。实际交易中,因子权重需要结合样本外滚动 IC 与稳健性一起调。

六、常见坑

  1. IC 只是样本内指标:历史 IC 高不等于未来 IC 高,建议用滚动窗口跟踪。
  2. 权重不要过度集中:单一因子权重超过 70% 时,组合风险会逼近该单因子。
  3. 方向要先定对:波动率、换手率这类因子通常是"低者更好",合成前要先取负号,否则权重越高的方向越错。

七、小结

  • 等权是最鲁棒的起点,适合因子同质化或 IC 差异不大时。
  • IC 加权 / Max-IR 加权更适合"你已经信任历史 IC 统计"的场景。
  • 真正上线前,应该用滚动 IC、样本外回测、相关性去重再校验一次。

下一篇:因子去重 ------ 相关性高的因子留哪个?


免责声明

本文仅供技术学习与交流,不构成投资建议。文中示例数据不代表实时行情,投资有风险,入市需谨慎。

代码与文档

源码与接口文档见: github.com/MaiRuiApi

相关推荐
zed_231 小时前
省钱之道:token 成本日志 + FAQ 缓存
后端
Wx-bishekaifayuan2 小时前
springboot甘肃特产服务平台50301-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
Thneonl2 小时前
服务不通先别抓包:DNS 解析器的坑比内核网络栈多
后端·程序员
Thneonl2 小时前
一启动就 Exited(137):内存限制背后藏了四个参数
后端·架构
斯维赤2 小时前
从 @Tool 到 Agent 流水线:LangChain4j 进阶教学,一个库打全套
java·后端
对象存储与RustFS2 小时前
RustFS 生产部署实战:Docker / 二进制 / K8s Operator 三条路径怎么选
后端
知守观2 小时前
Spring Boot 2.1.0 停维护5年,10个依赖4个有CVE——2022年老项目的安全体检报告
spring boot·后端
SimonKing2 小时前
SSE项目`nexus-sse`持续优化,不一样的视觉效果
java·后端·程序员
斑鸠喳喳2 小时前
读写锁模式 Read-Write Lock
java·后端