以编程方式移除 EA 交易和脚本:ExpertRemove

如有必要,开发者可以组织对以下两种类型 MQL 程序的停止和卸载:EA 交易和脚本。这可以通过 ExpertRemove函数来实现。

void ExpertRemove()

该函数没有参数,也不返回值。它向 MQL 程序执行环境发送删除当前程序的请求。实际上,这会导致设置 _StopFlag 标志,并停止接收(和处理)所有后续事件。之后,程序会有 3 秒钟的时间来正常完成其工作:释放资源、中断算法循环等。如果程序未能完成这些操作,系统将强制卸载该程序,并可能导致中间数据丢失。

该函数在指标和服务中无效(程序会继续运行)。

每次调用该函数时,日志中都将包含“ExpertRemove () 函数已被调用”条目。

该函数主要用于无法通过任何其他方式中断的 EA 交易。对于脚本而言,通常使用 break 语句来中断循环(如果存在)会更容易。但如果循环是嵌套的,或算法存在多个函数相互调用的情况,则在继续计算的条件中,在不同级别考虑停止标志会更容易,并且在出现错误情况时,可以使用ExpertRemove设置此标志。如果不使用此内置标志,无论如何,都需要引入一个具有相同用途的全局变量。

脚本 ScriptRemove.mq5提供了 ExpertRemove 用法示例。

可通过ProblemSource类进行模拟算法运行中可能导致需要卸载脚本的潜在问题。 ExpertRemove 会在其构造函数中随机进行调用。

class ProblemSource
{
public:
   ProblemSource()
   {
      // simulating a problem during object creation, for example,
      // with the capture of some resources, such as a file, etc.
      if(rand() > 20000)
      {
         ExpertRemove(); // will set _StopFlag to true
      }
   }
};

接下来,会在全局级别和辅助函数内部会创建该类的对象。

ProblemSource global// object may throw an error
   
void SubFunction()
{
   ProblemSource local//object may throw an error
   // simulate some work (we need to check the integrity of the object!)
   Sleep(1000);
}

现在,我们在 OnStart操作中使用 SubFunction,并在带有 IsStopped 条件的循环内部调用它。

void OnStart()
{
   int count = 0;
   // loop until stopped by the user or the program itself
   while(!IsStopped())
   {
      SubFunction();
      Print(++count);
   }
}

下面是一个日志示例(由于随机性,每次运行的结果都会不同):

1
2
3
ExpertRemove() function called
4

请注意,如果在创建全局对象时发生错误,循环将完全不会执行。

由于 EA 交易可以在 测试程序中运行,因此ExpertRemove函数同样可以在测试程序中使用。其效果取决于函数调用的位置。如果在 OnInit 处理程序中执行此操作,该函数将取消测试,即终止测试程序针对当前 EA 交易参数集的单次执行。这种终止将被视为初始化错误。当在算法的其他任何位置调用 ExpertRemove时,EA 交易的测试将提前中断,但会按照常规方式进行处理,即会调用 OnDeinitOnTester 。在这种情况下,所积累的交易统计数据和优化标准值将保留,但需注意,模拟服务器时间 TimeCurrent 并未达到测试程序设置中的结束日期。