神经网络变得轻松(第三十六部分):关系强化学习(基础篇)
◍ 关系强化学习在 MT5 里的落地起点
关系强化学习(Relational RL)把状态表示为对象之间的关系,而非扁平向量,这在多品种联动的外汇与贵金属行情里更贴近真实结构。MT5 自带的 MQL5 环境可以直接加载这类自定义智能系统,无需外接 Python 服务。 作者在 2023 年 8 月 3 日发布的这一篇,原文页面显示 1 617 次浏览、18 条讨论,说明基于关系的 RL 思路在量化交易者里有稳定关注度。你可以在 MT5 的「导航器—智能系统」里新建一个 EA 骨架,把关系特征抽取逻辑先写成函数占位,再逐步接训练好的权重。 外汇与贵金属杠杆高、跳空频繁,关系强化模型在样本外仍可能失效,实盘前务必用策略测试器跑至少三年 tick 级回测。
从游戏画面到真实行情:卷积模型的盲区
前面几篇里我们一直拿卷积模型跑强化学习,底层逻辑很直白——参考的都是电脑游戏,输入给模型的正是游戏关卡截图。游戏图像干净、无噪点、物体不变形,卷积网络做识别和定位几乎零压力。 但真实市场数据完全是另一回事。以MT5的XAUUSD分钟线为例,报价流里混着滑点、跳空和微观噪声,K线形态还常被拉伸、压缩或斜置。卷积模型对这类失真和相对位移的鲁棒性明显下滑。外汇和贵金属杠杆高、波动随机,用理想化思路套实盘风险极大。 更复杂的是,当画面里不止一个物体、且它们的相对位置决定胜负时(比如两均线的交叉角度、价格与通道的偏离关系),普通卷积很难抓到这种结构信息。关系模型在这类任务上反而更顺手,后续我们会直接上代码验证。
「用自关注把价格对象连成依赖图」
关系模型的价值在于能在对象间建立依赖,而不是只识别孤立形态。以通道突破为例,可以在示图里画出通道形成、上下边界突破、以及价格回滚到边界三个层级的节点;突破节点各自连向前置通道,回滚节点再连向对应突破节点,但上下两组互不相连,这样能过滤掉假突破后的追单。卷积或全连接层做不到这种跨序列的同对象不同形态分离,它们只能检出对象,建不了依赖。 自关注(self-attention)给了一条出路。它最早在 2014 年 9 月作为机器翻译的附加层提出,用来收集编码器隐藏状态、缓解长程记忆问题;2017 年 3 月的 Transformer 架构则彻底去掉递归,只用自关注分析序列内配对依赖。对 MT5 端来说,核心是把每根 K 线或每个事件写成固定维要素行,再乘三个权重矩阵得到 Query、Key、Value 三种嵌入。 依赖系数 = Softmax( (Query × Keyᵀ) / √d_key ),结果是一个行和为 1 的非对角方阵:A 对 B 的依赖和 B 对 A 的反依赖不相等,零值代表节点间无链接,非零值就是加权影响。把这个系数方阵乘 Value 张量,就得到自关注输出;多目击者版本只是前面拼了降维矩阵,最后再把输入加回并规范化。输出张量尺寸不变,但噪声要素被压小、有效要素被放大。 需要留意的是,自关注模块只负责凸显要素间的结构,不替你下单。后面必须接全连接感知器或别的决策层来输出信号。外汇与贵金属波动剧烈、杠杆风险高,这套结构在 MT5 里验证时建议先用历史数据跑依赖矩阵,再接轻量决策层,避免直接实盘。
◍ 在 MT5 里搭一套带关系模块的强化学习模型
想直接改模型内部架构又不想动 EA 主逻辑,可以另存一份 RLL-Learning.mq5,只换中间层、不动结果层。不过不少人在加载 NetCreator 生成的模型时踩坑,所以这里回到 EA 代码里硬编码模型架构更稳。 模型文件名由「品种全名_时间帧_EA 文件名」拼接,再加 nnw / fwd / inv 扩展名区分训练、前向、逆模型。文件必须丢进 Files 或 Common/Files,且 common 标志为 true 时只能对应 Common/Files——策略测试器给每个代理建沙箱,不碰普通 Files,但共享目录能访问,实盘和回测因此不用改路径。 OnInit 里先初始化 RSI、CCI、ATR 指标类,再尝试从 Common/Files 加载模型;加载失败就调 CreateDescriptions 现场建架构,任一步失败直接 INIT_FAILED 退出。训练模型输入层是全连接层,每根历史烛条传 12 个值(烛身描述+指标),账户状态和持仓另加 9 个值,合计 21 维输入。 预处理用批量规范化接卷积层(窗口 3、步长 1、16 过滤器、LeakReLU+Adam),卷积后不降采样而是接 LSTM 保留时序动态,再重复卷积+LSTM 模块。关系模块用 defNeuronMLMHAttentionOCL,Keys=16、目击者=64、叠 4 层,把市场状态做多头自关注。输出层用 defNeuronFQF 描述分位数函数。前向/逆模型复用前篇架构,逆模型输入是前后状态级联,输出接 Softmax 给动作概率。外汇与贵金属杠杆高,这套系统仅提供研究框架,实盘前务必在策略测试器跑通。
class="macro">#define FileName Symb.Name()+"_"+EnumToString(TimeFrame)+"_"+StringSubstr(__FILE__,class="num">0,StringFind(__FILE__,".",class="num">0)) class="type">bool CNet::Load(class="type">class="kw">string file_name, class="type">class="kw">float &error, class="type">class="kw">float &undefine, class="type">class="kw">float &forecast, class="type">class="kw">datetime &time, class="type">bool common = true) class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert initialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- if(!Symb.Name(_Symbol)) class="kw">return INIT_FAILED; Symb.Refresh(); class=class="str">"cmt">//--- if(!RSI.Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice)) class="kw">return INIT_FAILED; class=class="str">"cmt">//--- if(!CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice)) class="kw">return INIT_FAILED; class=class="str">"cmt">//--- if(!ATR.Create(Symb.Name(), TimeFrame, ATRPeriod))