更新的MQL4
MQL4有什么新特性
从构建600开始,MQL4编程语言已经完全被修改,达到了MQL5的级别。现在您可以使用统一的元编辑器开发环境、创建自己的风格、使用库和调试工具在MQL4/5中开发交易机器人。
MQL4因为易于学习和使用MetaTrader 4终端多年生成的大量代码,在自动化系统开发人员中非常流行。然而,这种语言也存在一些缺点——简单的编程语言无法允许开发复杂的系统,并且妨碍从高级语言移植经过调试的库。因此,我们决定在其中实现尽可能多的MQL5语言函数和功能,以完全保留MQL4功能。换句话说,所有强大的MQL5功能,包括ООP和本地代码编译器,将在MQL4变得好用。
为了实现这一点,我们开发了一个统一的编译器,它自动支持MQL4和MQL5语言。MetaEditor还将成为MetaTrader 4和MetaTrader 5平台的统一应用程序。因此,可以从任何版本编译MQL4和MQL5。MQL5存储也可以用于工作。
MQL4应用程序的保护上升到MQL5级别。新的EX4/EX5文件提供了严格的、完全修改过的保护。这意味着EX4应用程序的市场也可以为MetaTrader 4所用。
此外,MQL4现在具有新的图形物件和处理图表的新功能。MQL5标准库将被移植到MQL4,为开发人员提供了创建自己的图形界面和交易库的新的可能性。现在,您可以使用资源在MetaTrader 4中创建成熟的应用程序。
MQL4语言中的更改
MQL4语言中的更新,添加了char、short、long、uchar、ushort、uint、ulong和double数据类型。这使其允许从其他c++语言传输代码。不同类型的数据是按不同的速率进行处理的。其中整数数据是处理速度最快。还采用一种特殊的协同处理器来处理双精度数据。由于浮点数据所具有的内部复杂性,故处理速度慢于整数1。现在,各类型转换功能也已经实现。
字符串现在以Unicode格式显示,在以前它们是ANSI格式(单字节)。程序中如果使用dll并将字符串变量传递给它们,则应该考虑这一方面的问题。
预定义的量现在是long类型的。对于量的时间序列的访问也由long类型数组组成。所以建议在旧的MQL4程序中,将具有此类型的数据显式转换为目标类型,以避免类型出错。
结构和类,对象指针,void类型和 this关键字允许一个对象接收一个对它自己的引用已经添加。支持所有面向对象的编程标准:
- 类型的封装和可扩展性
- 继承
- 多态性
- 过载
- 虚函数l functions
ООP允许使用类开发项目。这有助于大型应用程序的调试和开发,并提供了重新再用以前生成的代码的能力 due to inheritance。但是,这不意味您不能像以前那样以面向过程的方式生成MQL4代码。如果不需要新特性,仍可以像以前那样开发程序。
为具有兼容性init()、deinit()和start()预定义函数仍然可用,不过,现在可以使用OnInit()、OnDeinit()、OnStart()、OnCalculate()和OnTick()等函数做为替代。此外,还实现了新的预定义的OnTimer()、OnChartEvent()和OnTester()处理程序函数。在旧版MQL4中,预定义函数可以具有任何参数和任何返回类型,且可以通过名称而非签名来调用它们。而在新MQL4中,所有预定义的函数都具须严格对应它们的签名。换句话说,它们具有精确定义的参数集和返回类型。
现在,变量名不能再包含特殊的字符和点,新的MQL4语言中的关键字不能再用作名称。旧MQL4程序可以用采新编译器重新编译一一下,以便在跟着编译器的消息轻松地纠正此类错误。
优先规则现在需匹配C语言标准。如果您还不能确定,可以在旧MQL4应用程序中填加入括号,以明确指出提高可靠性的优先级。
现在在逻辑操作使用缩短了条件检查,这与旧MQL4版本不同,在旧版本中J是计算了所有表达式,然后执行检查。
假设逻辑和"&&"的使用:
if(条件1表达式 && 条件2表达式)
{
// some block of statements
}
如果条件1表达式为false,则不执行条件2表达式的计算,因为false && true结果仍然等于false。
ArrayCopyRates()函数行为改变了。在旧MQL4版本中,这个函数用于将系列复制到array double[][6]中。现在,如果需要接收时间序列,请使用MqlRates结构元素的数组:
//--- 存储价格、数量和传播信息的结构
struct MqlRates
{
datetime time; // 开盘时
double open; // 开盘价
double high; // 最高价
double low; // 最低价
double close; // 收盘价
long tick_volume; // Tick量
int spread; // 滑点
long real_volume; // 交易volume
};
另外,在没有实际复制的情况下,可以使用新的函数格式进行虚拟复制,访问复制的值实际上就是访问价格数据。
int ArrayCopyRates(
MqlRates& rates_array[], // 通过参考MQL考贝数据数组
string symbol=NULL, // 币种
int timeframe=0 // 时间框
);
为了提高与旧的MQL4程序的兼容性,仍保留了以前的调用格式,但现在它将数据复制到double类型数组中。
int ArrayCopyRates(
void& dest_array[][], // 通过参考,考进数组中
string symbol=NULL, // 币种
int timeframe=0 // 时框
);
这意味着,当时间序列中的值发生变化(如添加新棒、重新构造、最后棒的收盘价被调优)时,必须将所需的数据重新复制到dest_array[]中。接收数组方将自动分配给所需的复制棒数,哪怕它是静态声明的。
改变RateInfo历史数据存储格式。旧版本的RateInfo结构如下:
struct RateInfo
{
unsigned int ctm; // 棒时
double open; // 开价
double low; // 低价
double high; // 高价
double close; // 收价
double vol; // 量
};
在新的格式,RateInfo结构特征区域给存储传和交易值:
/---在新的终端版本中的标准报价表示:
struct RateInfo
{
INT64 ctm; // 时
double open; // 开 (absolute value)
double high; // 低
double low; // 高
double close; // 收
UINT64 vol; // tick量
INT32 spread; // 滑点
UINT64 real; // 成交量
};对了
因此,如果MQL4程序包含用于传递/接受价格数据的dll,则源代码中相应的函数应考虑格式更改而重写和重新编译,以确保正确操作。
旧的EX4应用程序和基于旧RateInfo格式的dll无法在新终端中工作。需要转换为新格式。
在文件操作中,同时打开的文件数量现在可达64个,而旧的MQL4中不可能超过32个。直到最近,文件总是以FILE_SHARE_READ或FILE_SHARE_WRITE模式打开。现在,应该以显式指定必要的打开模式。
对于FileWrite()、FileWriteArray()、FileWriteDouble()、FileWriteInteger()和FileWriteString()函数,返回值的类型已从int更改为uint。函数返回的字节数,实际上是写入的字节数,或者在出现错误时返回0 (在旧版MQL4中,出现错误时返回负数)。
在本地数组中使用函数、变量的范围和内存释放也进行了更改。由于更改的数量足够大,因此引入了新的#property strict属性,以提供与以前开发MQL4程序的方法的最大兼容性。当使用MQL向导创建新的MQL4应用程序时,该属性总是添加到模板中。
datetime类型的字符串表示取决于编译模式:
datetime date=D'2014.03.05 15:46:58';
string str="mydate="+date;
//--- str="mydate=1394034418" - 旧编译器/新编译器没有严格的#属性
//--- str="mydate=2014.03.05 15:46:58" - 带有#property strict的新编译
下表包含了MQL4、新版MQL4不使用严格的的和使用严格的编译模式的差别:
.#property strict
在严格模式下编译库时,应为每个导出函数添加导出修饰符,否则无法从外部访问该函数。
编译器之间的差异:
(旧版: Old MQL4 compiler
新兼: MQL4 compiler
新严:New MQL4 with #property stricti)
1
旧版:nit()、start()和deinit()入口点可能具有任何参数和任何返回类型
新兼:为了具有兼容性,init()、start()和deinit()保持不变,
新的OnInit()、OnStart()、OnCalculate()、OnTick()、OnTimer()、OnTimer()、OnChartEvent()、OnTester()和OnDeinit()函数应该严格地对应它们的命名
新兼:同样
2
旧版:运行时子系统不分析init()函数返回的结果
新兼:运行时子系统不分析init()和OnInit()函数返回的结果
新严:如果从OnInit()返回非零值,则停止EA或指标的操作,则卸载程序
3
旧版:几乎所有的变量名(除了保留的单词)都是可能的,包括特殊的字符和点
新兼:变量名不能有特殊的字符和点。
保留词的列表已经扩展。因此,诸如短、长、常量等广泛使用的单词不能用作名称
新严:同样
4
旧版:变量作用域是从声明(甚至是嵌套块)到函数结束
新兼:同样
新严:变量作用域是从声明到块的末尾,其中声明了变量
5
旧版:隐式初始化所有变量(全局变量和局部变量)为零
新兼:同样
新严:只初始化全局变量。在局部变量中,只有字符串是隐式初始化的
6
旧版:退出函数时不会释放本地数组
新兼:退出函数时会释放本地数组
新严:当退出{}块时会释放本地数组
7
旧版:“数组超出范围”不会导致严重错误"
新兼:同样,除了结构和类的数组,这个错误是非常重要的
新严:“数组超出范围”是导致程序停止的一个关键错误
8
旧版:没有结构和类
新兼:有结构和类。实现了其他数据类型
新严:同样
9
旧版:字符串是单字节。
datetime是一个32位整数
预定义的卷变量是双类型的
新兼:字符串是unicode的。
datetime是一个64位整数
预定义的卷变量是长类型的
新严:同样
10
旧版:ArrayCopyRates() 执行虚拟复制到double[][6] 数组
新兼:ArrayCopyRates() 执行虚拟复制到MqlRates[]数组. 复制到double[][6]数组 为了兼容性,复制是真实的,而不是虚拟的。
新严:同样
11
旧版:即使函数具有类型,它们也可能不返回值。为此,由编译器在函数端自动插入return(0)
新兼:同样
新严:任何类型的函数都应该返回一个值
12
旧版:同时打开的文件数量为32个
新兼:同时打开的文件数量为64个
新严:同样
13
旧版:文件总是以FILE_SHARE_READ、FILE_SHARE_WRITE模式打开
新兼:应该显式指定FILE_SHARE_READ和/或FILE_SHARE_WRITE
新严:同样
14
旧版:输入参数窗口中显示了用于脚本的extern变量的名称
新兼:输入参数窗口中显示show_input模式下的脚本的extern和输入变量的名称
新严:在输入参数窗口中,以show_input模式显示脚本的字符串注释而不是extern和输入变量名
请特别注意“Array out of range”(数组超出范围)的错误- 许多旧的自定义指标将显示这个错误在严格的模式下的新编译器时启动的图表。建议找出原因并消除它。
在新的MQL4和MQL5中,FILE_SHARE_READ和FILE_SHARE_WRITE标志负责文件共享使用模式。在旧的MQL4中没有这样的文件。
文件结构的变化
在旧MetaTrader 4客户端(509及更老版本)之前的构建中,所有MQL4应用程序都存储在\experts\ root directory的子目录中:
\experts ------专家顾问(交易机器人)
\experts\indicators ——定制指标,
\expert \scripts--------(单次运行在图表上的MQL4应用程序),
\include ---------源代码MQH和MQ4文件实现到其他程序,
\libraries ——以MQ4源代码和EX4可执行文件的形式编译的库。它们用于其他MQL4程序中包含的函数的动态调用,
\files -------特殊的“文件沙箱”。MQL4应用程序只允许在这个目录中执行文件操作。
而在新MQL4版本中,存储源代码的文件结构发生了更改。现在,所有MQL4应用程序都应该位于\MQL4\目录的适当文件夹中:
\专家-专家顾问(交易机器人)
\指标——自定义指标,
\脚本-脚本(MQL4应用程序在图表上运行一次),
\包含-源代码MQH和MQ4文件实现到其他程序,
\库——以MQ4源代码和EX4可执行文件的形式编译的库。它们用于其他MQL4程序中包含的函数的动态调用,
\图像-在资源中使用的图像文件,
\文件-特殊的“文件沙箱”。MQL4应用程序只允许在这个目录中执行文件操作。
当将MetaTrader 4终端从构建509更新到新版本时,前一个版本的标准根目录中的所有MQ4、MQH和EX4文件都会自动复制并重新定位到适当的文件夹中。用户额外创建的子文件夹,以及其中包含的文件则未被处理。如有必要,应手动将其移至新位置。
没有文件或文件夹删除期间更新! 所有文件复制操作,包括使用的文件路径,都在更新期间固定在终端日志中。
在更新期间,不会自动将旧的EX4文件重新编译到新版本。用户可以自主地决定哪些源代码应该编译到新的EX4版本。所有旧EX4将在新的metatrader4终端工作。新编译器编译的EX4库只能从新版本中编译的EX4程序中调用。
在某些情况下,您可能需要为源文件中包含的文件(如果相对路径已经更改)编辑#include中的路径。请注意MetaEditor的根目录现在是\MQL4\。所有程序都应该位于正确的子目录中。
您可以通过终端菜单或MetaEditor: File - Open data文件夹找到计算机上MetaTrader 4终端的每个副本的数据文件夹()。