神经网络在交易中的应用:市场异常的自适应检测(终篇)·综合运用
📘

神经网络在交易中的应用:市场异常的自适应检测(终篇)·综合运用

第 3/3 篇

◍ 反向传播里的断点保护

这段训练循环把状态编码器、策略网络、概率层的反向传播串在一起,任何一步返回 false 就立刻打印函数名加行号、置 Stop 并 break,避免脏梯度继续污染权重。 Actor 的反向传播依赖 Encoder 指针与 LatentLayer,随后还要单独调 Encoder.backPropGradient 把潜层梯度回传;若两次调用任一失败,同样走断点逻辑。 target 向量按 NActions/3 长度置零,依据 fstate[0,0] 正负填 1 到 [0] 或 [1],再灌给 Probability 层反传;这里若 AssignArray 或 backProp 失败也会中止。 每累计 tick 超过 500 毫秒,就按 (iter+i-start)/Iterations*100 算进度百分比,分别用 15.8f 精度打印 Encoder 与 Actor 的近期平均误差,方便在 MT5 Experts 日志里盯训练曲线。外汇与贵金属模型训练涉及高杠杆与样本偏移,回测误差低不代表实盘概率占优。

MQL5 / C++
         {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            class="kw">break;
         }
      class=class="str">"cmt">//--- State Encoder
      if(!Encoder.backProp(GetPointer(bState), (CBufferFloat*)NULL, NULL))
         {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            class="kw">break;
         }
      class=class="str">"cmt">//--- Actor Policy
      if(!Actor.backProp(GetPointer(bActions), (CNet*)GetPointer(Encoder), LatentLayer)
         || !Encoder.backPropGradient((CBufferFloat*)NULL, (CBufferFloat*)NULL, LatentLayer, true)
         )
         {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            class="kw">break;
         }
      target = vector<class="type">class="kw">float>::Zeros(NActions / class="num">3);
      if(fstate[class="num">0, class="num">0] > class="num">0)
         target[class="num">0] = class="num">1;
      else
         if(fstate[class="num">0, class="num">0] < class="num">0)
            target[class="num">1] = class="num">1;
      if(!Result.AssignArray(target) ||
         !Probability.backProp(Result, (CBufferFloat*)NULL)
         || !Encoder.backPropGradient((CBufferFloat*)NULL, (CBufferFloat*)NULL, LatentLayer)
         )
         {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            class="kw">break;
         }
      class=class="str">"cmt">//---
      if(GetTickCount() - ticks > class="num">500)
         {
            class="type">class="kw">double percent = class="type">class="kw">double(iter + i - start) * class="num">100.0 / (Iterations);
            class="type">class="kw">string str = StringFormat("%-13s %class="num">6.2f%% -> Error %class="num">15.8f\n", "Encoder",
percent, Encoder.getRecentAverageError());
            str += StringFormat("%-14s %class="num">6.2f%% -> Error %class="num">15.8f\n", "Actor", percent,
Actor.getRecentAverageError());

把概率误差打进终端日志

这段收尾代码负责把神经网络两层(Actor 与 Probability)的最近平均误差输出到 MT5 终端,并在跑完测试后自动卸载 EA。 str += StringFormat("%-13s %6.2f%% -> Error %15.8f\n", "Probability", percent, Probability.getRecentAverageError()); 把当前概率层的命中百分比与平均误差按左对齐 13 字符、误差保留 8 位小数的格式拼进字符串。 Comment(str) 在图表左上角实时刷新;随后 ticks = GetTickCount() 重设计时锚点,避免每帧重绘拖慢回测。外层循环结束后 Comment("") 清空注释,PrintFormat 用 %10.7f 把 Actor 与 Probability 的误差打到 Experts 日志,最后 ExpertRemove() 终止 EA——外汇与贵金属品种波动剧烈,这类自研网络的误差仅反映样本内拟合,实盘迁移需警惕过拟合风险。

MQL5 / C++
    str += StringFormat("%-13s %class="num">6.2f%% -> Error %class="num">15.8f\n", "Probability",
percent, Probability.getRecentAverageError());
    Comment(str);
    ticks = GetTickCount();
   }
  }
 }
 Comment("");
class=class="str">"cmt">//---
 PrintFormat("%s -> %d -> %-15s %class="num">10.7f", __FUNCTION__, __LINE__, "Actor", Actor.getRecentAverageError());
 PrintFormat("%s -> %d -> %-15s %class="num">10.7f", __FUNCTION__, __LINE__, "Probability", Probability.getRecentAverageError());
 ExpertRemove();
class=class="str">"cmt">//---
}

「用 MT5 回测验证 DADA 模型的外推能力」

把 DADA 框架写进 MQL5 并接上可训练模型后,下一步必须丢进真实历史里跑一遍,否则无从判断它在实盘噪声下的可行性。我们用 MetaTrader 5 策略测试器,拿 2024 年 EURUSD 的 M1 数据生成随机运行集做训练,指标全用默认设置,尽量压住外部干扰。 测试切到 2025 年 1—2 月的历史段,参数一字未改,专门考察模型在训练集没见过的数据上的表现。这套做法直接反映接近真实的泛化水平,是客观评估 Actor 学习行为的底线。 跑下来共成交 57 笔,盈利单占比超 35%。胜率不算高,但盈利单均值约为亏损均值的 3 倍,总利润因子 1.53,账面整体为正。 利润大部分集中在 1 月上半月,之后净值在窄区间晃荡,说明该版本还有优化空间。外汇与贵金属高杠杆、滑点随时吃人,这套结果仅对应本次改过的 DADA 架构,换一版实现可能完全走样。 实盘前建议自己在 MT5 重跑这段 2025 年 1—2 月 EURUSD M1,把利润因子和月度分布对齐,再决定是否动架构。

◍ 动态适配不等于躺赢

DADA 框架把自适应瓶颈和双并行解码器拼到一起,核心卖点是无需事先调参就能贴合不同数据结构。我们在 MQL5 里手搓了这套方法,接进可训练模型,用真实历史数据训完跑测试,确实出了盈利表现。 但净值曲线没有稳定向上的斜率,回测里盈利和回撤是交替出现的,说明框架只是把异常检测做活了,离直接当策略用还差一层风控和再平衡。外汇和贵金属这种高杠杆品种,光靠动态适配容易在极端行情里被洗出去。 真要验证,把 Study.mq5 和 Test.mq5 拖进 MT5 跑一遍自己的品种,重点看净值曲线的回撤段而不是总收益。哪段塌得最狠,就从那里动手改瓶颈宽度。

常见问题

在梯度更新环节设阈值,当权重变化超过预设范围就截断并写日志,避免数值爆炸导致整轮训练作废。
在预测函数里用 Print 输出实际值与预测值的差值及时间戳,回看日志能快速定位哪段行情外推失效。
小布可加载你导出的概率误差序列,自动标出偏离带并推送提醒,省去手动翻终端日志。
外推能力受样本外结构变化影响,动态适配只是降频失效而非免死,实盘需每周重校一次参数。
不是,动态适配不等于躺赢,行情机制切换时仍要人工介入复核,否则误差会累积成单边亏损。