← 返回博客列表

【Python量化实战全攻略 #15】股票池日更与行业中性手册:申万行业中性化(附代码)

2026年10月16日 08:40 · 智兔数服 · Python量化实战全攻略

摘要:【Python量化实战全攻略 #15】股票池日更与行业中性手册:申万行业中性化(附代码) 手册定位:模块二第 7 篇。多因子打分后容易「行业暴露」——比如全选了银行。本篇讲 申万行业中性化 :在行业内打分排名,避免策

手册定位:模块二第 7 篇。多因子打分后容易「行业暴露」——比如全选了银行。本篇讲申万行业中性化:在行业内打分排名,避免策略押注单一行业;并讲股票池日更的框架。
数据来源复用 #03 板块(行业归属)+ #14 合成分。

1. 你将得到什么

  • 用申万一级行业做行业内分位排名的代码(行业中性核心);
  • 股票池日更的取数框架;
  • 中性化前后行业暴露对比;
  • 行业中性的 4 个坑(行业定义漂移、空行业、小行业噪声、中性后收益下降)。

2. 取数约定(复用)

用途 来源 见
行业归属 板块/行业列表 /hs/list/sectors、/hibk/zjhhy #03
因子分 多因子合成分 #14

3. 数据来源(复用,不重复罗列)

本篇是组合层,行业归属见 #03,因子分见 #14,不新增接口。

4. 核心模板函数(自包含可跑)

import pandas as pd

_MOCK = True


def industry_neutral_score(df, score_col="总分", ind_col="申万一级"):
    df = df.copy()
    df["行业中性分"] = df.groupby(ind_col)[score_col].rank(pct=True)
    return df


def run_check():
    df = pd.DataFrame([
        {"代码": "600519", "申万一级": "食品饮料", "总分": 1.2},
        {"代码": "000858", "申万一级": "食品饮料", "总分": 0.8},
        {"代码": "600036", "申万一级": "银行", "总分": 1.0},
        {"代码": "601398", "申万一级": "银行", "总分": 0.5},
    ])
    out = industry_neutral_score(df)
    assert out.groupby("申万一级")["行业中性分"].max().between(0.99, 1.01).all()
    print("校验通过 | 行业中性分:", out["行业中性分"].round(2).tolist())
    return out


if __name__ == "__main__":
    run_check()

5. 跑通示例

out = run_check()
top_each = out.sort_values("行业中性分", ascending=False).groupby("申万一级").head(1)
print(top_each[["代码", "申万一级", "行业中性分"]])

6. 坑与注意事项

  1. 行业定义漂移:申万行业会定期调整,历史回测要用当时的分类。
  2. 空行业/单只行业:某行业只剩 1 只时排名无意义,设最小样本阈值。
  3. 小行业噪声:三级行业样本太少,中性化建议用一级或二级。
  4. 中性后收益下降:完全中性会抹掉行业 alpha,可保留小幅暴露。

7. 小结与下一篇预告

行业中性让股票池行业分散。下一篇讲选股策略回测验证——把前面所有因子向量化跑一遍,看策略到底赚不赚钱。

下一篇预告:《【Python量化实战全攻略 #16】选股策略回测验证手册:向量化跑一遍(附代码)》

8. 免责声明

本文为组合构建方法示例,演示数据为虚构,不构成投资建议。


关于数据来源:本文行业归属所需的板块接口来自智兔数服(www.zhituapi.com)官方文档(详见本系列 #03/#14),覆盖 200+ 已验证路径,注册可领免费 token 做研究测试。
更多实战手册见技术博客:zhituapi.com/blog.html。
本系列《Python量化实战全攻略》共 32 篇,下一篇讲选股回测。

想亲自试一下?免费获取证书