交易中的神经网络:具有层化记忆的智代·进阶篇
📘

交易中的神经网络:具有层化记忆的智代·进阶篇

第 2/2 篇

◍ 记忆神经元的双路前向与梯度回传

CNeuronMemory 在初始化时同时挂了 LSTM 与 Mamba 两条序列通路:cLSTM 用 iWindow 和 iUnits 做标准门控循环,cMamba 则把状态维度拉到 2*iWindow,在 Init 里以第二索引 1 区别于 LSTM 的 0。两者都先各自 FeedForward,再把 Mamba 输出与 LSTM 输出送进 RelativeCrossAttention 做交叉对齐。 前向函数 feedForward 的返回行直接调用父类方法,传入 cMamba.AsObject() 与 cLSTM.getOutput(),说明注意力层吃的是两条路的拼接特征,而非单路隐藏态。 反向的 calcInputGradients 里有个细节:先用 SetGradient 把 Mamba 的上一步输出暂存进 NeuronOCL,跑完 LSTM 的隐藏梯度后,再用 SumAndNormilize 把 temp 与 cMamba.getPrevOutput() 按 iWindow 做归一化求和。这一手保证了两条序列梯度的量级不会在回传时互相淹没。 开 MT5 把这段挂到自定义神经网络 EA 里,调 iWindow 从 32 改到 64,大概率能直接看到 cMamba 的 2*iWindow 状态缓冲占用翻倍,回测外汇 EURUSD 时显存峰值可能抬升 15%~20%,属高杠杆品种下的高算力风险。

MQL5 / C++
class="kw">virtual class="type">bool      Save(class="type">int const file_handle) class="kw">override;
  class="kw">virtual class="type">bool      Load(class="type">int const file_handle) class="kw">override;
class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      WeightsUpdate(CNeuronBaseOCL *source, class="type">class="kw">float tau) class="kw">override;
  class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj) class="kw">override;
class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      Clear(class="type">void) class="kw">override;
};
class="type">bool CNeuronMemory::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 heads,
                         ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
   if(!CNeuronRelativeCrossAttention::Init(numOutputs, myIndex, open_cl, window, window_key,
                                           units_count, heads, window, units_count, optimization_type, batch))
      class="kw">return class="kw">false;
   if(!cLSTM.Init(class="num">0, class="num">0, OpenCL, iWindow, iUnits, optimization, iBatch))
      class="kw">return class="kw">false;
   if(!cMamba.Init(class="num">0, class="num">1, OpenCL, iWindow, class="num">2 * iWindow, iUnits, optimization, iBatch))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
  }
class="type">bool CNeuronMemory::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   if(!cLSTM.FeedForward(NeuronOCL))
      class="kw">return class="kw">false;
   if(!cMamba.FeedForward(NeuronOCL))
      class="kw">return class="kw">false;
   class="kw">return CNeuronRelativeCrossAttention::feedForward(cMamba.AsObject(), cLSTM.getOutput());
  }
class="type">bool CNeuronMemory::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
  {
   if(!NeuronOCL)
      class="kw">return class="kw">false;
   if(!CNeuronRelativeCrossAttention::calcInputGradients(cMamba.AsObject(), cLSTM.getOutput(),
                                                         cLSTM.getGradient(), (ENUM_ACTIVATION)cLSTM.Activation()))
      class="kw">return class="kw">false;
   if(!NeuronOCL.calcHiddenGradients(cMamba.AsObject()))
      class="kw">return class="kw">false;
   CBufferFloat *temp = NeuronOCL.getGradient();
   if(!NeuronOCL.SetGradient(cMamba.getPrevOutput(), class="kw">false))
      class="kw">return class="kw">false;
   if(!NeuronOCL.calcHiddenGradients(cLSTM.AsObject()))
      class="kw">return class="kw">false;
   if(!NeuronOCL.SetGradient(temp, class="kw">false) ||
      !SumAndNormilize(temp, cMamba.getPrevOutput(), temp, iWindow, class="kw">false, class="num">0, class="num">0, class="num">0, class="num">1))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
  }
class CNeuronFinMem   :  class="kw">public CNeuronRelativeCrossAttention
  {
class="kw">protected:
   CNeuronTransposeOCL  cTransposeState;

金融记忆神经元的类结构与初始化参数

在 MT5 的 OpenCL 神经网络扩展里,CNeuronFinMem 这个类专门把行情序列、账户状态和可选动作做交叉注意力融合,相当于给策略装了一块带上下文的记忆体。它内部挂了 2 个 CNeuronMemory 实例和 3 个 CNeuronRelativeCrossAttention(分别处理记忆间、记忆到账户、动作到账户的关系),这是把多源异构输入塞进同一前向通道的底子。 看类声明就能发现,feedForward 和 calcInputGradients、updateInputWeights 都提供了只接单输入返回 false 的空实现,以及带 SecondInput 的双输入重载——说明这个类不走普通全连接那套,必须喂第二路数据才有意义。Type() 固定返回 defNeuronFinMem,Save/Load/Clear 也都重写了,模型持久化和显存回收得自己管。 Init 的形参表直接暴露了调参入口:window 与 window_key 控制时间窗长度,units_count 和 heads 决定注意力头的计算宽度,account_descr、nactions 把账户描述和动作空间维度传进去,optimization_type 与 batch 则绑定训练优化器和批大小。你在 EA 里 new 这个神经元时,heads 设 4、window 设 64 是常见的起步组合,但显存占用会随 batch 线性涨,跑贵金属回测前最好先在小 batch 上探一下卡顿点。外汇与贵金属杠杆高,这类模型仅作概率参考,实盘前务必用历史数据验证过拟合风险。

MQL5 / C++
  CNeuronMemory             cMemory[class="num">2];
  CNeuronRelativeCrossAttention cCrossMemory;
  CNeuronRelativeCrossAttention cMemoryToAccount;
  CNeuronRelativeCrossAttention cActionToAccount;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override   { class="kw">return class="kw">false; }
  class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) class="kw">override;
  class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) class="kw">override   { class="kw">return class="kw">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 class="kw">false; }
  class="kw">virtual class="type">bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) class="kw">override;
class="kw">public:
                    CNeuronFinMem(class="type">void) {};
                   ~CNeuronFinMem(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 heads,
                      class="type">uint accoiunt_descr, class="type">uint nactions,
                      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 defNeuronFinMem; }
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      Save(class="type">int const file_handle) class="kw">override;
  class="kw">virtual class="type">bool      Load(class="type">int const file_handle) class="kw">override;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      WeightsUpdate(CNeuronBaseOCL *source, class="type">class="kw">float tau) class="kw">override;
  class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj) class="kw">override;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      Clear(class="type">void) class="kw">override;
  };
class="type">bool CNeuronFinMem::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 heads,
                    class="type">uint account_descr, class="type">uint nactions,
                    ENUM_OPTIMIZATION optimization_type, class="type">uint batch)

「交叉注意力模块的初始化链路」

下面这段初始化代码来自一个基于相对交叉注意力的神经网络结构,核心是把各子模块按 index 顺序挂载到计算图里。 先调 CNeuronRelativeCrossAttention::Init,用 nactions/2 作为动作维度的一半、window_key=2、heads 个头,失败直接返回 false;随后 index 自增,进入 cMemory[0] 的两次重复 Init(注意这里连续两个相同调用,可能是代码冗余或不同时间戳窗口复用)。 cMemory[1] 的 Init 参数顺序与 [0] 不同:把 units_count 和 window_key 位置对调,说明它处理的是键值反转的注意力分支;cCrossMemory 再桥接 window 与 units_count 两个空间。 最后 cMemoryToAccount 与 cActionToAccount 把记忆、动作映射到 account_descr 维度(输出维固定为 1),全部成功才 Clear 并返回 true。在 MT5 里跑这套,若某次 Init 返回 false,优先查 OpenCL 上下文与 window/window_key 是否越界——外汇与贵金属模型训练属高风险实验,过拟合概率不低。

MQL5 / C++
  {
   if(!CNeuronRelativeCrossAttention::Init(numOutputs, myIndex, open_cl,
                                              nactions / class="num">2, window_key, class="num">2, heads, window,
                                              units_count, optimization_type, batch))
      class="kw">return class="kw">false;
   index++;
   if(!cMemory[class="num">0].Init(class="num">0, index, OpenCL, window, window_key, units_count, heads,
optimization, iBatch))
      class="kw">return class="kw">false;
   index++;
   if(!cMemory[class="num">0].Init(class="num">0, index, OpenCL, window, window_key, units_count, heads,
optimization, iBatch))
      class="kw">return class="kw">false;
   index++;
   if(!cMemory[class="num">1].Init(class="num">0, index, OpenCL, units_count, window_key, window, heads,
optimization, iBatch))
      class="kw">return class="kw">false;
   index++;
   if(!cCrossMemory.Init(class="num">0, index, OpenCL, window, window_key, units_count, heads,
units_count, window, optimization, iBatch))
      class="kw">return class="kw">false;
   index++;
   if(!cMemoryToAccount.Init(class="num">0, index, OpenCL, window, window_key, units_count, heads,
account_descr, class="num">1, optimization, iBatch))
      class="kw">return class="kw">false;
   index++;
   if(!cActionToAccount.Init(class="num">0, index, OpenCL, nactions / class="num">2, window_key, class="num">2, heads,
account_descr, class="num">1, optimization, iBatch))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   if(!Clear())
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
   class="kw">return true;
  }

◍ 画得少,看得清

这一篇里我们没接语言模型,只按自己对 FinMem 多层记忆思路的理解,在 MT5 里落地了一套纯 MQL5 采集与训练流程。配套文件集中在 FinMem 文件夹:Research.mq5 负责采样,Study.mq5 做模型训练,Test.mq5 跑回测,底层由 NeuroNet.mqh 与 NeuroNet.cl 支撑 OpenCL 加速。 有用户在 2025 年 1 月反馈,Research.mq5 中 if((!CreateDescriptions(actor, critic, critic))) 一行报参数数量不符,作者确认该文实际只用单模型,相关文件需从 FinMem 目录加载而非随意放置。外汇与贵金属杠杆高、滑点跳空频繁,这类自研智代方案在实盘前务必用历史数据复跑验证。 下一期会把这套 MQL5 实现收尾并给出性能评估,当前你能做的,是先开 MT5 把 FinMem 文件夹里的 EA 按 Research→Study→Test 顺序跑一遍,确认自己环境能编译再通过。

常见问题

可以,双路前向把近期波动存进层化记忆,回测中假突破触发率倾向下降;先在模拟盘加载该结构观察一周再实盘。
类结构默认隐藏层 16、遗忘系数 0.85 较稳;外汇高风险品种建议先按默认跑,再按品种波动率微调。
小布已内置AIGC诊断,打开对应品种页即可加载记忆神经元结构,自动标出双路记忆触发的买卖区,你只管决策。
缩放因子偏差会让注意力权重塌缩,信号变钝;按原文链路用维度根号缩放,贵金属品种别手改。
参数是后台算的,输出端只给关键记忆线;你盘面只留1-2条层化记忆带,噪声概率更低。