神经网络变得轻松(第二十八部分):政策梯度算法(基础篇)
📘

神经网络变得轻松(第二十八部分):政策梯度算法(基础篇)

第 1/3 篇

◍ 用策略梯度直接优化交易决策

在 MT5 里做强化学习,最常见的误区是拿 Q-learning 硬套连续动作空间。政策梯度(Policy Gradient)绕开了这个值函数估计,直接对策略网络的参数求期望回报的梯度,更适合仓位比例、止损距离这类连续输出。 原文给出的基础采样环境里,单 episode 步数设为 200,奖励采用当期账户净值变化减去 0.0001 倍换手率惩罚,这个惩罚系数偏小,高频策略容易过拟合历史。 下面这段是原文里构建策略网络前向与梯度近似的核心片段,注意其用正态分布采样动作、用对数概率乘折扣回报做梯度上升。外汇与贵金属杠杆高,实盘试这段代码前务必在策略测试器关掉实时成交、用 2020—2022 tick 数据回测验证梯度稳定性。

MQL5 / C++
class="type">class="kw">double PolicyGradient::Train(const class="type">int episode){
   class="type">class="kw">double returns[class="num">200];
   class="type">class="kw">double log_probs[class="num">200];
   for(class="type">int t=class="num">0;t<class="num">200;t++){
      class="type">class="kw">double action = Mean(t) + StdDev(t)*MathRand()/class="num">32767.0-class="num">0.5;
      log_probs[t] = -class="num">0.5*MathPow((action-Mean(t))/StdDev(t),class="num">2);
      returns[t] = AccountInfoDouble(ACCOUNT_EQUITY)-prev_equity-class="num">0.0001*MathAbs(action);
      prev_equity = AccountInfoDouble(ACCOUNT_EQUITY);
   }
   class="type">class="kw">double norm_ret[class="num">200];
   Normalize(returns,norm_ret);
   for(class="type">int t=class="num">0;t<class="num">200;t++)
      UpdateWeights(log_probs[t]*norm_ret[t]);
   class="kw">return norm_ret[class="num">199];
}

用 SoftMax 把交易动作变成概率分布

在强化学习框架里,策略梯度方法不直接输出买卖信号,而是输出一个动作概率分布。代理根据环境状态选择动作,再用回报反馈调整分布参数,这使得模型能在不确定行情中保留探索空间。 实现上先用 SoftMax 把线性得分映射成概率。给定动作得分向量 z,第 i 个动作概率 = exp(z_i) / Σ exp(z_j)。这样得分最高的动作概率最大,但其他动作仍非零,避免过早收敛到局部策略。 [CODE] double SoftMax(double &scores[], int action) { double sum=0.0; for(int i=0;i<ArraySize(scores);i++) sum+=MathExp(scores[i]); return MathExp(scores[action])/sum; } [/CODE] 上面这段 MQL5 函数接收得分数组与指定动作索引,先累加所有动作的 exp 值,再返回该动作的归一化概率。在 EA 中每次决策调用它,就能拿到当前状态下「观望 / 买 / 卖」三类动作的概率。外汇与贵金属杠杆高,概率分布只代表模型倾向,实盘前务必在策略测试器用历史数据验证稳定性。

MQL5 / C++
class="type">class="kw">double SoftMax(class="type">class="kw">double &scores[], class="type">int action)
  {
   class="type">class="kw">double sum=class="num">0.0;
   for(class="type">int i=class="num">0;i<ArraySize(scores);i++)
      sum+=MathExp(scores[i]);
   class="kw">return MathExp(scores[action])/sum;
  }

「市场无常下的 Q 学习软肋」

上一篇文章里我们用深度 Q-学习,让神经网络去近似动作功用函数,本质就是给「某个状态下做某动作能拿多少奖励」打个分,代理者挑分数最高的动作下手。这背后是贝尔曼公式那套:尽可能把整局预期奖励做大。 有意思的是,研究强化学习时很少有人提过拟合——代理者的目标本来就是把环境摸透,摸得越细表现越好。但外汇和贵金属市场是另一回事:状态几乎不会重复,即便两张图看起来像,下一步也可能走出完全反向的走势,这种高风险环境里没有「稳态」可言。 Q 函数近似只给了一个平均预期奖励,既没管数值离散程度,也没算正奖励的概率。贪婪策略永远选最大项,动作变得可被环境预判;一旦对手盘反着做、改了奖励规则,旧 Q 函数就失效,代理还在用过期认知挨打。 绕开这条死路的一种思路是不靠近似 Q 值,而是让模型自己长出一个动作策略。政策梯度法就是这类路子,接下来我们展开说。

◍ 随机政策梯度怎么替代理者定策略

强化学习里代理者跟环境交互,每步转换拿到奖励,用来评估动作好坏。政策梯度法不显式写死策略,而是假设有个函数 P 评估当前状态、返回最佳动作,顺带省掉了 DQN 里近似 Q 函数的麻烦。 本文落点是随机政策梯度:P 函数输出的是「各动作拿到正奖励」的概率分布,而不是确定动作。代理者按正态分布采样选动作,概率高的被抽中更频繁,采样本身带来行为可变性,避免过早收敛。 探索与开发的平衡在这里交给概率自己调节。训练初期各动作概率接近相等,环境探索最充分;随着奖励反馈,盈利动作概率上升、其余下降,平衡自然倒向高期望动作。 我们用神经网络近似 P 函数,本质是个分类问题:每个动作为一类,网络输出该状态归属各类的概率。输出必须经 SoftMax 压到 0~1 且总和为 1,公式此前在聚类里见过,这次按奖励把状态分给动作类,便于数值区分和训练。

代理政策模型的训练逻辑与损失函数

训练政策函数近似模型时,环境在每个新状态返回奖励,但目标不是预测奖励本身,而是预测最优动作。奖励符号只提示当前动作对结果的方向性影响,模型据此提升正奖励动作被选中的概率,压低负奖励动作的概率。 概率输出被限制在 0 到 1 之间,而奖励可正可负,两者量纲不直接可比。实操中把正奖励动作的目标值设为 1,模型误差定义为预测概率与 1 的偏差;用偏差/方差框架套入已有的梯度下降,就能在最小化距 1 方差的过程中,最大化正奖励动作的选取概率。 损失函数可回退到监督学习的分类思路,交叉熵在此处适用:p(y) 是真实分布,p(y') 是模型预测。对数项很关键——连续事件联合概率等于各自概率乘积,取对数后变求和,训练稳定性明显更好。 和 DQN 类似,代理者用固定参数跑完场次,把状态、动作、奖励写进缓冲区,再统一做反向传播。没有动作功用函数时,用场次内奖励总和替代 Q 值(即每状态的 Q 为后续到结束的奖励累加)。循环训练到误差达标或触达最大场次上限即可,外汇与贵金属行情噪声大、杠杆高风险突出,这套机制在实盘前务必用 MT5 历史数据复跑验证。

常见问题

可以。策略梯度不依赖价值表,而是用神经网络输出动作概率,直接对交易决策序列做梯度优化,更适合非平稳行情。
Q 学习在无常市场易过估状态价值导致激进亏损;SoftMax 把买卖持变成概率分布,保留探索余量,回撤更可控。
小布内置 AIGC 分析工具,可加载政策梯度模板并对接你的品种数据,自动给出动作概率与训练诊断,你只需调参验证。
它通过采样动作并计算带基线回报的梯度,让多头、空头、空仓按概率被公平更新,抑制单边过拟合。
正常,因采样随机性。看批次平均回报斜率与熵衰减,熵稳在低位且回报缓升即倾向收敛,勿盯单步损失。