您应该知道的 MQL5 向导技术(第 01 部分):回归分析(基础篇)
用回归分析给价格序列建模
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 逻辑。外汇与贵金属杠杆风险极高,回测通过不代表实盘概率占优,参数请先在策略测试器验证。
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class</span> CSignalDUAL_RA : <span class="keyword">class="kw">public</span> CExpertSignal { <span class="keyword">class="kw">protected</span>: CiMA m_h_ma; <span class="comment">class=class="str">"cmt">// highs MA handle</span> CiMA m_l_ma; <span class="comment">class=class="str">"cmt">// lows MA handle</span> CiATR m_ATR; <span class="comment">class=class="str">"cmt">//--- adjusted parameters</span> <span class="keyword">class="type">int</span> m_size; <span class="keyword">class="type">class="kw">double</span> m_open_determination,m_close_determination; <span class="keyword">class="type">int</span> m_open_collinearity,m_open_data,m_open_error; <span class="keyword">class="type">int</span> m_close_collinearity,m_close_data,m_close_error; <span class="keyword">class="kw">public</span>: CSignalDUAL_RA(); ~CSignalDUAL_RA(); <span class="comment">class=class="str">"cmt">//--- methods of setting adjustable parameters</span> <span class="comment">class=class="str">"cmt">//--- PARAMETER FOR SETTING THE NUMBER OF INDEPENDENT VARIABLES</span> <span class="keyword">class="type">void</span> Size(<span class="keyword">class="type">int</span> <span class="keyword">value</span>) { m_size=<span class="keyword">value</span>; } <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 型参数,它们直接压缩或放宽信号确认区间;外汇与贵金属波动跳变频繁,阈值过窄可能频繁假触发,实盘前务必用历史数据验证。
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);