English Русский Español Deutsch 日本語 Português
preview
理解并有效地使用 MQL5 策略测试器

理解并有效地使用 MQL5 策略测试器

MetaTrader 5测试者 | 13 十一月 2023, 10:57
741 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

概述

作为 MQL5 程序员或开发人员,我们发现我们需要很好地理解和使用策略测试器,才能获得有效的结果。 通过使用这款颇具价值的工具,我们可以获得有关我们所创建 MQL5 程序的性能的宝贵认知,这对获得更好的交易结果颇具影响。 故此,我们发现在进行测试之前,我们需要充分了解重要的主题,例如处理所有错误类型,因为作为开发人员,我们犯糊涂导致出错是很正常的。 我们还需要深刻理解的另一个主题是调试,它让我们以交互方式执行我们创建的程序。 然后,我们来到最重要和最有价值的工具,即策略测试器,用于测试和评估我们创建的程序,其功能比 MetaTrader 4 版本的更有趣。 因此,在本文中,学习使用 MQL5 策略测试器的最重要方面会是一次了不起的学习之旅,我们将遍历以下主题涵盖所有内容:

我们将尝试涵盖有关上述主题的最热门要点,以便更好地理解我们作为程序员或开发人员需要处理的内容。 我在这里需要提及的是,当我们应对这个主题时,正常的话,所有读者都已经了解 MQL5 编程语言,并且他们知晓如何编写他们的程序,因为这是一个前置的主题,您需要能够理解,才能从阅读本文中获得最大收益。 如果您需要先学习该语言,您可以去查阅 MQL5 文档。 此外,您可以阅读我关于学习 mql5 编程基础知识,以及如何基于最流行的技术指标创建交易系统的其它文章,我希望它们对您有所帮助。

错误

在本主题中,我们将学习在创建、执行和运行 MQL5 程序时可能发现的错误。 理解这个主题的一个要点是,MQL5 会正确报告这些错误,但如果我们不知道这些错误意味着什么,或者在程序的哪个阶段,相较于我们已经知道它们的含义,我们就要花费更多的时间来处理或解决它们。

我们将根据我们在 MQL5 程序上的工作阶段来讲述这个主题,在我们编写代码时,可能会遇到错误和警告,即编译错误和警告。 我们在执行 MQL5 程序时也可能会遇到运行时错误,当我们的 MQL5 程序尝试交易时,我们也可能会遇到其它类型的错误,即交易服务器错误。 因此,我们将涵盖以下类型的错误:

  • 编译错误和警告
  • 运行时错误
  • 交易服务器错误

在涵盖这些错误之前,您需要知道错误出现的位置。 在 MQL5 IDE 中,在最低部分有一个工具箱窗口,如果您未能在默认位置找到它,您可以通过以下方法之一查看它:

1- 单击“查看” ==> 选择“工具箱”

工具箱

2- 从键盘按 Ctrl+T

3- 从主工具箱窗口单击 “工具箱” 按钮

工具箱2

之后,我们可以如下图一般发现它

工具箱3

编译错误和警告:

当我们为特定程序编写代码时,我们可能会犯错误,这是极其正常的,例如,一句编写错误的语法或拼写错误,这都会导致编译代码时出现错误。 在这一部分中,我们将分享最流行和最常遇到的此类错误。 您需要知道的最重要的事情是,在消除或解决错误之前,程序无法编译成功。 我将根据此类错误讲述我们可能面临的最常见的错误:

分号预期错误:

当忘记在行尾写分号时,我们将面临这个错误,故我们少了一个分号,或者如果我们也忘记了左括号。 我们必须正确使用这些类型的符号,从而避免此类错误。 下面的代码是此类错误的一个示例。

出错的错误代码:

int a=(2+1)

错误将与以下内容相同:

分号预期

更正无错误代码:

在代码行末尾添加分号更正代码之后,我们可以得到正确的代码,如下所示:

int a=(2+1);

编译代码后,我们发现错误被消除,代码编译后没有任何错误,如下所示:

分号预期解决

意外的令牌错误:

这是我们经常遇到的另一种代码,其原因是忘记了最后一行代码中的右括号,或者我们可能会在已有代码行中加入了额外的左括号。 我们可以看到此类错误的示例,如下所示:

出错的错误代码:

int a=(2+1;

我们可以在 “工具箱” 的 “错误” 选项卡中看到错误,如下所示:

意外的令牌

更正无错误代码:

int a=(2+1);

如同以下内容,通过添加右括号,我们可以看到在 “错误” 选项卡,其中无任何错误:

 意外的令牌解决

未声明的标识符错误:

当我们使用变量而没有事先声明它时,就会发生这种类型的错误,因为我们必须在使用它、或为其分配任何数值之前声明任何新变量。 通过选择正确且合适的数据类型来声明它,我们需要将相应值返回到这个变量,例如整数或字符串。 下面是此类错误的示例,即在不声明新变量的情况下使用它。

出错的错误代码:

a=5;

在上面的代码中,我们在未声明情况下使用了变量(a),并为其赋值 5。 因此,当我们编译此代码时,我们会发现未声明的标识符错误,如下所示:

未声明的标识符

正如我们所见,错误描述的准确性可能非常有帮助,因为它不仅报告错误,而且指出了导致此错误的变量 “a”。

更正无错误代码:

int a=5;

此代码正确编译后,我们从同一图片中未发现任何之前所提及的“工具箱”的“错误”选项卡里的错误。

左括号不平衡错误:

当我们缺少右括号、或多用了额外的右括号时,就会发生此类错误。 我们可以通过以下示例发现该错误。

出错的错误代码:

   bool a=7;
   if (a=5
   a=5;

在前面的代码中,我们发现,若忘记右括号,除了 “预期某些运算符” 的错误外,还出现了 “左括号不平衡” 的错误,如下图所示

左括号不平衡

更正无错误代码:

   bool a=7;
   if (a=5)
   a=5;
更正代码后,我们会发现编译时没有错误。


程序意外结束错误:

有时我们在代码中遗漏了一个右括号,继而发生意外的程序结束错误,我们必须检查我们的代码,查看需要添加的内容,或者我们需要确保每个左括号匹配一个右括号来解决此错误。 下面是该代码的示例。

出错的错误代码:

void OnStart()
  {
   bool a=7;
   if (a=5)
   a=5;

编写与上一段代码模块相同的代码,故意遗漏最后一行(a=5)后面的右括号,我们可以发现“意外的程序结束”错误,以及另一个 “不平衡括号” 错误,如同下图

程序意外结

更正无错误代码:

void OnStart()
  {
   bool a=7;
   if (a=5)
   a=5;
   }

添加右括号更正代码后,我们会发现代码成功编译没有错误。

表达式不允许出现在全局范围错误:

当我们在复合运算符中缺少左括号时,就会发生该错误,或者当我们在特定函数范围之外编写语句或表达式时,可能会发生该错误,因为我们只能在函数范围内使用表达式。 以下示例示意此类错误。

出错的错误代码:

   int a=(7+5);
   if (a<7)
   
   a=7;
   }

在前面的代码中,我们遗漏了与(})配对的起始({),故系统报告 “表达式不允许出现在全局范围” 错误。 以下是 “错误” 选项卡中的错误。

表达式不允许出现在全局范围:


更正无错误代码:

   int a=(7+5);
   if (a<7)
   {
   a=7;
   }

更正代码后,与前面的代码模块相同,我们会发现代码编译后没有任何错误。

错误的参数计数错误:

当我们用到拥有指定参数的特定函数时,若我们未正确指定这些参数,意即或多或少,我们会体验到这种类型的错误代码。 如果我们使用预定义的函数或我们创建的函数,则会出现此错误。 以下是该错误的示例。

有错误的代码:

如果我们创建了一个 “myVal” 函数,返回两个整数值求和的结果,这意味着该函数中有两个参数? 故此,当我们调用此函数时传递个数的参数时,我们将得到此类错误,其与以下代码相同

void OnStart()
  {
   int example=myVal(10);
  }
//+------------------------------------------------------------------+
int myVal(int a, int b)
  {
   return a+b;
  }

编译上面的编写代码,我们将得到如下内容的错误:

错误参数计数

无错误代码:

为了正确编写此代码,我们需要为这个创建的函数传递相应个数的参数,如下所示

void OnStart()
  {
   int example=myVal(10,20);
  }
//+------------------------------------------------------------------+
int myVal(int a, int b)
  {
   return a+b;
  }

编译此正确代码后,我们不会发现任何错误。

某些操作符预期错误:

当我们在特定位置完全遗漏或放错操作符时,我们就会遇到这种类型的错误。 以下是该类错误的示例。

有错误的代码:

int a= 7 10;

在上面的代码中,我们在两个数字之间遗漏运算符,这就是我们将得到 “某些运算符预期” 错误的原因,如下图所示:

某些操作符预期

无错误代码:

int a= 7+10;

通过添加(+)更正代码后,我们会发现代码将编译完毕,没有错误。

所提及错误都是此类错误中最常见的,如编译错误;但我们说过,还有一类编译警告,我们需要了解它们是什么,它们是为了提示目的而显示的,它们并非错误。 下面是一个示例代码,我们发现它将在 “错误” 选项卡中收到警告

int a;

编译上面的代码,我们将得到变量 “a” 未使用的警告,因为我们声明了一个新的 “a” 变量,但我们并未用到它,或为它赋值。 以下是警告图片

 警告

您可以从文档中查看以下所有 MQL5 链接,获取有关以下内容的更多信息:

一些提示非常实用,有助于在发生这些错误时应对:

  • 从最开始的错误进行修复,因为也许会解决由其原因导致的所有错误。
  • 在 “工具箱” 的 “错误” 选项卡中双击错误行,将定位到出现问题的代码行。

现在我们了解了在编写 MQL5 程序代码时在第一阶段可能遇到的错误。 我们将进入第二阶段,执行程序时发生的错误,即运行时错误。

运行时错误:

正如我们之前提及的,运行时错误是执行 MQL5 程序期间发生的错误类型。 这些错误不会阻挡代码本身没有错误的情况下编译,但它执行或操作时不会符合我们的需要或期望。 我们可以在日志中发现这些错误,作为打印的消息,其中包含错误的原因,以及源代码中产生错误的行。

这些错误的示例:

错误的代码 错误的原因
4007
  内存不足,无法重新分配数组,或尝试更改静态数组的大小
4101   图表 ID 错误
4301   未知品种作为市场信息
4754   订单未找到
5120   内部数据库错误

如果您注意到,由于 MQL5 将所有运行时错误定义为易于识别的代码,如此您就可以调用 GetLastError() 函数查找这些代码,并将错误处理方法添加到您的程序当中,我们可以在测试时在 “日志” 选项卡中看到这些错误报告,或者在“智能系统” 选项卡中看到加载到当前图表上的程序执行错误报告,您可以通过以下链接查看 MQL5 文档中所有运行时错误的代码:

https://www.mql5.com/zh/docs/constants/errorswarnings/errorcodes

我在此需要提到的是,程序不会遇到运行时错误就结束执行,除了一些严重错误会结束执行,例如数组超出范围错误。

交易服务器错误:

这些类型的错误发生在交易执行阶段,调用 OrderSend() 函数提交 MqlTradeRequest 结构的交易请求,我们在测试时可从 “日志” 选项卡中看到这些错误,或者在当前图表加载程序执行期间,从 “智能系统” 选项卡中看到这些错误。 如果您需要查看这些错误的示例,如下既是:

错误的代码
错误的原因
10006
  请求被拒绝
10032
  仅真实账户允许操作
10033
  挂单数量已达到限制
10034
  交易品种的订单和持仓量已达到限制
10041
  挂单激活请求被拒绝,订单被取消

您可以通过以下链接在 MQL5 文档中找到此类错误的所有代码,并查阅:

https://www.mql5.com/zh/docs/constants/errorswarnings/enum_trade_return_codes

调试

在本主题中,我们将学习如何通过 MQL5 调试器工具来进行调试,因为它可基于历史或实时数据执行我们创建的程序,我们可以单击开始/恢复调试,如下图所示的工具箱中的调试器按钮,并基于真实或历史数据来做到这一点

 调试按钮

1- 基于历史数据开始/恢复调试

2- 基于真实数据上开始/恢复调试

3- 暂停调试

4- 停止调试

一旦我们基于历史数据启动开始按钮进行调试,我们会发现程序将在历史数据上执行,方法是打开图表基于历史数据进行调试;或者如果我们选择基于真实数据进行调试,程序将加载到图表,并基于真实数据,在程序旁边,您将找到(调试)。

策略测试器

在这一部分或主题中,我们将了解 MetaTrader 5 中最重要和最有价值的工具,即策略测试器,其新功能比 MetaTrader 4 版本的测试器更好,例如多币种测试,等等。 如何获得这个策略测试器,我们可以通过以下方法之一:

1- 打开 MetaTrader 5 交易终端时,按键盘上的 Ctrl+R。

2- 从菜单中 “查看” ==> 选择“策略测试器”。

测试器

之后,我们将找到如同 “概览” 选项卡里的策略测试器,并选择您需要的测试类型

测试器1

简单地说,通过 “概览” 选项卡,我们将选择需要测试类型,一旦我们完成这一步,选项卡将更改为 “设置” 选项卡,其中包含基于您所选择测试类型的预设。

  • 信号:用于测试没有可视化模式的智能系统信号。
  • 指标:用于测试指标。
  • 可视化:用于在图表测试期间使用可视化模式进行测试,以便查看程序将如何根据其指令对数据做出反应。
  • 压力和延迟:测试压力和延迟,功如其名。
  • 优化选项(完整、遗传、正向)。
  • 市场扫描器:用于测试市场扫描。
  • 数学计算:用于测试数学计算。

您还可以通过最后一个选项 “查看以前的结果” 来查看以前的测试结果。 您还可以通过测试选项下方的 “搜索” 来搜索以前的特定测试。

如果我们移到设置选项卡,我们将得到如下内容:

 测试器2

  •   1- 智能系统:选择我们需要测试的程序文件。
  •   2- IDE:打开所选程序的源代码。
  •   3- 保存或加载特定设置。
  •   4- 品种:选择我们需要测试的品种。
  •   5- 为选定品种选择测试的时间帧。
  •   6- 用于所选品种的规格。
  •   7-日期:选择我们需要测试的时间段。
  •   8- 选择测试的开始日期。
  •   9- 选择测试的结束日期。
  •  10- 前向:选择将留出用于前向测试的优化周期的所需部分。
  •  11- 选择前向测试的开始日期。
  •  12- 延迟,调整得到数据的延迟,接近实际值。
  •  13- 尝试接近真实数据和真实执行。
  •  13/2- 模型:选择要测试的模型,是按跳价、还是按其它方式?
  •  14- 如果您需要以点数为单位计算利润,请勾选。
  •  15- 选择我们需要开始测试的存款金额。
  •  16- 选择存款的货币。
  •  17- 选择杠杆。
  •  18- 选择我们是否要优化,我们稍后会用到。
  •  19- 勾选我们是否需要在测试期间可视化交易或执行。


我们还有 “输入” 选项卡,检查所测试程序是否可由用户插入或编辑输入参数。

确定我们的设置,并按下 “开始” 按钮后,程序进行测试,我们可以通过图表来监控该测试,如果我们选择可视化测试,则该图表中会出现选项卡,在 “交易” 栏可看到我们的程序所执行的交易,“历史” 栏可监控已平仓或取消的订单,“操作” 栏可查看所有操作,而 “日志” 栏检查程序和其它进程打印的消息。 我们还可以通过策略测试器窗口中的 “图形” 选项卡来监控程序的性能。

测试完毕后,我们还可以检查将出现的 “回测” 选项卡,因为它将包含与以下示例相同的所有测试统计信息和洞察力

测试器3

测试器4

根据您将要测试的每款程序,此回测选项卡中的数据将与您在上一个示例中看到的数据相似或不同。

我在这里还需要提到一件事,因为它在测试过程中非常重要,那就是优化,包括选择各种不同的参数和输入,并检查这些输入或参数的每个可能的组合,从而检验和测试哪些参数将产生最佳结果。 在此,我们将从 “概栏” 选项卡中选择一个 “优化” 模型,并选择合适的 “优化” 设置,如下图所示

测试器5

测试器6

测试后我们需要检查和评估的最重要的元素:

  • 净利润:这是从毛利润中减去毛亏损计算得出。
  • 回撤:这是账户在交易过程中经历的最大亏损。
  • 盈利因子:这是毛利润与毛亏损的比率。
  • 预期收益:这是交易的平均盈利或亏损。
  • 恢复因子:衡量测试策略在遭受亏损后的恢复情况。  


结束语

我们学到的这些基本主题,都是关于在开发任何 MQL5 程序时都需要掌握的最重要和最有价值的工具之一,即通过 MetaTrader 5 交易终端的策略测试器进行测试的过程,这有助于理解和高效地使用这款工具。 我们还学习了我们在开发 MQL5 程序时遇到的错误,这些错误类型包括:

  • 编译错误和警告。
  • 运行时错误。
  • 交易服务器错误。

然后,我们学习了如何利用 MQL5 IDE 调试器来进行调试;通过了解 MetaTrader 5 的不同模型,我们学会了如何利用 MetaTrader 5 的策略测试器,我们可以根据模型设置测试设置;我们如何通过不同的选项卡监控测试过程,该选项卡在测试所有 MQL5 程序时报告的所有内容;在测试之后,我们如何解读测试报告,并确定我们需要检查和评估的最重要元素;以及如何通过测试优化我们的策略,并从测试中获得 MQL5 程序的最佳结果。

我希望本文及其信息对您有用,依靠有效的测试来帮助您制作 MQL5 程序,并改进结果。 如果您觉得这篇文章有用,并且需要阅读更多文章,您可以查看我分享的其它文章,譬如我们如何根据最流行的技术指标创建交易系统。

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

复购算法:模拟多币种交易 复购算法:模拟多币种交易
在本文中,我们将创建一个模拟多币种定价的数学模型,并针对多元化原理进行彻底研究,作为搜索提高交易效率机制的一部分,我在上一篇文章中已经开始了理论计算。
MQL5 中的范畴论 (第 8 部分):幺半群(Monoids) MQL5 中的范畴论 (第 8 部分):幺半群(Monoids)
本文是以 MQL5 实现范畴论系列的延续。 本期,我们引入幺半群作为域(集合),通过包含规则和幺元,将范畴论自其它数据分类方法分离开来。
如何用 MQL5 创建自定义真实强度指数指标 如何用 MQL5 创建自定义真实强度指数指标
这是一篇关于如何创建自定义指标的新文章。 这一次,我们将与真实强度指数(TSI)共事,并基于它创建一个智能系统。
MQL5 中的矩阵和向量:激活函数 MQL5 中的矩阵和向量:激活函数
在此,我们将只讲述机器学习的一个方面 — 激活函数。 在人工神经网络中,神经元激活函数会根据一个或一组输入信号的数值,计算输出信号值。 我们将深入研究该过程的内部运作。