程序运行
如何使程序运行
想让MQL4程序运行起来,须对它进行编译(按“编译”按钮或F5键)。
在编译过程中不允许出现任何错误(可以有警告提示,但须对它进行分析)。
编译成功后,将会在相应的目录中,自动创建一个扩展名为.EX4的可执行文件,只有创建了相应的.EX4文件,MQL4程序(EA,脚本,自定义指标)才能够被用户运行起来。
用鼠标把EA、自定义指标和脚本从“导航”窗口拖到相应图表上(拖曳技术)即可。MQL4程序只有在客户端已启动的基础上才能运行。
要停止EA,须从图表的菜单中删除它(智能交易系统-取消)。
“启用智能交易”按钮状态将会直接影响智能交易的运行。
要使自定义的指标停止,直接从图表上删除。否则会一直运行着。
EA和自定义指标的信息在客户端启动之时保存于客户端内。
脚本操作完成后,如果当前图表被关闭或其状态己发生改变,或当客户端中断运行时,脚本都只执行一次任务,并被自动删除掉。
由于不保存运行状态信息,当客户端再次重启时脚本并不自动运行。
在同一个图表内,智能交易、脚本和更多数量的指标可以同时运行。
程序运行过程
初始化
程序附加到图表之后,它立即开始与初始化函数init()协同运行。
在客户端开始运行和历史数据(仅与EA有关,与指标无关)被另外加载之后、当货币对和图表时段改变了、在MetaEditor里重新编译之后、或者从智能交易或自定义指标的设置窗口改变了输入参数,附加到图表上的EA和自定义指标中的init()函数将会运行。当计算结果发生变化时,智能交易同样也会被初始化。
反初始化
每一个附加到图表上的程序可以借助反初始化函数deinit()完成善后工作。当客户端关机、关闭图表、在改变货币对或改变时框之前、程序重编译成功、改变参数输入或计算结果,deinit()函数都会运行。该deinit()函数执行期间,用户可使用UninitializeReason()函数查看未初始化成功的原因。
deinit()函数必须在2.5秒内执行完毕,如果函数在这段时问内没有完成它的工作,则将会被强制结束。而脚本是这一条规则的例外,因为它们能正常地自主完成它们的工作,其运行不取决于任何外界的命令。如果一个脚本工作时间过长(比如永无止境的死循环),用户可以应使用外部命其结束运行(从图表的上下文菜单中删除脚本、在原有的图表上添加新的脚本、改变图表的货币对或时框)。 在这种情况下,deinit()函数同样被限制在2.5秒内。
主运行
在收到新报价时,EA和自定义指标中主函数start()将会被执行。当新报价进入时,如果start()函数还在忙着处理前面的报价,EA会忽略新报价而不予处理。在start()函数运行期间,所有新收的报价都会被一跳而过,直到当前start()函数运行完成为止。从那之后,仅在收到源源不断的新报价时,start()函数才一会运行。对于自定义的指标,由于收到了新报价,当前图表货币对或时段发生了变化,start()函数将会重新运行。start()函数是否运行还取决于“启用/禁用智能交易”按钮状态,当“启用/禁用智能交易”按钮处于禁用状态时,start()函数不会运行,但是,当通过该按钮切换到禁用状态时,不会中断当前start()函数运行。在EA属性窗口打开时,start()函数将停止运行,在其执行期间也不会被打开。
从图表中卸载程序、改变货币对或图表时段、计算结果发生了变化、关闭图表、客户端关机,都将会中断程序的执行。如果这些中断程序执行的指令到来的时候,start()函数此刻还在运行,那留给它的工作时间依然被限制在2.5秒之内。程序知道用内置IsStopped()函数试着把它关闭并正确地结束它的工作。
脚本的执行不依赖收到的报价。在货币对或图表时框发生改变时,脚本将完成它的工作并从客户端上卸载下来。
脚本和智能交易运行在自己的线程里,自定义指标则工作在主接口线程上。但是,如果一个自定义指标被iCustom()函数调用,这个指标就运行在调用它的程序线程中,库(导入)函数也同样工作在调用程序的线程里。
导入函数调用
为了在mql4程序执行期间导入函数,采用了所谓的“滞后联编”。这就意味着,导入函数被调用前,不会被加载相应的模块(EX4或DLL)。 MQL4和DLL库在调用模块线程下运行。
这里不推荐使用全路径模块名 Drive:\Directory\FileName.Ext 加载模块。MQL4库是从 terminal_dir\experts\libraries 文件夹中载入进来。如果库中未找到,将会尝试从terminal_dir\experts 文件夹下加载。
系统动态链接库(DLL)按照操作系统规则加载。如果一个DLL已经加载过(例如被其他智能交易系统,或从同时启动的另一个客户端程序加载),则将直接引用已加载过的库,否则,搜索会按照以下顺序进行:
- terminal_dir\experts\libraries 目录 。
- terminal_dir 目录,客户端程序启动的目录。
- 当前目录。
- windows_dir\SYSTEM32 系统目录 (或是Win98下 windows_dir\SYSTEM 目录 )。
- windows_dir 目录,即操作系统安装的目录。
- 系统环境变量PATH中列出的目录。
如果一个DLL运行时调用了另一个DLL,而后者又不可用,那么前者就不会被加载。
与系统库不同,自定义库(MQL4)是每个调用模块各自单独加载,而不管是否被其它模块独立地加载过。例如,调用.ex4模块可以从lib1.ex4和lib2.ex4库中调用函数,反过来,lib1.ex4库也可以从lib2.ex4库中调用函数。在这种情况下,一个以上lib1.ex4副本和两份lib2.ex4副本被加载,根本不考虑所有的调用都来自同一个调用.ex4模块。
从DLL导入到MQL4程序的函数必须符合Windows API函数的链接规则。为了确保在程序源码里符合这样的规定,我们用C或C++语言编程时使用关键字_stdcall予以说明,表示是用微软公司编译器编译。上述链接规定有以下特点:
为了将函数参数以适当的方式置入堆栈,调用函数(这种情况下,是一个MQL4程序)必须“看得见”被调用函数的原型(来自DLL导入函数);
调用函数(这种情况下,是一个MQL4程序)以逆序方式将参数置入堆栈,也就是说,从右到左;它就是以这种顺序让导入函数读取传递给它的参数;
参数通过值传递,除那些明确说明通过引用传递之外;
在读取传递给它的参数后,导入函数本身将会自行清除堆栈。
在描述导入函数原型时,由于所有的参数必须明确地传递给导入函数,所以参数的默认值是无用的。
如果调用导入函数失败(智能交易设置不允许DLL导入,或是由于一些原因导致无法加载相应的库),智能交易会停止运行并把相关信息输出到“智能交易停止”日志。另外,智能交易只有在重新初始化之后才能启动。重新编译或打开智能交易属性表并按OK键,其结果就是智能交易系统重新初始化。