MQL4课程前言

在做这门课之前我想了很多,想如何把这门课完整地教给大家,以便大家在做外汇交易时可以方便地将自己的策略实现,同时又不会那么复杂难懂,最后还是觉得毕竟这是一门用于实践的计算机语言的课,所以也没有必要从最基础的计算机开始讲起了。本课将着重偏向于实战,从最基础的MQL语法讲起,对于一些有基础的同学前面一部分相信会比较简单,对有MQL4编程经验的同学可以跳过。虽然有些枯燥,但是要想开始打怪升级总是要先进行无味的修炼。

之后这门课会教大家如何去编写一些有用的脚本、EA之类的程序并与大家探讨交易系统。注意这门课仅仅只是一个引子,量化交易的世界非常大,趋势追踪、剥头皮、高频交易、神经网络、时间序列分析等等,每一块内容都值得去深入探索开发,相信这门课会把大家带入MQL4量化交易的大门中。

当然未来的路还是需要自己去探索的,量化交易者的目标是拿到那传说中的圣杯,虽然它是飘渺虚无的,在途中你会经历自己花了无数心血编写的交易系统测试后有盈利能力的狂喜,也会经历程序用于模拟盘测试后表现不佳的失落,甚至会经历用于实盘后爆仓的绝望,但是在不断地追逐过程中,你会一点点发现圣杯的蛛丝马迹,不要停下,直到将自己变成自己的圣杯。

第一节 MQL4基础知识介绍

1.编辑器界面介绍

工欲善其事必先利其器,MT4是一款非常方便的交易软件,其内置的MQL4语言也是量化的利器。首先让我们看看这把利器放在哪儿:



如图,点击红框中的按钮进入编辑器,进入编辑器后的界面以及对该界面的一些简介如下图。



我们点击左上角的新建按钮(参考下图)以新建一个脚本。步骤如下图:



于是我们新建了我们的第一个脚本,如下图:



上面的几个函数如下,代表了该脚本的属性,从上到下的意思分别是该脚本所属的公司,网站,版本号,以及编译方式,除了编译方式之外其他的内容可以不考虑,关于strict编译方式与普通编译方式有何不同将在未来提到,因此这一部分我们可以忽略。


#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict


接下来是非常重要的OnStart函数,这个函数只在脚本加载以后运行一次,与其同样重要的还有OnInit函数、OnDeinit函数、OnTick函数,这几个函数是组成EA最基础的三个部分,另外OnCalculate函数是组成指标的最基础的函数,这几个函数将在以后的课程中介绍。

现在我们有了第一个脚本,但是我们还没有写任何东西进去,就像一张白纸。接下来在我们在这张白纸上画画之前,先了解一下画画的基本内容。

2.数据类型和变量

2.1数据类型

我们采用程序进行交易,往往是要定义一系列变量的,那么计算机是如何识别我们定义的变量的?一般来说,计算机会将变量大体区分为整数类型、浮点型、布尔型以及字符串,另外MQL语言增加了两种类型分别是时间变量类型datetime以及颜色变量类型color,变量的定义可以参考下面的语句:


void OnStart()
  {
      int a=1; //长整数类型,定义范围为-2147483648~2147483647
      char b=1; //短整数类型,定义范围为-128~127
      uchar c=1; //短整数类型,定义范围为0~255
      short d=1; //中整数类型,定义范围为-32768~32767
      ushort e=1; //中整数类型,定义范围为0~65535
      uint f=1; //长整数类型,定义范围为0~4294967295
      long g=1; //长整数类型,定义范围比int更大,为
		-922337203685477808~9223372036854775807
      ulong h=1; //长整数类型,定义范围为0~18446744071709551615
      double i=123.1; //双精度浮点型,15位有效数字
      float j=11.005f; //单精度浮点型,6位有效数字,一般不用
      bool k=true; //布尔型,只有true和false两个值
      string l="Lesson 1"; //字符串型
      datetime m=D'2016.09.23 00:00:00'; //时间类型
      color n=clrAntiqueWhite; //颜色类型;
  }


可以看到整数的类型有很多,这主要是为了节约数据占用的字节(存储空间)。我们每声明一个变量,都需要在计算机中有地方存储,而计算机存储的最小单位就是字节。比如char和uchar类型的数据只占1个字节,而short类型则占2个字节,int类型占4个字节。对于K线来说,有时候需要存储K棒的数量,而K棒数量动辄几十万根,超过了短整型和中整型的范围,会造成数据的溢出报错,所以一般情况下我们用占用的字节较少而范围满足要求的int来定义就可以了。注意整数类型只能定义整数,无法定义小数。

布尔类型仅有两个值,真值true和假值false,一般布尔型用在逻辑判断上,判定是否满足某个条件,其中true也可以用1代替,false可以用0代替。

字符串类型用来存储字符串,大家都知道计算机只能识别”0”和”1”,是无法直接识别你输入的一句话的,为了让计算机识别字符串,将字符串进行了编码,这就是字符串类型能达到的功能。

浮点型用于存储小数,单精度float类型和双精度double类型区别在于存储的小数的有效数字不同,float类型只能存储6位有效数字,占4个字节,而double可以存储15位,占用8个字节。为了方便价格的存储,一般选用double类型。

日期时间型变量定义的开始时间是1970年1月1日,如果不采用如上的定义方法而直接输入数字x,那么得到的时间是从1970年1月1日起经过x秒后的日期。日期时间变量可以拆分,可以只要年月日,也可以只要时分秒。

关于颜色类型,可以打开帮助中的MQL4帮助文件,搜索“clrAliceBlue”查找更多的颜色,如下图:



以上就是变量的一些基础知识,现在我们来看一下我们的定义有没有用,我们可以通过Print函数来输出我们的结果,注意Print函数中P是大写,代码如下:


void OnStart()
  {
      int a=1;
      Print("a的数值为"+(string)a);
  }


以上代码中,Print函数输出字符串类型,所以可以将整数类形的a转变成字符串类型再用Print函数输出,在其前面加上“(string)”即可将其转换。

编译脚本后我们回到MT4的页面,双击编好的脚本,如下图,可以看到运行脚本后输出了“a的数值为1”,所以我们的定义是没有问题的。其他的类型可以自己编写输出,在此不赘述。



2.2变量的命名

变量的命名有一套规范,一般来一个变量的名字可以由以下几个类型组成:

1.字母或汉字,MQL4支持汉字,但是不建议使用中文,有时会出现错误;

2.数字;

3.下划线

注意变量中必须要有字母或汉字

2.3全局变量与局部变量

所谓全局变量,即该变量在任何子函数中都可以用的变量,而局部变量只能用于当前函数中。全局变量的写法如下:


int a=1;
void OnStart()
  {
      int b=2;
      Print("a的数值为"+(string)a);
      Print("b的数值为"+(string)b);
  }


当变量在任何函数开始前就被定义了,这样的变量即为全局变量,如上面的变量a。而在函数中定义的变量即为局部变量,如上面的变量b。

3.运行表达式和操作运算符

3.1运算符

运算符包括算术运算符如加减乘除,关系运算符如大于、等于,布尔运算符与、或、非,赋值运算符和迭代运算符,关于运算符不做详细的介绍,以下的代码是各运算符在MQL4中的应用,可以参考。

void OnStart()
  {
      int a=1; 
      int b=1; 
      b=2; //赋值运算;
      b=a*b+a/b+a-b; //加减乘除运算;
      bool c=true; 
      bool d=false; 
      bool e=a && b; //与运算;
      e=a || b; //或运算;
      e=!a ; //非运算;
      a++; //迭代运算;
      Print("a的数值为"+(string)a);
  }


3.2关系运算式

关系运算式用来判断两个变量之间的关系,如大于号小于号等,如下:


void OnStart()
  {
      int a=1; 
      int b=2; 
      if(a<b)
      {
      		Print("b更大");
      }
      else if(a==b)
      {
      		Print("a与b相等");
      }
      else
      {
      		Print("a更大");
      }
  }


以上的代码的意思是比较a和b哪个更大,如果a更大则输出“a更大”,如果b更大则输出“b更大”,相等则输出“a与b相等”。

注意在判断两个变量是否相等时用的符号是”==”,若只有一个等号是代表赋值。

4.MQL4错误警告及检查

在编程过程中免不了会有很多错误,如何高效排除错误可以帮我们省去大量的时间。

当程序编译出现问题时,我们可以在下方的错误和警告栏找到发生错误的位置,如下图所示,在右侧我们可以看到发生编译错误的行和列,在下方能看到错误的内容。这里的错误是”’w2’-undeclared identifier”,意思是没有对w2这个变量进行定义,只要定义w2即可。



编译没有问题了,但是有时也会在运行时出现错误,可以在EA一栏中找到错误的记录,如下图所示:



可以看到上图有一个错误是“zero divide in “hudge indicator.mq4””,这个错误的意思是在hudge indicator.mq4这个文件中出现了除以0的情况导致程序无法执行下去而中断了。

有时程序不会提示错误的详细内容,而会显示一个错误代码,这时我们可以在MQL4帮助文件中查找ERR来查找错误代码对应的错误编号,如下图:



这里的错误就不一一讲了,如果出现错误,别忘了可以在帮助文件中查找。

另外,有时我们会碰到没有任何警告或错误,但是程序并没有按照我们的预期来运行,这种情况总是特别麻烦,因为不知道错误出在哪里,此时我们需要一块一块地检查我们的程序逻辑是不是有问题,可以分段来打印程序的输出来检查哪里的输出不符合我们的预期来检查程序的错误,当然也可以采用添加断点的方式来检验某一段程序。

双击行号可以添加程序断点,如下图的第87行和90行,添加断点后按F5进入调试模式,然后按F11可以一步一步清晰地看到程序执行的步骤。一般来说调试模式用于调试循环语句。



下面再说几个编程时常犯的错误:

1.语句中忘记在结尾加“;”号;

2.已经定义的变量在同一个函数中再定义了一次;

3.在子函数中定义的变量名字与全局变量重名;

4.在逻辑判断时需要用“==”两个等号,但是只用了一个等号“=”;

以上是本节课程的内容,这节课中我们知道了MQL4的一些基础的知识和操作,知道了如何去排错,下节课将介绍MQL4的一些常用语句。


更多内容请关注公众号【火象】~