上一篇文章我们讲了「博彩偏好异象」:散户爱买彩票型股票,而高 MAX 股票长期跑输。但那篇是横截面快照——给你一个时点的分组结果。真正想把它用进组合,得回答三个更硬的问题:
- 如果每月末都按 MAX 重新分组、多空对冲,因子净值长什么样?
- 它的预测力每个月都稳吗?还是只在特定年份灵?
- MAX 和我们已经熟知的动量是不是同一回事?会不会只是动量的马甲?
这篇文章就是把 MAX 从「一个异象」升级成「一个因子」——给它装上时间维度,跑一遍面板回测,并老老实实把它的不稳定性拆给你看。
数据声明:全文收益序列为自洽合成(每只股票带偶发巨阳线的「彩票跳涨」,未来 1 月收益被设定为随 MAX 单调下降),目的是把因子构建与检验的机制跑通、可复现。所有量级(年化、IC、终值)均为合成校准下的量级,真实市场里会被卖空成本、涨跌停、幸存者偏差大幅压缩——重点看结构与方法,不抄量级。
一、从「异象」到「因子」:差在哪#
异象(anomaly)回答的是「截面里有没有这个现象」;因子(factor)回答的是「我能不能持续地、可复制地用它赚钱」。
差三件事:
- 时间维度:异象看一个快照,因子要每个月都做一次,形成一条净值曲线。
- 可交易性:因子必须处理「怎么买、怎么卖、空头腿怎么建」——异象可以只做多。
- 稳定性检验:因子要逐期算 IC(信息系数),看预测力是不是在大部分时间都成立。
MAX 因子的核心假设不变:MAX 越高 → 博彩溢价越厚 → 未来 1 月收益越低。下面用 Python 搭一个 N=500 只股票 × M=120 个月(约 10 年)的面板。
import numpy as np
def simulate_panel(N=500, M=120, T=21, seed=20260720):
rng = np.random.default_rng(seed)
base_p = rng.uniform(0.02, 0.28, size=N) # 每只股票的「彩票倾向」基线
mkt = rng.normal(0.004, 0.035, size=M) # 月度市场收益(牛熊切换)
drift = rng.normal(0.003, 0.012, size=(N, M)) # 月度特质漂移
MAX = np.zeros((N, M)); future = np.zeros((N, M)); mom = np.zeros((N, M))
for t in range(M):
p = np.clip(base_p * (1.0 + 0.4 * (mkt[t] < 0)), 0.01, 0.5) # 熊市更赌
jumps = (rng.random((N, T)) < p[:, None]) * rng.exponential(0.05, size=(N, T))
daily = rng.normal(0, 0.022, size=(N, T)) + jumps
MAX[:, t] = daily.max(axis=1) # 过去 21 日最大单日收益
future[:, t] = (0.010 - 0.16 * MAX[:, t] # 核心:随 MAX 单调下降
+ 0.35 * mkt[t] + drift[:, t]
+ rng.normal(0, 0.05, size=N))
if t >= 12:
mom[:, t] = future[:, t-12:t].mean() # 过去 12 月动量
return MAX, future, mom, mkt
MAX, future, mom, mkt = simulate_panel()python
散点把「异象」又画了一遍,但这次是全样本每个月混在一起的 6 万点。拟合线负斜率清晰——这是因子成立的前提。
二、月度再平衡的多空因子净值#
每月末,把 500 只按 MAX 排序,做多最低十分位(50 只)、做空最高十分位(50 只),等权、月度换仓:
M = MAX.shape[1]
ls_ret = np.zeros(M)
for t in range(M):
order = np.argsort(MAX[:, t])
long_ret = future[order[:50], t].mean() # 低 MAX → 多头
short_ret = future[order[-50:], t].mean() # 高 MAX → 空头
ls_ret[t] = long_ret - short_ret
ls_cum = np.cumprod(1 + ls_ret)python
合成校准下,因子净值长期向上,但中途有明显回撤。这和「静态分组看图」很不一样——净值曲线会暴露换仓时的失效期。注意左图里那条虚线是「仅低 MAX 多头」:它也能赚,但波动更大,说明空头腿(高 MAX)确实贡献了对冲。
三、IC 稳定性:因子最该被审的地方#
单看净值曲线容易被平均掩盖。真正检验因子,要看逐月 rank-IC——每个月 MAX 排序与未来收益的排序相关系数。IC 稳定为正,因子才可信;如果经常转负,说明它在「赌风格」。
ic = np.array([np.corrcoef(MAX[:, t].argsort().argsort(),
future[:, t].argsort().argsort())[0, 1]
for t in range(M)])
ic_mean, ic_std = ic.mean(), ic.std()
ic_ir = ic_mean / ic_std # 信息比率python
合成校准下 IC 均值约为 −0.13(符号为负,因为 MAX 越高收益越低,这里取的是「MAX 排序 vs 收益排序」的相关系数,方向与因子定义一致),IR 约 −2.4。关键不是均值,是红绿交替——有相当比例的月份 IC 翻正(即高 MAX 反而涨),这就是 MAX 因子最大的软肋:它赚的是长期统计优势,单月会连续失效。
实操含义:MAX 因子不适合单独满仓做,更适合作为多因子里的一个「负向权重维度」,或配合止损/市值中性化使用。
四、二维分组:MAX 是不是动量的马甲#
有人会质疑:MAX 高的股票往往刚涨过一根大阳线,那它不就是动量吗?用 MAX × 动量二维分组(各五分位)验证冗余度:
def quintile_labels(x):
order = np.argsort(np.argsort(x))
return (order * 5 // len(x)).clip(0, 4)
Q = 5; avg = np.zeros((Q, Q))
for t in range(M):
qi = quintile_labels(MAX[:, t]); qj = quintile_labels(mom[:, t])
for i in range(Q):
for j in range(Q):
m = (qi == i) & (qj == j)
if m.sum() > 0:
avg[i, j] += future[:, t][m].mean()
avg /= Mpython
热力图读法是:看每一行(固定 MAX 分组),从左到右动量 Q1→Q5 收益是否递增;看每一列(固定动量分组),从上到下 MAX Q1→Q5 收益是否递减。
合成结果:两个方向都成立,且互不抵消。说明 MAX 捕捉的是「彩票跳涨带来的博彩溢价」,动量捕捉的是「价格惯性」,二者是正交的两类信息——MAX 不是动量的马甲,可以并列进多因子模型。
五、四类真实陷阱(必须诚实拆穿)#
- IC 频繁转负:上面已经看见,MAX 因子的预测力是统计性的、非单调的。在动量崩溃期或散户风险偏好高涨期,高 MAX 股票反而可能继续涨,因子连续回撤。绝不能单因子满仓。
- 卖空不可得:高 MAX 股票往往是小盘、高换手、融券最贵的标的。空头腿的借券成本 + 涨时逼空,会把「理论上稳赚」的空头收益磨掉一大块,甚至会变成「多头赚小钱、空头亏大钱」。
- 涨跌停 / 流动性门槛:A 股有 ±10%(创业板 ±20%)涨跌停,极端 MAX 当天可能封板,你根本买不到/卖不出;且这类票流动性薄,大资金进出冲击成本极高。面板回测里的「无摩擦成交」是最大幻觉。
- 幸存者偏差:合成数据没有退市,但真实里高 MAX 的彩票股更容易最终退市归零。回测只看到活下来的,把「死掉的那批」的巨亏删掉了,会系统性高估因子收益。
五之二、换手率与容量:因子能不能装上规模#
面板回测里「每月完美换仓」默认了零成本。真实里 MAX 因子的换手率极高——低 MAX 池和高 MAX 池每个月都有近一半股票进出,双边换手常年在 100%~200%/月。按 0.1% 单边成本算,光交易成本一年就能吞掉因子收益的 20%~40%。更现实的做法是设置换手阈值:只有 MAX 排序跨过十分位边界才调仓,或用 3 月滚动窗口平滑信号,把月度换手压到 50% 以下。容量上,低 MAX 池往往偏大票(平淡无奇的蓝筹),容量反而比高 MAX 池好;真正卡容量的是空头腿——小盘彩票股根本接不住大资金,所以机构通常用股指期货/ETF 近似替代空头,或干脆只做多低 MAX 池。
六、落地建议(不是代码,是纪律)#
- 方向:把 MAX 当负向因子——在低 MAX 股票池里做多,而不是去硬做空高 MAX。
- 中性化:务必对市值、行业做中性化,否则 MAX 因子会偷偷暴露小盘风格。
- 频率:月度换仓足够,日频换仓会被交易成本吃掉。
- 组合:和动量、低波、质量并列,用 IC 加权或风险平价,别单押。
文末路径(真实落地,替换合成数据):MAX 用个股过去 21 个交易日日收益率的
max();未来收益用真实复权月收益;分组前对市值/行业做中性化;空头腿用股指期货或 ETF 近似替代,或干脆只做多低 MAX 池。因子 IC、分组收益、回撤全部重算——合成只是把方法跑通。
七、与低波动因子的关系:同源异象#
MAX 因子和经典的低波动异象常被放在一起看,因为它们指向同一个行为根源:散户对高波动/高刺激资产的超额需求。低波动因子做多「平淡低波」、MAX 因子做多「无彩票感」,二者多头池高度重叠。区别在于杠杆与可交易性:低波动池容量大、做空端(高波动)反而流动性好,所以低波动因子更易落地;MAX 的空头端是流动性最差的小盘彩票股,所以 MAX 更适合只做多。实务上把二者合成一个「防御-反博彩」复合维度,比单押任一个更稳。
MAX 因子的魅力在于它极简、行为金融底子硬、几十年跨市场存在。但它的代价是不稳定、难做空、易被偏差美化。把它当「彩票税」的反向收割机,纪律比模型更重要。