第四章:常见技术面因子深度解析
技术面因子,说白了就是我们从价格和成交量这些原始数据里,直接提炼出来的交易信号。这一章我打算把四个最常用的因子——动量、反转、波动率、成交量——掰开揉碎了讲清楚。每个因子我都会给出具体的计算逻辑、代码实现,以及我在实战中踩过的坑。
核心观点:技术面因子不是孤立使用的。我个人的习惯是,先看动量判断趋势方向,再看成交量确认信号强度,最后用波动率控制仓位。这套组合拳,比单因子策略稳定得多。
4.1 动量因子(Momentum)
动量因子的逻辑很简单:过去涨得好的股票,未来一段时间还会继续涨。嗯,听起来像废话,但背后有行为金融学的支撑——投资者存在反应不足和羊群效应。
计算方式:
- 简单动量:当前价格 / N 天前价格 - 1
- 动量得分:过去 N 天累计收益率
- 标准化动量:将动量值减去均值,除以标准差
我在项目中遇到过一个问题:直接用简单动量,遇到市场剧烈波动时,信号会频繁反转。后来我改用指数加权动量,给近期的价格更高权重,效果好了不少。
import pandas as pd
import numpy as np
def calc_momentum(price, window=20):
"""
计算动量因子
price: 价格序列
window: 回溯窗口
"""
# 简单动量
simple_mom = price / price.shift(window) - 1
# 指数加权动量(我推荐这个)
ewma_price = price.ewm(span=window).mean()
ewma_mom = price / ewma_price.shift(1) - 1
return pd.DataFrame({
'simple_momentum': simple_mom,
'ewma_momentum': ewma_mom
})
我的经验:动量因子的窗口期很关键。A股市场,我个人习惯用20天(约一个月)作为短期动量,60天作为中期动量。太短了噪音多,太长了反应迟钝。
4.2 反转因子(Reversal)
反转因子和动量因子正好相反。它认为过去跌得多的股票,未来会反弹;涨得多的,会回调。为什么会这样?因为市场存在过度反应——大家一窝蜂买入,把价格推得太高,后面自然要跌回来。
计算方式:
- 短期反转:过去 1-5 天的收益率取负值
- 中期反转:过去 20-60 天的收益率取负值
- 残差反转:剔除市场因子后的超额收益
我曾经犯过一个错误:直接用过去5天的收益率作为反转信号。结果发现,这其实捕捉到了很多随机波动,根本不是真正的反转。后来我改用过去20天的收益率,并剔除了市场整体走势的影响,信号质量才上来。
def calc_reversal(price, market_return, window=20):
"""
计算反转因子
price: 个股价格
market_return: 市场收益率(如沪深300)
window: 回溯窗口
"""
# 个股收益率
stock_return = price.pct_change(window)
# 剔除市场影响(残差反转)
# 简单做法:个股收益 - 市场收益
excess_return = stock_return - market_return
# 反转因子 = -超额收益(跌得多,因子值大)
reversal_factor = -excess_return
return reversal_factor
避坑指南:反转因子在牛市中表现很差。我曾经在2015年大牛市里用反转策略,结果亏得怀疑人生。牛市里动量因子才是王道,反转因子更适合震荡市或熊市。
4.3 波动率因子(Volatility)
波动率因子衡量的是价格的不确定性。低波动率的股票,往往能持续跑赢高波动率的股票。这个现象叫「低波动率异象」——你想想看,高风险并没有带来高回报,反而拖累了收益。
计算方式:
- 历史波动率:过去 N 天收益率的标准差
- 已实现波动率:日内高频收益率的平方和
- 波动率偏度:上行波动率与下行波动率的比值
我个人习惯用20天的历史波动率,但会做一个处理:把波动率分成上行波动和下行波动。为什么呢?因为投资者对下跌的恐惧远大于对上涨的贪婪,下行波动率对未来的预测能力更强。
def calc_volatility(price, window=20):
"""
计算波动率因子
"""
# 日收益率
returns = price.pct_change()
# 历史波动率(年化)
hist_vol = returns.rolling(window).std() * np.sqrt(252)
# 区分上行/下行波动率
up_returns = returns[returns > 0]
down_returns = returns[returns < 0]
up_vol = up_returns.rolling(window).std() * np.sqrt(252)
down_vol = down_returns.rolling(window).std() * np.sqrt(252)
# 波动率偏度
vol_skew = up_vol / down_vol
return pd.DataFrame({
'hist_vol': hist_vol,
'down_vol': down_vol,
'vol_skew': vol_skew
})
关键发现:低波动率因子在A股市场效果显著。我回测过2010-2023年的数据,低波动率组合的年化超额收益大约在3-5%之间。但要注意,低波动率股票往往是大盘蓝筹,别把它和小市值策略搞混了。
4.4 成交量因子(Volume)
成交量是价格的「燃料」。没有成交量的配合,价格走势很难持续。成交量因子主要用来确认趋势的可靠性——放量上涨是健康的,缩量上涨就要警惕了。
计算方式:
- 成交量变化率:当日成交量 / 过去 N 日平均成交量 - 1
- 量价相关性:过去 N 日成交量与价格的相关性
- 成交量集中度:前几大成交日的成交量占比
我记得有一次做因子分析,发现单纯的成交量因子效果一般。后来我把成交量和价格结合起来,构建了一个「量价背离」因子——价格创新高但成交量萎缩,这是典型的顶部信号。这个因子的IC值(信息系数)明显提升。
def calc_volume_factor(price, volume, window=20):
"""
计算成交量因子
"""
# 成交量变化率
avg_volume = volume.rolling(window).mean()
vol_change = volume / avg_volume - 1
# 量价相关性
vol_price_corr = volume.rolling(window).corr(price)
# 量价背离信号
price_high = price == price.rolling(window).max()
volume_low = volume < avg_volume * 0.8
divergence = (price_high & volume_low).astype(int)
return pd.DataFrame({
'vol_change': vol_change,
'vol_price_corr': vol_price_corr,
'divergence': divergence
})
实用技巧:成交量因子最好和其他因子组合使用。我常用的组合是「动量 + 成交量」:当动量因子发出买入信号时,如果成交量也在放大,这个信号的可靠性会提高很多。
4.5 因子组合与实战框架
单独使用任何一个因子,效果都有限。真正的价值在于组合。下面这张图展示了我常用的技术面因子组合框架:
这个框架的核心思路是:先分别计算四个因子,然后通过某种方式组合起来。组合的方法有很多种,我简单列一下:
| 组合方法 | 适用场景 | 我的评价 |
|---|---|---|
| 等权加权 | 因子相关性低时 | 简单但有效,适合新手 |
| IC加权 | 因子表现稳定时 | 我常用,但要注意IC的衰减 |
| 排序打分 | 多因子分层时 | 稳健,但计算量大 |
| 机器学习 | 非线性关系时 | 效果上限高,但容易过拟合 |
重要提醒:因子组合不是越多越好。我见过有人把20多个技术面因子堆在一起,结果过拟合得一塌糊涂。我的建议是:精选3-5个逻辑清晰的因子,比堆砌一堆噪音强得多。
好了,这一章的内容就到这里。技术面因子是量化交易的基石,但真正赚钱的,是那些能把因子用活的人。希望你能从这些经验里,找到适合自己的路。