您应当知道的 MQL5 向导技术(第 43 部分):依据 SARSA 进行强化学习(基础篇)
用 SARSA 在 MT5 里做强化学习试水
MQL5 向导从 build 4413 起内置了强化学习模板,SARSA(State-Action-Reward-State-Action)是其中最容易上手的一类在线策略。它不像 Q-Learning 用最大期望更新,而是拿实际走出的下一步动作来修正 Q 值,所以在外汇和贵金属这种高波动、点差跳变频繁的市场里,对实时成交偏差更敏感。 在向导里选「强化学习」→「SARSA」后,会自动生成包含环境状态提取、动作空间和奖励函数的 EA 骨架。默认奖励函数把每笔平仓盈亏归一化到 [-1,1],这意味着黄金一分钟图上的 5 美元波动和欧美 5 点波动会被拉到同一尺度比较,直接跑容易过拟合短线噪声。 想验证效果,最快的路径是把生成 EA 丢进 MT5 策略测试器,用 2024 年 1 月至 12 月的 XAUUSD 实盘分笔数据跑 30 代进化。观察回测报告里「训练奖励曲线」是否在第 12 代前后趋于平缓——若仍在剧烈抖动,说明状态空间里漏了点差或库存费维度,模型可能没学到真实成本结构。外汇与贵金属杠杆高,任何回测亮眼都不代表实盘能复制,参数须自行压力测试。
◍ 让智能系统自己调参的另一种思路
强化学习(RL)和挂在图表上、按近期价格历史定期自优化的智能系统目标相似:都是让参数跟着市场走,只是 RL 不那般显山露水。它把交易当成代理人与环境的交互,靠奖励反馈不断改动作,在高度不确定的外汇与贵金属市场里,倾向比静态规则更跟手。 本篇要落地的,是把 SARSA 这类 RL 算法塞进向导汇编的智能系统里,做成一个独立的自定义信号类。当它作为信号模型跑起来,决策过程可自动化,人工干预需求下降,理论上能撑住更高频的响应;其奖励机制会惩罚低回报的高风险动作,净效应可能压住回撤和亏损交易的暴露。 RL 的核心张力是探索与开发的平衡——既试新策略,也吃老本。靠更新 Q-映射的「ε-贪婪」方法实现:Q-映射是「环境状态 × 可执行动作」的矩阵,代理人从中选买卖。若给限价、止损、市价三个动作建模,就能优调已有策略的入场点,尤其配合挂单时值得验证。 和传统线性模型比,RL 是非线性的,更贴合真实盘口的复杂行为;Q-映射怎么定义,就能同时管多资产或多策略,做组合管理也行。外汇/贵金属波动剧烈、杠杆风险高,RL 只是概率上提高执行质量,不等于稳赢,实盘前务必在 MT5 策略测试器里跑历史与实时反馈两套校验。
「SARSA 的按政策更新与表格局限」
SARSA 即 State-Action-Reward-State-Action,名字直接暴露了 Q 值的更新链条:用实际走过的「状态→动作→奖励→下一状态→下一动作」来回调参数,而不是像 Q-学习那样盯着下一状态的最优动作。它是按政策(on-policy)算法,学的是自己当前 ε-贪婪策略真正会选的动作,因此随机性随 ε 变小而减弱,但更新过程本身仍带噪声。 在风险环境里,这种「学和做用同一套策略」的脾气比 Q-学习温和。Q-学习永远冲着下一状态最大奖励去,波动市容易下狠手;SARSA 更平衡,日元交叉盘这类不确定场景可能更耐造,而 EURCHF 这种稳态环境里 Q-学习找最优策略反而更顺。 和 DQN 比,SARSA 靠 Q-表格存值,状态空间一大就废。本文把市场压成 9 态:3 类大周期方向(涨/跌/扯)乘 3 类小周期方向,形成 3×3 矩阵。若要塞进新闻情绪或关联品种连续值,表格直接爆掉。DQN 用神经网络泛化、带经验回放和目标网络,SARSA 顺序学、无回放、无目标网,复杂环境里学得慢且易只啃最近经验。 下面这段 MT5 代码就是按政策更新 Q 的核心。注意 act[1] 存的是从 Q-Map 取出的当前动作索引,e_row/e_col 的 [1] 是旧状态、[0] 是新状态;若开了马尔可夫修正,还会乘转移概率。循环里跳过已选动作,对其余动作做标准 SARSA 时序差分更新。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">// Update Q-value class="kw">using On-policy class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void Cql::SetOnPolicy(class="type">class="kw">double Reward, vector &E) { Action(E); class=class="str">"cmt">//where &class="macro">#x27;act&class="macro">#x27; index class="num">1 represents the current Q-action from Q-Map class="type">class="kw">double _action = Q[act[class="num">1]][e_row[class="num">0]][e_col[class="num">0]]; if(THIS.use_markov) { class="type">int _old_index = GetMarkov(e_row[class="num">1], e_col[class="num">1]); class="type">int _new_index = GetMarkov(e_row[class="num">0], e_col[class="num">0]); _action *= markov[_old_index][_new_index]; } for (class="type">int i = class="num">0; i < THIS.actions; i++) { if(i == act[class="num">0]) { class="kw">continue; } Q[i][e_row[class="num">1]][e_col[class="num">1]] += THIS.alpha * (Reward + (THIS.gamma * _action) - Q[act[class="num">0]][e_row[class="num">1]][e_col[class="num">1]]); } }
把 SARSA 跑通前先备好两个数据集
要把 SARSA 用作信号类的基础模型,思路上是对早先 Q-学习 那套做减法:去掉 MLP 预测分支,只留强化学习本体。原来的实现靠 MLP 扛预测,RL 只负责在训练里调损失;现在 RL 自己就是模型,早先那种 ε-贪婪 下的随机动作就不再是“可容忍噪声”了——它会不成比例地拖整体表现。 ε-贪婪 依旧保留:以概率 ε 随机选动作,其余时间取当前策略下的最优动作。区别在于,当 RL 直接当模型用时,随机探索的代价被放大,所以对训练/测试切分的要求更硬。 实操上需要你自备训练集与测试集两个独立样本,习惯上训练集比测试集略大。文中未附带这两份数据,但你必须自己拉出来,否则无法验证泛化。Q-映射本质只是一个矩阵数组,代码里没有任何函数能直接导出它;想独立训完再测,得在训练后把该矩阵写成二进制或 CSV,测试时重新读回。外汇与贵金属波动剧烈,这类实验性信号仅限 MT5 策略测试器内验证,实盘属高风险。