金融时间序列中的保形预测探索·进阶篇
(2/3)·单点预测在厚尾行情里形同裸奔,保形预测如何给出90%覆盖的概率护栏
◍ 保形分类里的一致性分数怎么选
MAPIE 里的一致性分数直接决定预测集合长什么样。LAC 用 1 减去真实标签的 softmax 得分当分数,理论上有边际覆盖率保证,集合通常偏小;但模型在决策边界附近高度不确定时会吐出空集——金融场景里空集等于没有信号,交易动作直接断链。 APS 把 softmax 从高到低累加直到覆盖真实标签,从定义上杜绝空集,边际覆盖率仍在,比 LAC 更适合行情模糊时保底出参考。RAPS 在 APS 基础上加正则项压集合大小,让覆盖率和信号集中度平衡,集合越小越方便实盘直接拿来用。 蒙德安(Mondrian)给每个类别单独算分位数,做到类别感知的条件覆盖率 (1−α)。二分类买卖里“买入”样本常远少于“卖出”,标准保形只看边际均值,稀有买入类的覆盖可能掉到目标以下;蒙德安按类隔离,买入信号可靠性不被卖出表现拖垮。 外汇与贵金属属高风险品种,任何信号都只是概率参考。从 LAC 到 APS/RAPS 再到蒙德安,演变逻辑很直白:先保证有集可出,再控集大小,最后按类保覆盖,避免关键稀有权限信号系统性欠覆盖。
分类任务里保形预测集怎么一步步搭出来
| 做保形分类,第一步是挑非一致性度量(也叫评分函数)。常用做法是直接吃训练好的分类器输出:若模型给的是 softmax 概率,对样本 (xi, yi) 取 αi = 1 − P^(yi | xi),α 小说明模型认这个真实类,α 大就是它没把握。若只吐 logits,先过一道 softmax 再算同样的 1 − P(yi | xi);SVM 这类给有符号距离的,就对分对的取负距离、分错的取正距离来反映不一致程度。 |
|---|
校准集必须和训练集切干净。训练集训基础分类器,校准集专门算非一致性分数并定阈值,不能回头污染模型。对校准集每个点算 αj 后升序排成 α(1)≤…≤α(m),m 是校准样本量。 设显著性水平 δ∈(0,1),1−δ 是目标覆盖概率。有限样本下别直接用 q=α(⌈(m+1)(1−δ)⌉),更稳的是找最小的 α(k) 使 k/(m+1)≥1−δ,记这个值为 q^,这是带有限样本修正的经验分位数。 新样本 xtest 来了,对类别集合每个候选标签 k 都假装它是真标签,算 αtest,k = 1 − P^(k|xtest),凡满足 αtest,k ≤ q^ 的 k 全收进预测集 Ytest。你在 MT5 里接分类信号时,可以用这套把“模型模糊”的标的圈出来而不是硬取 argmax。
「用prefit把保形预测塞进高频交易管线」
MapieClassifier 只认实现了 fit / predict / predict_proba 的 scikit-learn 评估器,不传就用逻辑回归兜底。cv 参数决定一致性分数怎么算:"split" 和 "crossval" 走 Jackknife 或 CV 划分,"prefit" 则假定模型已训好,传入数据只用来算分和校准,不碰训练。 金融实盘里模型常在大规模数据上持续更新,高频场景下还按流式数据频繁重训。prefit 直接用预训练模型加独立校准集做保形预测,省掉计算密集的训练步,不确定性量化能低延迟挂进现有交易系统,MT5 外接 Python 服务时这点延迟差异很关键。 原 method 参数已弃用,改由 conformity_score 控制保形机制,目的是把“不匹配度怎么算”模块化。外汇与贵金属属高风险品种,把“买入”误判成“卖出”的代价远高于反向错,自定义 conformity_score 能按这类非对称风险调权重,不必受预设方法限制。
◍ 保形预测在金融落地中的三条硬建议
MAPIE 的价值不在准确率数字,而在把「模型自己也没底」这件事显式暴露出来。金融场景下它给的是无分布依赖、有限样本覆盖率保证,能直接把样本切成可靠与不可靠两堆,这对外汇、贵金属这种高杠杆高风险环境意味着可量化地控仓。 一致性评分优先挑 APS 或 RAPS。二分类任务里这俩能保证预测集合非空,即使行情极度无序,推断流程也不会断——你永远拿得到「该观望还是该动」的集合输出,而不是空值。 类别不平衡时上蒙德安保形预测。像强势买入这种稀有信号,边际覆盖率会骗人,蒙德按类别单独给保证,避免稀有事件被多数类稀释成系统性漏报。 时间序列验证不能偷懒。可交换性假设在价格序列里天然易破,MapieTimeSeriesRegressor 只是工具不是免死金牌,必须叠严格回测看突发跳空下的集合萎缩情况。 策略层按集合大小调敞口:单类集合=高置信,可满仓;多类集合=低置信,减仓或对冲。贵金属隔夜跳空前若集合扩到全类,就是小布让你降杠杆的直接信号。
用交叉保形预测筛出高置信样本
MAPIE 提供拆分式与交叉式两种保形预测包装器,这里直接选 CrossConformalClassifier,思路和滚动向前验证接近:把数据切多折交叉训练校准,比单次切分训练/验证更稳。基础评估器用 sklearn 的 RandomForestClassifier,MAPIE 支持该库全部分类器,后续要换模型只改 estimator 参数即可,但它只负责生成预测集合,真正下单模型仍是 CatBoost。 函数 meta_learners_mapie() 收三个参数:n_estimators_rf 控制树数量、max_depth_rf 控树深、confidence_level 默认 0.9 决定集合宽度。数据经 get_prices→get_features→get_labels 三级辅助函数处理后,按时间索引截留 backward 与 forward 之间的记录并 .copy(),躲开 SettingWithCopyWarning。 特征矩阵取除首列与末两列外的所有列,目标取 labels 列。CrossConformalClassifier 包住随机森林,cv=5 做 5 折校准,fit_conformalize(X,y) 一步完成训练与校准。predict_set(X) 吐出单点 predicted 与布尔型 y_prediction_sets,形状常是 (n_samples, n_classes, 1),需压掉末维冗余。 set_sizes 按行求和得到每样本集合大小;data.loc[set_sizes==1,'meta_labels']=1.0 是核心——集合恰为 1 类代表模型在 90% 置信下唯一确定方向,标为元标签 1,空集合或多类集合留 0。打印 empty/single/multi 三类计数可直观看校准质量,返回帧含原特征、原标签与 meta_labels,供元模型或可靠样本筛选用。外汇与贵金属波动剧烈,这类置信筛选只降不确定性,不消除爆边风险。 别把 90% 当安全垫 置信水平调高,集合普遍变宽、single_element_sets 数量倾向下降;想在多品种上复跑,先盯住 single 占比再决定阈值,而非默认 0.9 一把梭。
pip install mapie from mapie.classification class="kw">import CrossConformalClassifier class="kw">import pandas as pd class="kw">import math from class="type">class="kw">datetime class="kw">import class="type">class="kw">datetime from catboost class="kw">import CatBoostClassifier from sklearn.model_selection class="kw">import train_test_split from sklearn.model_selection class="kw">import cross_val_predict from sklearn.model_selection class="kw">import StratifiedKFold from bots.botlibs.labeling_lib class="kw">import * from bots.botlibs.tester_lib class="kw">import test_model from mapie.classification class="kw">import CrossConformalClassifier from sklearn.ensemble class="kw">import RandomForestClassifier def meta_learners_mapie(n_estimators_rf: class="type">int, max_depth_rf: class="type">int, confidence_level: class="type">class="kw">float = class="num">0.9): dataset = get_labels(get_features(get_prices()), markup=hyper_params[&class="macro">#x27;markup&class="macro">#x27;]) data = dataset[(dataset.index < hyper_params[&class="macro">#x27;forward&class="macro">#x27;]) & (dataset.index > hyper_params[&class="macro">#x27;backward&class="macro">#x27;])].copy() # Extract features and target feature_columns = list(data.columns[class="num">1:-class="num">2]) X = data[feature_columns] y = data[&class="macro">#x27;labels&class="macro">#x27;] mapie_classifier = CrossConformalClassifier( estimator=RandomForestClassifier(n_estimators=n_estimators_rf, max_depth=max_depth_rf),
「用保形集大小筛出高确定性样本」
这段 Python 逻辑接在随机森林 + 交叉保形分类之后,核心是把预测集(prediction set)的尺寸当成二级标签的过滤器。 y_prediction_sets 经 np.squeeze 压掉最后一维后,set_sizes = np.sum(..., axis=1) 得到每个样本的预测集元素个数。若 set_sizes == 1,说明模型在该置信水平下只输出了一个类别,确定性相对高,于是 data['meta_labels'] 标为 1.0;其余(含空集与多类集)标 0.0。 打印的三类统计直接给出可验证数字:empty_sets(集大小为0)、single_element_sets(恰为1)、multi_element_sets(≥2)。在默认 confidence_level=0.9、cv=5 的设置下,你可以跑一遍看 single_element_sets 占比,若过低说明当前特征区分度差,倾向需要调 markup 或特征窗口。 外汇与贵金属行情受突发事件扰动大,保形集扩张是常态,这套 meta_labels 只能降低模糊样本干扰,不保证方向判断正确,实盘仍属高风险。
y_prediction_sets = np.squeeze(y_prediction_sets, axis=-class="num">1) # Calculate set sizes(sum across classes for each sample) set_sizes = np.sum(y_prediction_sets, axis=class="num">1) # Initialize meta_labels data[&class="macro">#x27;meta_labels&class="macro">#x27;] = class="num">0.0 # Mark labels as "good" (class="num">1.0) only where prediction set size is exactly class="num">1 data.loc[set_sizes == class="num">1, &class="macro">#x27;meta_labels&class="macro">#x27;] = class="num">1.0 # Report statistics on prediction sets empty_sets = np.sum(set_sizes == class="num">0) single_element_sets = np.sum(set_sizes == class="num">1) multi_element_sets = np.sum(set_sizes >= class="num">2) print(f"Empty sets(meta_labels=class="num">0): {empty_sets}") print(f"Single element sets(meta_labels=class="num">1): {single_element_sets}") print(f"Multi-element sets(meta_labels=class="num">0): {multi_element_sets}") # Return the dataset with features, original labels, and meta labels class="kw">return data[feature_columns + [&class="macro">#x27;labels&class="macro">#x27;, &class="macro">#x27;meta_labels&class="macro">#x27;]]