Anticor 反相关组合:把资金从刚涨过的资产搬去反相关的落后者
Anticor(Borodin-El-Yaniv-Gogan 2004)是在线组合选择里的『统计套利派』:它不追求 Cover/ONS 那种最坏情况遗憾界,而是直接押注一个可证伪的经验假设——资产间存在滞后交叉相关,刚跑赢的资产的动能会传导给与它正相关滞后的资产。算法用相邻两个窗口的交叉相关矩阵决定资金搬运方向:后窗口里 i 跑赢 j 且 corr(i前,j后)>0,就把 i 的部分权重搬给 j。1500 日 60 日块轮动市场实测:w=90 时终值 10.62,把事后最优 CRP(1.42)按在地上摩擦——但窗口敏感性扫描揭示这是刀尖上的收益:w=8 时终值 0.03(亏掉 97%),从 0.03 到 10.62 横跨 300 倍,w 与轮动周期的匹配是生死线。趋势市对照:单边行情下 Anticor 终值 1.04 vs 买入持有强者 1.27——反复给落后者输血是均值回归策略在趋势世界的结构性税负。三盆冷水:无任何遗憾保证(错误市场里可以亏到接近归零)、窗口选择本质是对轮动周期的隐性预测、日均 4% 换手在成本下的生存空间。与 Cover/EG/ONS 的世界观分野:保证派 vs 押注派,Anticor 赢的时候赢得多,输的时候没有底。
一句话版本#
Anticor 的全部逻辑就是标题那句话:把资金从刚涨过的资产搬去和它反相关(准确说:正滞后相关)的落后者。它赌的是资产轮动——A 涨完轮到 B 涨。赌对了收益惊人,赌错了没有任何理论兜底。
从『保证派』到『押注派』#
这个系列前面写过的 Cover 通用组合、ONS 在线牛顿步、CORN 模式匹配,本质上都是保证派:先证明一个最坏情况遗憾界(“不管市场多恶劣,我不会输事后最优 CRP 太多”),再谈实际表现。
Borodin、El-Yaniv 和 Gogan 在 2004 年的 Anticor 论文里做了一个刺头式的选择:放弃遗憾界,直接押注一个经验假设。这个假设是:
金融资产之间存在滞后交叉相关(lagged cross-correlation):如果资产 i 在上一个窗口跑赢、且 i 的历史涨跌与 j 的后续涨跌正相关,那么 i 的动能大概率会”传导”给 j——现在应该把钱从 i 搬到 j 去等着。
注意这不是玄学,是可证伪的统计命题。有意思的是论文的实证结果:在 NYSE 历史数据上,Anticor 把所有带遗憾保证的算法(包括 Cover UP)打得找不着北。这引出一个直到今天还在被讨论的问题:理论保证和实际收益,到底哪个更值钱?
算法:两个窗口,一个交叉相关矩阵#
Anticor 每天做一次决策,材料只有两段历史:
- 前窗口 LX1:第 t-2w 到 t-w 天的对数收益
- 后窗口 LX2:第 t-w 到 t 天的对数收益
用这两段算一个 m×m 的交叉相关矩阵 M_cor:第 (i,j) 元是”i 在前窗口的收益”与”j 在后窗口的收益”的相关系数。M_cor[i][j] > 0 意味着:历史上 i 先动,j 跟着动。
然后是资金搬运规则。资产 i 要向资产 j 转移权重,需要同时满足两个条件:
- i 最近跑赢了 j:后窗口里 i 的平均收益 ≥ j 的
- i 领先 j:M_cor[i][j] > 0
转移量正比于 claim(i→j) = M_cor[i][j] + 惩罚项。惩罚项是 i 和 j 各自的负自相关部分——如果 i 自己在均值回归(corr(i前, i后) < 0),说明 i 的涨势更不可持续,搬得更多。
def anticor_weights(X, w):
"""Borodin-El-Yaniv-Gogan 2004.
X: (T, m) 价格相对比(今收/昨收),返回每日权重矩阵"""
T, m = X.shape
b = np.ones(m) / m
B = np.zeros((T, m))
logX = np.log(X)
for t in range(T):
B[t] = b
if t >= 2 * w:
LX1 = logX[t-2*w : t-w] # 前窗口
LX2 = logX[t-w : t] # 后窗口
mu1, mu2 = LX1.mean(0), LX2.mean(0)
s1, s2 = LX1.std(0, ddof=1), LX2.std(0, ddof=1)
Mcov = (LX1 - mu1).T @ (LX2 - mu2) / (w - 1)
Mcor = np.nan_to_num(Mcov / np.outer(s1, s2))
claim = np.zeros((m, m))
for i in range(m):
for j in range(m):
if i != j and mu2[i] >= mu2[j] and Mcor[i, j] > 0:
claim[i, j] = (Mcor[i, j]
+ max(0, -Mcor[i, i]) # i 自身均值回归 → 多搬
+ max(0, -Mcor[j, j])) # j 自身均值回归 → 多接
transfer = np.zeros((m, m))
for i in range(m):
tot = claim[i].sum()
if tot > 0:
transfer[i] = b[i] * claim[i] / tot
b = b - transfer.sum(1) + transfer.sum(0)
b = np.maximum(b, 0); b /= b.sum()
return Bpython整个算法没有任何优化步骤——没有梯度、没有投影、没有先验混合。它就是一个基于交叉相关的资金调度器。
实验:60 日块轮动市场#
合成一个 Anticor 理论上的主场:两个资产,领涨权每 60 天交接一次(方波轮动),领涨方日均漂移 +44bp、落后方 -36bp,波动率相同(1.2%)。跑 1500 天:

| 策略 | 终值 |
|---|---|
| Anticor (w=90) | 10.62 |
| 事后最优 CRP(b*=1.00,全仓资产1) | 1.42 |
| 买入持有资产 1 | 1.42 |
| 50/50 每日再平衡 | 1.09 |
| 买入持有资产 2 | 0.73 |
Anticor 终值是事后最优 CRP 的 7.5 倍。这不是 bug——CRP 是常数再平衡,它的表达能力上限就是”固定比例”,而这个市场的赚钱机会恰恰在于换边。Anticor 的对标根本不该是 BCRP,而是”每次轮动都踩对”的先知换边策略。这一点和 CORN 的结论完全一致:自适应算法的正确基准是条件最优,不是常数最优。
权重轨迹把机制看得很清楚:

资产 1 进入劣势相位后,Anticor 的资产 1 权重开始爬升——它在提前给下一个领涨者建仓。这正是”把资金搬去反相关的落后者”的字面意思:现在的落后者是下一轮的领涨者,而交叉相关矩阵就是探测这种交接的雷达。
窗口敏感性:从 0.03 到 10.62 的生死线#
同一个市场、同一个算法,只扫窗口长度 w:

| w | 3 | 5 | 8 | 10 | 15 | 20 | 30 | 45 | 60 | 90 | 120 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 终值 | 0.07 | 0.04 | 0.03 | 0.03 | 0.09 | 0.12 | 0.44 | 1.28 | 1.69 | 10.62 | 0.83 |
从亏掉 97% 到赚 10 倍,横跨 300 倍,只差一个超参数。机制不难理解:
- w 太短(< 轮动周期的一半):两个窗口都落在同一个轮动块内,交叉相关探测到的是块内噪声,Anticor 在错误的时机反复搬钱——每次搬运都是在给正在领涨的资产撤资。这不是”不赚钱”,是系统性反向操作。
- w ≈ 1.5 倍块长(w=90,块长 60):前后窗口恰好各自跨越相位交接,交叉相关矩阵能干净地捕捉”i 涨完 j 涨”的接力结构。
- w 太长(w=120 = 2 倍块长):每个窗口内部包含整数个完整轮动周期,相位信息被平均抵消,信号消失。
这张表是全文最重要的一张表。它说明 Anticor 的窗口选择本质上是对轮动周期的隐性预测——你以为你只是在调超参数,实际上你在回答”这个市场多少天换一次风格”这个没人能稳定答对的问题。实务上的缓解方案和 CORN 一样:跑一个专家池(BAH(Anticor) 组合多个 w 取财富加权),论文里也正是这么做的——代价是收益被平均稀释。
趋势市对照:均值回归策略的结构性税负#
把市场换成单边趋势:资产 1 日均 +9bp 持续跑赢,资产 2 只有 +1bp,没有任何轮动。

Anticor 终值 1.04,买入持有强者 1.27,50/50 也有 1.15。Anticor 在这个世界里做的事情是:强者每涨一段,它就把利润搬去给弱者”等轮动”——而轮动永远不来。每一次搬运都是一次小额献血。
这和 CORN 在无模式市场跑输 50/50 是同一类现象的不同侧面:押注派算法在假设不成立的世界里不是无害退化,而是持续为假设付费。Anticor 的论文标题里有一句很诚实的话——“can we beat the best CRP?”——答案是:能,在轮动市场里;但在趋势市场里,你连最笨的买入持有都跑不过。
三盆冷水#
第一盆:没有遗憾保证意味着没有底。 Cover UP 最差也只输 BCRP 一个多项式因子,Anticor 在错配窗口下可以亏到 0.03。这不是理论洁癖——窗口扫描表里 w=8 那一格就是活生生的例子。把 Anticor 用在真实市场前,你必须回答:如果市场风格从 60 日轮动漂移到 200 日轮动,我的止损机制是什么?算法本身不提供任何。
第二盆:日均 4.1% 的单边换手。 本实验里 w=90 的 Anticor 日均换手 4.1%,按单边 10bp 成本算每天磨掉约 0.4bp,1500 天累计吃掉约 6% 对数财富——在 10 倍收益面前不致命。但真实市场的轮动强度远弱于本实验的 ±40bp 日漂移差,信号变弱后换手不会等比例下降(交叉相关的噪声部分仍在驱动搬运),成本占信号的比例会急剧恶化。
第三盆:滞后交叉相关在真实市场里既弱又不稳定。 本实验的方波轮动是教科书设定。真实市场的领先滞后关系(参考高频领先滞后那篇)强度低一个数量级、还会随 regime 变号。2004 年论文里 NYSE 数据上的惊人表现,后续研究发现相当部分来自幸存者偏差严重的老数据集和零成本假设。Anticor 是一个漂亮的机制原型,不是一个可以直接上生产的策略。
A 股注记#
A 股的行业轮动叙事(“喝酒吃药 → 新能源 → AI”)表面上是 Anticor 的完美主场,但有三个落地约束:T+1 使当日搬运次日才能完成,轮动交接期的一两天恰恰是信号最强的时候;个股涨跌停会让交叉相关矩阵在最需要它的极端日失真;以及 A 股风格轮动周期本身极不稳定(几周到几年都有),窗口错配风险比本实验更严重。相对可行的用法是把 Anticor 的 claim 矩阵降级为轮动监测指标而非直接的调仓指令。
与保证派的世界观对照#
| Cover UP / ONS / EG | Anticor | |
|---|---|---|
| 理论保证 | 最坏情况遗憾界 | 无 |
| 押注假设 | 无(对抗性市场也成立) | 滞后交叉相关存在 |
| 假设成立时 | 温和跟上 BCRP | 大幅超越 BCRP |
| 假设失效时 | 仍不输 BCRP 太多 | 可以亏到接近归零 |
| 超参数风险 | 低(学习率影响温和) | 致命(w 错配 = 300 倍差距) |
这两派没有谁对谁错——它们是风险偏好的两端。保证派卖的是保险,押注派卖的是杠杆。真正危险的是拿着押注派的收益曲线、以为自己买了保证派的保险。
下一篇会看 Discord 异常子序列:把 Matrix Profile 反过来用,找的不是”重复出现的形态”,而是”全序列独一无二的片段”。