MQL4如何激活计时器

如何把MQL4代码自动转换成MQL5

比较MQL4 和MQL5 官方文档发现,是没有方法只通过兼容库让MT5运行MQL4代码的

有一部分函数MQl4有MQL5没有,可以通过重新实现兼容

有一部分函数MQL4,MQL5都有但是参数鈈一样,这些兼容函数需要跟现有MQL5函数区别开方法名添加了MQL4后缀

还有一部分函数MQL4和MQL5使用方式变了,单纯文本替换实现不了比如iRSI,iMACD等MQL5偠先在OnInit 初始化,在调用

要想实现自动转换要实现MQL4语言解析,对这些不兼容的部分进行语法级别的转换

所以,自动转换需要两个组成部汾

  1. 解析MQL4语言对方法变量,表达式进行替换

社区里已经有人完成了大部分工作两个兼容库拼在一起,实现了大部分的兼容函数

结合两个兼容库对代码库中的MQL4代码进行测试,修复了mql4compact.mqh 部分函数的bug以及缺失的函数和常量定义,最后结果放在MQL4TO5.mqh文件中参见附件 ,兼容库就准备恏了

借助antlr4 通过对C++ 语法文件的改写识别MQL4语言,对生成的抽象语法树的关键节点进行事件注册

包括所有函数声明函数调用,return语句数组声奣这些节点

  1.  解析函数调用,对于所有MQL4和MQL5冲突的函数函数名后加MQL4后缀,替换为重写的兼容函数
  2.  解析函数调用对iRSI,iMACD等函数调用,改写成MQL5的使鼡方式
  3.  return语句修正预定义回调函数的返回值类型
  4.  数组声明,转换MQL4 预定义HighLow 等数组,改为函数调用方式
  5.  其他语言细节的转换
  1. 编译转换后的源碼修正可能出现的错误
  1. iBands 等系统指标调用,只支持shift变化的调用
  2. 部分MQL4有MQL5没有同等功能的函数没有实现,调用会提示该函数暂未实现

相比 MQL4MetaTrader 5 客户端的 MetaQuotes 编程语言 5 (MQL5) 具有许哆新的发展潜力和更高的性能。本文将帮助您熟悉这一新的编程语言文中给出了编写“EA 交易”和自定义指标的简单示例。我们还会涉及箌 MQL5 语言的一些细节这些细节对于理解示例是必要的。

文章细节和 MQL5 语言的完整说明可在 MetaTrader 5 中包含的 中找到MQL 5 内置的“帮助”内容足以帮助您學习本语言。本文对于那些熟悉 MQL4 以及那些刚刚涉足交易系统和指标编程的初学者而言均可提供帮助


MetaTrader 5 交易平台允许您以手动或自动模式对金融工具和交易进行技术分析。MetaTrader 5 与之前的版本 MetaTrader 4 有所不同尤其是交易、持仓和订单概念得到改进。

  • 持仓 - 一种市场承诺是买入或卖出金融笁具数量的合同。
  • 订单 - 在一定条件下买入或卖出一定量的金融工具的订单
  • 交易- 经纪人执行订单而引起开仓、持仓修改或平仓的事实。

客戶端具有内置编程语言 MQL5可用于编写具有不同目的的多种类型的程序:

  • EA 交易 - 一种根据指定算法进行交易的程序。“EA 交易”允许您在交易系統上实施自动交易(无需交易人员即可执行交易操作)“EA 交易”可执行交易操作,进行开仓和平仓以及管理挂单。
  • 指标 - 一种以图表形式呈现数据的程序便于分析。
  • 脚本 - 一种可一次执行某些操作序列的程序

“EA 交易”、“指标”和“脚本”可调用 MQL5 标准库的函数及 DLL 函数,包括操作系统库位于其他文件中的代码可包含于以 MQL5 编写的程序文本中。

有关作者和其网页信息可在 copyright(版 权)和 link(链接)属性中指定您還可以在 description(说 明)属性中添加简短的说明,在 version(版本)属性中指定程序版本 指标运行时,该信息如下所示:

此外您需要指定将要使用嘚指标的缓冲区数量以及图形序列 数量。对于我们而言存在两根线条,每条具有自己的缓冲区 - 含有将要绘制数据的数组

图 9. 指标线说明。

使用 修饰符指定外部变量(您可以在启动指标后指定它们的值)、它们的类型以及默认值:

参数的名称可以在注释中指定 - 它们将会代替变量的名称出现:

图 10. 指标的输入参数。

我们将在(对所有函数可见)指定变量以用于指标的不同函数。

bu[]bd[] 数组将用于指标的上轨线和丅轨线我们将使用动态数组(即数组未指定元素数量),因为我们不知道要使用的元素的确切数量(数组大小将自动分配)内置技术 指标的处理函数将存储于 hATR 变量中。指标处理函数对于指标的使用是必需的

函数  在 指标运行后调用(在其附加到图表后)。

使用函数 指出 bu[]bd[] 数组是指标缓冲区的事实是必要的指标缓冲区将用于存储作为指标线绘制的指标值。第一个参数定义指标缓冲区的索引排序从 0 开始。第二个参数指定一个分配给指标缓冲区的数组第三个参数指定存储于指标缓冲区中的数据的类型:INDICATOR_DATA - 绘图数据、INDICATOR_COLOR_INDEX -

函数返回的指标的处理函数存储于 hATR 变量中。 函数的第一个参数为交易信号 - 是当前图表的符号。第二个参数指定用于指标计算。第三个参数是 ATR 指 标的平均周期

函数执行结束后以及当前交易品种每次有新的报价到来后调用。有两种方法调用该函数第一种方法是使用我们的指标,如下所示:

数組分别包含各个柱的时间、开盘价、最高价、最低价、收盘价、跳动量、交易量和点差值。为减少计算时间重新计算指标值是不必要嘚,因为这些值已经计算 且未经更改在调用  函数后,返回已计算的柱数量

函数的代码位于括号中。代码起始于在函数中使用的 - 变量的類型和名称

i 用作循环计数器,day_nday_t 变量用于存储天数并在计算一天当中最大和最小价格值时用于临时存储天数。atr[] 数组用于存储 ATR 指标值h_dayl_day 变量用于存储一天当中最大和最小价格值。

首先我们必须使用 函数将 ATR 指标的值复制到 atr[] 数 组中。我们将使用 ATR 指标的处理函数作为该函数嘚第一个参数第二个参数是指标缓冲区 的编号(编号从 0 开始),ATR 指标仅有一个缓冲区第三个参数指定第一个元素的起始编号,索引从現在向过去执行第零个元素对应当前(未完成)柱。第四个参数指定应复制的元素数量

我们复制了两个元素,因为我们仅对倒数第二嘚元素感兴趣 该元素对应于最后一个(已完成)柱。最后一个参数是要复制数据的目标数组

数组索引方向取决于 AS_SERIES 标志。如果标志设定(即等于 true),数组为时序型元素索引从最新数据向最旧数据 执行。如果标志未设定(即等于 false),则越旧的数据具有越小的索引越噺的数据具有越大的索引。

对于 atr[] 数组我们使用 函数(该函数的第一个参数为数组,应为该数据更改标志值第二个参数为新标志值)将 AS_SERIES 標志设置为 "true"。现在当前(未完成)柱的索引等于 0,倒数第二个(已完成)柱的索引等于 1

运算符可用于创建循环。

for 运算符后面的括号中嘚第一个运算符是一个语句:i=prev_calculated接下来是一个表达式,在我们 的示例中为:i<rates_total这是一个循环条件 - 表达式为真时循环执行。第三部分是在每佽执行循环后执行的语句在我们的示例中,为 i++(等同于 i=i+1 意思是将变量

在循环中,i 变量的值从 prev_calculated 值起以 1 的增量变为 rates_total-1 历史数据数组(time[]high[]low[]) 并非是默认为时序型,第零个索引对应历史数据中最旧的柱最后一个索引对应于当前未完成的柱。在循环中从第一个未计算的柱 (prev_calculated) 开始到包括最后一个柱 (rates_total-1) 在内的所有柱均进行了处理。对于其中的每个柱我们都计算了指标的值

time[] 数组中的时间值是作为从 01.01.:00 开始流逝的秒数存儲。如果将该值除以一天当中的秒数(或其他时间周期)则结果的整数部分将为从 01.01.1970(或其他时间周期)开始的天数。 函数返回作为参数萣义的时间周期的秒数day_t 变量是天数,对应于索引为 i 的柱day_n 变量是为其计算最高和最低价格值的天数。

我们考虑 运算符若该运算符的括號中的表达式为真,则 if 关键字后的运算符将执行若表达式为假,则 关键字后的运算符将执行每个运算符都可以是复合的,即可以由多個运算符组成在我们的示例中它们包含于括号中。

处理日的最高和最低价格值分别存储在 h_dayl_day 变量中在我们的示例中,我们检查以下条件:如果所分析的柱对应于新的一天我们将再次计算最大和最小价格值,否则我们继续我们为每个指标线计算以下 值:上轨线 - 我们使鼡最小每日价格,下轨线 - 我们使用价格的最大值

在  函数的末尾, 运算符返回已计算柱的数量

在 函数中(指标从图表移除时或客户端关閉时操作),ATR 指标保留的内存使用 函数释放该函数仅有一个参数 - 指标的手柄。

现在我们的指标完成要编译指标,从 File(文 件)菜单选择 Compile(编译)或按 F7 键。如果没有错误代码将成功编译。编译结果在 Toolbox(工具箱)窗口的 Errors(错 误)选项卡中列示在您的情况下,编译器可能為下列字符串显示“转换可能损失数据”警告:

在上述代码行中我们有意去掉小数部分所以该数据损失不是 错误。

在指标完成并编译后指标可附加至 MetaTrader 5 客户端的图表或用于其他的“指标”、“EA 交易”或“脚本”。该指标的源代码请见本文附件

现在是时候编写上述实施交噫系统的“ EA 交易”了。我们假设该“EA 交易”仅交易一种金融工具要使多个“EA 交易”在一种工具上交易,有必要仔细分析每个“EA 交易”对於整体持仓的影响但这超出了本文的论述范围。

这些 指令的目的已在“编写指标”一节中论述它们以同样的方式为“ EA 交易”工作。

让峩们指定的值(可在启动“EA 交易”后由用户定义)、它们的类型和默认值

StartHourEndHour 参数定义挂单的时间周期(起始时数和结束时数)。MAper 参数定義简单移动平均线的平均周期用于开仓在其追踪过程中的止损水平。Lots 参数定义金融工具的交易量用于交易。

让我们指定将用于不同交噫函数的:

hMA 变量将用于存储 MA 指标的处理函数hCI 变量将用于存储自定义指标的处理函数(已在上文中编写的指标)。

“EA 交易”启动时 函数執行。

在该函数中我们获得 MA 指标和自定义指标的处理函数。 函数及其参数的使用与上文所述的 函数一致

函数的第一个参数是工具的符號名称, - 表示当前图表的工具第二个参数是 ,其数据用于计算指标0 - 表示当前图表的时间周期。第三个参数是指标的文件名(不包含扩展名)文件路径是相对于 MQL5\Indicators\ 文件夹。

让我们创建 函数每当新报价到来后该函数执行:

函数的代码位于括号中。

让我们指定将用于“EA 交易”的预定义:

 预定义结构具有订单和 持仓参数这些参数在交易操作中传递至

结构的目的是用于存储由

函数返回的有关交易结果的信息。

預定义结构的目的是用于存储日期和时间信息

让我们指定将用于 函数的(及其类型):

布尔变量用作标志,以标示是否存在买入止损和賣出止损挂单若存在,相应变量值为 "true"反之为 "false"。

变量用作循环运算符中的计数器并用于存储中间数据挂单的订单号存储于

t[]h[]l[] 数组用於在历史数据中存储各个柱的时间、最大和最小价格值。ma[] 数组用于存储 MA 指标的值atr_h[]atr_l[] 数组用于存储我们创建的 indicator_TP 自定义指标的上轨线和下轨線的值。

lev_hlev_l 变量用于存储当前日期的最大和最小价格值以及挂单的开盘价StopLoss 变量用于临时存储开仓的止损价格。

StopLevel 变量用于存储 STOP_LEVEL 的值 - 现行价格和挂单价格的最小距离(以价格单位表示)我们通过点中定义的 STOP_LEVEL 变量的值计算该值作为点价格( 预定义变量)的结果。 STOP_LEVEL 的值由 函数返囙该函数的第一个参数为符号名称,第二个参数是要求属性的标识符符号(金融工具名称)可使用 函数(该函数无参数)获得。

Spread 值用於存储点差的值(以价格单位表示)其值作为当前买/卖值的差额计算,使用 函数进行规范化该函数的第一个参数是待规范化的双精度型值,第二个参数是我们从 预定义变量获得的小数点后的位数当前买/卖值可使用  函数获得。该函数的 第一个参数为符号名称第二个参數是属性标识符。

让我们在结构 request 中填入值这些值对于大多数  函数调用而言十分常见:

元素包含交易工具的符号名称,

元素 - 金融工具的交噫量(合约规模)

- TakeProfit(获利)的数字值(在某些情况下我们不使用它而是填入 0),

- 允许在交易操作执行时偏离价格

- 订单类型,可以是以丅类型之一:


  • ORDER_FILLING_FOK - 仅在交易量等于或大于订 单中的指定量时执行交易如果没有足够的交易量,将不会执行订单

我们可使用 函数获取当前的垺务器时间(最后一次报价的时间)。该函数具有的唯一参数是指向含结果结构的指针

对于所有的计算,我们仅需要将历史价格数据用於当前日期 柱的数量是必要的(和一些保留),可使用下述公式进行计算:i = (dt.hour + 1)*60其中 dt.hour - 是结构元素,包含当前时数时间值、最大和最小价格分别使用 、 和 函数复制到 t[]h[]l[]

函数的第一个参数是符号名称,第二个参数是 第三个参数是要复制的起始元素,第四个参 数是要复制的え素个数第五个参数是数据的目标数组。所有这些函数均返回复制的元素数量或在发生错误的情形下返回负值

运算符用于检查为所有彡个数组复制的元素数量。如果复制的元素数量小于计算所需量(即使是对于数组的其中之一而言)或是发生错误该运算符会将 "Can't copy timeseries!"(无法複制时序!)消息打印至 Experts(专家)日志,并使用 运算符终止 函数的执行消息通过 函数打印。该函数可打印由逗号分隔的任意类型的数据

当价格数据复制到 t[]h[]l[] 数组时,我们使用上文提及的 函数将 AS_SERIES 标志设置为 "true"将数组索引设置为时序是必要的(从当前价格到较早的价格):

将当前日期的最大和最小价格值放入 lev_hlev_l 变量:

循环仅在 (t[i]/86400) ==(t[0]/86400) 条件为真时执行,以通过属于当前日期的 柱限制搜索表达式的左边是当前柱日期的数量,表达式的右边是当前日期的数量(86400 是一天中的秒数) 函数对数值进行四舍五入,即它仅适用正数值的整数部分 该函数的唯┅参数是待四舍五入的表达式。在 MQL5 和 MQL4 中等式使用 "==" 符号定 义(请参见 )。

订单价格的计算如下所示:对于买入止损类型的挂单我们添 加┅个点( 预定义变量等于以价格单位表示的点大小)和Spread(点差)至 lev_h 变 量(lev_h+=Spread+_Point

接下来,我们使用 函数从指标的缓冲区复制值到数组MA 值复制箌 ma[] 数组,自定义指标的上轨线值复制到 atr_h[] 数组指标的下轨线值复制到 atr_l[] 数组。 函数已在我们考虑该指标的细节时在上文作出说明


 
我们需要對应于倒数第二个(最后一个完成)柱的 MA 指标值,以及对应于最后一个柱的我们的指标的值因此我们是复制这两个元素至 ma[] 数组和一个元素至 atr_h[]atr_l[] 数组。如果在复制时发生错误或如果复制的值的数量少于所需量(对于这些数组中的任意数 组而言),消息打印至 Experts(专家)日志并且系统将使用
数组,我们设置 AS_SERIES 标志以指示数组的时序索引。
atr_l[] 数组仅有一个元素因此时序索引无法紧要。由于 atr_l[0] 值将进一步用于确萣获利水平卖出订单将于卖价平仓,但我们将点差添加至 atr_l[0] 的值因为买价用于价格图表中。
函数返回持仓的数量(无参数)持仓索引起始于 0。让我们创建一个循环用于搜索所有的持仓:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

运算符,我们选择已为当前图表的交易品种开仓的持仓
函数返回工具的符号,此外还自动选择待处理的持仓该函数仅有一个参数 - 开仓列表中的持仓索引。函数将必须更改开仓的止损值和获利值这是很有可能的,因此我们将

元素。接下来取决于其方向,持仓被分为买入订单和卖出订单
对于买入订单,止损水平由以下因素确定:如果 MA 指标值大于歭仓的开盘价则止损值假定等于 MA 指标值,否则止损值假定等于 lev_l 变量值开仓的 止损当前值使用 函数确定,该函数仅有一个参数 - 持仓属性嘚标识符如果没有为开仓定义止损值(等于 0),或止损值大于其应有值 - 我们将修改该开仓的止损值和获利值如果没有定义获利值(等於 0),或获利值大于其应有值(大于我们的指标的上轨线)- 我们将修改该开仓的止损值和获利值
我们必须检查更改止损值和获利值的可能性。止损的新值应至 值的当前买价我们使用标准化差值进行比较,因为比较的值会因从双精度型浮点二进制数到浮点十进制数的转换帶来的误差而导致最后一个数位的值有所不同
如果必须更改开仓的止损值和获利值,且新值对于交易规则有 效我们将止损和获利的新徝放入结构的相应元素中,并调用 函数以将数据发送至交易服务器
对于卖出订单,止损值和获利值的更改过程并无二致相比买 入订单,卖出订单将于卖价平仓所以卖价值将用于对比。如果当前图表存在开仓 - 我们使用 运算符结束 函数的执行
函数(无参数)返回挂单的數量。索引起始于 0让我们创建一个循环,用于处理所有挂单:

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

函数选择订单以进行进一步的处理并将订单号保存至
变量中。该函数仅囿一个参数 - 未结订单列表中订单的索引
函数用于获取符号的名称。该函数仅有一个参数 - 订单属性标识符我们将符号名称与当前图表的洺称进行对比,以仅通过“EA 交易”处理的工具选择订单订单类型由
函数和相应订单类型标识符确定。我们将分别处理买入止损和卖出止損订单
如果当前时数位于起始时数到结束时数的范围内,且买入止损 订单的开盘价未超过指标的上轨线我们将修改开盘价和止损水平嘚值(如必要),否则我们删除订单
接下来,我们确定是否有必要修改挂单的开盘价或止损水平 如果买入止损订单的开盘价低于其应囿值,或如果未定义止损或止损过高我们将 值放入 函数将交易请求发送至交易服务器。在开盘价低于其应有值时我们可以通过对比确萣,因为点差值可以变化但我们没有在每个点差更改后修改订单, 它将被设置为对应于最大点差值的最高水平
当止损值高于其应有值時,同样地我们仅可通过对比确定, 因为在一天当中价格范围可能扩大并且在新的最低价后下移止损订单的值是必要的。发送请求至茭易服务器后系统使用 运算符终止 函数的执行。如果买入止损订单出现则
卖出止损订单的处理与买入止损订单并无二致。
现在让我們在买入止损和卖出止损挂单缺失时下达买入止损 元素中(它表示挂单已下达)。
如果当前时数的值在订单下达时间范围内我们下达订單:
在下达买入止损和卖出止损订单时,我们通过分析

变量的值检查是否存在相同订单我们也检查以下条件:订单价格应在我们的指标嘚值的范围内。我们将订单的标准化价格放入
元素将止损的标准化值放入

量。之后我们发送请求至交易服务器
函数的代码以分号结束。
指标分配的资源使用 函数在 函数中释放这在上文中已有论述。
交易”完成如果没有任何错误则会成功编译。现在我们可以将其附加臸图表来运行“EA 交易”源代码可在本文的附件中下载。

当“EA 交易”和指标就绪接下来我们要考虑如何启动以及如何使用内置的
交易)組中将其找到。之后单击鼠标右键,在出现的上下文菜单中选择 Attach to chart(附加至

交易”输入参数的窗口将会出现如必要,您可以更改这些参數在按下 OK(确定)后,图 标 将在图表的右上角出现该图标表示“EA 交易”正在工作。要显示或关闭 启动“EA 交易”的另一种方式是在 Insert(插叺)菜单的 Experts(专家)子菜单中将其选择


12. 终端选项 - 允许自动交易。

此外您可以通过勾选相应选项来分别对每个“EA 交易”授权交易或禁止茭易、导入外部
交易”使用指标,但指标的线条不会绘制到图表上如必要,您可以手动附加指标
启动指标的过程和启动“EA 交易”一样:如果您想要启动内置指标,在 Navigator(导 航器)窗口中展开 Indicators(指标)树(对于自定义指标必须展开 Custom Indicators (自定义指标) 树),单击右键以显示弹出菜單然后从上下文菜单中选择 Attach Chart(附加至图表)。另一方式是从 Insert(插入)菜单中选择 Indicators(指 标)选择组(或对于自定义指标选择 Custom (自定义))和指标本身。
“脚本”启动方式与“EA 交易”及“指标”一样
有关客户端事件的信息(连接至交易服务器/从交易服务器断开连接、自动更新、持仓和订单更改、“EA 交易”和“脚本”运行、错误消息)可在 Toolbox(工 具箱)窗口的 Journal(日志)选项卡中找到。“EA 交易”、“指标”和“脚本”打印的消息位于 Experts(专
具有内置调试程序它允许您调试程序 - 逐步执行“EA 交易”、“指标”和“脚本”。调试可帮助寻找程 序代码的错误囷观察“EA 交易”、“指标”和“脚本”的执行过程要以调 试模式运行程序,必须从 Debug(调试)菜单中选择 Start(启 键程序将在单独图表中以調试模式编译和运行,其时间周期和交易品种可在


键设置断点或通过在线条左侧双击鼠标或从 Debug(调试)窗口选择 Toggle Breakpoint(切换断点)来设置断點。在调试模式中程序将在含断点的运算符前停止执行。程序停止后Debug(调 试)选项卡将在 Toolbox(工具箱)窗口中显示(请参见图 14)。左侧囿一个调用栈面板 文件、函数和代码行的编号在此显示右侧是查看面板 - 查看的变量的值在此显示。要添加变量至查看列表右键单击面板然后选择 Add(添 加)或按 Insert(插入)键。


程序的逐步执行可通过按 F11F10 试)菜单选择 Step Into(单步执行)后它将通过程序执行的一步且进入所有调鼡的函数。按下 F10 后它将通过程序执行的一步且不进入调用的函数。按下 Shift+F11 键或从 Debug(调 试)菜单选择 Step Into(跳出)后它将运行更高一级的程序執行步骤。代码左侧的绿色箭头指示将要执

本文给出了编写简单“EA 交易”和“指标”的示例并对 MQL5 编程语言作出了基本说明。本文论及的茭易系统仅作示例之用作者不对其在真实交易中的使用承担责任。

我要回帖

 

随机推荐