交易中的神经网络:具有预测编码的混合交易框架(StockFormer)·综合运用
🧠

交易中的神经网络:具有预测编码的混合交易框架(StockFormer)·综合运用

(3/3)·把长期短期与跨资产三路变换器融进 RL 策略,这套混合机器到底怎么跑通

实战向进阶 第 3/3 篇
很多人把强化学习直接喂原始 K 线,结果策略在噪声里反复横跳。StockFormer 的思路是先做预测编码提纯,再让评论者反哺编码器——这一步没做,模型基本学不到跨资产依赖。

「交叉多头注意力层的类骨架与初始化」

在 MT5 的 OpenCL 神经网络扩展里,CNeuronCrossDMHAttention 这个类把自注意力、交叉注意力和前馈卷积叠成可堆叠的多层结构。protected 段里大量虚函数被 override 成返回 false 或只留声明,说明单输入路径在该层被禁用,必须走带 SecondInput 的双路前向。 看 Init 的参数表就能反推训练时的张量形状:window*units_count 作为自注意力窗口展平长度,window_cross 与 units_cross 控制交叉注意力的外部序列尺寸,heads 决定多头拆分数,layers 控制堆叠深度。若 units_count 传 0,use_self 为假,循环里只建交叉注意力,不建自注意力。 初始化第一段先调基类 CNeuronBaseOCL::Init,输入神经元数被强行改成 window*units_count,这一步若失败直接返回 false,意味着窗口与单元数乘积超过显存或 OpenCL 缓冲上限时,层根本建不起来。实盘跑贵金属模型时,window=64、units_count=32、heads=4、layers=2 的组合在普通独显上可能占用数百 MB 显存,外汇品种同理属高风险算力消耗。 callout 标题示例:双路输入不是可选项 基类里单输入 feedForward 被 override 返回 false,说明这个类在设计上拒绝单序列流入。复制代码时若只接价格序列不接 SecondInput,前向会静默失败,调参前先确认你的 SecondInput 缓冲已挂好。

MQL5 / C++
class="kw">protected:
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override { class="kw">return false; }
  class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) class="kw">override;
  class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *prevLayer) class="kw">override { class="kw">return false; }
  class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput,
CBufferFloat *SecondGradient,
ENUM_ACTIVATION SecondActivation = None) class="kw">override;
  class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override { class="kw">return false; }
  class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) class="kw">override;
class="kw">public:
                    CNeuronCrossDMHAttention(class="type">void)  {};
                   ~CNeuronCrossDMHAttention(class="type">void)  {};
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                         class="type">uint window, class="type">uint window_key, class="type">uint units_count,
                         class="type">uint window_cross, class="type">uint units_cross,
                         class="type">uint heads, class="type">uint layers,
                         ENUM_OPTIMIZATION optimization_type, class="type">uint batch);
  class=class="str">"cmt">//---
  class="kw">virtual class="type">int       Type(class="type">void) class="kw">override  const   {  class="kw">return defNeuronCrossDMHAttention; }
  };
class="type">bool CNeuronCrossDMHAttention::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                         class="type">uint window, class="type">uint window_key, class="type">uint units_count,
                         class="type">uint window_cross, class="type">uint units_cross, class="type">uint heads,
                         class="type">uint layers, ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
  if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, window * units_count, optimization_type, batch))
     class="kw">return false;
  cLayers.Clear();
  cLayers.SetOpenCL(OpenCL);
  CNeuronRelativeSelfAttention *attention = NULL;
  CNeuronRelativeCrossAttention *cross = NULL;
  CNeuronMHFeedForward *conv = NULL;
  class="type">bool use_self = units_count > class="num">0;
  class="type">int layer = class="num">0;
  for(class="type">uint i = class="num">0; i < layers; i++)
    {
     if(use_self)

多头交叉注意力层的堆叠与反向梯度回传

在 CNeuronCrossDMHAttention 的初始化尾部,代码依次把三种层压进 cLayers 容器:先循环创建 CNeuronRelativeSelfAttention(自注意力),再建一个 CNeuronRelativeCrossAttention(交叉注意力),最后补一层 CNeuronMHFeedForward(多头前馈)。每一层都走 Init 后立刻 cLayers.Add,任一环节返回 false 就 delete 并整体退出,保证对象图要么完整要么不建。 注意前馈层 Init 的窗口参数被写成 window 与 2*window,units_count 与 heads 沿用上游设置,这意味着特征维度在卷积式前馈处被翻倍展开,再经多头压缩回原 units_count。layer 变量在每次 Add 后自增,实质是给 OpenCL 内核用的层索引偏移。 反向传播由 calcInputGradients 接管。它先从 cLayers 末尾往前遍历,对每层调用 calcHiddenGradients;当遇到类型为 defNeuronCrossDMHAttention 的下一层时,额外跑一次 SumAndNormilize 把 SecondGradient 与 PrevOutput 做归一累加。这种从后往前的链式回传,是 Transformer 类结构在 MT5 端能训练的前提。 开 MT5 把这段塞进你自己的神经网络 EA,重点改 window 与 heads 两个量:heads 从 4 提到 8 时,前馈层的 2*window 展开宽度不变但并行头数翻倍,显存占用倾向明显上升,低端卡可能直接 Init 失败。外汇与贵金属模型训练属高风险,过拟合导致的实盘回撤概率不低。

MQL5 / C++
{
   attention = new CNeuronRelativeSelfAttention();
   if(!attention ||
      !attention.Init(class="num">0, layer, OpenCL, window, window_key, units_count, heads, optimization, iBatch) ||
      !cLayers.Add(attention)
      )
      {
       class="kw">delete attention;
       class="kw">return false;
      }
   layer++;
   }
   cross = new CNeuronRelativeCrossAttention();
   if(!cross ||
       !cross.Init(class="num">0, layer, OpenCL, window, window_key, units_count, heads,
window_cross, units_cross, optimization, iBatch) ||
       !cLayers.Add(cross)
      )
      {
       class="kw">delete cross;
       class="kw">return false;
      }
   layer++;
   conv = new CNeuronMHFeedForward();
   if(!conv ||
       !conv.Init(class="num">0, layer, OpenCL, window, class="num">2 * window, units_count, class="num">1, heads, optimization, iBatch) ||
       !cLayers.Add(conv)
      )
      {
       class="kw">delete conv;
       class="kw">return false;
      }
   layer++;
   }
   SetOutput(conv.getOutput(), true);
   SetGradient(conv.getGradient(), true);
class=class="str">"cmt">//---
   class="kw">return true;
   }
class="type">bool CNeuronCrossDMHAttention::calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput,
CBufferFloat *SecondGradient, ENUM_ACTIVATION SecondActivation = -class="num">1)
  {
   if(!NeuronOCL || !SecondInput || !SecondGradient)
      class="kw">return false;
   if(PrevOutput.Total() != SecondGradient.Total())
     {
      PrevOutput.BufferFree();
      if(!PrevOutput.BufferInit(SecondGradient.Total(), class="num">0) ||
         !PrevOutput.BufferCreate(OpenCL))
         class="kw">return false;
     }
   if(!SecondGradient.Fill(class="num">0))
      class="kw">return false;
   CObject *next = cLayers[-class="num">1];
   CNeuronBaseOCL *current = NULL;
   for(class="type">int i = cLayers.Total() - class="num">2; i >= class="num">0; i--)
     {
      current = cLayers[i];
      if(!current ||
         !current.calcHiddenGradients(next, SecondInput, PrevOutput, SecondActivation))
         class="kw">return false;
      if(next.Type() == defNeuronCrossDMHAttention)
         if(!SumAndNormilize(SecondGradient, PrevOutput, SecondGradient, class="num">1, false, class="num">0, class="num">0, class="num">0, class="num">1))
            class="kw">return false;
      next = current;
     }
   if(!NeuronOCL.calcHiddenGradients(next, SecondInput, PrevOutput, SecondActivation))
      class="kw">return false;

◍ 注意力层梯度归一的回传出口

在自定义神经网络的反向传播里,遇到类型为 defNeuronCrossDMHAttention 的神经元时,必须先调用 SumAndNormilize 对 SecondGradient 与 PrevOutput 做累加归一,再决定是否继续回传。 上述代码片段中,SumAndNormilize 的实参顺序是:目标梯度 SecondGradient、前层输出 PrevOutput、源梯度 SecondGradient、缩放系数 1、非反向标志 false、四个偏移与维度参数均为 0,最后通道数 1。任一返回 false 都会直接中断整段训练流程。 在 MT5 里接这段逻辑时,重点确认 defNeuronCrossDMHAttention 的枚举值与你网络定义一致;多头部注意力若扩到通道数大于 1,最后那个参数要同步改,否则梯度尺度会偏掉。外汇与贵金属模型训练本身属高风险实验,过拟合导致的实盘回撤概率不低。

MQL5 / C++
  if(next.Type() == defNeuronCrossDMHAttention)
      if(!SumAndNormilize(SecondGradient, PrevOutput, SecondGradient, class="num">1, false, class="num">0, class="num">0, class="num">0, class="num">1))
          class="kw">return false;
class=class="str">"cmt">//---
  class="kw">return true;
}

「别急着下结论」

StockFormer 把预测编码和深度强化学习揉在一起,靠三条分支分别抠出短趋势、长动态和跨资产依赖,再用级联多头注意力压进统一状态空间,这套结构在多元品种联动上比单资产模型更不容易瞎拟合。 我们已经在 MQL5 里落地了雏形变换器,并接进了多头注意力编码器和解码器,配套文件里 Research.mq5 到 Test.mq5 共 5 个智能系统加上 3 个类库,ZIP 包 2253.87 KB,直接丢进 MT5 就能跑通数据收集到测试的全链路。 下一篇才会碰可训练模型架构和训练细节,现在先别急着拿这套框架下实盘结论,外汇和贵金属杠杆高、跳空频繁,光看表征整合优雅不代表样本外能活下来,开 MT5 把 Study1 和 Study2 的日志打出来比对一下再说。

把三路潜在状态交给小布对齐
小布盯盘的 AIGC 已内置多资产相关性诊断,打开对应品种页即可看到短长期态分叉提示,你只需把融合权重拿去回测,不必手搓并行 FFN。

常见问题

它将原前馈拆成多个子空间并行模块共享原参数规模,靠多头注意力分配特征,不扩参但提升分解能力。
目前小布提供跨资产依赖与短长期趋势的可视化,融合权重需自行接 RL 模块,AIGC 层不代训策略。
为了让隐藏状态提取贴合交易回报目标,避免编码自监督与策略优化脱节,提升投资回报概率。
实验显示其抗噪优于传统方法,但外汇贵金属属高风险,实盘仍可能失效,须小仓验证。