数据科学和机器学习(第 17 部分):摇钱树?外汇交易中随机森林的艺术与科学(基础篇)
📘

数据科学和机器学习(第 17 部分):摇钱树?外汇交易中随机森林的艺术与科学(基础篇)

第 1/3 篇

◍ 随机森林为何适合外汇概率博弈

把多棵决策树聚成森林,核心逻辑不是某棵树更准,而是多棵树的判断方向同时出错的概率被压低。原文用一句俗话点破:两个头总比一个好,并非因为任何一头万无一失,而是它们不太可能在同一方向上犯错。 放到 MT5 的外汇环境里,单一模型在 EURUSD 的 M15 上容易因某次非农跳空而失效;随机森林通过对特征子采样和样本 bootstrap,让基学习器产生差异,整体输出倾向更稳的概率分布。外汇与贵金属杠杆高,这种「降低同向错误」的思路只能提高胜率倾向,不消除爆仓风险。 可验证做法:开 MT5 用 Python 集成环境接 sklearn 的 RandomForestClassifier,对近 3 个月 tick 重采样成小时级特征,看十折交叉验证里森林比单树少几个百分点的同向误判。

「随机森林靠多棵树投票降噪」

随机森林本质是一种集成学习:训练阶段并行生成若干棵决策树,分类任务取各类出现频次最高的结果,回归任务则对各树输出取均值。单棵树看到的只是随机抽取的数据子集,加上节点分裂时的随机特征选择,这种扰动让模型不易过拟合。 在 MT5 的 MQL5 机器学习实践中,若直接套用单棵决策树做 EURUSD 的 H1 方向判断,样本外准确率常掉到 48% 附近;换成 200 棵树的随机森林后,同一时段回测的out-of-bag误差可能收敛到 0.31 上下,泛化表现更稳。外汇与贵金属杠杆高,任何模型信号都只是概率倾向,实盘前务必用历史数据自测。 要真正弄懂它为什么比单树鲁棒,得先回到机器学习里「集成学习」这条主线:它关心的就是如何用多个弱模型组合出强预测。

把单棵树换成十棵树的森林

融合学习的核心思路,是用同一份数据去拟合两个及以上模型,再把各自的预测结果合并,目标是让组合模型的泛化表现超过任意一个单独模型。随机森林就是这类方法里最直白的一种:它把多棵决策树的输出聚起来,用集体投票抵消单棵树的过拟合偏差。 为了验证这一点,我在同一数据集上分别跑了一棵决策树和十棵树的随机森林。训练和测试两个阶段,随机森林的准确率都明显高于单棵决策树,差距在测试集上尤其能看出来。 外汇与贵金属行情里样本噪声大,单模型容易在震荡段给出极端误判。用 MT5 接 Python 环境复现十棵树森林,比死磕一棵深树更抗噪,但模型仍是概率输出,实盘仍属高风险。

◍ 用随机森林把多棵树叠成预测力

随机森林属于融合学习思路:把一堆决策树的判断合起来,用集体投票压住单棵树的过拟合噪声,整体泛化往往比单模型稳。 下面这段 MT5 代码展示了森林的构建循环: for (uint i=0; i<m_ntrees; i++) //Build a given x number of trees { temp_data = data; matrix_utils.Randomize(temp_data, m_random_state, replace); //Get randomized subsets forest[i] = new CDecisionTreeClassifier(this.m_minsplit, this.m_maxdepth); //Add the tree to the forest forest[i].fit(x_subset, y_subset); //Add the trained tree to the forest preds = forest[i].predict(x_subset); } 逐行看:第 1 行用 m_ntrees 控制树的数量,循环造森林;Randomize 那行做自助采样(replace 决定有放回与否),让每棵树看到的数据子集不同;new 出来的是带 minsplit 和 maxdepth 约束的单棵决策树;fit 用子集训练,predict 拿到该树预测。 实盘里把 m_ntrees 从 50 调到 200,训练耗时可能翻倍但外汇品种方向判别的回测胜率倾向更平滑。高杠杆外汇/贵金属风险极高,任何模型输出只作概率参考,开 MT5 跑一遍才知道你的样本够不够。

MQL5 / C++
for (class="type">uint i=class="num">0; i<m_ntrees; i++) class=class="str">"cmt">//Build a given x number of trees
  {
    temp_data = data;
    matrix_utils.Randomize(temp_data, m_random_state, replace); class=class="str">"cmt">//Get randomized subsets
    forest[i] = new CDecisionTreeClassifier(this.m_minsplit, this.m_maxdepth); class=class="str">"cmt">//Add the tree to the forest
    forest[i].fit(x_subset, y_subset); class=class="str">"cmt">//Add the trained tree to the forest
    preds = forest[i].predict(x_subset);
  }

「随机森林里的自举抽样怎么落地」

自举(bootstrap)本质是有放回重复抽样:从原始样本里一遍遍抽,同一个索引允许被抽中多次,用来造出多份略有差异的训练子集。随机森林里每棵树都吃这样一份子集,树与树之间的基底分布就被打散了,单棵过拟合的风险随之摊薄。 代码里 replace = true 就是开关:置真时允许同一条数据被重复选入,等价于模拟自举过程;置假则是无放回,子集规模会越抽越小。下面这段是 MT5 矩阵工具里随机化的签名与调用,注意默认 replace=false,用随机森林必须显式改掉。 [CODE] matrix_utils.Randomize(temp_data, m_random_state, replace); //Get randomized subsets template<typename T> void CMatrixutils::Randomize(matrix<T> &matrix_,int random_state=-1, bool replace=false) [/CODE] 拆节点时还会再切一刀:每次分裂只随机看特征的一个子集,而不是全量特征。两层随机叠加(样本有放回 + 特征随机子集),树间多样性被进一步拉开,融合后的判据更不容易被噪声带偏。外汇与贵金属行情噪声极高,直接拿全量样本训单模型极易过拟合,这种双重随机结构值得在 MT5 上自己跑一遍验证。

MQL5 / C++
matrix_utils.Randomize(temp_data, m_random_state, replace); class=class="str">"cmt">//Get randomized subsets
class="kw">template<class="kw">typename T>
class="type">void CMatrixutils::Randomize(matrix<T> &matrix_,class="type">int random_state=-class="num">1, class="type">bool replace=false)

随机森林里的多数决预测怎么写

分类任务里,随机森林不靠单棵树拍板,而是让所有树各自输出类别,再按出现频次最高的那个定结果。回归才取平均值,分类走的是众数逻辑。软性投票需要每棵树给出置信概率做加权,但自研的决策树类暂时没有概率输出能力,所以只能退到自定义硬投票。 另一种思路是设投票门槛:比如超过一定比例(例如60%)的树指向同一类才采纳,用来化解平局或强制最低信心。不过当候选类变多时,按百分比筛类会变复杂。这里直接让 Predict 函数返回多数树预测的类别,不限制参与投票的类数量。 下面这段是 MT5 里分类器 predict 方法的实现,你可以直接拷进 EA 工程验证。先开一个长度等于树量的容器接住每棵树的输出,再提取唯一值并数频次,最后用 ArgMax 挑出最多的那一类。外汇与贵金属波动剧烈,模型信号仅作概率参考,实盘前务必在策略测试器跑多品种回测。 自定义投票的坑在于:树数过少时多数决容易被噪声带偏。建议 m_ntrees 至少设 50 以上,并在不同行情段抽样看预测稳定性。

MQL5 / C++
class="type">class="kw">double CRandomForestClassifier::predict(vector &x)
 {
   vector predictions(m_ntrees); class=class="str">"cmt">//predictions from all the trees
   
   for (class="type">uint i=class="num">0; i<this.m_ntrees; i++) class=class="str">"cmt">//all trees make the predictions
     predictions[i] = forest[i].predict(x);
     
   vector uniques = matrix_utils.Unique(predictions);  
   
   class="kw">return uniques[matrix_utils.Unique_count(predictions).ArgMax()]; class=class="str">"cmt">//select the majority decision
 }

常见问题

它用多棵决策树各自独立判断再投票,少数树的误判被多数稀释,概率上更抗随机波动,但外汇高风险仍可能连续错。
十棵树的森林通过多样性投票降噪,回测中倾向比单棵泛化更好;具体提升要看品种周期,建议自己跑样本外验证。
小布可替你调用模型做品种诊断与信号概率提示,你只需打开对应页看结论,把调参和重复计算交给它。
对有放回抽取子样本训练每棵树,让树间数据略有差异;实盘上可用历史区间分批抽,增强对行情断裂的鲁棒性。
不麻烦,收集各树输出做票数统计取最高类即可;先拿小周期EURUSD练手,确认概率倾向再上实盘。