4. 行业因子构建:虚拟变量法、市值加权法、行业收益率法

行业因子这东西,说白了就是给股票打上行业标签。你想想看,一只银行股和一只医药股,它们的涨跌逻辑完全不同。如果不把行业影响剥离掉,你算出来的因子暴露可能全是行业差异,根本不是个股本身的特征。

我在做多因子模型的时候,踩过不少坑。最开始我直接用申万一级行业分类,结果发现某些行业里只有三五只股票,回归出来的系数方差大得吓人。后来我学乖了——行业分类要合并,样本量要够,不然统计上就不显著。

行业因子的构建方法,主流的有三种。我一个个说。

4.1 虚拟变量法

这是最直接的方法。每个行业设一个0/1变量。股票属于哪个行业,那个行业对应的变量就是1,其余是0。

举个例子。假设有3个行业:银行、医药、科技。某只股票是招商银行,那它的行业虚拟变量就是 [1, 0, 0]。如果是恒瑞医药,就是 [0, 1, 0]。

代码实现也很简单:

import pandas as pd
import numpy as np

# 假设df是包含股票行业标签的数据框
df = pd.DataFrame({
    'stock': ['招商银行', '恒瑞医药', '腾讯控股', '工商银行'],
    'industry': ['银行', '医药', '科技', '银行']
})

# 虚拟变量法
dummies = pd.get_dummies(df['industry'], prefix='industry')
df_with_dummies = pd.concat([df, dummies], axis=1)
print(df_with_dummies.head())

输出结果:

      stock industry  industry_医药  industry_科技  industry_银行
0  招商银行       银行            0            0            1
1  恒瑞医药       医药            1            0            0
2  腾讯控股       科技            0            1            0
3  工商银行       银行            0            0            1

注意陷阱:虚拟变量法有个经典问题——完全多重共线性。如果你有K个行业,只能引入K-1个虚拟变量,否则回归时会报错。我刚开始做的时候,直接把所有行业都扔进去,结果回归系数全是NaN。后来才意识到,需要去掉一个基准行业。

实际操作中,我一般会去掉市值最大的那个行业作为基准。这样解释起来也方便——其他行业的系数都是相对于这个基准行业的偏离。

4.2 市值加权法

虚拟变量法有个硬伤:它假设同一行业里所有股票都一样。但现实是,工商银行和张家港行虽然都是银行股,体量差了几百倍。它们的行业影响力能一样吗?

市值加权法就是来解决这个问题的。它用市值作为权重,构建行业因子。具体做法是:

  1. 计算每个行业内所有股票的市值占比
  2. 用市值占比作为权重,加权平均得到行业因子值

代码实现:

# 假设df包含市值信息
df['market_cap'] = [10000, 3000, 5000, 8000]  # 单位:亿

# 计算每个行业的总市值
industry_total_cap = df.groupby('industry')['market_cap'].sum()

# 计算每只股票在行业内的市值权重
df['weight'] = df.apply(
    lambda row: row['market_cap'] / industry_total_cap[row['industry']], 
    axis=1
)

# 构建市值加权行业因子
df['industry_factor_weighted'] = df['weight'] * 1  # 这里1代表该股票属于该行业
print(df[['stock', 'industry', 'market_cap', 'weight']])

输出:

      stock industry  market_cap    weight
0  招商银行       银行       10000  0.555556
1  恒瑞医药       医药        3000  1.000000
2  腾讯控股       科技        5000  1.000000
3  工商银行       银行        8000  0.444444

你看,同样是银行股,招商银行的权重是0.556,工商银行是0.444。大市值股票对行业因子的贡献更大。这更符合实际情况——工商银行的涨跌对整个银行板块的影响,确实比小银行大得多。

我的经验:市值加权法在A股特别适用。因为A股行业集中度很高,白酒行业里茅台一家就占了半壁江山。如果用虚拟变量法,茅台和一个小酒厂在行业因子里的权重一样,这显然不合理。我建议在构建行业因子时,优先考虑市值加权。

4.3 行业收益率法

这个方法稍微绕一点,但很实用。它不是直接给股票打标签,而是用行业整体的收益率作为因子值。

具体做法:

  1. 每天计算每个行业内所有股票的市值加权平均收益率
  2. 这个平均收益率就是该行业当天的因子值
  3. 每只股票在该行业因子上的暴露就是1(如果属于该行业)或0(如果不属于)

代码实现:

# 假设有每日收益率数据
# 这里用模拟数据演示
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=5, freq='D')
data = []

for date in dates:
    for _, row in df.iterrows():
        data.append({
            'date': date,
            'stock': row['stock'],
            'industry': row['industry'],
            'return': np.random.randn() * 0.02,  # 模拟收益率
            'market_cap': row['market_cap']
        })

df_daily = pd.DataFrame(data)

# 计算每日行业收益率(市值加权)
def calc_industry_return(group):
    total_cap = group['market_cap'].sum()
    weighted_return = (group['return'] * group['market_cap'] / total_cap).sum()
    return weighted_return

industry_returns = df_daily.groupby(['date', 'industry']).apply(calc_industry_return)
industry_returns = industry_returns.reset_index()
industry_returns.columns = ['date', 'industry', 'industry_return']

print(industry_returns.head(10))

输出示例:

        date industry  industry_return
0 2024-01-01       医药         0.008234
1 2024-01-01       科技        -0.012456
2 2024-01-01       银行         0.003456
3 2024-01-02       医药        -0.005678
4 2024-01-02       科技         0.015678
...

这个方法的好处是:行业因子本身就是一个可交易的策略。你可以直接买入某个行业的股票,卖出另一个行业的股票,来对冲行业风险。

核心要点:行业收益率法构建的因子,天然具有经济含义。它反映的是「做多该行业、做空基准」的收益率。在Barra模型中,行业因子就是用这种方法构建的。我个人在实盘中也是用这种方法,因为它和后续的风险归因、绩效分析衔接得最顺畅。

三种方法对比

方法 优点 缺点 适用场景
虚拟变量法 简单直观,容易理解 忽略市值差异,存在多重共线性 初步分析、教学演示
市值加权法 考虑市值影响,更贴近实际 需要市值数据,计算稍复杂 多因子模型、风险模型
行业收益率法 具有经济含义,可交易 需要收益率数据,对数据质量要求高 Barra模型、对冲策略

我个人在实际项目中,通常这样组合使用:

  • 做因子测试和选股时,用市值加权法构建行业因子
  • 做风险归因和绩效分析时,用行业收益率法
  • 虚拟变量法基本只用在快速验证阶段

曾经踩过的坑:有一次我在做行业中性化时,用了虚拟变量法,结果回归出来的残差里还有明显的行业特征。查了半天才发现,是因为某个行业里有一只超级大盘股,它的权重被低估了。换成市值加权法后,问题立刻解决。所以,千万别图省事用虚拟变量法做正式模型。

嗯,行业因子构建就讲到这里。三种方法各有千秋,关键看你用在什么场景。记住一点:行业因子是中性化的基础,基础打不好,后面的风格因子分析全是白搭。

行业因子构建方法 行业因子 虚拟变量法 市值加权法 行业收益率法 0/1编码 K-1个变量 市值权重 加权平均 市值加权收益率 可交易因子 建议:因子测试用市值加权法,风险归因用行业收益率法

公众号:蓝海资料掘金营,微信deep3321