Continued
输入变量是MQL5中仅有的,可供用户修改数值的变量。这些变量可由交易配置,指示器配置,止损收益配置等等组成。这些变量展示在程序的属性窗口。
输入变量由input关键字声明。放置在程序顶部,在所有程序代码和任意函数之前定义。输入变量可以是任意类型,包括枚举。但是数组和结构体不能用于输入变量。输入变量命名应遵循整洁,富有描述性的特点。
下例是一些EA程序中的输入变量:
input int MAPeriod = 10;
input ENUM_MA_METHOD MAMethod = MODE_SMA;
input double StopLoss = 20;
input string Comment = "ea";
上述输入变量设置周期,移动平均线的计算方法,设置了订单的止损价和描述信息。
静态输入变量可以用sinput关键词声明。静态输入变量的值可以修改,但是在策略测试中不可优化。静态输入变量仅在输入参数的逻辑组合上有些意义。
sinput string MASettings; // 移动平均值设置
输入变量使用枚举,你得先定义枚举,然后再定义input并使用枚举的值。因为程序是顺序执行的,上面的先执行,线面的后执行。所以你应该知道所有变量,都得是“先定义,再使用”。这是铁律。
enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
};
input DayOfWeek Day = Monday;
,很人性化啊,定义输入变量为枚举类型后,在程序属性窗口,这个输入变量的值,可-以-下-拉-选-择!
本地变量,或局部变量,是定义在一个function内的变量,函数首次运行时,分配内存空间。函数一旦退出,变量也就从内存中销毁了,这很好理解。临时用的,用完就丢弃了。
比如我们写一个无用的函数如下:
void bsh()
{
int lvInt = 34;
Print(lvInt); // 输出34
}
变量lvInt仅在bsh函数内使用,函数执行完毕,就丢弃了。
让我们通过例子,再次近距离地看看,局部变量的“作用域”。
void myFunction()
{
bool varBool = true;
if(varBool == true)
{
int varInt = 5;
Print(varInt); // = 5
}
}
变量varBool先声明为布尔类型,=true。下面用if语句判断==true,这当然是成立的。于是进入if语句内执行。先声明了varInt整型并赋值=5,接着Pirnt打印varInt的值。我们稍作修改:
void myFunction()
{
bool varBool = false;
if(varBool == true)
{
int varInt = 5;
}
Print(varInt); // 找不到变量
}
varBool = false,if语句不执行,那么变量varInt就不能被声明,也就是分配不了内存。下面执行Print语句的时候自然也就找不到该变量。“先定义,再使用”,大家印象深刻了吗?
再把例子修改一下:
void myFunction()
{
bool varBool = true;
if(varBool == true)
{
int varInt = 5;
}
Print(varInt); // 找不到变量
}
注意,这也不能运行。为什么?因为变量varInt是在if语句内定义的,if语句之外,不是其作用域。那样怎么改?
void myFunction()
{
bool varBool = false;
var varInt = 7;
if(varBool == true)
{
varInt = 5;
}
Print(varInt); // =7
}
你看,进入函数之后,先把变量声明好,下面用判断语句了,循环语句了,游刃有余,可以随意使用,再也不担心了。所以,养成一个良好的书写习惯很重要哦。
还有一点很关键,必须说一说,一个函数体内,不同作用域,如果声明了同一变量,我们看看会有什么神奇的事情发生:
void myFunction()
{
bool varBool = true;
int varInt = 7;
if(varBool == true)
{
int varInt = 5;
Print(varInt); // 输出: 5
}
Print(varInt); // 输出: 7
}
先定义了varInt = 7,接着if语句内又定义了一次,值居然改变了。跳出if之后,值居然又回来了!这是什么情况?这不是最佳实践,我们也不会这样用。编译的时候会抛出:“declaration of 'varInt' hides local declaration...”。像if语句内,如果真有需要,不要再定义重名的变量了,改一改名吧,这不费劲!
这些程序分析起来简直繁琐的不要不要的。可以,大多数现代的编程语言,都是这么规划变量作用域的。MQL5遵循了这一“优秀设计”!
不过MQL4的用户可能不填习惯了,因为MQL4的局部变量,无论定义在函数的那个地方,函数体内均有效!这个不同之处,希望大家清楚。
全局变量定在在任意函数体之外,位于程序顶部,一般位于输入变量下方。这个程序内均可放心使用。
全局变量重复定义了怎么办?没有意义,换个名字,不要重名,加前缀,后缀都行。
全局变量在整个程序内均可修改值:
// 全局变量
int i= 5;
// 此处我们假设fa()先调用
void fa()
{
i= 7;
}
// 此处我们假设,fb()后调用
void fb()
{
Print(i); // 输出: 7
}
我们假设fa()先调用,将全局变量i的值修改为了7.那么别的地方在用,它就是i=7。全局可修改,可访问。
静态变量是局部变量,程序运行到退出了该变量的作用域,也能驻留在内存。举例说明。我们声明一个函数,用于自加:
void incr()
{
static int sv = 0;
sv++; // 自加1
Print(sv); // 输出: 1, 2, 3, 等等.
}
我们多次调用这个函数,那么静态变量sv每次自加1。依次递增上去。为什么?为什么没有在进入函数的时候执行初始化?这是static静态类型决定的。函数退出了,sv还在内存里呢!再次进入函数,直接拿来就开始用了。
MQL5内有许多预定义的变量,可供全局使用。这些变量有个共同点,是以下划线开头。这些变量在程序内到处都是,可是程序依然那么好读。
预先定义变量的值在MQL5程序启动之前通过客户端建立,预先定义变量是不变的,也不会通过MQL5程序转变。例外是,特殊变量_LastError,通过ResetLastError函数重设至0。
_AppliedTo _AppliedTo变量可以找出用于指标计算的数据类型
_Digits 小数位数字
_Point 在引用货币中当前交易品种的大小
_LastError 最后的错误代码
_Period 当前表格的时间表
_RandomSeed 假随机整数生成器的当前状态
_StopFlag 停止标记程序
_Symbol 当前图表的交易品种名称
_UninitReason 阻止初始化原因代码
_IsX64 _IsX64变量可以找出运行MQL5应用程序的程序端的位元版本
第二章结束