一种采用纯MQL5语言实现的基于能量学习的特征选择算法·综合运用

一种采用纯MQL5语言实现的基于能量学习的特征选择算法·综合运用

(3/3)·把FREL算法跑通在MT5脚本里,看特征权重如何稳定筛出有效预测变量

偏理论 第 3/3 篇
很多交易者把几十个指标一股脑喂给模型,以为变量越多预测越准,结果过拟合到连样本内都崩。特征选择不是可选项,直接决定策略在外汇贵金属高噪声环境下的存活概率。

「用FREL脚本揪出隐藏的目标变量」

在 MT5 里跑 FrelExample.mq5,能直观看到特征选择算法怎么从一堆噪声列里挑出真正驱动目标的变量。脚本先造一个随机矩阵:行数由 num_observations 定,列数是候选变量数加 1,最后一列被强制写成第 1、3、5、7 列之和,这就是我们埋好的目标。 默认参数下正则化关死、只做一次采样,FREL 倾向于把高权重准确压在 1、3、5、7 列上。把 regularization_factor 调到 0.1 和 1.0 后,权重开始外溢到无关列——正则越强,有用和没用的变量越难分。 瓶颈在 total_loss() 反复扫全量数据。原脚本用 2000 行跑一次,BTCUSD D1 上实测 Runtime of FREL 273375 ms,约 273 秒。换思路:bootstrap_size 设 40、number_of_bootstraps 设 100,用小样本多次抽样,速度能砍下来,权重估计也还稳。 外汇和贵金属波动受宏观扰动,这类合成实验只验证算法逻辑,实盘特征关系会漂移,高杠杆品种请先旁路上仿真。

MQL5 / C++
class=class="str">"cmt">//---user adjustable class="kw">input parameters
class="kw">input class="type">int number_of_partitions = class="num">8; class=class="str">"cmt">//Number of partitions
class="kw">input class="type">class="kw">double regularization_factor = class="num">0.0; class=class="str">"cmt">//Regularization factor
class="kw">input class="type">int number_of_bootstraps = class="num">1;
class="kw">input class="type">int bootstrap_size = class="num">0;
class="kw">input class="type">ulong num_observations = class="num">2000;class=class="str">"cmt">// Sample size of random dataset
class="kw">input class="type">ulong num_candidate_predictors = class="num">10;class=class="str">"cmt">// Maximum number of candidate predictors in dataset
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   srand(class="num">126);
class=class="str">"cmt">//---check user class="kw">input parameters
   if(number_of_partitions<class="num">2 || num_observations<class="num">10 || num_candidate_predictors<class="num">8)
     {
       Print("Invalid class="kw">input parameters");
       class="kw">return;
     }
class=class="str">"cmt">//---the data
   matrix dataset;
class=class="str">"cmt">//---initialize size of random dataset
   dataset.Init(num_observations,num_candidate_predictors+class="num">1);
class=class="str">"cmt">//---fill dataset with random data
   dataset.Random(class="num">1.0,class="num">10.0);
class=class="str">"cmt">//---set the target variable in the last column
   if(!dataset.Col(dataset.Col(class="num">1) + dataset.Col(class="num">3) + dataset.Col(class="num">5) + dataset.Col(class="num">7),num_candidate_predictors))
     {
       Print("error ", GetLastError());
       class="kw">return;
     }
class=class="str">"cmt">//---initialize Frel object
   FREL frel(dataset,number_of_bootstraps,bootstrap_size);
class=class="str">"cmt">//---declare containers to recieve output from Frel operation
   class="type">class="kw">double optimal_weights[];
   class="type">int index[];
class=class="str">"cmt">//---
   class="type">ulong timeIT = GetTickCount64();
class=class="str">"cmt">//---find the most relevant predictors
   if(!frel.WeighVars(number_of_partitions,regularization_factor,index,optimal_weights))
     class="kw">return;
class=class="str">"cmt">//---calculate runtime
   Print("Runtime of FREL ", GetTickCount64() - timeIT, " ms");
class=class="str">"cmt">//---display results
   for(class="type">uint i = class="num">0;i<optimal_weights.Size(); i++)
     Print("Predictor at Column index ", index[i], " weight ", optimal_weights[i]);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
ON       class="num">0       class="num">18:class="num">12:class="num">30.906    FrelExample(BTCUSD,D1) Runtime of FREL class="num">273375 ms

◍ FREL 权重排序暴露的日线预测因子

在 BTCUSD 的 D1 周期上跑完一次 FREL 特征选择,日志会直接打印每个列索引对应的权重。第一次运行里,Column 7、3、5、1 的权重分别是 24.47、24.22、22.27、22.14,而 Column 0、8、4、2、6、9 全在 1.16 以下,差距接近 20 倍,说明前四个因子几乎垄断了模型解释力。 第二次运行耗时 331296 毫秒(约 5.5 分钟),权重分布出现漂移:Column 3 降到 19.63,Column 0 却从 1.16 升到 4.11,Column 8 也从 1.15 升到 4.08。这种跨运行的权重跳动,提示日线样本量下 FREL 的稳定性偏弱,单看一次排序容易误判。 开 MT5 把 Expert Advisor 的日志级别打开,搜 Predictor at Column index 就能复现这两段输出。权重绝对值没有上下界约束,横向比同一次运行内的相对大小,比盯某个具体数字更有意义。 加密资产与外汇贵金属均属高波动品种,这类特征权重仅反映历史样本拟合倾向,实盘信号可能随行情结构变化而失效。

FREL 跑完 BTCUSD 日线后吐了什么

在 BTCUSD 的 D1 周期上跑 FREL 特征选择,日志会直接打印每个预测列的权重。第一次运行耗时 362984 毫秒(约 6 分钟),列索引 2、6、9、4 的权重集中在 4.02~4.07 之间,说明这批因子对目标变量的线性解释力偏弱。 第二次运行耗时骤降到 22985 毫秒(约 23 秒),权重分布完全变样:列索引 3 冲到 18.71,列 7、5、1 也在 10.0 上下,列 0、8、2、6、9、4 落在 9.77~9.90。两次权重量级差了 4 倍以上,样本窗口或随机种子变动都会让特征排序重写。 外汇和贵金属这类高波动品种做同样的事,权重跳变会更凶,实盘前务必多跑几遍不同时间段确认稳定性。 打开 MT5 终端的 Experts 标签,搜 FrelExample 就能看到你本地这组数字,别光信别人贴的权重表。

「特征权重排序暴露了日线预测的主驱动」

在 BTCUSD 的 D1 周期上跑完 FREL 示例后,日志按权重从高到低打印了各预测列的贡献。排在最前的三列索引 1、5、7,权重分别为 18.3208、18.1940、16.2983,三者合计已超过总权重的一半,说明日线级别的方向判断主要由这几路特征决定。 其余列权重陡降到个位数:索引 4 为 5.8389,索引 9 为 5.2493,索引 8 为 4.7916,索引 6 为 4.7702,索引 0 为 3.9750,索引 2 为 3.8557。这种长头短尾的分布意味着,若你要做特征裁剪,删掉后三分之一的列对模型输出影响可能有限。 外汇与贵金属品种换进去跑同样的逻辑,权重排序往往和 BTCUSD 不同,加密资产的波动结构不能直接外推。打开 MT5 把 Symbol 改成 XAUUSD 重跑一遍,对比权重序列就能看出品类差异。

MQL5 / C++
OL      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">1 weight class="num">18.32079620338284
RS      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">5 weight class="num">18.194009676469012
HG      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">7 weight class="num">16.298306686632337
MI      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">4 weight class="num">5.838867272535404
LM      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">9 weight class="num">5.249285089162589
FQ      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">8 weight class="num">4.791606631149278
DE      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">6 weight class="num">4.770223641360407
KI      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">0 weight class="num">3.974977300216029
KM      class="num">0    class="num">18:class="num">30:class="num">55.441    FrelExample(BTCUSD,D1) Predictor at Column index class="num">2 weight class="num">3.855654746910961

◍ 把工具请下神坛

基于正则化能量模型的特征加权在合成数据上验证了有效性,但原生实现的运算开销偏大,单次分析耗时明显。改用小样本多次自助抽样后,执行速度有可见提升;若再叠加多线程或 GPU 加速,瓶颈会进一步松动。 三个头文件构成了可复用的底层:np.mqh 管向量矩阵运算,Powells.mqh 封装 Powell 法做函数极小化,frel.mqh 里的 FREL 类才是算法主体,配套脚本 FrelExample.mq5 直接演示调用。 它终究只是加权特征的一种手段,不是圣杯。外汇与贵金属市场高杠杆、高波动,直接上实盘前务必在 MT5 策略测试器里用历史数据跑通,再按自己的品种和周期改样本量与线程数。

把重复劳动交给小布
这些特征权重的计算过程小布盯盘的 AIGC 已内置,打开对应品种页即可看到哪些变量被算法判为低权重,你只管决定是否采纳。

常见问题

相关系数只看两两线性关联,FREL 通过能量正则化同时优化准确与稳定,倾向保留在扰动下仍一致有效的特征。
小布已内置类似加权逻辑,你不必自己编译脚本,在品种页查看 AIGC 给出的特征权重分布即可,外汇贵金属波动大仍需自行风控。
曼哈顿距离对异常点更不敏感,在tick级报价跳变频繁时可能比欧氏更稳健,具体依数据分布选。
它给输入配置打能量值,学习时压低观测配置能量、抬高非观测配置能量,从而区分理想与非理想结构。