交易中的神经网络:双曲型潜在扩散模型(终篇)·综合运用
「堆叠 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 跑一次编译,能直接看到层数与张量形状变化。外汇与贵金属杠杆高,这类模型信号仅作概率参考,实盘请控仓。
!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 重跑。
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 设备没配对。 这类方法目前实测效果一般,但作为把几何先验塞进行情建模的切口,值得在下一轮参数扰动里继续试。