交易中的神经网络:配备注意力机制(MASAAT)的智代融汇(终章)(基础篇)
用注意力机制给行情序列加权
传统 RNN 把历史 K 线一视同仁地塞进隐藏层,但真正驱动下一根走势的往往只是最近几根特定位置的波动。MASAAT 的思路是在序列输入后接一层注意力权重,让模型自己学出「哪几根值得多看一眼」。 在 MT5 里跑这套,核心是先构造带时间步的特征矩阵,再接注意力打分。下面这段把收盘价序列做了缩放与掩码,注意力分数用 softmax 归一,输出的是加权上下文向量。 外汇与贵金属杠杆高,模型给的只是概率倾向,实盘前务必用策略测试器跑至少 3 个月 tick 数据验证过拟合。
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,把区段当整体看。外汇与贵金属行情受宏观事件冲击,这类张量重构只解决计算视角问题,不预示任何价格走向,实盘验证请自担高风险。
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 上跑通再放大。
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 算子时波动放大,回测外的实盘风险偏高。
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; }