4. 案例04:计算换手率因子并做行业中性化
任务说明
本案例基于日频行情数据,用成交量与流通股本计算换手率因子,再按行业分组做去均值处理,得到行业中性化后的换手率因子。核心公式:turnover = volume / float_share,中性化:turnover_neutral = turnover - industry_mean(turnover)。
环境与依赖
pip install pandas numpy
完整实现
import pandas as pd
import numpy as np
# 1. 构造最小示例数据:3只股票、2个行业、2个交易日
df = pd.DataFrame({
"date": ["2024-01-02"] * 3 + ["2024-01-03"] * 3,
"code": ["A", "B", "C"] * 2,
"industry": ["银行", "银行", "科技"] * 2,
"volume": [1.0e7, 2.0e7, 3.0e7, 1.5e7, 2.5e7, 4.0e7], # 成交量(股)
"float_share": [1.0e8, 2.0e8, 1.5e8, 1.0e8, 2.0e8, 1.5e8], # 流通股本(股)
})
# 2. 计算换手率因子
df["turnover"] = df["volume"] / df["float_share"]
# 3. 按“日期 + 行业”分组去均值,实现行业中性化
df["turnover_neutral"] = df["turnover"] - df.groupby(
["date", "industry"]
)["turnover"].transform("mean")
print(df[["date", "code", "industry", "turnover", "turnover_neutral"]])
运行与验证
直接运行上述脚本。判定通过条件:
- 每个
(date, industry)分组内,turnover_neutral的均值应约等于 0(浮点误差范围内)。 - 同一分组内两只股票的
turnover_neutral符号相反、绝对值相等(因为只有两只股票时去均值即对称化)。
可用一行代码验证:
print(df.groupby(["date", "industry"])["turnover_neutral"].mean())
输出应全部为 0(或接近 0 的极小值)。
关键点
- 中性化必须按
date分组,否则不同交易日的量纲会互相污染。 - 用
transform("mean")而非mean(),可直接把组均值广播回原行,避免 merge。 - 若某行业当日只有 1 只股票,去均值后该股票因子恒为 0,属于正常现象,需在后续使用中注意。