halo 的技术博客

返回

上一篇文章我们讲了「博彩偏好异象」:散户爱买彩票型股票,而高 MAX 股票长期跑输。但那篇是横截面快照——给你一个时点的分组结果。真正想把它用进组合,得回答三个更硬的问题:

  1. 如果每月末都按 MAX 重新分组、多空对冲,因子净值长什么样?
  2. 它的预测力每个月都稳吗?还是只在特定年份灵?
  3. MAX 和我们已经熟知的动量是不是同一回事?会不会只是动量的马甲?

这篇文章就是把 MAX 从「一个异象」升级成「一个因子」——给它装上时间维度,跑一遍面板回测,并老老实实把它的不稳定性拆给你看。

数据声明:全文收益序列为自洽合成(每只股票带偶发巨阳线的「彩票跳涨」,未来 1 月收益被设定为随 MAX 单调下降),目的是把因子构建与检验的机制跑通、可复现。所有量级(年化、IC、终值)均为合成校准下的量级,真实市场里会被卖空成本、涨跌停、幸存者偏差大幅压缩——重点看结构与方法,不抄量级。

一、从「异象」到「因子」:差在哪#

异象(anomaly)回答的是「截面里有没有这个现象」;因子(factor)回答的是「我能不能持续地、可复制地用它赚钱」。

差三件事:

  • 时间维度:异象看一个快照,因子要每个月都做一次,形成一条净值曲线。
  • 可交易性:因子必须处理「怎么买、怎么卖、空头腿怎么建」——异象可以只做多。
  • 稳定性检验:因子要逐期算 IC(信息系数),看预测力是不是在大部分时间都成立。

MAX 因子的核心假设不变:MAX 越高 → 博彩溢价越厚 → 未来 1 月收益越低。下面用 Python 搭一个 N=500 只股票 × M=120 个月(约 10 年)的面板。

面板散点:MAX 越高,未来 1 月收益越低(负斜率)

散点把「异象」又画了一遍,但这次是全样本每个月混在一起的 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 空:长期为正但波动不小肠

合成校准下,因子净值长期向上,但中途有明显回撤。这和「静态分组看图」很不一样——净值曲线会暴露换仓时的失效期。注意左图里那条虚线是「仅低 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

逐月 rank-IC:均值显著为正,但频繁转负

合成校准下 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 /= M
python

MAX × 动量二维分组:每行(固定 MAX)内仍有动量梯度,每列(固定动量)内 MAX 效应独立

热力图读法是:看每一行(固定 MAX 分组),从左到右动量 Q1→Q5 收益是否递增;看每一列(固定动量分组),从上到下 MAX Q1→Q5 收益是否递减

合成结果:两个方向都成立,且互不抵消。说明 MAX 捕捉的是「彩票跳涨带来的博彩溢价」,动量捕捉的是「价格惯性」,二者是正交的两类信息——MAX 不是动量的马甲,可以并列进多因子模型。

五、四类真实陷阱(必须诚实拆穿)#

  1. IC 频繁转负:上面已经看见,MAX 因子的预测力是统计性的、非单调的。在动量崩溃期或散户风险偏好高涨期,高 MAX 股票反而可能继续涨,因子连续回撤。绝不能单因子满仓
  2. 卖空不可得:高 MAX 股票往往是小盘、高换手、融券最贵的标的。空头腿的借券成本 + 涨时逼空,会把「理论上稳赚」的空头收益磨掉一大块,甚至会变成「多头赚小钱、空头亏大钱」。
  3. 涨跌停 / 流动性门槛:A 股有 ±10%(创业板 ±20%)涨跌停,极端 MAX 当天可能封板,你根本买不到/卖不出;且这类票流动性薄,大资金进出冲击成本极高。面板回测里的「无摩擦成交」是最大幻觉。
  4. 幸存者偏差:合成数据没有退市,但真实里高 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 因子的魅力在于它极简、行为金融底子硬、几十年跨市场存在。但它的代价是不稳定、难做空、易被偏差美化。把它当「彩票税」的反向收割机,纪律比模型更重要。

博彩偏好与最大日收益因子 MAX:把彩票性做成可交易的横截面因子
https://blog.halo26812.eu.org/blog/lottery-max-factor
Author halo
Published at 2026年7月20日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨