高精度计时器:EventSetMillisecondTimer

如果程序需要计时器的触发频率高于每秒一次,则应使用 EventSetMillisecondTimer函数而非 EventSetTimer 函数。

不同单位的计时器不能同时启动:必须使用其中一个函数,而不是同时使用多个函数。实际运行的计时器类型取决于最后调用的函数。属于 标准计时器 固有的所有功能对高精度时器同样有效。

bool EventSetMillisecondTimer(int milliseconds)

该函数向客户端终端表明,需要为该 EA 交易或指标生成频率小于 1 秒的计时器事件。周期以毫秒为单位设置(参数为 milliseconds)。

该函数返回操作状态标识:成功(true)或失败(false)。

在策略测试程序中运行时,需记住,计时器周期越短,测试耗时越长,因为计时器事件处理程序的调用次数会增加。

在正常运行期间,由于硬件限制,计时器事件的生成频率不超过每 10-16 毫秒一次。

为了演示如何使用毫秒级计时器,我们来扩展一下指标示例MultipleTimers.mq5。由于全局计时器的激活由应用程序负责,我们可以在不修改逻辑计时器类的情况下轻松更改计时器类型。唯一的区别在于,它们的乘数将应用于我们在 EventSetMillisecondTimer函数中指定的以毫秒为单位的基础周期。

为了选择计时器类型,我们将定义一个枚举并添加一个新的输入变量。

enum TIMER_TYPE
{
   Seconds,
   Milliseconds
};
   
input TIMER_TYPE TimerType = Seconds;

默认情况下,我们使用秒级计时器。在 OnInit函数中,启动所需类型的计时器。

void OnInit()
{
   Print(__FUNCSIG__" "BaseTimerPeriod" "EnumToString(TimerType));
   if(TimerType == Seconds)
   {
      EventSetTimer(BaseTimerPeriod);
   }
   else
   {
      EventSetMillisecondTimer(BaseTimerPeriod);
   }
}

我们来观察选择毫秒级计时器时日志中将显示的内容。

                                               // time ms
17:27:54.483  void OnInit() 1 Milliseconds        |             
17:27:54.514  void MyCountableTimer::notify()2 0    |           +31
17:27:54.545  bool OnTimer3()                        |          +31
17:27:54.561  void MyCountableTimer::notify()2 1      |         +16
17:27:54.561  void MyCountableTimer::notify()4 0      |
17:27:54.577  bool OnTimer5()                          |        +16
17:27:54.608  void MyCountableTimer::notify()2 2        |       +31
17:27:54.608  bool OnTimer3()                           |
17:27:54.608  void MySuspendedTimer::notify()1 0        |
17:27:54.623  void MySuspendedTimer::notify()1 1         |      +15
17:27:54.655  void MyCountableTimer::notify()2 3          |     +32
17:27:54.655  void MyCountableTimer::notify()4 1          |
17:27:54.655  void MySuspendedTimer::notify()1 2          |
17:27:54.670  bool OnTimer3()                              |    +15
17:27:54.670  void MySuspendedTimer::notify()1 3           |
17:27:54.686  void MyCountableTimer::notify()2 4            |   +16
17:27:54.686  void MySuspendedTimer::notify()1 4            |
17:27:54.686  Forcing all timers to stop                    |

事件生成的顺序与我们在秒级计时器中看到的完全相同,但执行速度显著加快,几乎是瞬间完成。

由于系统计时器的精度限制在几十毫秒,实际事件间隔会远超无法达到的 1 毫秒。此外,每个“时间步长”存在波动。因此,即使使用毫秒级计时器,也建议不要设置小于几十毫秒的周期。