了解MT4编程的同学应该都知道,MT4的EA编写中有三个最重要的系统函数OnInit(),OnTick() 和 OnDeinit(const int reason)。这三个函数分别会在EA初始化的时候,EA运行(接收到市场报价)的时候和EA退出(反初始化)的时候。如果我们在EA运行的途中去修改EA的参数、修改图表的周期或者品种时, EA会分别运行OnDeinit(const int reason)函数来反初始化EA,再重新运行OnInit()来重新按照新的参数、品种、周期来重新运行。

         那么还有一种极端的情况,就是EA正在执行OnTick()函数里面的指令,这时MT4并不会强制终止OnTick()函数,而是会等到OnTick()函数执行完毕之后,再执行OnDeinit(const int reason)和OnInit()来重新初始化EA。

         小编在发现这个细节的时候也是经历了一个大乌龙的。具体情况是这样:在写下单函数的时候,通常会把它封装在一个while循环中,目的就是如果需要下单的手数超出了平台单笔手数限制的时候,可以把单子拆分开来下单,保证总的手数与希望下单的手数保持一致。

在某年某月某日,小编在没有勾选“允许实时自动交易”选项的情况下,挂上了此EA,这时就出现了一个问题,由于没有允许EA下单,所以EA在运行下单函数的时候就会报错4109,而且一直没有走出这个while循环,没有意识到这个问题的小编在另一天修改了EA参数之后,勾上了“允许实时自动交易”按钮,点击确定,让EA按新的参数运行,然而EA先是按照旧的参数下了单子,把之前没有走完的while循环结束之后,才开始运行了新的参数。

         刚开始遇到这个问题的时候小编还很纳闷,不知道为什么会出现这么个乌龙,后来冥思苦想了半天之后才恍然大悟,想起来MT4之前是进入了死循环,然后在换参数,勾选了“允许实时自动交易”的时候MT4才从这个死胡同里走出来。后来小编也使用了类似的代码验证了刚才的结论,测试代码和截图如下:

input string Symbols = "XAUUSD";
double lots = 0;

int OnInit() {
   lots = 0.1;
   return INIT_SUCCEEDED;
}

void OnTick() {
   int myticket = 0;
   while(lots) {
      myticket = OrderSend(Symbols,OP_BUY,lots,Ask,10,0,0,"test",123456,0,clrBlue);
      if(myticket >= 0) {
         lots -= 0.1;
      }
      else {
         Print("order send error: ", GetLastError());
      }
   }
}

本文作者:小土豆