English Русский Español Deutsch 日本語 Português
preview
您应当知道的 MQL5 向导技术(第 25 部分):多时间帧测试和交易

您应当知道的 MQL5 向导技术(第 25 部分):多时间帧测试和交易

MetaTrader 5交易系统 | 12 三月 2025, 09:45
297 0
Stephen Njuki
Stephen Njuki

概述

在我们的上一篇文章中,我们视察了毕达哥拉斯(Pythagorean)均值,这是一组移动平均线,其中一些非常新颖、且不常见,尽管正如我们在测试报告中暗示的那样,它们具有令一些交易者受益的潜力。这些毕达哥拉斯均值是用一个半圆图解表示,其汇总了当由两个不相等数值表述时,每个平均值加起来等于半圆的直径。在文章中未涉及的半圆和弦值中,表示为 Q 的值,它代表两个值 a 和 b 的二次平均值

二次均值(QM)通常也称为均方根,且作为一种均值,它更倾向于在均值集中寻求朝向较大值加权,这与我们在上一篇文章中研究的几何与调和均值不同。它就像几何均值仅返回正值一样,故需要寻求采样集的均值只具有正值。然而本文的标题是在由向导组装的智能系统中实现多时间帧策略,故此 QM 只是工具,我们用其展示如何在由向导构建的智能系统中测试多时间帧。

那么,为什么由向导构建的智能系统在测试多时间帧时很棘手呢?嗯,在我看来,这是因为在向导组装空间中添加的每个信号都应当定制化,而这往往被忽视。至于由向导组装的智能系统,其品种名称和时间帧的自定义能在向导信号选择步骤中完成,但往往大多数人假设一旦您选择了一个信号,您就可以选择品种和周期,但若由向导组装,则不是这种情况。在之前的这篇文章中,我曾展示过依据修改的组装源代码,在由向导组装的智能系统中容纳多个品种进行交易的各种方式。还有一种明显且主要的方式我并未分享,即执行多个信号挂件,其中每个信号挂件将针对一个特定的品种。尽管附加的都是同一个信号,但仍会发生多个挂件。为信号自定义分配品种应在下面示意的这些步骤中完成:

n1


n2

类似地,可以为每个智能系统内的信号自定义多时间帧,作为输入参数(附上示例代码)。不过,首选方式能把每个所需时间帧分配给一个信号,并在向导组装中独立加载该信号。为每个信号自定义时间帧的步骤,与我们上面分享的多品种交易非常类似。

f1


f2

多时间帧策略可能是一个福音,例如在所跟踪时间帧之间寻找背离机会时,譬如在较大时间帧中的主要涨势背景下,在更快(或更短)的短线时间帧内发生跌势,则这可能是一个主要信号。或者,多时间帧策略可以围绕两个、或多个测试时间帧之间,演化出确认设置。这些和其它原因,就是为什么我们要深入研究在由向导组装的智能系统中实现多时间帧策略。

同样,在这篇文章中已研究过多品种交易,无疑拓展了交易者的可能性。至于本文,我们将研究 3 对货币,它们在套利设置中潜在会相互抵消,但我们不会寻求开发或测试对冲套利系统,而是尝试探索当由一个智能系统交易所有货币对时,常见移动平均线的设置(如果有)。

多时间帧交易、和多品种交易非常有趣,但因为由向导组装的智能系统如何编码,当向导组装时,其固有设计是添加并行或多信号,每个添加的信号都承接特定品种或时间帧。主要原因,在我看来,根源来自向导组装的智能系统的初始化阶段。'CExpertBase' 类初始化阶段有 4 步,对于信号它不仅当作锚点类,还当作资金管理和尾随停止管理。这些阶段是启动初始化、设置参数值、检查参数值,最后完成初始化。

具体上,在参数设置阶段是智能系统信号类的一个实例获得分配给其的品种和时间帧。相应地,根据文档,这也可能发生在参数检查阶段。我认为参数设置阶段称为谐调阶段,但我未能找到这方面的文档。故此,因为交易品种决定了信号类所依赖的许多参数,像是要加载的 OHLC 价格、点大小、等等,设计上这些东西要在初始化时一次性设置。类似地,用于检索 OHLC 价格缓冲区的时间帧需要预先确定,这也发生在初始化期间,且之后不会再做。

因此,这些设计约束意味着使用多品种和时间帧的预期方式,是在向导组装期间预先分配信号类的实例,如此这些品种和时间帧值就会充当常量参数。

需要注意的是,向导中的这种预分配制度下仍会遇到交易多个品种。正如我们在多货币文章中所见,我们仍然需要创建 'CExpert' 类的实例数组,并将我们预期的交易品种重新分配给该数组中智能系统类的每个实例。这表明,向导品种分配所做的只是确定在 'USED_SERIES' 枚举下获取 OHLC 价格数据时应使用哪个品种。然而,在 Symbol-Info 类实例 'm_symbol' 初始化后交易的实际品种,分配的品种是向导组装的第一步,在选择任何信号之前。

s1

多品种交易的这种约束不会反映在多时间帧交易当中,因为在向导组装期间分配的信号时间帧,足以确保一旦智能系统开始交易,每个分配的时间帧都能用于信号处理。


初始化中谐调阶段的含义。

因为我们只能在初始化时为交易品种和时间帧获取自定义设置,故该约束意味着一旦智能系统组装完毕,我们就无法探索或优化可交易品种、或理想的时间帧。有一些变通办法,其中寻求把交易品种、或时间帧当作自定义信号类的输入参数。这样的输入参数将分别采用字符串和时间帧枚举的形式。它们自然也会有默认值,一般来说,自定义时间帧值的分配应该更直接了当,因为选项来自已经设置的 ENUM_TIMEFRAMES 枚举。不过,当涉及到要交易的品种名称时,应使用额外的步骤或函数来确保键入的品种名称真实有效,已在市场观察中列出,且可交易。


二次移动平均线

二次平均值(QA)也称为均方根,只是一个集合中所有平方值平均值的平方根。与大多数非算术均值一样,它们拥乖离、或优先权重,不像是几何均值和谐波均值,它偏向集合中较大的值。在上一篇文章所示的半圆图解中,其中均值的不同类型,如两个 u 相等值 a 和 b 代表在半圆内的缩放,还有示意的二次平均值,它等于标记为 Q 的弦长度。

其中

  • n 是集合中数值的数量
  • x 是集合中在各自索引处的数值

我们使用 QM 来开发并测试一个依据多时间帧交易的自定义信号,以及另一个跨多品种交易的自定义信号。在上一篇文章中,由于几何平均值和调和平均值的集合中,乖离或优先权重朝向较小值,我们开发出镜像平均值,朝向较大值。利用 MQL5 实现的 QM 代码给出如下:

//+------------------------------------------------------------------+
//| Quadratic Mean                                                   |
//+------------------------------------------------------------------+
double CSignalQM::QM(int Index, int Mask = 8)
{  vector _f;
   _f.CopyRates(m_symbol.Name(), m_period, Mask, Index, m_length);
   vector _p = _f*_f;
   double _m = _p.Mean();
   return(sqrt(_m));
}

在我们深入挖掘、并开始探索可能的应用之前,严谨的做法是针对 QM 类似行事,因为按照标记为 QM' 的镜像平均值,它更倾向于较大值,而 QM' 的权重则更偏向于较小值。再者,这种较小值加权,与较大值加权的二分法,可令我们分别取得低价缓冲区、及高价缓冲区。

在上一篇文章中,我们曾用这些缓冲区对来生成轨道线(布林带),和背离信号。除了这两个应用之外,我们还可生成替代应用,举例,如果我们要获取 OSMA 信号,不过由于本文的主要目的不是 QM 、或平均值的概述本身,而是多品种交易、及多时间帧交易,故我们将坚持上一篇文章中已讲述的应用。如常,读者可以独立修改随附的代码,从而探索 QM 的其它实现途径。

QM 镜像 QM' 可按类似于我们在上一篇文章中分享的公式来给出:

//+------------------------------------------------------------------+
//| Inverse Quadratic Mean                                           |
//+------------------------------------------------------------------+
double CSignalQM::QM_(int Index, int Mask = 8)
{  double _am = AM(Index, Mask);
   double _qm = QM(Index, Mask);
   return(_am + (_am - _qm));
}

这个公式的中心论点是,算术均值提供了最中正和公平的均值,这意味着如果我们取这个原生算术平均值作为镜像线,那么与这个平均值的任何距离都可以被“镜像”。因此,实现这一点的 MQL5 源代码与我们已经分享的相同,故于此不再分享。它会附在文后。

再者,我们的意图是展示多品种和多时间帧交易。两种类型的智能系统。因此,我们可以将 QM 作为布林带信号,而其它则采用背离信号,这两者的实现都已在上一篇文章中讲述。

正如我们上面强调的,MQL5 向导组装的智能系统设计用于基于每个信号的乖离,进行多时间帧、及多品种测试(和交易)。智能系统所用的每个信号,在向导中加入之前都会获得其自定义品种和/或时间帧。这意味着我们可以在任何信号上测试多品种和多时间帧,不过由于我们在上一篇文章中刚刚视察过新的平均值,故我们的二次均值继续一脉相承。


依据 QMA 开发自定义信号类

我们不能针对多货币品种智能系统执行测试,因为由向导组装的内容需要修改,我们已在这篇文章中解决了。如上所述,多品种和多时间帧智能系统的测试,可据相同信号文件完成,因为这些品种和时间帧数值是分配给每个信号的。做多和做空条件的处理将遵循我们在上一篇文章中依据几何平均值生成信号的总体方式。我们正在进行一些修改,因为在上一篇文章中我们只与一个信号打交道,我们能够寻找清晰的入场点,例如我们在寻找看跌信号的同时,价格与上轨交叉;或寻找看涨信号的同时,价格与下轨交叉。

在本文中,由于我们要并行处理多个信号,且它们不太可能同时并发交叉,如此这般,取代寻找这样的清晰入场点,我们把波带当作看涨和看跌概率的衡量标准,即衡量收盘价相对于两条波带基线的远近程度,高于(看跌)、或低于(看涨)。故此,当前收盘价越高于基线,看跌权重越高,类似地,收盘价越低于基线,看涨权重越高。

故此,所用的每个信号在不同的时间帧上运行,即为看涨亦、或看跌提供了条件,具体取决于它们各自收盘价的位置。然后,取独立优化的信号权重将这些条件组合起来,通过加权平均得出单个条件。正是这个平均值决定了当前持仓是否可以平仓,以及是否能开立任何新持仓。我们修改后的做多和做空条件的代码分享如下:

//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//+------------------------------------------------------------------+
int CSignalQM::LongCondition(void)
{  int result = 0;
   m_close.Refresh(-1);
   if(m_close.GetData(StartIndex()) > m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) > BandsDn(StartIndex()) && m_close.GetData(StartIndex() + 1) < BandsDn(StartIndex() + 1))
   {  result = int(round(100.0 * ((m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex()))))));
   }
   return(result);
}
//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//+------------------------------------------------------------------+
int CSignalQM::ShortCondition(void)
{  int result = 0;
   m_close.Refresh(-1);
   if(m_close.GetData(StartIndex()) < m_close.GetData(StartIndex() + 1) && m_close.GetData(StartIndex()) < BandsUp(StartIndex()) && m_close.GetData(StartIndex() + 1) > BandsUp(StartIndex() + 1))
   {  result = int(round(100.0 * ((m_close.GetData(StartIndex()+1) - m_close.GetData(StartIndex()))/(fabs(m_close.GetData(StartIndex()) - m_close.GetData(StartIndex()+1)) + fabs(BandsUp(StartIndex()) - BandsDn(StartIndex()))))));
   }
   return(result);
}


实际实现和测试

一旦在向导中使用我们上述信号组装好智能系统,如果我们用到多时间帧,那么 *MQ5 文件头部分将如下所示:

//+------------------------------------------------------------------+
//|                                                           qm.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\Signal\My\SignalWZ_25.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingNone.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedMargin.mqh>
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string Expert_Title           = "qm_frame"; // Document name
ulong        Expert_MagicNumber     = 2028; //
bool         Expert_EveryTick       = false; //
//--- inputs for main signal
input int    Signal_ThresholdOpen   = 10;   // Signal threshold value to open [0...100]
input int    Signal_ThresholdClose  = 10;   // Signal threshold value to close [0...100]
input double Signal_PriceLevel      = 0.0;  // Price level to execute a deal
input double Signal_StopLevel       = 50.0; // Stop Loss level (in points)
input double Signal_TakeLevel       = 50.0; // Take Profit level (in points)
input int    Signal_Expiration      = 4;    // Expiration of pending orders (in bars)
input int    Signal_0_QM_Length     = 50;   // QM(50) H1 Averaging Length
input double Signal_0_QM_Weight     = 1.0;  // QM(50) H1 Weight [0...1.0]
input int    Signal_1_QM_Length     = 50;   // QM(50) H4 Averaging Length
input double Signal_1_QM_Weight     = 1.0;  // QM(50) H4 Weight [0...1.0]
input int    Signal_2_QM_Length     = 50;   // QM(50) D1 Averaging Length
input double Signal_2_QM_Weight     = 1.0;  // QM(50) D1 Weight [0...1.0]
//--- inputs for money
input double Money_FixMargin_Percent = 10.0; // Percentage of margin

正如所见,我们为三个选定的时间帧中的每一个分配了一条移动平均线长度参数、及加权参数,在本例中为 PERIOD_H1、PERIOD_H4 和 PERIOD_D1。由于为智能系统生成信号是取收盘价与布林带基线之间距离的加权平均值,这意味着我们在任何时候都有信号,这与我们在上一篇文章中探索的几何平均值的清晰入场点不同。这意味着在没有离场价格目标的情况下,像是止损或止盈,执行测试大概是一个好主意。在上一篇文章中,我们使用的唯一目标价位是止盈。止损设置一直被吹捧为一种合理的止损限制策略,然而止损价格从来没有保证,且从广泛的测试来看,大多数账户耗尽保证金,主要是因为他们的持仓规模过于激进,而不是没有止损。显然,关于止损重要性的争论肯定会继续下去,但这就是我的看法。尽管,在本文中,我们将坚持仅用止盈目标价格,欢迎读者在测试时修改输入参数,从而适配自己的亏损管理方式。


策略测试器报告和分析

如果我们针对 EURJPY 货币对,据 2023 年的 H1 时间帧内进行测试运行,同时从 H1、H4、和日线时间针中寻求权衡信号,我们会得到以下结果,作为我们的一些公平结果:

r2

c2

从某种意义上说,结果与我们依靠上轨和下轨价格交叉的清晰入场点所取得的成就相去甚远。因此,我们在利用布林带价格交叉的清晰入场点进行多时间帧的测试,令人惊讶的是,除了性能之外,等到这些交叉时下单的交易数量,比我们上面刚刚采用的加权平均方法更多。结果如下:

r1

c1


结束语

总而言之,我们已经展示了如何在向导组装的智能系统中使用多时间帧。我们在展示这一点时涵盖的要点是,向导组装过程允许每个信号不仅有自己的时间帧,而且还有自己的交易品种。通过为其分配特定的时间帧来自定义信号,意味着该信号的 OHLC 缓冲区将与该时间帧绑定,这是一个相对简单的过程,与自定义信号按指定品种进行交易不同。这是因为当为信号分配特定品种进行交易时,需要对 'CExpert' 类实例进行额外修改,其中它应采用数组格式以便适配要交易的每个品种。在演示多时间帧交易时,我们使用二次均值作为信号,而与上一篇文章一样,我们得到了一个镜像版本,鉴于二次均值默认更偏向于较大值,因此其镜像更偏向于平均集中的较小值。我们对这两种设置进行了测试,其一始终评估概率,另一个则寻找特定的入场信号,我们得到的两种方法结果截然不同。

不过,多时间帧交易通常旨在通过同时监控宏观趋势的大时间帧,并同时在较短的时间帧上选择实际入场信号,意在瞅准清晰或“最正确”的入场点。为此,使用搭配不同时间帧的不同信号,可能会更严谨,其中较大的时间帧采用我们在上述第一个测试案例中研究的概率方式,而较小时间帧的实际交叉点则视为信号的触发点。

这可由读者实现和测试,因为这些信号类的两个实例都附加在文后,此外,还有替代的多时间帧实现,可将指标时间帧作为输入,其中该时间帧与智能系统所加载图表的时间帧不同。该方式,针对向导组装期间给信号分配时间帧之后,无法选择最优时间帧的问题,提供了一条权宜之计。通过将其作为信号的输入参数,可对其进行优化,从而最佳拟合策略。有趣的是,这种方式甚至可用于为自定义 OHLC 序列缓冲区分配时间帧。它的主要缺点是在多品种交易中,即使价格和指标读数可从作为参数的品种名称获得,但只有在如上所述对组装的智能系统文件进行修改后,才能进行交易。


本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/15185

威廉·甘恩(William Gann)方法(第一部分):创建甘恩角度指标 威廉·甘恩(William Gann)方法(第一部分):创建甘恩角度指标
甘恩理论的精髓是什么?甘恩角度是如何构建的?我们将为MetaTrader 5创建甘恩角度指标。
让新闻交易轻松上手(第3部分):执行交易 让新闻交易轻松上手(第3部分):执行交易
在本文中,我们的新闻交易EA将根据存储在数据库中的经济日历开始交易。此外,我们将改进EA的图表,以显示更多关于即将到来的经济日历事件的相关信息。
从基础到中级:变量 (III): 从基础到中级:变量 (III):
今天,我们将学习如何使用预定义的 MQL5 语言变量和常量。此外,我们将分析另一种特殊类型的变量:函数。知道如何正确使用这些变量可能意味着一个有效的应用程序和一个无效的应用程序之间的区别。为了理解这里介绍的内容,有必要理解前几篇文章中讨论的材料。
开发多币种 EA 交易系统(第 16 部分):不同报价历史对测试结果的影响 开发多币种 EA 交易系统(第 16 部分):不同报价历史对测试结果的影响
正在开发中的 EA 预计在与不同经纪商进行交易时都会表现出良好的效果。但目前我们一直使用 MetaQuotes 模拟账户的报价进行测试。让我们看看我们的 EA 是否准备好使用与测试和优化期间使用的报价不同的交易账户。