4. 常见风格因子:市值、价值、动量、反转与波动率
风格因子,说白了就是能解释股票收益的共同特征。我刚开始做多因子模型那会儿,总觉得因子越多越好,恨不得把能想到的指标全塞进去。后来吃过亏才明白——因子不在多,在于有效且稳定。今天咱们就聊聊五个最经典的风格因子,它们几乎构成了所有量化模型的基石。
核心观点:这五个因子分别从公司规模、估值水平、历史表现、价格行为、风险特征五个维度刻画股票。它们之间既有互补,也有冲突,组合使用时需要仔细权衡。
4.1 市值因子(Size Factor)
市值因子是最早被发现的因子之一。Fama-French三因子模型里,它和估值因子、市场因子并列。逻辑很简单:小市值公司通常比大市值公司有更高的风险溢价。
我个人习惯用总市值(Total Market Cap)来构建这个因子。具体做法是取对数,然后做市值中性化处理。为什么要取对数?因为市值分布太偏了,取完对数后更接近正态分布,模型跑起来更稳。
# 市值因子构建示例(Python伪代码)
import pandas as pd
import numpy as np
# 假设df包含股票代码和总市值
df['log_market_cap'] = np.log(df['total_market_cap'])
# 市值中性化:减去行业均值,除以行业标准差
df['size_factor'] = (df['log_market_cap'] - df.groupby('industry')['log_market_cap'].transform('mean')) / \
df.groupby('industry')['log_market_cap'].transform('std')
避坑指南:我曾经在回测中发现小市值因子在牛市中表现极好,但一到熊市就崩得厉害。后来才意识到,小市值股票的流动性风险被低估了。建议在使用市值因子时,同时加入流动性过滤条件,剔除日均成交额低于某个阈值的股票。
4.2 价值因子(Value Factor)
价值因子衡量的是股票是否被低估。经典的指标包括市盈率(PE)、市净率(PB)、市销率(PS)、股息率(Dividend Yield)等。你想想看,如果一家公司基本面没问题,但股价跌得比同类公司多,那它大概率是被低估了。
我建议用综合价值得分来替代单一指标。为什么?因为单一指标容易受会计政策影响。比如PE,亏损公司就是负值,没法直接用。我的做法是:
- 分别计算PE、PB、PS的百分位排名
- 对排名做等权或加权平均
- 得到综合价值因子
| 指标 | 计算方式 | 注意事项 |
|---|---|---|
| 市盈率(PE) | 股价 / 每股收益 | 亏损公司需特殊处理 |
| 市净率(PB) | 股价 / 每股净资产 | 金融行业适用性高 |
| 市销率(PS) | 股价 / 每股销售额 | 适用于高增长行业 |
| 股息率 | 每股股息 / 股价 | 需考虑分红稳定性 |
个人经验:价值因子在A股市场有个特点——低估值不等于好投资。很多低PE的股票其实是“价值陷阱”,比如钢铁、煤炭等周期性行业。我一般会叠加一个盈利质量因子(如ROE、毛利率)来过滤掉这些陷阱。
4.3 动量因子(Momentum Factor)
动量因子,说白了就是“追涨杀跌”。学术上叫趋势效应:过去表现好的股票,未来一段时间内往往继续表现好;过去表现差的,未来也容易继续差。这个效应在A股市场尤其明显,特别是短期动量(1-3个月)。
构建动量因子时,我习惯用过去12个月剔除最近1个月的累计收益率。为什么要剔除最近1个月?因为要避免短期的反转效应干扰。嗯,这里要注意:动量因子对计算窗口非常敏感。
# 动量因子构建示例
def compute_momentum_factor(df, price_col='adj_close', date_col='trade_date'):
"""
df: 包含股票代码、日期、复权价格的DataFrame
返回:过去12个月(剔除最近1个月)的累计收益率
"""
# 按股票分组,计算月度收益率
df['monthly_ret'] = df.groupby('stock_code')[price_col].pct_change()
# 滚动12个月累计收益,剔除最近1个月
df['momentum'] = df.groupby('stock_code')['monthly_ret'].rolling(window=11).apply(
lambda x: (1 + x).prod() - 1
).reset_index(level=0, drop=True)
return df
我曾经踩过的坑:动量因子在极端行情下会失效。比如2015年股灾期间,所有动量策略都亏得惨不忍睹。原因很简单——系统性风险爆发时,所有相关性都趋近于1。建议在动量因子中加入市场状态识别,比如用VIX指数或市场宽度指标来判断是否适合使用动量策略。
4.4 反转因子(Reversal Factor)
反转因子和动量因子是一对“冤家”。动量因子赚趋势的钱,反转因子赚过度反应的钱。逻辑是:市场短期内会过度反应某些信息,导致价格偏离合理价值,随后价格会回归。
我常用的反转因子有两种:
- 短期反转(1-2周):捕捉日内或周度的过度反应
- 长期反转(3-5年):捕捉市场对长期趋势的过度定价
你想想看,为什么A股市场短期反转效应特别强?因为散户占比高,情绪化交易多。一只股票连续涨停后,大概率会回调——这就是反转因子的用武之地。
实战技巧:我一般把动量因子和反转因子组合使用。比如,先用动量因子筛选出强势股,再用反转因子剔除那些短期涨幅过大的股票。这样既能吃到趋势,又能避开回调风险。
4.5 波动率因子(Volatility Factor)
波动率因子衡量的是股票的风险水平。学术研究发现一个有趣的现象:低波动率的股票,长期收益反而更高。这就是所谓的“低波动异象”。为什么会这样?因为很多投资者偏好高波动、高收益的彩票型股票,导致它们被高估,而低波动股票被低估。
我构建波动率因子时,通常用过去60个交易日的日收益率标准差。但要注意:
- 波动率有聚集效应(高波动后往往跟着高波动)
- 不同行业的波动率基准不同(比如科技股天生比公用事业股波动大)
- 需要做行业中性化处理
# 波动率因子构建
def compute_volatility_factor(df, ret_col='daily_ret', window=60):
# 计算滚动波动率
df['raw_vol'] = df.groupby('stock_code')[ret_col].rolling(window).std().reset_index(level=0, drop=True)
# 行业中性化:减去行业均值
df['vol_factor'] = df['raw_vol'] - df.groupby('industry')['raw_vol'].transform('mean')
return df
我的建议:波动率因子最好和换手率因子一起使用。因为高波动往往伴随着高换手,两者结合能更准确地刻画股票的投机程度。我在实盘中就发现,低波动+低换手的组合,夏普比率明显优于单独使用波动率因子。
知识体系总览
下面这张图展示了五个风格因子的核心逻辑和相互关系。我把它画成了SVG,方便你理解整个框架。
这五个因子,每一个单独拿出来都能写一篇论文。但在实战中,我更看重它们的组合效应。比如,我常用的一个组合是:低市值 + 低估值 + 低波动,这个组合在A股市场长期跑赢基准。当然,没有完美的因子组合,关键是要理解每个因子背后的经济逻辑和风险暴露。
最后说一句:因子不是万能的。再好的因子,如果市场环境变了,也会失效。我见过太多人死磕一个因子,结果亏得血本无归。记住——因子是工具,不是信仰。保持开放心态,持续迭代,才是量化投资的生存之道。