高精度计时器: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 毫秒。此外,每个“时间步长”存在波动。因此,即使使用毫秒级计时器,也建议不要设置小于几十毫秒的周期。