3 MQL4语言基础

MetaQuotes Language 4 (MQL4)是一种新型的交易策略内置语言。用来编写交易策略的程序语言。这种语言可以创建你自己的智能交易, 使自己的交易策略能够完全地自动执行。程序内包含了分析历史报价的必备函数, 以及一些基本的运算法和逻辑操作和一些基本的指标和操作命令。 而且,MQL4 还能自定义自己的客户指标,脚本和数据库。

3.1 语法

MQL4 的语法类似于C语言,除了以下这些特点:

没有运算地址;

没有 do … while 语句;

没有 goto … 语句;

没有复合数据类型 (结构);

复合负值是不允许的,例如:val1=val2=0; cond=(cnt=5)>0;

逻辑表达式的计算完成前不可以提前终止。

3.1.1注释

注释的意义与用途:在程序中经常会对程序的功能进行备注,以便自己查看和编写程序;又或者在程序调试时我们需要屏蔽某些功能。这部分语言是不需要编译的。因此我们要告诉编译器这部分语言不做任何处理。此时就使用注释来达到此目的。

注释分为单行注释和多行注释。

单行注释使用: // 需要注释的语句

多行注释使用: /* 需要注释的语句 */

多行注释中可以嵌套单行注释。

示例:

① 单行注释:

// 单独注释

②多行注释:

/* multi-

line // 嵌入单行注释

comment

*/

3.1.2标识符

标识符用来给变量、函数和数据类型进行命名,也就是说标识符就是一个名字。长度不能超过31个字节你可以使用数字0-9、拉丁字母大写A-Z和小写a-z(大小写有区分的)还有下划线(_)。此外首字母不可以是数字,标识符不能和保留字冲突.

示例:

①NAME1

②namel

③Total_5

④Paper

3.1.3保留字

下面列出的是固定的保留字。不能使用以下任何保留字进行命名。

数据类型 储存类型 操作符 其他
bool extern break false
color static case true
datetime   continue  
double   default  
int   else  
string   for  
void   if  
    return  
    switch  
    while

3.2 数据类型

所有的程序都依靠数据来运作,数据因目的不同可以有不同的类型 。比如,访问数组可以用整型数据,价格可以用双精度的浮点型数据。在 MQL 4 中没有专门用来标记货币值的数据类型。

不同的数据类型有不同的处理速度,整型数据是最快的。 双精度的数据处理需要额外的处理器,所以处理浮点型数据比较复杂, 比处理整型数据慢一些。字符串是处理速度最慢的,因为它要存取动态内存。

主要的数据类型如下:

整型类型        (int)

布尔类型        (bool)

字符类型        (char)

字符串类型        (string)

浮点型类型        (double)

颜色类型        (color)

日期时间类型    (datetime)

colordatetime 可以使我们更清楚的区分图表中的内容,在 EA 和 指标中经常使用这些数据类型。颜色和日期时间数据用整数来表示。intdouble 都属于数值(数字)型。

3.2.1类型转换

表达式中使用强制的数据转换,转换时类型的优先级如下:

int (bool,color,datetime);

double;

string;

在运算完成之前(除了数据已被定义的),数据会根据优先级被转换。当定义数据的操作完成前 ,数据会转换成被定义的数据类型。

示例:

int
i = 1 / 2; // 没有类型转换,结果为 0

int
i = 1 / 2.0; // 表达式中有浮点型数据,但会转换成整型数据,结果为 0

double
d = 1.0 / 2.0; // 没有类型转换,结果为 0.5

double
d = 1 / 2.0; // 表达式计算的结果是浮点型数据,和定义的类型一样,结果为 0.5

double
d = 1 / 2; // 表达式是整型数据的计算,然后被定义为浮点型数据,结果为 0.0

3.2.2整型

十进制: 数字 0 – 9 ,包括负数。

示例:

12, 111, -956 1007

十六进制: 数字 0 – 9 , 字面 a – f 或者 A – F 代表 10 – 15; 以 0x 或者 0X 开头。

示例:

0x0A, 0x12, 0X12, 0x2f, 0xA3, 0Xa3, 0X7C7

整型数据占用 4 字节的空间,其数值范围介于
-2147483648 ~ 2147483647 之间。如果超出这个范围,则视为无效。

3.2.3字符类型

任何带单引号的单一字符或者十六进制的 ASCII 码如 ‘\x10’ 都是字符数据。一些特殊的字符如单引号(‘)、双引号(“)、问号(?)、反斜线(\)和控制符必须以反斜线开头(\), 组合表达原来的意思,如下表所示:

换行 NL (LF) \n

制表符 HT \t

回车 CR \r

反斜线 \ \\

单引号 ‘ \’

双引号 ” \”

十六进制ASCII hh \xhh

如果上述字符不使用反斜线,结果将不被定义:

int
a = ‘A’;

int b = ‘$’;

int
c = ‘?’; // 代码0xA9

int
d = ‘\xAE’; //货币对代码 ?

字符数据占用 4 字节的空间。其数值范围介于 0 ~ 255 之间。如果超出这个范围,则视为无效。

3.2.4布尔类型

Boolean 用来表示 是 和 否, 还可以用数字 1 和 0 进行表示。True和Flase可以忽略大小写。

示例:

bool
a = true;

bool
b = false;

bool
c = 1;

它的十进制表示一个长度为4-byte的整数值。Boolean 常数可以表示0 或 1值。

3.2.5浮点数(双精度)

浮点型数据由整数部分、小数点(.)和小数部分组成,其中整数部分和小数部分为一系列十进制数字。

示例:

double
a = 12.111;

double
b = -956.1007;

double
c = 0.0001;

double
d = 16;

浮点型数据 (双精度)占用 4 字节的空间。其数值范围介于 -1.7 * e-308 ~ 1.7 * e308 之间。如果超出这个范围,则视为无效。

3.2.6 字符串类型

字符串数据是带有双引号的一连串 ASCII 字符 ,如: “Character constant”。

字符串数据是引号里的一组字符,如果字符串中需要插入一个双引号(“) 必须在它前面使用反斜线(\)。任何特殊字符都必须有前置的反斜线(\)才能在字符串中使用。 字符串可以容纳 0 到 255 个字符,如果超过这个长度,右边多余的字符将被忽略,编译器也会有相应的警示。

示例s:

string a=”This is a character string”;
string b=”Copyright symbol \t\xA9″;
string c=”this line contains a line feed symbol \n”;
string d=”C:\\Program Files\\MetaTrader 4″;
string e=”A” ;
string f=”1234567890″;
string g= “0”;
string h=”$”;

字符串数据占用 8 个字节的空间。其中第一部分为长的整型存储字符串缓冲区分布的长度。第二部分是32位的存储字符串缓冲区的地址。

3.2.7颜色类型

颜色数据可以用三种方法表示: 字符数据、整型数据或者是颜色名(只能是 Web colors 中已命名的).

字符数据的表达方法是用三个数字来表示三种主要颜色:红、绿、蓝的比例。 以 C 开头,用单引号括住。数字的值在 0 ~ 255 之间按比例选取。

整数数据的表达方法使用十六进制或十进制数字。十六进制数字如 0x00BBGGRR, 其中 RR 是红色的比例,GG 是绿色的比例,BB 是蓝色的比例。十进制数不能直接体现红绿蓝的比例 ,而是十六进制数字的十进制表示方式。

特殊的颜色名可以参考表表2.2.3.1。

示例:

// 字符数据

C’128,128,128′ // 灰色

C’0x00,0x00,0xFF’ // 蓝色

// 颜色名

Red

Yellow

Black

// 整型数据

0xFFFFFF // 白色

16777215 // 白色

0x008000 // 绿色

32768 // 绿色

颜色数据占用 4 字节的空间。第一个字节一般被忽略,后三个字节包含了红绿蓝的组成信息。

lrBlack

clrDarkGreen

clrDarkSlateGray

clrOlive

clrGreen

clrTeal

clrNavy

clrPurple

clrMaroon

clrIndigo

clrMidnightBlue

clrDarkBlue

clrDarkOliveGreen

clrSaddleBrown

clrForestGreen

clrOliveDrab

clrSeaGreen

clrDarkGoldenrod

clrDarkSlateBlue

clrSienna

clrMediumBlue

clrBrown

clrDarkTurquoise

clrDimGray

clrLightSeaGreen

clrDarkViolet

clrFireBrick

clrMediumVioletRed

clrMediumSeaGreen

clrChocolate

clrCrimson

clrSteelBlue

clrGoldenrod

clrMediumSpringGreen

clrLawnGreen

clrCadetBlue

clrDarkOrchid

clrYellowGreen

clrLimeGreen

clrOrangeRed

clrDarkOrange

clrOrange

clrGold

clrYellow

clrChartreuse

clrLime

clrSpringGreen

clrAqua

clrDeepSkyBlue

clrBlue

clrMagenta

clrRed

clrGray

clrSlateGray

clrPeru

clrBlueViolet

clrLightSlateGray

clrDeepPink

clrMediumTurquoise

clrDodgerBlue

clrTurquoise

clrRoyalBlue

clrSlateBlue

clrDarkKhaki

clrIndianRed

clrMediumOrchid

clrGreenYellow

clrMediumAquamarine

clrDarkSeaGreen

clrTomato

clrRosyBrown

clrOrchid

clrMediumPurple

clrPaleVioletRed

clrCoral

clrCornflowerBlue

clrDarkGray

clrSandyBrown

clrMediumSlateBlue

clrTan

clrDarkSalmon

clrBurlyWood

clrHotPink

clrSalmon

clrViolet

clrLightCoral

clrSkyBlue

clrLightSalmon

clrPlum

clrKhaki

clrLightGreen

clrAquamarine

clrSilver

clrLightSkyBlue

clrLightSteelBlue

clrLightBlue

clrPaleGreen

clrThistle

clrPowderBlue

clrPaleGoldenrod

clrPaleTurquoise

clrLightGray

clrWheat

clrNavajoWhite

clrMoccasin

clrLightPink

clrGainsboro

clrPeachPuff

clrPink

clrBisque

clrLightGoldenrod

clrBlanchedAlmond

clrLemonChiffon

clrBeige

clrAntiqueWhite

clrPapayaWhip

clrCornsilk

clrLightYellow

clrLightCyan

clrLinen

clrLavender

clrMistyRose

clrOldLace

clrWhiteSmoke

clrSeashell

clrIvory

clrHoneydew

clrAliceBlue

clrLavenderBlush

clrMintCream

clrSnow

clrWhite

 

 

 

 

表2.2.3.1

3.2.8时间类型

日期时间数据由 6 个部分的字符组成:年、月、日、时、分、秒,以 D 开头, 用单引号括起。日期(年、月、日)或者时间(时、分、秒)甚至两者一起都可以不用填写。 日期时间数据开始于 1. 1. 1970 截止到12.31. 2037

示例:

D’2004.01.01 00:00′ // 新年

D’1980.07.19 12:30:27′

D’19.07.1980 12:30:27′

D’19.07.1980 12′ //等于 D’1980.07.19 12:00:00′

D’01.01.2004′ //等于 D’01.01.2004 00:00:00′

D’12:30:27′ //等于 D'[编译日期] 12:30:27′

D” //等于 D'[编译日期] 00:00:00′

日期时间数据占用 4 字节空间长度的整型数值。其值从1970年1月00:00开始以秒的形式显示总数。

3.3运算符&表达式

一些数字和字符的组合是特别重要的,它们被称为运算符,例如:

+ – * / %        算术运算符

&& ||        逻辑运算符

= += *=        赋值运算符

运算符应用在表达式中实现特定的作用。

需要特别注意标点符号如圆括号、方括号、逗号、冒号、分号。

运算符、标点符号、空格用来分割语句的不同部分。

3.3.1表达式

一个表达式可以拥有多个字符和操作符,一个表达式可以写在几行里面。

示例:

a++; b = 10;

x = (y * z) /

(w + 2) + 127;

一个表达式的最后是一个分号(;) 操作符。每个语句结束都必须有一个分号。

3.3.2算数运算符

算术运算符包括加法和乘法运算:

求和 i = j + 2;

求差 i = j – 3;

改变运算符 x = – x;

求积 z = 3 * x;

求商 i = j / 5;

求模 minutes = time % 60;

自加1 i++;

自减1 k–;

自加1和自减1的运算符不能使用在表达式中。

示例:

int a=3;

a++;
// 有效表达式

int
b=(a++)*3; // 无效表达式

3.3.3赋值运算符

表达式的值包括左边值给出的赋值运算符。

把变量 x 的值赋予变量 y y = x;

下列表达式中赋值运算符结合了算术运算符或位运算符:

在 y 值上加上 x                            y += x;

在 y 值上减去 x                            y -= x;

在 y 值上乘以 x                            y *= x;

在 y 值上除以 x                            y /= x;

在 y 值上求 x 的模                        y %= x;

把 y 值向右做 x 位逻辑移位                y >>= x;

把 y 值向左做 x 位逻辑移位                y <<= x;

AND 位运算符                            y &= x;

OR 位运算符                                y |= x;

把 x 和 y 按做逻辑异或的操作                y ^= x;

表达式中可以只能有一个赋值运算符。 位运算符只能用于整型数据。逻辑移位运算符中 x 值只能是小于 5 位的二进制数,过大的数值将会被拒绝。所以移动范围只能是 0 到 31 。 用 %= 运算符 ( 用x的模板求y值),其结果等于余数。

3.3.4关系运算符

逻辑值FALSE代表整数零值,逻辑值TRUE 代表不同于零的任何值。
用返回0(False)或1(True)来表示两个量之间的关系。

等于b                    a == b;

不等于b                    a != b;

小于b                    a< b;

大于b                    a >b;

小于等于 b                a <=b;

大于等于 b                a >= b;

2个不规范的浮点型数据不能用 = 或 != 运算符比较,但是我们可以把2者相减, 正常化后和 0进行比较。

3.3.5布尔运算符

否定运算符(!),用来表示真假的反面的结果。如果运算值是FALSE (0) 结果为TRUE (1);如果运算不同于FALSE (0)等于FALSE (0) 。

if(!a) Print(“不是 ‘a'”);

x和y值的逻辑运算符或OR (||)用来表示两个表达式只要有一个成立即可。如果x和y值为真的,表达式值为TRUE (1)。否则,值为FALSE (0)。逻辑表达式被完全计算。

if(x<0 || x>=max_bars) Print(“超出范围”);

x和y值的逻辑运算符AND (&&)。如果x和值都是真实的,表达式值为TRUE (1)。 Otherwise, it is FALSE (0).

if(p!=x && p>y) Print(“TRUE”);

3.3.6位运算操作符

运算符对操作数执行按位求补操作。表达式的数字值中包含1,其中n 包含 0和数字值中包含0 ,其中 n 包含 1。

b = ~n;

运算符x 向右移动到数字y 代表二进制代码。向右移动是逻辑运算,即左侧将被零填满。

x = x >> y;

运算符x 向右移动到数字y 代表二进制代码。左侧将被零填满

x = x << y;

二进制的x 和y代表位逻辑运算符AND 。在所有数组中x和y的值都不含有零表达式的值包含1 (TRUE);在所有其他数字中包含0 (FALSE)。

b = ((x & y) != 0);

二进制的x 和y代表位逻辑运算符OR。在所有数字中x和y的值都不等于零表达值包含1 并且在所有其他数字中包含0。

b = x | y;

二进制的x 和y代表位逻辑运算符EXCLUSIVE 。在所有数字中x和y的值都不同于二进制值表达值包含1并且在所有其他数字中包含0 。

b = x ^ y;

位逻辑运算符只作用于Integers类型。

3.3.7其他操作符

在数组第一元素的位置,表达式值为i的系列数变量值。

示例:

array[i] = 3; //给数组的第i个元素赋值为3。

只有整数能够成为数组元素。四维以上的数组是禁止的。每组的检测是从0 到 测量大-1。 特定情况下,对于一维数组由50 个元素组成,参照的第一个数组将为[0],这样最后一个数组将是[49]。

获取超出数组,将会发生常规错误 ERR_ARRAY_INDEX_OUT_OF_RANGE, 可以调用 GetLastError()
函数。

调用x1,x2,…,xn 自变数函数
每一个自变数可以显示一个常数,一个变量和相应类型表达式。自变数的通过必须根据通道命令。

用此函数返回表达式值。如果返回的表达式值为空,一些函数不能进行中转。请确认表达式x1,x2,…,xn 是按照命令执行的。

示例:

double
SL=Bid-25*Point;

Int
ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,SL,Ask+25*Point,”My comment”,123,0,Red);

标点操作符
从左到右的表达式用标点分开。所有表达式的计算是从左至右的。结果类型和值相互吻合,说明表达式是正确的。参量列表可以作为范例被通过。

示例:

for(i=0,j=99; i<100; i++,j–) Print(数组[i][j]);

3.3.8各运算符的优先级

面是从上到下的运算优先规则,优先级高的将先被运算。

() 函数调用 从左到右

[] 数组元素参考

! 真假运算符 从右到左

– 改变运算符

++ 增量

— 减量

~ 位逻辑运算符

& 位逻辑运算符 AND 从左到右

| 位逻辑运算符 OR

^ 位逻辑运算符 OR

<< 左移

>> 右移

* 乘法 从左到右

/ 除法

% 百分比

+ 加法 从左到右

– 减法

< 小于 从左到右

<= 小于等于

> 大于

>= 大于等于

== 等于

!= 不等于

|| 逻辑 OR 从左到右

&& 逻辑 AND 从左到右

= 值 从右到左

+= 加法值

-= 减法值

*= 乘法值

/= 除法值

%= 百分比值

>>= 右移值

<<= 左移值

&= 位逻辑运算符 AND值

|= 位逻辑运算符OR值

^= 位逻辑运算符 OR值

, 逗号 从左到右

注意:在MQL4程序中执行优先运算不同于在C 语言范围内的运算。

3.4操作符运算

语言操作符必须对执行完成任务的一些运算法操作进行描述。程序本身是这样的序列语句 。语句逐个随后以分号分离。

一个语句能占领一条或几条线。二个或更多语句可能位于同样线。单独执行命令的语句(if, if-else, switch, while and for) 可以相互插入

示例:

if(Month() == 12)

if(Day() == 31) Print(“赚钱快乐!”);

3.4.1复合运算

一个复合操作符有一个(一个区段)和由一个或多个任何类型的操作符组成的的附件{}. 每个表达式使用分号作为结束(;)。

示例:

if(x==0)

{

Print(“无效位置 x=”,x);

return;

}

3.4.2表达式操作

任何以分号(;)结束的表达式都被视为是一个操作符。这里是一些表达式操作符得范例:

赋值运算符:

Identifier=expression; //标识符=表达式,将表达式的值赋给标识符

x=3;        //将3赋值给x

y=3;        //将3赋值给y

y=x=3;     // 错误

函数调用运算符:

Function_name(argument1,…, argumentN);

FileClose(file);

空运算符
它是由分号(;)组成并且使用在一个检测运算符中。

3.4.3终止操作

一个嵌入break操作符终止最近外部操作符 switch, whilefor
的执行。在终止操作符之后给出检测操作符。这个操作符的目的之一:当中心值指定为变量时,操作符完成循环执行。

示例:

// 搜索第一个零元素

for(i=0;i<array_size;i++)

if((array[i]==0)

break;

程序意义:使用for循环检测数值中的元素,如果数组中的某元素的值等于0,那么退出for循环。

3.4.4继续操作

一个continue 继续操作符。 我们将其放在嵌套内的指定位置,用来在指定情况下跳过接下来的运算,直接跳入下一次的循环 while
或for
操作符。操作符 嵌入 位置与此操作符相反。

示例:

// 计算数组非零元素

int
func(int array[])

{

int array_size=ArraySize(array);

int sum=0;

for(int i=0;i<array_size; i++)

{

if(a[i]==0) continue;//如果a[i]等于0,后边语句不执行,直接跳转到for循环继续执行

sum+=a[i];

}

return(sum);

}

3.4.5返回操作

一个return将需要返回的结果放在return后面的()中。

示例:

int
CalcSum(int x, int y)

{

return(x+y);

}

在函数中省缺值类型被返回,此 return操作符必须使用:

void
SomeFunction()

{

Print(“Hello!”);

return; // 这个操作符被删除

}

函数正确的震动表示return操作符执行。

3.4.6条件操作 if-else

如果表达式为true,操作符执行并按照操作符2 给出的检测。如果表达式为false,操作符2 执行。

if (expression)

operator1

else

operator2

if操作符 else部分可能被忽略。 if操作符忽略 else部分,显示分歧可能会嵌入。这种情况下, else 位置在先前if操作符的最近部位,这样不会出现else部分。

示例:

// else 部分提及到第二个if操作符:

if(x>1)

if(y==2) z=5;

else z=6;

// else 部分提及到第一个if操作符:

if(x>l)

{

        if(y==2) z=5;

}

else        z=6;

// 嵌入操作符

if(x==’a’)

{

y=1;

}

else if(x==’b’)

{

y=2;

z=3;

}

else if(x==’c’)

{

y = 4;

}

else Print(“ERROR”);

3.4.7条件操作switch-case

在case全部变量和相应表达式值检测的操作符之内比较常数表达式值。每一个case变量会在整数或常数表达式内标注。常数表达式不包含函数变量调用。switch表达式操作符必须是整数类型。

switch(expression)

{

case constant: operators

case constant: operators


default: operators

}

如果在case操作符等于表达式值,操作符 default标签连接将会执行。此default 变量无需在最后。如果相应表达式值和 default变量没有获取,不会有任何执行。关键词case和常数被标注,并且if 操作符执行 case变量,程序将执行以下所有操作符直至break操作符生成。

一个常数表达式的计算是在编译期间。在一个switch操作符内部存在两个相同值的常数。

示例:

switch(x)

{

case ‘A’:

Print(“CASE A”);

break;

case ‘B’:

case ‘C’:

Print(“CASE B or C”);

break;

default:

Print(“NOT A, B or C”);

break;

}

3.4.8 while 循环操作

如果表达式为true, 操作符执行直至表达式变成false。如果表达式为false,将检测最近操作符。

while(表达式)

运算符;

在操作符执行前,一个表达式值已经被指定。不过,如果开始表达式为 false,操作符根本不会执行。

示例:

while(k<n)

{

y=y*x;

k++;

}

3.4.9 for 循环操作

用表达式1 Expression1来定义初始变量,当表达式2 Expression2 为真的时候执行操作运算符,在每次循环结束后执行表达式3 Expression3。如果true, 运算符 for 将被执行。循环重复直至Expression2变为false。如果false,循环将会被中断并且检测运算符文本。稍候执行。

for (Expression1; Expression2; Expression3)

operator;

此 for 运算符下列运算符成功:

Expression1;

while(Expression2)

{

operator;

Expression3;

};

使用for(;)可以造成一个死循环如同while(1)一样. 表达式1和表达式3都可以内嵌多个用逗号(,)分割的表达式。 <

示例:

for(x=1;x<=7;x++) Print(MathPower(x,2));

for(;;)

{

Print(MathPower(x,2));

x++;

if(x>10) break;

}

for(i=0,j=n-l;i<n;i++,j–) a[i]=a[j];

3.4.10函数

函数是部分程序的一个名称,它可以在需要时从任何一个部分调用。

函数是一系列表达式的合集,目的是完成某些工作。做成函数的目的是将某些需要经常重复使用的语句模块化在任何需要使用它的时候可以随时使用。

它是由定义分类返回值,名称,形式参量和合成运算符组成并执行的。函数名字被限定在64字符内。

示例:

double
// 被返回值的类型

linfunc (double x, double a, double b) // 函数名称和参量列表 {

// 合成运算符

return (a + b); // 返回值

}

将函数定义为double类型,函数返回时必须返回一个double型的数据。其中linfunc是函数名字。括号里是将要传递给函数的参数,可以没有,也可以有很多个,即使没有参数,也后边的括号也不能省略。这里我们称为函数的形式参数,称为形式参数是因为在这里只是定义了这个参数,并没有实实在在的传入任何数据。

“返回”运算符可以返回在这个运算符内表达式的值。如果需要,此表达式值可以转换为函数结果类型。函数没有返回的值必定是”省缺” 类型。

示例:

void errmesg(string s)

{

Print(“错误: “+s);

}

通过函数的参量可能存在由特定类型常数指定的默认值。

示例:

int somefunc(double a, double d=0.0001, int n=5, bool b=true, string s=”passed string”)

{

Print(“需求参量 a=”,a);

Print(“下列参量被传送: d=”,d,” n=”,n,” b=”,b,” s=”,s);

return (0);

}

如果此默认值指定一个参量,那么所有的参量也必须存在默认值。

错误范例:

int
somefunc(double a, double d=0.0001, int n, bool b, string s=”passed string”)

{

}

3.4.10.1函数调用

如果显示的文件没有描述, 它将考虑上下文的联系作为函数名称。

函数名称 (x1, x2,…, xn)

自变数(形式参量) 以值的形式通过。 计算每一个表达式 xl, . . . , xn 并将其值发送到函数。 表达式计算命令值是被保证的。在执行系统测试数字和自变数类型期间会给出函数。 这种形式的函数调用被称作调用值。调用函数是一个通过函数返回的表达式的值。 描述函数类型必须相应类型返回的值。全球范围内程序的任何一个部分函数是被公布或描述的,即其他函数之外。在另外函数里,函数不能被公布或描述。

例如:

int
start()

{

double some_array[4]={0.3, 1.4, 2.5, 3.6};

double a=linfunc(some_array, 10.5, 8);

//…

}

double linfunc(double x[], double a, double b)

{

return (a*x[0] + b);

}

函数的调用是默认参量,通过参量的列表是被限定的,但不是之前的第一默认参量。

例如:

void
somefunc(double init,double sec=0.0001,int level=10); // function prototype

somefunc(); // 错误调用, 第一请求参量必须存在。

somefunc(3.14); // 正确调用

somefunc(3.14, 0.0002); // 正确调用

somefunc(3.14, 0.0002, 10); // 正确调用

当我们调用一个函数时,不可以忽略参量,存在默认值:

somefunc(3.14, , 10); // 错误调用。第二参量被忽略。

3.4.10.2特殊函数

在MQL4中存在三种预定义名称函数:

init() 在载入时调用,可以用此函数在开始自定义指标或者自动交易之前做初始化操作。

start() 是基本函数。对于智能交易,在下一个替克进入之后被调用。对于客户指标,在指标添加到图表之后,客户端开始(如果指标添加到图表)并且下一个替克进入之后,函数被调用。对于脚本,在脚本被添加到图表之后立即执行并初始化。如果在模板中不存在start()函数,模板 (智能交易,脚本或客户指标) 不能开启。

deinit() 当数据变动时触发,对于自定义指标或者自动交易的编程主要依靠此函数进行

预定义函数需要一些参量。不过,当这些参量被客户端调用时,外部没有参量提供。 start(), init()和 deinit()函数从模板的任何一点按照常规调用,等于其他函数。

不建议从init()函数调用 start()函数或是执行交易业务,作为图表数据,市场开价格。模板的初始化会出现残缺。这时,init() 和 deinit() 函数必须尽可能结束运行。在调用start()函数之前,尝试重新全面开启运行。

3.4.11变量

可变量必须在公开之前使用。 可变量必须拥有特殊的辨认名。相关可变量的定义描述会显示。

基本类型如下:

布尔数据 -布尔值的true 和 false;

字串符数据 – 特殊字符串;

双精度数字 – 带有浮点双精度数字。

示例:

string MessageBox;

int Orders;

double SymbolPrice;

bool bLog;

附加类型:

颜色 为整数代表RGB 颜色;

日期时间 为日期和时间, 起始时间从1979年1月上午0.00开始以秒数计算。

添加数据类型在输入参量的属性窗口方便查看。

示例:

datetime tBegin_Data = D’2004.01.01 00:00′;

color cModify_Color = C’0x44,0xB9,0xE6′;

数组

相同数列数据被标注序列。

int a[50]; // 50整数的一维数组

double m[7][50]; // 7个数组的二维数组


//每一个由50 个整数组成。

唯一整数可以是数组指数。不允许四唯数组。数组元素开始编号为0 。 一个一维列阵的最后元素是数组大小减1。这就意味着, 请求数列的最后元素包括50 个整数将出现作为a[49 ] 。 维度被标注从0 到维度大小-1. 一个二维数组的最后元素从示例将出现作为m[6][49 ] 。

如果访问超出数列范围, 执行系统将发生错误可能生成错误 ERR_ARRAY_INDEX_OUT_OF_RANGE,在GetLastError()函数中可以得到。

3.4.11.1局部变量

局部变量可以简单的理解为在函数内定义的变量,且只能用于该函数内部。 每次函数的运行只可以初始化一个局部变量。局部变量储存在相应的存储器上。

示例:

int somefunc()

{

int ret_code=0;

….


return(ret_code);

}

3.4.11.2 形式参数

通过函数的变量 是局部的。范围是在作用块内。在作用之内正式变量的名称必须不同于其他外部定义变量和函数变量。 作用块内的正式变量值已经被赋予。

示例:

void func(int x[], double y, bool z)

{

if(y>0.0 && !z)

Print(x[0]);


}

正式参量可能由常数初始化。在这种情况下, 初始化的值作为缺省值被考虑。参量, 在旁边(intialized) , 必须初始化。

示例:

void func(int x, double y = 0.0,
bool z = true)

{


}

这样作用显现时, 初始化的参量可能被省去, 缺省值会代替它们。

示例:

func(123, 0.5);

MQL4 资料库功能在外部函数变量 模块之内无法有默认值初始化。

参量值通过。在任何情况下,变量里布局的修改将不会显示在功能板块内。 它是可以通过数列作为参量。但是, 为了数列可以作为变量,需要改变它的数列元素。

它是还可能通过参量参考。在这种情况下, 修改的这样参量将被显示在对应的变量。 数组元素无法参考通过。参量可能只在一个模块参考通过, 数据库不提供。

示例:

void func(int& x, double& y, double& z[])

{


double calculated_tp;


for(int i=0; i<OrdersTotal(); i++)

{

if(i==ArraySize(z)) break;

if(OrderSelect(i)==false) break;

z[i]=OrderOpenPrice();

}

x=i;


y=calculated_tp;

}

数组可以通过参考通过, 全部改变会在数列来源内显示。 不同于简单的参量, 数组可以进入数据库…

以缺省值参量通过无法初始化。

最大参量不可以超过64个。

3.4.11.3静态变量

“静止” 记忆被称作静态变量。在数据类型之前指定成分”静止” 被公开。

示例:

int somefunc()

{


static int flag=10;

….

return(flag);

}

静态变量被存放在永久记忆里,在函数退出后静态变量不会丢失。所有在同一板块内(除正式变量作用外),可能作为静止变量定义。 静态变量可以由相对应的类型常数初始化。 与局部变量不同。如果没有明确地初始化, 静态变量初始化以零。 静态变量在”init()” 函数之前只可应用一次。

3.4.11.4全局变量

整体变量作为函数被定义在相同水平,即,不可以局部使用。

示例:

int GlobalFlag=10; // 全局变量

int start()

{


}

整体变量的范围是整个程序。整体变量在所有程序内是被定义的。 如果它的值没有被定义,初始化值为零。 整体变量只对于相应的常数初始化。 整体变量只可以在init()函数操作之前一次性初始化。

注解: 变量在整体变量的水平位上不能够与客户端GlobalVariable…() 函数混淆。

3.4.11.5外部定义变量

外部定义的可变量。 在数据类型公布之前指定外部变量。

示例:

extern double InputParameter1 = 1.0;

extern color
InputParameter2 = red;

input double InputParameter3 = 1.0;

input color
InputParameter4= red;

int init()

{


}

确定从外部程序输入的变量, 会直接显现输入数据窗口。数列本身不能作为外部变量。

使用extern定义的外部变量在程序中可以重新赋值,使用input定义的外部变量在程序中不能重新赋值。

3.4.11.6变量初始化

任何情况定义可变物可以初始化。如果它的原始值未被限定,任何可变物初始化为零(0)。 整体变量和静态变量的初始化由相应的常数进行。

整体变量和静态变量只能一次性初始化。局部变量的初始化与相应的调动进行。

示例:

int n = 1;

double p = MarketInfo(Symbol(),MODE_POINT);

string s = “hello”;

double f[] = { 0.0, 0.236, 0.382, 0.5, 0.618, 1.0 };

int a[4][4] = { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };

数组元素值列表必须被附寄在括号内。初始化省去的值被考虑为零。 如果初始化的数组大小不被定义, 它将由编译器定义 。多维数组由一个一维序列, 即序列初始化没有另外的括号。所有数列, 只能以常数初始化

3.4.11.7 外部定义函数

类型外在作用被定义在程序的其它组分必须明确地被描述。 缺乏这样定义也许导致错误在程序期间的编辑、联结, 或施行。当描述一个外在对象, 主题词进口必须被使用以在模块的参考。

示例:

#import “user32.dll”


int MessageBoxA(int hWnd ,string szText,string szCaption,int nType);


int SendMessageA(int hWnd,int Msg,int wParam,int lParam);

#import “lib.ex4”


double round(double value);

#import

进口可能被使用容易地描述作用叫从外在DLLs 或编写EX4 函数库。

尖对可变物可能通过对进口的dll作用。串类型的数据 被通过作为尖对对应的记忆块(你应该记住串数据的内部表示法包括二份: 记忆块长度和记忆阻拦尖) 。如果有需要通过数据内部或双重型, 那么对应的型的一维一些应该参考通过作为参量。

示例:

#import “some_lib.dll”


void PassIntegerByref(int& OneInt[]);

#import

int start()

{


int array[1];

//…

PassIntegerByref(array);

Print(array[0]);

//…

}

3.4.12预处理程序

预处理程序是一个特殊MQL4的子程序,在程序执行之前预先准备的程序源代码。

预处理程序会尽可能地读取源代码。代码的结构可能包括MQL4 程序源代码的特殊文件。 对于读取的代码尽可能地按照具体常数分配储存。

预处理程序允许MQL4 程序参量指定。

如果# 标志被使用在程序的第一线, 这条线是预处理程序方针。预处理程序方向末端以换行字符结尾

3.4.12.1常数声明

使用#define定义常数可以在程序中指定货币对字串符并且定义货币对名称或货币对常数。 稍候,编辑器会按照相应的字串符名称还原所有显示。事实上,这些名称可以由任意数组文本替换:

#define identifier value

此常数识别符符合变量名称的规则 值可以是以下任意类型:

#define ABC 100

#define PI 0.314

#define COMPANY_NAME “MetaQuotes Software Corp.”



void ShowCopyright()


{

Print(“版权所有 ? 2001-2007, “,COMPANY_NAME);

Print(“http://www.metaquotes.net”);

}

3.4.12.2编译控制

每个MQL4 程序允添加以#property名称特殊的参量来帮助客户端服务。这是一个内设指标。

#property 识别值

常数 类型 描述
link string 公司网站的相关连接
copyright string 公司名称
stacksize int 栈式储存器大小
library   资料库;查看任何可出现的功能错误
indicator_chart_window void 在图表窗口显示指标
indicator_separate_window void 在指定窗口显示指标
indicator_buffers int 对于指标计算的数字,最大为 8
indicator_minimum double 在指标窗口下端
indicator_maximum double 在指标窗口的上端
indicator_colorN color 在1和8之间显示线的颜色
indicator_widthN int 在1和8之间显示线的宽度
indicator_styleN int 在1和8之间显示线的风格
indicator_levelN double 在客户指标窗口1和8之间N的水平
indicator_levelcolor color 水平线颜色
indicator_levelwidth int 水平线宽度
indicator_levelstyle int 水平线风格
show_confirm void 在脚本运行之前显示确认
show_inputs void 在脚本运行之前显示它的属性和确认

示例:

#property link “http://www.metaquotes.net”

#property copyright “MetaQuotes Software Corp.”

#property library

#property stacksize 1024

在执行模板设定时,编译器将会写入值。

3.4.12.3头文件包含

#include 命令可以放置到程序的任意部分,但是通常所有文件的源代码被统一放置。调用格式;

#include <file_name>

#include “file_name”;

示例:

#include <WinUser32.mqh>

#include “mylib.mqh”

对于 WinUser32.mqh.文件内容预处理程序还原线。三角括号表示WinUser32.mqh文件将会从默认目录调用(通常默认目录 terminal_directory\experts\include)。不需要搜索当前目录。

如果载开盘价栏内文件名称未锁,搜索将在当前目录中执行(加载的源代码主文件)。 不需要搜索标准目录。

3.4.12.4函数导入

函数从MQL4 编译模板 (*.ex4 文件) 和执行系统文件模板(*.dll文件)通过。模板名称被指定在#import指令中。来自输入函数和通过参量的兵役数据需要带有完整的描述部分。函数描述会立即按照#import “模板”名称执行。新的#import 命令完成引入输入函数描述部分。

#import “file_name”

func1 define;

func2 define;


funcN define;

#import

输入函数必须有自己的名称。相同名称的函数无法从不同的模块同时引入。引入的函数名不能与那些内部函数融合。

因为引入函数是在模块外面被编写, 编译器无法检查通过参量的正确性。这就是为什么, 避免运行错误, 它是必要精确地公开命令的原因。在参量引入函数(从EX4 和从DLL 模块)后, 没有任何值。

示例:

#import “user32.dll”


int
MessageBoxA(int
hWnd, string
lpText, string
lpCaption, int
uType);

#import “stdlib.ex4”


string
ErrorDescription(int error_code);


int
RGB(int red_value, int green_value, int blue_value);


bool
CompareDoubles(double number1, double number2);


string
DoubleToStrMorePrecision(double number, int precision);


string
IntegerToHexString(int integer_number);

#import “Expert示例.dll”


int
GetIntValue(int);


double
GetDoubleValue(double);


string
GetStringValue(string);


double GetArrayItemValue(double arr[], int, int);


bool
SetArrayItemValue(double& arr[], int,int, double);


double GetRatesItemValue(double rates[][6], int, int, int);


int
SortStringArray(string& arr[], int);


int
ProcessStringArray(string& arr[], int);

#import

在mql4 程序执行期间引入输入函数,需要使用稍后安装。 这就意味着直到调用输入函数,相应模板(ex4 或 dll)将不会进行加载。

不建议使用Drive:\Directory\FileName.Ext为文件名安装。MQL4 资料库会从 terminal_dir\experts\libraries 文件夹中卸下。如果没有发现资料库,则没有可能从 terminal_dir\experts文件夹中卸下

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注