您应该知道的 MQL5 向导技术(第 01 部分):回归分析(基础篇)
📘

您应该知道的 MQL5 向导技术(第 01 部分):回归分析(基础篇)

第 1/3 篇

用回归分析给价格序列建模

MQL5 向导里内置了回归分析模块,能让交易者在 MT5 里直接对历史价格序列做拟合,而不必自己从零写最小二乘。它的核心思路是把收盘价序列当作因变量,以样本索引为自变量,求出一条最能代表趋势的直线或曲线。 在外汇与贵金属市场,这类拟合对高噪音序列容易过拟合,实战中建议先用日线或 H4 以上周期跑,样本量低于 200 根 K 线时斜率置信度会明显塌缩。打开 MT5 的向导面板,选「技术指标创建」里的回归模板,即可生成可直接编译的骨架。 回归得到的斜率正负,只能说明该样本窗口内价格倾向上行或下行,不代表后续必续趋势;杠杆品种波动剧烈,请自担高风险。

◍ 向导能省的事与绕不开的自定义

MQL5 向导把建仓、平仓、风控这些重复活儿在自带函数库里预先写好了,交易者能直接套用加速器振荡器、自适应移动平均等现成信号类,省掉大量底层编码。 但函数库里的信号大多基于滞后指标,对多数交易者而言,只靠这些很难扭出稳定盈利的策略。实际做 EA 时,自己写入场离场逻辑才是绕不开的基本功。 本文这一篇先铺个底:后面会用回归分析手搓一个自定义信号类,让你在向导里也能挂上非滞后思路的触发条件。外汇与贵金属杠杆高,任何信号都只是概率倾斜,得上 MT5 跑历史段验证再谈实盘。

「用回归拆价格:从联立方程到信号类骨架」

回归分析本质是用历史自变量 x 估算因变量 y 的统计过程。把收盘价变化或均线变化当作 x,未来价格变动当 y,就能在 MT5 里测试“前两次波动如何牵引下一步”。若假设当前变化只取决于前两次变化,可列两个联立方程,用已知 y 截距(即上一期价格)反推系数 β 与误差 ε;用矩阵 LU 分解求解效率更高,MQL5 标准库 solvers.mqh 里的 CDenseSolver::RMatrixSolve 已封装好这套计算。 基于 CExpertSignal 派生自己的信号类时,LongCondition 与 ShortCondition 必须返回 0~100 的整数,方便向导用 Signal_ThresholdOpen / Signal_ThresholdClose 映射。实战中平仓阈值通常比开仓阈值更保守,所以类里要分两套输入参数:有持仓走平仓参数,空仓走开仓参数。 标准误差公式 s/√n 提醒你,任何回归预测在外汇、贵金属这种高波动市场都不可能 100% 准。我们可用 GetE 按 m_open_error / m_close_error 切换“标准差修正”或“末次差异”两种误差估算。另一个坑是共线性——自变量太像会吹胀预测值,可用最近 m_size(最小 3)组数据的 spearman 相关性倒数做归一化权重,2 减倒数再反转,按持仓状态挂到误差或预测值上。 判定系数 R² 衡量自变量解释因变量的能力,公式里真实值 y、预测值 f、y 的移动均值 ÿ 都要算平方和。下面这个类骨架已把 MA 句柄、ATR、尺寸与开平仓判定参数列好,复制进 MetaEditor 就能接着填 LongCondition 逻辑。外汇与贵金属杠杆风险极高,回测通过不代表实盘概率占优,参数请先在策略测试器验证。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="keyword">class</span> CSignalDUAL_RA : <span class="keyword">class="kw">public</span> CExpertSignal
&nbsp;&nbsp;{
<span class="keyword">class="kw">protected</span>:
&nbsp;&nbsp; CiMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_h_ma;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// highs MA handle</span>
&nbsp;&nbsp; CiMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_l_ma;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// lows MA handle</span>
&nbsp;&nbsp; CiATR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_ATR;
&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//--- adjusted parameters</span>
&nbsp;&nbsp; <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_size;
&nbsp;&nbsp; <span class="keyword">class="type">class="kw">double</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_open_determination,m_close_determination;
&nbsp;&nbsp; <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_open_collinearity,m_open_data,m_open_error;
&nbsp;&nbsp; <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_close_collinearity,m_close_data,m_close_error;
<span class="keyword">class="kw">public</span>:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CSignalDUAL_RA();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;~CSignalDUAL_RA();
&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//--- methods of setting adjustable parameters</span>
&nbsp;&nbsp;
&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//--- PARAMETER FOR SETTING THE NUMBER OF INDEPENDENT VARIABLES</span>
&nbsp;&nbsp; <span class="keyword">class="type">void</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size(<span class="keyword">class="type">int</span> <span class="keyword">value</span>)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ m_size=<span class="keyword">value</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;
&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//--- PARAMETERS FOR SETTING THE OPEN &class="macro">#x27;THRESHOLD&class="macro">#x27; FOR THE EXPERTSIGNAL CLASS</span>

信号类里的开仓平仓阈值接口

ExpertSignal 派生类把开仓与平仓的判断阈值拆成了两组 setter,分别控制共线性、确定性、误差与数据窗口。开仓组用 OpenCollinearity / OpenDetermination / OpenError / OpenData 写入成员变量,平仓组对应 Close 前缀的四个方法,逻辑完全对称。 下面这段声明直接给出了类对外的参数入口: //--- PARAMETERS FOR SETTING THE CLOSE 'THRESHOLD' FOR THE EXPERTSIGNAL CLASS void CloseCollinearity(int value) { m_close_collinearity=value; } void CloseDetermination(double value) { m_close_determination=value; } void CloseError(int value) { m_close_error=value; } void CloseData(int value) { m_close_data=value; } 虚函数 ValidationSettings 负责校验这些阈值是否自洽,InitIndicators 挂指标与序列,OpenLongParams / OpenShortParams 输出具体价格、止损、止盈与到期时间。LongCondition / ShortCondition 返回市场模型是否成立,返回值是 int 而非 bool,说明内部可能用多档状态区分强度。 真要在 MT5 里改策略灵敏度,优先动 OpenDetermination 与 CloseDetermination 这两个 double 型参数,它们直接压缩或放宽信号确认区间;外汇与贵金属波动跳变频繁,阈值过窄可能频繁假触发,实盘前务必用历史数据验证。

MQL5 / C++
class="type">void OpenCollinearity(class="type">int value) { m_open_collinearity=value; }
class="type">void OpenDetermination(class="type">class="kw">double value) { m_open_determination=value; }
class="type">void OpenError(class="type">int value) { m_open_error=value; }
class="type">void OpenData(class="type">int value) { m_open_data=value; }

class=class="str">"cmt">//--- PARAMETERS FOR SETTING THE CLOSE &class="macro">#x27;THRESHOLD&class="macro">#x27; FOR THE EXPERTSIGNAL CLASS
class="type">void CloseCollinearity(class="type">int value) { m_close_collinearity=value; }
class="type">void CloseDetermination(class="type">class="kw">double value) { m_close_determination=value; }
class="type">void CloseError(class="type">int value) { m_close_error=value; }
class="type">void CloseData(class="type">int value) { m_close_data=value; }

class=class="str">"cmt">//--- method of verification of settings
class="kw">virtual class="type">bool ValidationSettings(class="type">void);
class=class="str">"cmt">//--- method of creating the indicator and timeseries
class="kw">virtual class="type">bool InitIndicators(CIndicators *indicators);
class=class="str">"cmt">//--- methods for detection of levels of entering the market
class="kw">virtual class="type">bool OpenLongParams(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration);
class="kw">virtual class="type">bool OpenShortParams(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration);
class=class="str">"cmt">//--- methods of checking if the market models are formed
class="kw">virtual class="type">int LongCondition(class="type">void);
class="kw">virtual class="type">int ShortCondition(class="type">void);
class="kw">protected:
 class=class="str">"cmt">//--- method of initialization of the oscillator
 class="type">bool InitRA(CIndicators *indicators);
 class=class="str">"cmt">//--- methods of getting data
 class="type">int CheckDetermination(class="type">int ind,class="type">bool close);
 class="type">class="kw">double CheckCollinearity(class="type">int ind,class="type">bool close);
 class=class="str">"cmt">//
 class="type">class="kw">double GetY(class="type">int ind,class="type">bool close);
 class="type">class="kw">double GetE(class="type">int ind,class="type">bool close);

常见问题

看残差是否围绕零值随机散布;若残差出现明显趋势或周期性,说明线性模型已失效,应换更高阶或换个样本区间重算。
在信号类的阈值函数里按回归残差标准差的倍数设边界,例如1.5倍标准差作触发,避免拍脑袋定绝对值。
小布盯盘的 AIGC 已内置回归诊断,打开对应品种页即可看到拟合线与残差提示,你把决策留给人工判断就行。
贵金属受避险与利率预期跳变影响,线性假设在非农等时点会断裂;建议只取平稳波段样本,别拿全周期硬套。
把平仓阈值设得比开仓阈值更窄,或要求连续两根bar突破才成交,能过滤掉大部分毛刺假信号。