交易中的神经网络:配备注意力机制(MASAAT)的智代融汇(终章)(基础篇)
📘

交易中的神经网络:配备注意力机制(MASAAT)的智代融汇(终章)(基础篇)

第 1/3 篇

用注意力机制给行情序列加权

传统 RNN 把历史 K 线一视同仁地塞进隐藏层,但真正驱动下一根走势的往往只是最近几根特定位置的波动。MASAAT 的思路是在序列输入后接一层注意力权重,让模型自己学出「哪几根值得多看一眼」。 在 MT5 里跑这套,核心是先构造带时间步的特征矩阵,再接注意力打分。下面这段把收盘价序列做了缩放与掩码,注意力分数用 softmax 归一,输出的是加权上下文向量。 外汇与贵金属杠杆高,模型给的只是概率倾向,实盘前务必用策略测试器跑至少 3 个月 tick 数据验证过拟合。

MQL5 / C++
class="type">class="kw">double AttentionWeights(class="type">class="kw">double &series[], class="type">int window) {
   class="type">class="kw">double scores[window];
   class="type">class="kw">double max_s = -class="num">1e9;
   for(class="type">int i=class="num">0;i<window;i++) {
      scores[i] = series[i] * class="num">0.1; class=class="str">"cmt">// 简化打分
      if(scores[i] > max_s) max_s = scores[i];
   }
   class="type">class="kw">double sum = class="num">0;
   for(class="type">int i=class="num">0;i<window;i++) {
      scores[i] = MathExp(scores[i] - max_s);
      sum += scores[i];
   }
   for(class="type">int i=class="num">0;i<window;i++) scores[i] /= sum; class=class="str">"cmt">// softmax
   class="kw">return scores[window-class="num">1]; class=class="str">"cmt">// 返回最新权重
}

「用注意力机制拆跨资产价格联动」

投资组合管理核心在于跨资产动态再配置资本,以求在波动市中改善回报并压低风险。一篇基于注意力的融汇学习框架 MASAAT,把注意力机制和时间序列分析揉在一起,跑出一组交易智代,在多个粒度层做方向性走势交叉分析,持续再平衡仓位。 为抓显著价格变动,智代套了不同阈值的方向性过滤器,从价格序列里抽关键趋势特征,区分市场转强还是转弱。框架还搞了序列词元生成:横断面注意力(CSA)的词元按单资产指标造,再用注意力优化特征映射;时态分析(TA)的词元由时态特征构造,负责找跨时间点的关系。 CSA 和 TA 各自产出资产与时间点的相关评估,MASAAT 智代用注意力把这两路合并,覆盖观察区间内每个时间点上的资产依赖。前文已实现多智代对象 CNeuronPLRMultiAgentsOCL(多模态序列转多尺度分段线性表示)和 CSA 模块 CNeuronCrossSectionalAnalysis,本文接着这条线往下写。外汇与贵金属杠杆高、回撤快,这类跨资产框架只作分析参考,实盘信号仍可能失效。

◍ 张量转置撑起时间依赖分析

MASAAT 框架里的时态分析模块(TA)要挖出多模态序列中时间点之间的依赖,思路和横断面分析(CSA)很像,区别只在于把原始序列先转置再喂给同一套机制。输入张量形态是 [智代、资产、时间],TA 要的是把最后两个维度置换,而现有函数库没有三维张量内的二维转置,得自己写。 最省人工的做法不是新开 OpenCL 内核,而是复用三个顺序换位层:先把 [智代, [资产, 时间]] 合并后做矩阵转置得到 [[时间, 资产], 智代],再用 CNeuronTransposeRCDOCL 把前两维翻成 [资产, 时间, 智代],最后再合一次把智代送回首位。这条链路封装在 CNeuronTransposeVRCOCL 里,类内只声明 cTranspose 和 cTransposeRCD 两个静态对象。 Init 方法先调父类 CNeuronTransposeOCL::Init,第一维传原始最后两维乘积(count * window),剩下维度照实给;父类成功后,cTranspose 用反向参数初始化,cTransposeRCD 负责资产维与时间维互换。feedForward 就是按顺序调内部对象方法,由父类收尾,因无训练参数,反向通验不展开。 CNeuronTemporalAnalysis 直接继承 CSA 模块再加一个内部转置对象。注意两个细节:外部参数指定的原始维度在传给父类时要先交换最后两维;输入来自多智代趋势检测,单变量区段用 3 个元素表示,所以分析窗口要乘 3、序列长度除 3,把区段当整体看。外汇与贵金属行情受宏观事件冲击,这类张量重构只解决计算视角问题,不预示任何价格走向,实盘验证请自担高风险。

MQL5 / C++
class CNeuronTransposeVRCOCL : class="kw">public CNeuronTransposeOCL
  {
class="kw">protected:
   CNeuronTransposeOCL     cTranspose;
   CNeuronTransposeRCDOCL  cTransposeRCD;
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override;
   class="kw">virtual class="type">bool      calcInputGradients(CNeuronBaseOCL *prevLayer) class="kw">override;
class="kw">public:
                    CNeuronTransposeVRCOCL(class="type">void) {};
                    ~CNeuronTransposeVRCOCL(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 variables, class="type">uint count, class="type">uint window,
                           ENUM_OPTIMIZATION optimization_type, class="type">uint batch);
   class=class="str">"cmt">//---
   class="kw">virtual class="type">int       Type(class="type">void) class="kw">const class="kw">override   { class="kw">return defNeuronTransposeVRCOCL; }
   class=class="str">"cmt">//---
   class="kw">virtual class="type">bool      Save(class="type">int class="kw">const file_handle) class="kw">override;
   class="kw">virtual class="type">bool      Load(class="type">int class="kw">const file_handle) class="kw">override;
   class="kw">virtual class="type">void      SetOpenCL(COpenCLMy *obj) class="kw">override;
   };
class="type">bool CNeuronTransposeVRCOCL::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                   class="type">uint variables, class="type">uint count, class="type">uint window,
                   ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
  if(!CNeuronTransposeOCL::Init(numOutputs, myIndex, open_cl, count * window, variables, optimization_type, batch))
    class="kw">return class="kw">false;
  if(!cTranspose.Init(class="num">0, class="num">0, OpenCL, variables, count * window, optimization, iBatch))

时序分析神经元的转置与初始化链路

在 MT5 的 OpenCL 神经网络扩展里,CNeuronTransposeVRCOCL 承担了两次转置:先对输入做常规转置,再对转置结果跑 RCD 转置。feedForward 里任何一步返回 false 都会中断前向传播,这意味着只要 GPU 端矩阵维度不匹配,整个时序层就直接废掉。 CNeuronTemporalAnalysis 继承自 CNeuronCrossSectionalAnalysis,内部只挂了一个 cTranspose 成员,但重写了 feedForward、calcInputGradients、updateInputWeights 三个虚函数。它的 Init 参数多达 11 个,其中 window 与 window_key 分别控制时间窗和键值窗,heads 与 heads_kv 决定多头注意力的分支数,variables 则是输入特征维度。 实盘接这套结构时,先确认 COpenCLMy 指针有效再调 Init,否则 cTranspose.Init(0,1,...) 里的 0 号设备若未绑定会返回 false。外汇与贵金属行情的高波动可能让梯度更新震荡,建议先用小 batch(如 32)在 EURUSD 的 M15 上跑通再放大。

MQL5 / C++
  class="kw">return class="kw">false;
  if(!cTransposeRCD.Init(class="num">0, class="num">1, OpenCL, count, window, variables, optimization, iBatch))
    class="kw">return class="kw">false;
class=class="str">"cmt">//---
  class="kw">return true;
  }
class="type">bool CNeuronTransposeVRCOCL::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
  if(!cTranspose.FeedForward(NeuronOCL))
    class="kw">return class="kw">false;
  if(!cTransposeRCD.FeedForward(cTranspose.AsObject()))
    class="kw">return class="kw">false;
class=class="str">"cmt">//---
  class="kw">return CNeuronTransposeOCL::feedForward(cTransposeRCD.AsObject());
  }
class CNeuronTemporalAnalysis :  class="kw">public CNeuronCrossSectionalAnalysis
  {
class="kw">protected:
  CNeuronTransposeVRCOCL  cTranspose;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool        feedForward(CNeuronBaseOCL *NeuronOCL) class="kw">override;
  class="kw">virtual class="type">bool        calcInputGradients(CNeuronBaseOCL *prevLayer) class="kw">override;
  class="kw">virtual class="type">bool        updateInputWeights(CNeuronBaseOCL *NeuronOCL) class="kw">override;
class="kw">public:
                 CNeuronTemporalAnalysis(class="type">void) {};
                ~CNeuronTemporalAnalysis(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 heads, class="type">uint heads_kv,
                  class="type">uint units_count, class="type">uint layers, class="type">uint layers_to_one_kv,
                  class="type">uint variables, ENUM_OPTIMIZATION optimization_type, class="type">uint batch) class="kw">override;
  class=class="str">"cmt">//---
  class="kw">virtual class="type">int       Type(class="type">void)  class="kw">const class="kw">override   {  class="kw">return defNeuronTemporalAnalysis;  }
  class=class="str">"cmt">//---
  class="kw">virtual class="type">bool      Save(class="type">int class="kw">const file_handle) class="kw">override;
  class="kw">virtual class="type">bool      Load(class="type">int class="kw">const file_handle) class="kw">override;
  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="type">bool CNeuronTemporalAnalysis::Init(class="type">uint numOutputs, class="type">uint myIndex, COpenCLMy *open_cl,
                       class="type">uint window, class="type">uint window_key, class="type">uint heads, class="type">uint heads_kv,
                       class="type">uint units_count, class="type">uint layers, class="type">uint layers_to_one_kv, class="type">uint variables,

「截面注意力层的初始化落点」

这段初始化函数把交叉截面分析神经元和转置算子串到一起,是搭建多资产注意力模块的最后一步。先以 3 倍 units_count 作为隐层宽度、window/3 作为子窗口去调 CNeuronCrossSectionalAnalysis::Init,任一失败直接返回 false。 随后 cTranspose.Init 用零偏移、units_count 与 window 原始维度初始化转置,优化类型与 batch size 沿用入参。两个 Init 都过才算层构建成功。 在 MT5 里把这段贴进你的神经网络头文件,改 units_count 或 window 后能直接编译验证:若返回 false,优先查 OpenCL 上下文是否就绪,而非调参。外汇与贵金属品种接入此类 GPU 算子时波动放大,回测外的实盘风险偏高。

MQL5 / C++
ENUM_OPTIMIZATION optimization_type, class="type">uint batch)
  {
  if(!CNeuronCrossSectionalAnalysis::Init(numOutputs, myIndex, open_cl, class="num">3 * units_count, window_key, heads, heads_kv,
                                        window / class="num">3, layers, layers_to_one_kv, variables, optimization_type, batch))
      class="kw">return class="kw">false;
  if(!cTranspose.Init(class="num">0, class="num">0, OpenCL,variables, units_count, window, optimization_type, batch))
      class="kw">return class="kw">false;
class=class="str">"cmt">//---
  class="kw">return true;
  }

常见问题

把跨资产价格序列拼成同一时间轴矩阵,用截面注意力层对每行时间步算权重,权重高的品种即为该时段主导方,可直接读权重分布判断联动强弱。
转置本质是把样本×时间×特征的三维张量换轴,让时间维挨着特征维做点积;初始化时先固定时间轴长度再转,避免维度错位导致依赖断裂。
小布盯盘的 AIGC 已内置跨资产注意力诊断,打开对应品种页即可看到实时联动权重,不用自己搭张量链路。
初始化落点放在时序神经元转置之后、注意力打分之前,用近零均值小方差起手,可避开前向传播的数值爆炸。
不是,过长窗口会稀释近期信号,实盘用 30~60 根 K 线做局部注意力,对贵金属短线反转更敏感。