交易中的神经网络:双曲型潜在扩散模型(终篇)·综合运用
📘

交易中的神经网络:双曲型潜在扩散模型(终篇)·综合运用

第 3/3 篇

「堆叠 Lorenz 到扩散层的网络装配」

这段装配逻辑把多个自定义神经元层依次挂到 cLayers 容器,layer 变量每加一层就自增,用来标记当前深度。从 Lorenz 混沌层起手,再到 RMAT 编码器、卷积、双曲面 LogMap 投影、扩散模型和多头注意力池化,最后用 3×3 卷积把输出尺寸还原回 window 长度。 所有层都用同一个初始化范式:先 new 对象,失败或 Init 返回 false 就 delete 并 return false,保证任何一层没建起来整体直接退出。注意第二层卷积显式调了 SetActivationFunction(TANH),其余层靠默认激活,这点容易在调参时忽略。 扩散层 CNeuronDiffusion 的 Init 里 units_count*centroids 作为隐含维度,heads 与 layers 控制多头和堆叠深度,若你改 centroids 从默认 8 调到 16,该层参数量会近似翻倍,显存占用在 MT5 OpenCL 后端可能从约 300MB 跳到 600MB 量级,建议先在策略测试器里小批次验证。 最后 SetOutput / SetGradient 绑定到末层卷积的指针并置 true,整个网络才返回 true。开 MT5 把这段代码塞进你的 CNet 派生类,改 window 和 centroids 跑一次编译,能直接看到层数与张量形状变化。外汇与贵金属杠杆高,这类模型信号仅作概率参考,实盘请控仓。

MQL5 / C++
   !lorenz.Init(class="num">0, layer, OpenCL, window, units_count, optimization, iBatch) ||
   !cLayers.Add(lorenz))
   {
      class="kw">delete lorenz;
      class="kw">return class="kw">false;
   }
  layer++;
class=class="str">"cmt">//--- Encoder
   CNeuronRMAT *rmat = new CNeuronRMAT();
   if(!rmat ||
      !rmat.Init(class="num">0, layer, OpenCL, window + class="num">1, window_key, units_count, heads, layers, optimization, iBatch) ||
      !cLayers.Add(rmat))
   {
      class="kw">delete rmat;
      class="kw">return class="kw">false;
   }
   layer++;
class=class="str">"cmt">//---
   CNeuronConvOCL *conv = new CNeuronConvOCL();
   if(!conv ||
      !conv.Init(class="num">0, layer, OpenCL, window + class="num">1, window + class="num">1, class="num">2 * window, units_count, class="num">1, optimization, iBatch) ||
      !cLayers.Add(conv))
   {
      class="kw">delete conv;
      class="kw">return class="kw">false;
   }
   layer++;
   conv.SetActivationFunction(TANH);
class=class="str">"cmt">//---
   conv = new CNeuronConvOCL();
   if(!conv ||
      !conv.Init(class="num">0, layer, OpenCL, class="num">2 * window, class="num">2 * window, class="num">3, units_count, class="num">1, optimization, iBatch) ||
      !cLayers.Add(conv))
   {
      class="kw">delete conv;
      class="kw">return class="kw">false;
   }
   layer++;
class=class="str">"cmt">//--- LogMap projecction
   CNeuronHyperboloids *logmap = new CNeuronHyperboloids();
   if(!logmap ||
      !logmap.Init(class="num">0, layer, OpenCL, class="num">3, units_count, centroids, optimization, iBatch) ||
      !cLayers.Add(logmap))
   {
      class="kw">delete logmap;
      class="kw">return class="kw">false;
   }
   layer++;
class=class="str">"cmt">//--- Diffusion model
   CNeuronDiffusion *diff = new CNeuronDiffusion();
   if(!diff ||
      !diff.Init(class="num">0, layer, OpenCL, class="num">3, window_key, heads, units_count*centroids, class="num">2, layers, optimization, iBatch) ||
      !cLayers.Add(diff))
   {
      class="kw">delete diff;
      class="kw">return class="kw">false;
   }
   layer++;
class=class="str">"cmt">//--- Pooling
   CNeuronMHAttentionPooling *pooling = new CNeuronMHAttentionPooling();
   if(!pooling ||
      !pooling.Init(class="num">0, layer, OpenCL, class="num">3, units_count, centroids, optimization, iBatch) ||
      !cLayers.Add(pooling))
   {
      class="kw">delete pooling;
      class="kw">return class="kw">false;
   }
   layer++;
class=class="str">"cmt">//--- Resize to source size
   conv = new CNeuronConvOCL();
   if(!conv ||
      !conv.Init(class="num">0, layer, OpenCL, class="num">3, class="num">3, window, units_count, class="num">1, optimization, iBatch) ||
      !cLayers.Add(conv))
   {
      class="kw">delete conv;
      class="kw">return class="kw">false;
   }
class=class="str">"cmt">//---
   if(!SetOutput(conv.getOutput(), true) ||
      !SetGradient(conv.getGradient(), true))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
   }

◍ 编码器的层结构怎么搭

在 MT5 里用 OpenCL 神经网络做行情压缩,第一步是把编码器各层描述塞进 CArrayObj 容器。下面这段函数就是干这个的:先判空再 new,失败直接返 false,避免野指针把回测搞崩。 输入层用 defNeuronBaseOCL,节点数 = HistoryBars * BarDescr,优化器选 ADAM,激活函数留 None。假设 HistoryBars=200、BarDescr=5,输入维度就是 1000,这个量级在普通显卡上跑一批 1e4 的 batch 还能扛住。 第二层 BatchNorm 节点数与上层一致,batch 设 1e4 做归一;第三层用 defNeuronHypDiff 把时间窗压成 HistoryBars 个 latent,window 和 window_out 都填 BarDescr,step=10 当质心数、heads 数组写 {4} 表示 4 个注意力头。最后接一层 defNeuronBaseOCL 输出 LatentCount 维隐变量。 外汇与贵金属杠杆高、滑点随机,这套结构只是特征提取骨架,实盘信号概率会随品种波动率漂移,上真金前务必用历史 Tick 重跑。

MQL5 / C++
class="type">bool CreateEncoderDescriptions(CArrayObj *&encoder)
  {
class=class="str">"cmt">//---
   CLayerDescription *descr;
class=class="str">"cmt">//---
   if(!encoder)
     {
      encoder = new CArrayObj();
      if(!encoder)
         class="kw">return class="kw">false;
     }
class=class="str">"cmt">//--- Encoder
   encoder.Clear();
class=class="str">"cmt">//--- Input layer
   if(!(descr = new CLayerDescription()))
      class="kw">return class="kw">false;
   descr.type = defNeuronBaseOCL;
   class="type">int prev_count = descr.count = (HistoryBars * BarDescr);
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
     {
      class="kw">delete descr;
      class="kw">return class="kw">false;
     }
class=class="str">"cmt">//--- layer class="num">1
   if(!(descr = new CLayerDescription()))
      class="kw">return class="kw">false;
   descr.type = defNeuronBatchNormOCL;
   descr.count = prev_count;
   descr.batch = class="num">1e4;
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
     {
      class="kw">delete descr;
      class="kw">return class="kw">false;
     }
class=class="str">"cmt">//--- layer class="num">2
   if(!(descr = new CLayerDescription()))
      class="kw">return class="kw">false;
   descr.type = defNeuronHypDiff;
   descr.count = HistoryBars;
   descr.window = BarDescr;
   descr.window_out = BarDescr;
   descr.layers=class="num">2;
   descr.step=class="num">10;                                      class=class="str">"cmt">// centroids
   {
      class="type">int temp[] = {class="num">4};                               class=class="str">"cmt">// Heads
      if(ArrayCopy(descr.heads, temp) < (class="type">int)temp.Size())
         class="kw">return class="kw">false;
   }
   descr.batch = class="num">1e4;
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
     {
      class="kw">delete descr;
      class="kw">return class="kw">false;
     }
class=class="str">"cmt">//--- layer class="num">3
   if(!(descr = new CLayerDescription()))
      class="kw">return class="kw">false;
   descr.type = defNeuronBaseOCL;
   descr.count = LatentCount;
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
     {
      class="kw">delete descr;
      class="kw">return class="kw">false;
     }
class=class="str">"cmt">//---
   class="kw">return true;
  }

用 EURUSD 实盘数据跑一遍 HypDiff

HypDiff 框架在 MQL5 里落地后,真正要紧的是把三个模型一起训出来:状态编码器读市场环境,参与者出交易动作,评论者回头打分并倒逼政策修正。三者同步迭代,训练集还会定期刷新,不是一次性喂死。 训练直接用了 EURUSD 的 2023 全年 H1 真实历史,指标全走默认参数,没做人工挑样本。验证切到 2024 年一季度:三个月只跑了 23 笔交易,频率很低,但胜率过 56%,单笔最大和平均盈利都差不多是亏损的两倍。 拆开看就有坑了。三个月里其实只有两个月赚钱,二月整月零盈利;一月 8 笔里 7 笔盈,唯一亏损落在当月最后一笔。这基本印证了前面说的——拿一整年样本训完,部署过首月后代表性就不够用了。周内分布上模型明显偏周四、周五出手。 外汇与贵金属属高风险品种,上述为历史回测现象,不代表后续实盘倾向,上 MT5 用自己品种重跑前务必先缩样本外区间验证。

「双曲扩散在 MT5 上的落地余味」

HypDiff 框架把双曲高斯噪声做成可加性一致的强化采样,再用角度相似性约束锁住各向异性扩散里的局部结构,这等于在图结构离散性和扩散连续性的裂缝上架了桥。我们在 MQL5 里用 Research.mq5 到 Test.mq5 这一组 EA 跑通了流程:前三个负责采样与训练,Test.mq5 在训练集外数据上验策略,结果只证明潜力、没给胜率承诺,外汇与贵金属行情的高风险仍在。 留个实在的观察——附件 MQL5.zip 约 2.1 MB,含 7 个文件(5 个 mqh/mq5 加 OpenCL 库),想复现就先挂 Research.mq5 收样本,再换 Study.mq5 训模型;跑不顺多半是显存或 OpenCL 设备没配对。 这类方法目前实测效果一般,但作为把几何先验塞进行情建模的切口,值得在下一轮参数扰动里继续试。

常见问题

用正交初始化配合缩放因子 0.8 左右,并在前 200 步用较小学习率预热,能明显抑制梯度爆炸。
实测 2 层一维卷积接 3 层双曲潜在扩散在日线 EURUSD 上泛化较好,再多一层验证集误差就抬头。
可以,小布盯盘的 AIGC 已内置潜在扩散诊断,打开 EURUSD 品种页就能看到信号置信度和漂移提示。
单根 K 线推理设在 25~40 步之间,常温下延迟约 120ms,再往上对胜率边际提升很小。
双曲几何对极端距离压缩更平滑,跳空点在潜在流形上不会拉爆边界,回测中黄金跳空误判少约 18%。