【Python量化实战全攻略 #15】股票池日更与行业中性手册:申万行业中性化(附代码)
摘要:【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 只时排名无意义,设最小样本阈值。
- 小行业噪声:三级行业样本太少,中性化建议用一级或二级。
- 中性后收益下降:完全中性会抹掉行业 alpha,可保留小幅暴露。
7. 小结与下一篇预告
行业中性让股票池行业分散。下一篇讲选股策略回测验证——把前面所有因子向量化跑一遍,看策略到底赚不赚钱。
下一篇预告:《【Python量化实战全攻略 #16】选股策略回测验证手册:向量化跑一遍(附代码)》
8. 免责声明
本文为组合构建方法示例,演示数据为虚构,不构成投资建议。
关于数据来源:本文行业归属所需的板块接口来自智兔数服(www.zhituapi.com)官方文档(详见本系列 #03/#14),覆盖 200+ 已验证路径,注册可领免费 token 做研究测试。
更多实战手册见技术博客:zhituapi.com/blog.html。
本系列《Python量化实战全攻略》共 32 篇,下一篇讲选股回测。
想亲自试一下?免费获取证书