蒙特卡罗方法在强化学习中的应用·综合运用
🎲

蒙特卡罗方法在强化学习中的应用·综合运用

(3/3)·从单代理到蒙特卡罗枚举,用随机标签群提升交易模型对新数据的稳定性

进阶 第 3/3 篇
把强化学习直接塞进 EA 往往跑出漂亮回测却实盘失灵,根子在单代理过度拟合当前行情。用蒙特卡罗随机抽取标签并行训多个代理,能把泛化弱点摊开来看,而不是赌一个模型命好。

◍ 信号阈值触发下的平仓与反向开仓

这段逻辑把持仓清理和新单触发绑在同一套 Tsignal 阈值判断上。Tsignal 大于 0.5 时平掉多单(OrderType()==0),小于 0.5 时平掉空单(OrderType()==1),平仓成功后调用 ag1.updateRewards() 更新奖励,属于典型的强化学习 agent 反馈写入。 若当前市场仍有多单或空单残留(countOrders 不为 0),直接 return 不再开仓,避免加仓堆叠。只有当 Tsignal 偏离中线超过 treshhold——买侧低于 0.5-treshhold、卖侧高于 0.5+treshhold——才用 OrderSend 以市价 Ask/Bid 发单,成功后 ag1.updatePolicies(Tsignal) 更新策略参数。 下面把核心片段逐行拆开看: if(OrderType()==0 && Tsignal>0.5) // 持仓为多单且信号偏空 if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red)) // 按当前平仓价全平,滑点容差0,颜色Red {ag1.updateRewards();} // 平仓成交则更新奖励 if(OrderType()==1 && Tsignal<0.5) // 持仓为空单且信号偏多 if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),0,Red)) // 同上平空 {ag1.updateRewards();}

if(countOrders(0)!=0countOrders(1)!=0) return; // 有任意持仓就跳出,不开新单

if(Tsignal<0.5-treshhold && (OrderSend(Symbol(),OP_BUY,lotsOptimized(),SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0,NULL,OrderMagic,INT_MIN)>0)) // 信号足够低,市价买开 { ag1.updatePolicies(Tsignal); } // 开仓成功更新策略 if(Tsignal>0.5+treshhold && (OrderSend(Symbol(),OP_SELL,lotsOptimized(),SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0,NULL,OrderMagic,INT_MIN)>0)) // 信号足够高,市价卖开 { ag1.updatePolicies(Tsignal); } 外汇与贵金属杠杆高,这类信号驱动自动单在震荡市可能频繁往返,实盘前务必在 MT5 策略测试器用历史数据验证 treshhold 取值对回撤的影响。

MQL5 / C++
if(OrderType()==class="num">0 && Tsignal>class="num">0.5) if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),class="num">0,Red)) {ag1.updateRewards();}
if(OrderType()==class="num">1 && Tsignal<class="num">0.5) if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),class="num">0,Red)) {ag1.updateRewards();}
}

 if(countOrders(class="num">0)!=class="num">0 || countOrders(class="num">1)!=class="num">0) class="kw">return;
 if(Tsignal<class="num">0.5-treshhold && (OrderSend(Symbol(),OP_BUY,lotsOptimized(),SymbolInfoDouble(_Symbol,SYMBOL_ASK),class="num">0,class="num">0,class="num">0,NULL,OrderMagic,INT_MIN)>class="num">0)) { ag1.updatePolicies(Tsignal); }
 if(Tsignal>class="num">0.5+treshhold && (OrderSend(Symbol(),OP_SELL,lotsOptimized(),SymbolInfoDouble(_Symbol,SYMBOL_BID),class="num">0,class="num">0,class="num">0,NULL,OrderMagic,INT_MIN)>class="num">0)) { ag1.updatePolicies(Tsignal); }
}

「蒙特卡洛枚举与多代理调参实操」

number_of_passes 这个参数不会把任何值送进学习者,它只决定优化器跑几遍。若你已定好其他参数、只想用蒙特卡洛枚举来找解,那就只按这一条标准优化,其余四个设置仍可另行优化。当前版本不需要关测试代理,因为优化过程彼此独立,模型保存顺序无所谓。 用 M15 周期、两个月公开行情跑优化时,优化准则选 “Custom max”,一旦达到可接受值就能手动停。我在第 44 步停了,因为最佳模型精度越过 0.6,意味着测试集分类误差低于 0.4;模型越好误差越小,但若用遗传算法,误差值会被倒置。 停掉后切单测模式即可,最佳模型已写文件且只加载它。回看四个月历史,该模型撑了约一个月(几乎整月九月),八月却崩了。把 treshhold 设 0.2 微调,精度上升且交易数减少,说明合适训练长度下能更深测。 想比多代理和单代理效率,建代理组名加 “Multi” 后缀防文件混,工作单元设五个。各单元在 OnInit 里单独配:我按 500 到 25 降序排属性数,最佳特征数从 20 降到 2。 多代理优化最佳结果破 0.7,明显优于单代理;但单次测试余额图反而差——随机抽样的信号重叠让总交易只剩 21 笔。把 shift_probab 挪到近 0.5 可放大每代理交易量。年初起测模型较稳;shift_probab 设 0.3 再优化两个月找平衡,复杂计算下我取迭代几次后的结果:测试误差仍大,但 0.2 阈值下四个月盈利,测试数据波动明显。外汇与贵金属属高风险,此类概率模型仅作辅助。

MQL5 / C++
CRLAgents *ag1=new CRLAgents("RlMonteCarloMulti",class="num">5,class="num">500,number_of_best_features,class="num">50,regularize,shift_probab);
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EA 交易初始化函数                                                    | 
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit() {
   ag1.setAgentSettings(class="num">0,class="num">500,class="num">20,class="num">50,regularize,shift_probab);
   ag1.setAgentSettings(class="num">1,class="num">200,class="num">15,class="num">50,regularize,shift_probab);
   ag1.setAgentSettings(class="num">2,class="num">100,class="num">10,class="num">50,regularize,shift_probab);
   ag1.setAgentSettings(class="num">3,class="num">50,class="num">5,class="num">50,regularize,shift_probab);
   ag1.setAgentSettings(class="num">4,class="num">25,class="num">2,class="num">50,regularize,shift_probab);
   class="kw">return(INIT_SUCCEEDED);
   }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 计算 Tsignal                                                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void calcTsignal() {
   Tsignal=class="num">0;
   for(class="type">int i=class="num">0;i<ArraySize(ag1.agent);i++) {
      CopyClose(_Symbol,class="num">0,class="num">1,ArraySize(ag1.agent[i].inpVector),ag1.agent[i].inpVector);
      ArraySetAsSeries(ag1.agent[i].inpVector,true);
      }
   Tsignal=ag1.getTradeSignal();
   }
class="num">2018.11.class="num">30 class="num">01:class="num">56:class="num">40.441 Core class="num">2  class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   RlMonteCarlo TRAIN LOSS
class="num">2018.11.class="num">30 class="num">01:class="num">56:class="num">40.441 Core class="num">2  class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   class="num">0.02703 class="num">0.20000 class="num">0.09091 class="num">0.05714 class="num">0.14286

蒙特卡洛训练与泛化损耗的日志读数

在 MT5 策略测试器的日志里,强化学习类蒙特卡洛模型会按时间戳吐出两类损耗:TRAIN LOSS 是样本内训练误差,OOB LOSS 是袋外(out-of-bag)泛化误差。上面这段 2018.11.30 的回测日志,单模型 RlMonteCarlo 的 OOB LOSS 五个折页分别为 0.21622 / 0.23333 / 0.21212 / 0.17143 / 0.19048,整体偏低且平稳。 切换到多模型版本 RlMonteCarloMulti,TRAIN LOSS 五个值为 0.13229 / 0.16667 / 0.16262 / 0.14599 / 0.20937,比单模型训练误差更小,说明多模型在样本内拟合能力更强。但同一时刻的 OOB LOSS 直接跳到 0.45377 / 0.45758 / 0.44650 / 0.45693 / 0.46120,泛化误差翻了一倍多。 这种训练误差下降、袋外误差飙升的组合,是典型过拟合信号。外汇与贵金属市场高风险,这类模型直接上实盘可能触发频繁误判;开 MT5 把日志导出来,对照自己 EA 的 LOSS 行,若 OOB 长期高于 TRAIN 两倍,先降复杂度再谈上线。

MQL5 / C++
class="num">2018.11.class="num">30 class="num">01:class="num">56:class="num">40.441 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   RlMonteCarlo OOB LOSS
class="num">2018.11.class="num">30 class="num">01:class="num">56:class="num">40.441 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   class="num">0.21622 class="num">0.23333 class="num">0.21212 class="num">0.17143 class="num">0.19048
class="num">2018.11.class="num">30 class="num">02:class="num">53:class="num">17.236 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   RlMonteCarloMulti TRAIN LOSS
class="num">2018.11.class="num">30 class="num">02:class="num">53:class="num">17.236 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   class="num">0.13229 class="num">0.16667 class="num">0.16262 class="num">0.14599 class="num">0.20937
class="num">2018.11.class="num">30 class="num">02:class="num">53:class="num">17.236 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   RlMonteCarloMulti OOB LOSS
class="num">2018.11.class="num">30 class="num">02:class="num">53:class="num">17.236 Core class="num">2   class="num">2018.11.class="num">28 class="num">23:class="num">59:class="num">59   class="num">0.45377 class="num">0.45758 class="num">0.44650 class="num">0.45693 class="num">0.46120

◍ 选模型看分类误差而非表面拟合

强化学习在交易建模里最容易被神话,以为智能体自己跑就能解开外汇、贵金属的价格混沌。实际要落地,作者原系列第一篇的模型靠蒙特卡罗和按最小误差挑试验数据,才把过拟合压下去。 衡量模型好坏别只看训练集漂亮,应按交易信号数量和最小分类误差挑。训练集和测试集误差理想状态是大致相等,且都不能到 0.5——那是半数预测错,等于抛硬币。外汇和贵金属杠杆高,模型误差失控时实盘回撤可能远超回测。 随文给了 RL_Monte_Carlo.mqh(17.26 KB)、RL_Monte_Carlo_trader.mq5(10.33 KB)等文件。编译 trader 时有人报 complex.mqh 缺失、mqh 里 getRDFstructure 等函数重定义报错,前帖解法是在类声明前加 void。开 MT5 拖进代码先改这句再编译,能少绕两小时。

MQL5 / C++
&class="macro">#x27;getRDFstructure&class="macro">#x27; - unexpected token, probably type is missing? RL_Monte_Carlo.mqh               class="num">76    class="num">12
&class="macro">#x27;getRDFstructure&class="macro">#x27; - function already defined and has different type    RL_Monte_Carlo.mqh            class="num">43    class="num">22
see declaration of &class="macro">#x27;CRLAgent::getRDFstructure&class="macro">#x27;  RL_Monte_Carlo.mqh
&class="macro">#x27;RecursiveElimination&class="macro">#x27; - unexpected token, probably type is missing?    RL_Monte_Carlo.mqh    class="num">133    class="num">11
&class="macro">#x27;RecursiveElimination&class="macro">#x27; - function already defined and has different type    RL_Monte_Carlo.mqh    class="num">133    class="num">11
&class="macro">#x27;updatePolicy&class="macro">#x27; - unexpected token, probably type is missing?    RL_Monte_Carlo.mqh        class="num">221    class="num">11
&class="macro">#x27;updatePolicy&class="macro">#x27; - function already defined and has different type    RL_Monte_Carlo.mqh        class="num">221    class="num">11
把多代理枚举交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到不同代理组的误差分布与稳定性对比,你只需判断哪组更适合当下盘态。

常见问题

通过在优化器中随机抽标签并行创建多个代理,比较各自在测试样本上的误差,选最小误差模型写入文件,用模型群降低单模型过拟合概率。
基于 OOP 库在 EA 中实例化所需数量的 RL 代理,分别设不同参数,借助静态唯一 ID 区分并保存各自随机森林结构与误差矩阵。
每次优化迭代把模型误差写入文件,新迭代读取并比对,保留最小误差模型,使跨迭代选择稳定且可复现。
小布盯盘的 AIGC 模块可呈现代理组误差与稳定性视图,但策略逻辑仍需你在 MQL5 端实现并接入,它负责看板而非代写交易算法。
市场非平稳,代理可能倾向拟合噪声,实盘失效概率高,贵金属与外汇杠杆品种须严格小额验证并控风险。