第五章 当因子失效时——防守、反制与实盘生存

因子回撤时做出正确止损/调仓决策,反制主力猎杀

176页 · 预计45

本章实战输出:在因子回撤时做出正确的止损/调仓决策,识别失效前兆,反制主力猎杀行为,并用AI预测失效概率。

5.1 因子失效的早期预警信号

因子失效不是突然发生的。在它真正崩盘之前,会有一系列征兆。如果你能提前识别这些信号,就能在大跌之前减仓或清仓。
我总结了四个最可靠的预警信号。当其中两个同时出现时,我就会对这个因子高度警惕;当三个或以上出现时,我会果断减仓。

第一个信号:IC均值的滚动衰减
IC也就是信息系数,衡量因子预测能力的强弱。如果你计算过去60天的平均IC,发现它连续20天都在下降,或者比3个月前下降了30%以上,说明因子的预测能力正在减弱。
代码示例:

ic_rolling_mean = ic_series.rolling(60).mean()
# 如果当前值比20天前低30%
if ic_rolling_mean.iloc[-1] < ic_rolling_mean.iloc[-20] * 0.7:
    print("IC衰减预警")

第二个信号:换手率异常飙升
因子的换手率突然大幅上升,比如超过过去60日均值的2倍,说明因子值变化剧烈,可能是市场风格切换导致因子失效。
代码示例:

turnover_mean = turnover_series.rolling(60).mean()
turnover_std = turnover_series.rolling(60).std()
if turnover_series.iloc[-1] > turnover_mean.iloc[-1] + 2 * turnover_std.iloc[-1]:
    print("换手率异常预警")

第三个信号:因子拥挤度进入极端区间
我在第一章讲过拥挤度。当拥挤度超过80%分位,并且比一个月前上升了20个百分点以上,说明大量资金正在涌入这个因子,风险急剧增加。

第四个信号:分组收益收敛或倒挂
在分层回测中,最高组也就是因子值最大的组,和最低组也就是因子值最小的组,收益差距应该显著。如果你发现最近一段时间,最高组的收益不再高于最低组,甚至低于最低组,也就是倒挂,说明因子已失效。
代码示例:

# 假设你有每天的分组收益
top_group_ret = group_returns['top']
bottom_group_ret = group_returns['bottom']
spread = top_group_ret - bottom_group_ret
# 如果过去20天的平均spread小于0.1%,即接近零,或为负
if spread.rolling(20).mean().iloc[-1] < 0.001:
    print("分组收益收敛或倒挂预警")

实盘日志:2023年底的小市值因子预警
2023年11月,我注意到小市值因子的四个预警信号中,有三个同时亮起:
IC均值从0.04降到了0.015,下降幅度62%。
换手率从日均40%飙升到80%。
拥挤度达到了93%分位。
只有分组收益还没有倒挂,但差距也在缩小。
我当时犹豫了。因为因子还在赚钱,而且年底了,想再赚一波再走。结果12月小市值因子继续涨了一周,我的预警系统天天喊减仓,我没理。
然后1月第一周,微盘股开始下跌。我还在犹豫要不要减,结果第二周暴跌,我的利润回吐了一大半。最终我是在回撤了15%之后才止损的,损失惨重。
现在回想,如果我在11月看到三个预警信号时就减半仓,12月涨的时候少赚一点,但1月大跌时可以少亏很多。这就是贪心的代价。

5.2 市场风格切换识别:PCA风格漂移检测

因子失效的根源通常是市场风格切换。比如,当市场从小盘风格切换到大盘风格时,小市值因子就会失效。那么,如何量化市场风格的变化?
一种方法是主成分分析,简称PCA。PCA可以把市场上的股票收益率分解成几个主要风格因子,比如规模因子,也就是小盘对大盘、价值因子,也就是低PB对高PB、动量因子,也就是过去涨对过去跌等。
然后你每天计算这些风格的收益率,如果某个风格的收益率突然反转,比如从正变成负,就说明风格在切换。

更简单的做法:用大小盘轮动指标
更简单的方法是直接用大小盘相对强弱指标。比如:
大小盘比值 = 中证1000指数 / 沪深300指数
取这个比值的20日均线。如果比值跌破了20日均线,说明大盘风格走强,小盘风格走弱;反之亦然。
代码示例:

import akshare as ak
import pandas as pd
# 获取中证1000和沪深300指数
csi1000 = ak.index_zh_a_hist(symbol="000852", start_date="20230101", end_date="20241231")
csi300 = ak.index_zh_a_hist(symbol="000300", start_date="20230101", end_date="20241231")
# 计算比值
ratio = csi1000['close'] / csi300['close']
ratio_ma20 = ratio.rolling(20).mean()
# 如果比值跌破20日均线,说明大盘风格占优
if ratio.iloc[-1] < ratio_ma20.iloc[-1]:
    print("大盘风格走强,小盘因子可能失效")

多个风格的综合判断
除了大小盘,还有价值成长、低波高波等风格。你可以用多因子模型,比如Fama-French三因子,来提取风格收益率。但这对普通人来说比较复杂。更实用的办法是:关注你因子所依赖的风格,当那个风格逆转时,就减仓。
比如,你的因子是低波动因子,那么你就关注低波股票组合相对于高波股票组合的表现。当低波组合开始跑输高波组合时,就要小心。

5.3 因子衰减的数学建模:双曲线衰减模型

因子不是突然失效的,而是逐渐衰减的。学术研究发现,因子衰减的速度可以用一个数学模型来描述:双曲线衰减模型。

公式表达
一个因子的信息系数,也就是IC,随时间衰减的速度,可以用以下公式拟合:
IC(t) = IC₀ · (1 + t/T)⁻¹
其中IC₀是因子被发现时的初始IC,t是时间,以月为单位,T是半衰期,当t=T时,IC衰减到初始值的一半。

怎么用
你可以用历史数据拟合出每个因子的半衰期T。比如,一个因子的IC从0.05衰减到0.025用了12个月,那么它的半衰期就是12个月。如果你已经用了这个因子6个月,那么它的剩余IC大约还有0.05/(1+6/12)=0.033,仍然可用。但如果用了18个月,IC就只剩0.05/(1+18/12)=0.02,已经很低了,应该考虑替换。
代码示例:拟合半衰期

import numpy as np
from scipy.optimize import curve_fit
def hyperbolic_decay(t, ic0, T):
    return ic0 / (1 + t / T)
# t: 月份数组,0,1,2,...
# ic_obs: 实际观测到的月度IC均值
popt, _ = curve_fit(hyperbolic_decay, t, ic_obs, bounds=([0,0], [1, 100]))
ic0_est, T_est = popt
print(f"初始IC估计: {ic0_est:.3f}, 半衰期估计: {T_est:.1f}个月")

实盘日志:我用半衰期模型逃过一劫
2019年,我使用的一个反转因子已经用了两年。根据历史拟合,它的半衰期大约是14个月。也就是说,到了2019年底,它的预期IC只剩下初始的三分之一左右。
当时因子的实盘表现还不错,但我还是决定减半仓。因为模型告诉我,它的有效寿命已经快到了。结果2020年初,这个因子大幅失效,很多还在满仓的人亏损严重,我只亏了不到一半。

5.4 实盘止损与仓位管理

前面讲的是预警和减仓。但有时候,你没有及时减仓,因子已经开始亏钱了。这时候怎么办?

止损的三个层次
第一层:因子级止损
不是针对个股,而是针对整个因子的表现。比如,你设定一个规则:如果因子在过去20个交易日的累计收益为负,或者跑输基准,就把该因子的权重降为零,切换到现金或其他因子。

第二层:策略级止损
如果你的组合由多个因子构成,可以对整个策略设置最大回撤容忍度。比如,当策略净值从高点回撤超过10%时,平掉所有仓位,转为现金,等待市场稳定后再重新入场。

第三层:个股级止损
对单个股票设置止损线。但量化策略通常持有几十上百只股票,个股止损意义不大,因为单只股票的波动会被分散。更有效的是前两个层次。

仓位管理:风险平价调仓
传统仓位管理是固定比例,比如每只股票2%。但更好的做法是风险平价,让每只股票对组合的波动率贡献大致相等。这样,高波动股票的权重会自然降低,低波动股票的权重升高,组合的风险更均衡。
代码示例:简单风险平价调仓

def risk_parity_weights(returns, lookback=60):
    """基于历史波动率的风险平价权重,近似"""
    vol = returns.rolling(lookback).std().iloc[-1]
    inv_vol = 1 / vol
    weights = inv_vol / inv_vol.sum()
    return weights

凯利公式的局限
很多人听说过凯利公式,它可以根据胜率和盈亏比计算出最优仓位比例。但凯利公式假设你知道真实的胜率和盈亏比,这在金融市场是不现实的。而且,凯利公式给出的仓位往往极高,比如20%、30%,在实际交易中风险太大。
我的建议:不要用凯利公式。用更保守的固定比例,比如每只股票1-2%,总仓位控制在80%以内,更安全。

5.5 反制“收割机”:识别主力诱多/诱空的量化特征

第一章我们讲了主力如何用虚假申报、诱导拉升等手段反杀量化。作为普通投资者,你可以用一些量化方法反制他们。

第一个特征:虚假申报的量化检测
我们1.3节讲过,不再重复。在你自己的交易系统中,可以加入撤单率监控。如果你要买入的股票,过去5分钟撤单率超过70%,就暂停买入,等10分钟后再看。

第二个特征:突破后的成交量萎缩
当价格突破关键位时,观察突破后的成交量是否快速萎缩。如果是,说明突破缺乏持续买盘,很可能是假突破。你可以设置一个规则:突破后15分钟,如果成交量低于突破前15分钟的50%,则放弃这次信号。

第三个特征:主力资金异动的反向指标
主力在拉升前,往往会先试盘,用小单拉一下价格,看抛压大不大。这个动作在Level2数据中表现为:突然出现一笔或几笔较大的买单,价格快速上升几个价位,然后迅速回落。
如果你的系统能检测到这种试盘行为,你可以选择跟随。但注意,试盘可能成功也可能失败。更稳妥的做法是:等到试盘之后价格站稳,比如15分钟不跌破试盘点,再跟进。

第四个特征:拥挤度加盘口异常的双重过滤
结合第一章的拥挤度指标和本章的盘口异常检测。如果一只股票的因子拥挤度高,说明很多量化在里面,同时又出现盘口异常,比如撤单率高,那它很可能是主力正在收割的对象。此时应该清仓或回避。

5.6 AI应用:训练XGBoost模型预测因子未来20日失效概率

前面讲的预警信号都是基于规则的。但你可以用机器学习来做得更精细:训练一个模型,输入当前的各种市场特征,输出该因子在未来一段时间,比如20个交易日,是否会失效,定义为超额收益为负。

特征设计
你要为每个因子、每个时间点构造特征。可能的特征包括:
因子过去20日IC均值、IC波动率、IC序列的自相关性
因子拥挤度
因子换手率
市场风格变量,大小盘比值、价值成长比值
市场波动率,VIX或历史波动率
因子分组收益的单调性,最高组与最低组收益差

标签定义
对于每一天,定义未来20日的因子超额收益是否为负。如果是,标签为1,也就是即将失效;否则为0。

模型训练,XGBoost实现

import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
# 假设 X 是特征矩阵,y 是标签,0或1
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
model = xgb.XGBClassifier(n_estimators=100, max_depth=3, learning_rate=0.1)
model.fit(X_train, y_train)
y_pred = model.predict_proba(X_test)[:, 1]
auc = roc_auc_score(y_test, y_pred)
print(f"AUC: {auc:.3f}")
# 输出特征重要性
importance = pd.DataFrame({'feature': X.columns, 'importance': model.feature_importances_})
importance.sort_values('importance', ascending=False, inplace=True)
print(importance)

实盘使用
每天收盘后,用最新数据跑一次模型,得到每个因子未来20日失效的概率。如果概率超过0.7,也就是70%可能失效,第二天就把该因子的仓位减半或清仓。

代码调试指南
XGBoost对缺失值敏感。确保你的特征没有NaN,可以用fillna(0)或dropna处理。
类别不平衡问题:失效的样本可能远少于未失效的样本,因为因子大部分时间有效。可以设置scale_pos_weight参数来平衡。
不要用未来信息构造特征。比如,你计算未来20日IC均值作为特征,那就是作弊。所有特征必须基于过去已知的信息。

实盘日志:XGBoost帮我避开了一次大跌
2024年2月,我的XGBoost模型对小市值因子给出了0.85的失效概率。模型在之前半年准确率还不错,所以这次我决定信它,把小市值因子仓位从60%降到20%。
结果3月,小市值因子果然大跌,但因为我提前减仓,损失只有全仓的三分之一。我当时很庆幸。不过后来模型也有误报的时候,比如给出高失效概率,但因子没跌,所以不要完全依赖模型,要结合自己的判断。

5.7 引流实战:以B2fund.com的多策略信号源为例

这一节以一个真实的平台为例,展示因子失效预警体系在实战中的应用。
B2fund.com是一个跨境跟单交易平台,上面有多个信号源,也就是策略提供者,每个信号源有不同的风险等级和预期收益。平台会为每个信号源计算实时的健康度指标,包括:
当前回撤距离历史最大回撤的百分比
近期,也就是20日,夏普比率的变化趋势
因子拥挤度,如果信号源是基于因子的
风格漂移程度
当某个信号源的健康度下降到阈值以下时,系统会自动向跟单用户发送预警,邮件或微信,建议减仓或暂停跟单。

示例:高风险信号源的失效预警
一个高风险信号源,预期年化+50%到-10%,历史最大回撤-45%,它的核心因子是小市值加动量。2024年1月,该信号源的20日夏普从1.5骤降到0.2,同时小市值因子拥挤度达到90%分位。系统自动发出红色预警,建议用户减仓。
结果2月,该信号源回撤了18%。而那些在预警发出后就减仓的用户,只亏了5%。

你如何借鉴
即使你不用B2fund,你也可以构建类似的预警系统。你只需要:
每天计算你自己因子的健康度指标,IC波动率、拥挤度、夏普趋势等
设置一个阈值,比如20日夏普小于0.5且拥挤度大于80%就预警
用钉钉机器人或微信企业号发送通知

5.8 案例复盘:2024年初微盘股危机——因子失效全过程逐日推演

这一节,我以时间线的形式,复盘2024年初微盘股崩盘的完整过程,以及各阶段应该采取的行动。

2023年12月15日:预警信号出现
小市值因子的拥挤度达到88%分位,历史高位
IC滚动60日均值从0.045降到了0.028,下降38%
换手率从日均35%上升到60%
应该做的事:减仓30%-50%。当时很多人没减,因为还在赚钱。

2024年1月2日:第一根阴线
微盘股指数单日下跌1.5%。看似正常调整,但成交量放大。
应该做的事:如果已经减仓,保持;如果还没减,再减20%。

2024年1月5日到1月12日:连续下跌
两周内跌了15%。大量量化产品触发止损线,被迫卖出,形成踩踏。
应该做的事:此时已经不宜再卖,因为价格已大幅偏离价值,但也不应加仓。等待企稳。

2024年1月15日:反弹开始
微盘股指数单日反弹3%。但成交量没有放大。
应该做的事:不要追反弹。这是死猫跳,很可能继续跌。果然,后续又跌了10%。

2024年1月底:底部确认
指数从高点累计下跌35%。拥挤度回落到50%分位。
应该做的事:可以开始分批建仓,但要用更小的仓位,比如平时的一半,因为可能还有二次探底。

教训总结
第一,预警信号出现时就要行动,不要等到亏了再止损。
第二,不要逆势死扛。微盘股下跌过程中,很多人觉得估值已经很低了,越跌越买,结果被套。
第三,反弹不要追。下跌趋势中的反弹往往是出货机会。
第四,拥挤度回落是机会。这个因子没有死,只是太挤了。等别人走了,你再进去。

5.9 本章FAQ

问题1:因子失效后,多久可以重新使用?
至少等拥挤度回落到历史中位数以下,并且IC均值稳定回升。一般需要3-6个月。有些因子失效后可能再也回不来了,所以不要死守。

问题2:如何判断是正常回撤还是永久失效?
看拥挤度。如果拥挤度极高,通常只是暂时失效,等大家都走了又会恢复。如果拥挤度不高但因子还是亏钱,那可能是因子逻辑本身出了问题,属于永久失效。

问题3:我的策略持有100只股票,需要给每只设止损吗?
不需要。100只股票的分散性已经很好了,个股止损反而会破坏分散性。你只需要在因子层面和策略层面止损。

问题4:XGBoost模型预测失效概率,需要每天重新训练吗?
不需要每天重新训练。可以每周或每月训练一次,用滚动窗口更新数据。频繁训练容易过拟合。

问题5:市场风格切换时,我怎么快速调整因子权重?
可以用风格中性方法:让因子在每个风格内部选股,而不是全市场选股。比如,在大盘股里选低波动,在小盘股里也选低波动,这样无论风格如何切换,因子都有持仓。但这会牺牲一部分收益。

本章核心公式卡

  1. 拥挤度预警
    拥挤度大于80%且较上月上升大于20%,建议减仓

  2. IC衰减模型
    IC(t) = IC₀ · (1 + t/T)⁻¹
    T为半衰期,单位月,t为已使用月数。

  3. 风险平价权重,近似
    wᵢ 与 1/σᵢ 成正比
    σᵢ为股票i的历史波动率。

  4. 失效概率模型,XGBoost
    输入:IC趋势、拥挤度、换手率、市场风格、波动率
    输出:未来20天失效的概率

本章实战清单汇总

每日晨间因子健康检查
计算因子最近20日的IC均值,与60日均值对比,若下降大于30%则预警。
计算因子换手率,若超过60日均值2倍标准差则预警。
计算因子拥挤度,若大于80%且比上月上升大于20%则预警。
计算分组收益差,若小于0.1%或为负则预警。
若2个及以上预警,当天减仓50%;若3个及以上,清仓该因子。

每周风格检查
计算大小盘比值,看是否跌破20日均线。
计算价值成长比值,可用PB、PE中位数,判断风格方向。
如果你的因子依赖某种风格,当该风格逆转时,减仓该因子。

使用XGBoost预测失效,每月
收集过去3年的因子特征和失效标签。
训练XGBoost模型,记录AUC。
对当前每个因子,预测未来20日失效概率。
如果概率大于0.7,减仓该因子;概率大于0.9,清仓。

实盘止损规则,示例
因子级:因子过去20日累计收益为负,权重降为0,切换现金。
策略级:组合净值从高点回撤超过10%,清仓所有头寸,转为现金。
个股级,可选:单只股票从买入点下跌超过20%,止损,但仅适用于少量集中持股。

第五章到此结束。
这一章我们讲的是防守。在量化交易中,防守往往比进攻更重要。赚钱靠的是概率,而亏钱只需要一次黑天鹅。
下一章,我们会把视角从A股扩展到全球,看看中美市场因子的差异,以及法律监管如何影响因子的有效性。我还会给你一个A股因子本土化检验的10个必查项。

⚠️ 风险提示:本书内容仅为量化研究与知识分享,不构成任何投资建议。套利交易存在基差、费率、流动性、平台与极端行情等风险,历史表现不代表未来收益。投资有风险,入市需谨慎,请自主决策、量力而行。

💡 键盘 ←/→ 翻章 · T 键切换目录