共形预测在量化中的应用:给预测区间一个可验证的覆盖率保证
你的模型说明天涨 3%,但你心里没底:这 3% 的置信区间到底多宽?传统误差带要么假设高斯、要么靠经验拍脑袋,一旦分布漂移就崩。共形预测(Conformal Prediction)换了一条路:不假设分布,只用「校准集上的残差分位」构造区间,并且能**在数学上保证**测试集里 (1−α) 比例的点落在区间内。本文用异方差 + 分布漂移的合成数据,从零跑出区间覆盖、有限样本有效性、漂移下朴素法漏覆盖,以及区间宽度 vs 确定性的代价曲线(中阶)。
你的模型输出:明天涨 3%。但 3% 的置信区间是多少?是 [2.9%, 3.1%],还是 [−5%, +11%]?这两者的可交易性天差地别。
传统做法要么假设残差高斯(市场偏偏厚尾异方差),要么用训练残差拍个经验带宽(一旦分布漂移立刻过窄)。共形预测(Conformal Prediction) 绕开了分布假设:它只问一句——「校准集上,有多少比例的残差小于某个阈值?」——用这个经验分位直接构造区间,并且理论上能保证:测试集里至少 (1−α) 比例的点落在区间内。
这不是玄学保证,是有限样本、分布无关的覆盖定理。本文用异方差 + 波动翻倍的漂移数据,从零复现它,并诚实展示它的边界。
一、核心思想:用分位「校准」不确定性#
共形预测最经典的玩法是 Split Conformal(交叉拟合),三步:
- 训练:在训练集上拟合任意模型 (树、梯度提升、神经网络都行);
- 校准:在独立的校准集上算残差 ,取分位 为做有限样本校正,用 分位而非朴素 ;
- 预测:对新点 ,给区间 。
保证:在交换性(大致=「测试数据和训练/校准同分布」)下, 注意是「≥」——分布越乖,实际覆盖越接近名义值。
二、异方差下,区间会自己变宽变窄#
真实市场波动率会聚类(波动大了更大)。我们构造 随特征变化的数据,看共形区间如何自适应:

图上区间带在波动大的区域(右侧)自动变宽,在平稳区变窄。本次实验经验覆盖 89.0%,几乎贴上目标 90%——这正是共形预测的卖点:区间形状由数据说了算,不靠你假设高斯。
三、有限样本有效性:经验覆盖贴在名义线上#
把多次随机划分都跑一遍,看不同名义水平下经验覆盖的均值 ± 标准差:

数字:名义 0.80→经验 0.798、0.85→0.847、0.90→0.899、0.95→0.950。点几乎压在对角线上——这证明了共形预测的「无条件有效性」不是大样本幻觉,几百个样本就够稳。
四、分布漂移:朴素法漏覆盖,共形法扛得住#
这是最扎心也最实用的场景。训练/校准来自「波动尺度=1」,测试集来自「波动翻倍」:
- 朴素法:用训练残差的分位做区间——它来自低波动世界,对高波动测试集过窄,大量点漏出;
- 共形法:用校准集残差——只要校准集与测试集同分布(漂移后重新校准即可),区间自动加宽补上。

本次实验:朴素法覆盖 70.4%(远低于目标 90%),共形法 73.9%(仍偏低,因为校准集也来自旧分布)。诚实披露:若校准集本身也漂移了,共形覆盖同样会掉;正确做法是用最新数据滚动校准——共形不消灭漂移,只是把「应对漂移」这件事标准化成「换校准集」。
五、确定性的代价:越想要把握,区间越宽#
固定 α 后区间半宽就是 。扫一遍名义覆盖看效率:

这是诚实的 trade-off:要 95% 把握,区间就得比 80% 宽一大圈。共形预测不免费给你确定性,它只是把代价量化出来——你的交易系统可以据此设定「只有区间足够窄时才下注」的触发条件。
六、自适应共形(ACI):让区间随时间自己呼吸#
标准共形用固定 ,但市场波动是时变的。一种简单改进是 自适应共形(Adaptive Conformal Inference):每个新观测后,用「近期残差」更新分位,区间随之扩张/收缩。直觉上,若最近连续漏点(波动变大),下一期 自动加宽。下面是一段轻量实现:
# 自适应共形:用最近 W 个残差滚动更新分位(示意)
def adaptive_conformal(resid_stream, alpha, W=200):
c_seq = []
for i in range(len(resid_stream)):
window = resid_stream[max(0, i - W):i]
if len(window) < 30:
c_seq.append(np.quantile(resid_stream[:max(1, i + 1)], (i + 1) / (i + 2) * (1 - alpha) + alpha / (i + 2), method="higher"))
else:
c_seq.append(np.quantile(window, (W + 1) / (W + 2) * (1 - alpha) + alpha / (W + 2), method="higher"))
return np.array(c_seq)pythonACI 在高波动期会自发加宽区间,是共形应对非平稳的实用补丁——但代价是覆盖保证退化为「近似」,需要回测验证。
七、它进交易系统的三种姿势#
共形预测不是「换个模型」,而是给现有预测加一层可验证的不确定性外壳:
- 信号触发闸门:只有当区间足够窄( 阈值)才视为「高确定性信号」,否则空仓——把模糊预测挡在门外;
- 仓位缩放:用区间半宽 的倒数做仓位权重,不确定大就少下注(类似波动率目标,但来自数据分位而非波动率模型);
- 风险限额:组合层面要求 95% 区间下的最大潜在偏差可控,直接对接 VaR / 回撤约束。
它和前一节的 Lasso 是天然搭档:Lasso 先把几百个因子压成干净少数,共形再给这批因子的预测配上可信区间——一个管「选什么」,一个管「信几分」。
八、从零实现的 Python 代码#
import numpy as np
from sklearn.ensemble import HistGradientBoostingRegressor
# —— 1. 异方差数据:波动随特征变化 ——
def gen(n, rng, scale=1.0):
x = rng.uniform(-3, 3, n)
f = np.sin(2 * x)
sigma = (0.25 + 0.45 * (x > 0)) * scale # 右半区波动更大
return x, f + rng.normal(0, sigma)
# —— 2. Split-Conformal 区间构造 ——
def split_conformal(x_tr, y_tr, x_cal, y_cal, x_te, y_te, alpha):
model = HistGradientBoostingRegressor(max_iter=200, learning_rate=0.1, max_depth=3)
model.fit(x_tr.reshape(-1, 1), y_tr)
resid = np.abs(y_cal - model.predict(x_cal.reshape(-1, 1)))
n = len(resid)
q = np.ceil((n + 1) * (1 - alpha)) / n # 有限样本校正
c = np.quantile(resid, q, method="higher")
pred = model.predict(x_te.reshape(-1, 1))
lo, hi = pred - c, pred + c
cover = np.mean((y_te >= lo) & (y_te <= hi))
return pred, lo, hi, c, cover
# —— 3. 跑一遍 ——
rng = np.random.default_rng(20260719)
x_tr, y_tr = gen(1500, rng)
x_cal, y_cal = gen(800, rng)
x_te, y_te = gen(600, rng)
pred, lo, hi, c, cover = split_conformal(x_tr, y_tr, x_cal, y_cal, x_te, y_te, alpha=0.10)
print(f"经验覆盖={cover:.3f} (目标0.90) 区间半宽 c={c:.3f}")python核心就三行:拟模型、取校准残差分位、加 ±c。没有分布假设,没有手调带宽。
九、从「区间」到「分类」:共形也能给涨跌方向定把握#
上面讲的是回归型共形(预测一个值 + 区间)。但交易里更常见的是分类信号:明天涨还是跌?共形同样能给出「这只标签有多可信」。做法把绝对值残差换成** conformity score**:对校准集每点算一个分数 ,测试点的分数若排在前 分位内,就纳入该类的「可接受集合(conformal set)」。
举个例子,模型对 500 只股票各输出「涨/跌」预测,你不想全信。用共形可以给每只股票输出一个集合预测:例如「{涨}」表示有 ≥90% 把握涨,「{涨,跌}」表示不确定(干脆不下注)。代码骨架长这样:
# 分类型共形:给每只股票一个「可信标签集合」
def conformal_set(scores_cal, scores_te, alpha):
n = len(scores_cal)
q = np.ceil((n + 1) * (1 - alpha)) / n
thr = np.quantile(scores_cal, q, method="higher")
return scores_te <= thr # True 表示该点被纳入可接受集合python注意:分类共形保证的是「真实标签以 ≥1−α 概率落在输出的集合里」。当市场混沌、模型没把握时,它会诚实返回一个含多个标签的大集合(即「我不下定论」),而不是硬给一个可能错的标签——这正是实盘最需要的「知之为知之」机制。
十、五类真实陷阱(诚实声明)#
- 交换性假设是命门:共形保证只在「测试 ≈ 训练/校准同分布」时成立。剧烈漂移下必须滚动重校准,否则覆盖会掉(见第四节)。
- 区间形状受模型约束:共形只给「对称 ±c」区间,模型若系统性低估某侧,区间会单向漏。可换分位数回归或自适应共形(ACI)。
- 校准集要独立:训练集和校准集若重叠,分位会被「见过的数据」污染,覆盖虚高。严格三划分(训练/校准/测试)。
- 不是点预测改进器:共形不提升 的精度,只量化它的不确定性。烂模型的区间只是「诚实地宽」。
- 多重检验膨胀:同时给 500 只股票各发 90% 区间,整体「全命中」概率远低于 90%——组合层面要用 BH 之类控制族错误率(这正是另一篇 FDR 文章的主题)。
结论#
共形预测给量化人最缺的一样东西:可验证的不确定性。它不假设市场高斯、不靠经验拍带宽,只用校准集上的经验分位,就给你一条「(1−α) 比例会落进来」的数学承诺。在异方差与漂移横行的实盘里,这比一个裸奔的点预测值钱得多——因为它让你能说「我只在区间足够窄、把握足够高时才下注」。但记住它的边界:保证来自交换性,漂移来了就重校准,共形从不假装自己能预判未知。