检查 MQL 程序状态和终止原因

我们已经在本书不同示例中接触了 IsStopped 函数。当 MQL 程序执行较长的计算时,必须不时调用该函数。这样可以检查用户是否发起了程序关闭操作(即,用户是否尝试将其从图表移除)。

bool IsStopped() ≡ bool _StopFlag

如果程序被用户中断,则该函数返回 true(例如,在上下文菜单中的“Expert 列表”打开的对话框中,用户按下“删除”按钮)。

程序有 3 秒钟正常暂停计算,必要时保存中间结果,并完成其工作。若未完成,则将程序从图表强制移除。

如果不使用 IsStopped 函数,你可以检查内置 _StopFlag 变量的值。

EnvStop.mq5 测试脚本可模拟循环执行的长计算:搜索素数。退出 while 循环的条件是使用 IsStopped 函数编写的。因此,当用户删除脚本时,循环以正常方式中断,日志显示找到的素数日志统计(脚本还可以将这些数字保存到文件)。

bool isPrime(int n)
{
   if(n < 1return false;
   if(n <= 3return true;
   if(n % 2 == 0return false;
   const int p = (int)sqrt(n);
   int i = 3;
   for( ; i <= pi += 2)
   {
      if(n % i == 0return false;
   }
   
   return true;
}
   
void OnStart()
{
   int count = 0;
   int candidate = 1;
   
   while(!IsStopped()) // try to replace it with while(true)
   {
      // emulate long calculations
      if(isPrime(candidate))
      {
         Comment("Count:", ++count", Prime:"candidate);
      }
      ++candidate;
      Sleep(10);
   }
   Comment("");
   Print("Total found:"count);
}

如果我们以 true(无限循环)替换循环条件,则脚本将停止回应用户的停止请求,并被强制卸载(从图表中)。因此,我们将在日志中看到“异常终止”错误,而窗口左上角的注释仍会残留。这样,本示例中所有表示保存数据和清除忙碌资源的指令(例如,这可能是将你自己的图形对象从窗口删除)均被忽略。

在停止请求被发送到程序之后(值_StopFlag 等于 true),可使用 UninitializeReason 函数找到终止原因。

遗憾的是,此功能仅适用于 EA 交易和指标。

int UninitializeReason() ≡ int _UninitReason

该函数返回描述反初始化原因的预定义代码之一。

常量

说明

REASON_PROGRAM

0

ExpertRemove 调用了仅适用于 EA 交易和脚本的函数

REASON_REMOVE

1

程序已从图表中移除

REASON_RECOMPILE

2

程序已重新编译

REASON_CHARTCHANGE

3

图表交易品种或期间更改

REASON_CHARTCLOSE

4

图表关闭

REASON_PARAMETERS

5

程序输入参数更改

REASON_ACCOUNT

6

另一个账户连接到交易服务器,或者与交易服务器重新连接

REASON_TEMPLATE

7

应用了另一个图表模板

REASON_INITFAILED

8

OnInit 事件处理程序返回错误标志

REASON_CLOSE

9

终端关闭

若不使用函数,也可以访问内置全局变量 _UninitReason

反初始化原因代码还将作为一个参数传递给 OnDeinit 事件处理程序函数。

稍后在学习 程序启动和停止功能时,我们将看到一个指标 (Indicators/MQL5Book/p5/LifeCycle.mq5) 和一个 EA 交易(Experts/MQL5Book/p5/LifeCycle.mq5),它们将反初始化的原因记录到日志,可让你根据用户操作了解程序行为。