mql5语言的特点、微妙之处以及技巧 - 页 89

 
尼古拉-森科

  1. 见我以前的帖子
  2. 我有很多具有微秒级实际效益的例子。

到目前为止,我只看到GetTickCount的一个被提及的缺点--它被系统定时器的 分辨率所限制,这是一个严重的问题。 而其他的则没有特别的实际用途。你所做的是15毫秒的超短测试--没有人这样做。 这样的结果是不稳定的。 你需要让测试至少持续半秒,然后你才能说些什么。

 
阿列克谢-纳沃伊科夫

没有人做15毫秒的超短测试。 这样的结果是不稳定的。 你至少需要半秒的测试时间,然后你就可以谈论一些东西了。

你错了。在这15毫秒内,GetTickCount()函数 被调用超过6 000 000次。

我的计算是正确的。GetTickCount()值每1/(2^6)=1/64秒(15625微秒)变化一次。
开发人员,请确认。

 
ikolai Semko:

错了。在这15毫秒内,GetTickCount()函数被调用超过6 000 000次

当我们测量一个工作代码的性能时(不是真空中的球形马),它要运行足够长的时间间隔(几百毫秒以上)。 原因是系统的性能和工作量是不断变化的。 前一刻是一个,而下一刻就不同了。 所以在短间隔内,不同的测试结果会有很大的不同。 这就是为什么我们需要更长的间隔,但微秒在那里已经不重要了。

此外,我们有以毫秒为单位的引号,而ping也是以毫秒为单位的,所以我看不出微秒应该放在哪里。 总之,这不是重点。

现在我必须发明一个解决方案,如何摆脱这种情况,以避免两种功能的缺点。 对开发者来说,希望不大。

 
阿列克谢-纳沃伊科夫

现在我们必须想办法绕过这两个功能的缺点。 对开发者来说,希望不大。

我认为用这样的公式在第一时间近似地计算是可能的。

ulong RealGetMicrosecondCount=(GetTickCount()-StartGetTickCount)*1000+x+GetMicrosecondCount()%15625;

到目前为止,这只是一个响亮的想法。

 

一些我使用微秒的地方

  • 自定义时间电流,精确度约为毫秒。
  • 交易订单 执行时间的计算。
  • 计算终端中交易历史的同步时间。
  • 终端的滞后(~5毫秒)--在其OnTick/OnCalculate的时刻,tick的过时程度。
  • 对OnTimer进行修正,使任何(不仅是相邻)Time-events之间的距离是指定时间的倍数。
 
fxsaber:

一些我使用微秒的地方

  • 调整OnTimer,使任何(不仅仅是相邻的)Time事件之间的距离是给定时间的倍数。

其次,它的误差与GetTickCount() 相同,即15毫秒。 这就是为什么微秒的含义不是很清楚的原因。 假设你已经计算出一个精确到微秒的间隔,但实际上它会在几百万秒之后或之前出现。

 
阿列克谢-纳沃伊科夫

其次,它的误差与GetTickCount()相同,即15毫秒,所以这里的微秒有什么意义不是很清楚。 假设你用微秒的精度计算间隔,但实际上它会晚几百万秒或早几百万秒到来。


另外,命令被排队,执行可能在5秒内......

 
Alexey Navoykov:

现在我们必须想办法绕过这两种功能的缺点。 对开发者来说,希望不大。


唉。
,我只能为你提供这个变体的功能。

ulong RealMicrosecondCount()
  {
   static bool first=true;
   static ulong sum=0;
   static long delta;
   static long shift=0;
   static ulong  lasttickcount;
   ulong i=GetTickCount()+sum;
   ulong t=GetMicrosecondCount();
   if(first) // если первый вход, то вычисляем разницу GetMicrosecondCount и GetTickCount
     {
      lasttickcount=i;
      delta=((long)i*1000-long(t));
      first=false;
     }
   long curdelta=((long)i*1000-long(t));
   long d=curdelta-delta;
   if(fabs(d-shift)>20000) shift=d;
   if(i<lasttickcount) sum+=0x100000000;
   lasttickcount=i;
   return (t+shift);
  }

为什么是阿拉斯?
因为如果你改变了本地时间 或只是程序挂起,可能会在RealMicrosecondCount 函数中增加一个最多16毫秒的错误。没有办法避免。
,但在改变为夏季时间、时区变化、通过互联网更新时间时,不会有致命的后果。

附加的文件:
 
Nikolai Semko:


唉。
,只能提供这个版本的功能。

为什么是阿拉斯?
因为在本地时间改变或软件挂起的情况下,RealMicrosecondCount 函数可能会增加16毫秒的误差。没有办法。
,但在切换到夏季时间、时区变化、通过互联网更新时间时,不会有致命的后果。

还没有检查,但我不太确定16毫秒。 当我在网上搜索这个问题时,通常系统定时器 的错误是10毫秒,或者10-16毫秒。

 

这里有一个使用高分辨率winapi计时器的变体,给出了3.8e-07 秒的精度。

#import "Kernel32.dll"
  int QueryPerformanceCounter(ulong &lpPerformanceCount);
  int QueryPerformanceFrequency(ulong &lpFrequency);
#import


ulong QueryPerfomanceCounter() { ulong value;  if (QueryPerformanceCounter(value)) return value;  return 0; } 

ulong QueryPerformanceFrequency() { ulong freq;  if (QueryPerformanceFrequency(freq)) return freq;  return 0; }  


long GetPerfomanceCount_mcs()
{ 
  static long freq= QueryPerformanceFrequency();
  return freq ? QueryPerfomanceCounter()*1000000/freq : 0;
}


void OnStart()
{
  Print("Resolution of perfomance counter:  ",1.0/QueryPerformanceFrequency()," s");
  ulong  perfcount= GetPerfomanceCount_mcs(); 
  
  while(!IsStopped())
  {
    Comment((GetPerfomanceCount_mcs()-perfcount)/1000000.0);
    Sleep(10);
  }
}