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;

ここまでは単なる思いつきの声出しです。

 

マイクロ秒を使うところもある

  • カスタムTimeCurrent、ミリ秒単位のおおよその精度。
  • 取引注文の 実行時間の算出。
  • ターミナルでの取引履歴の同期時間の算出。
  • ターミナルの遅れ(~5ms) - そのOnTick/OnCalculateの時間によって、ティックがどれだけ古くなるかを示します。
  • 任意の(隣接する)Time-event間の距離が指定された時間の倍数になるようにOnTimerを修正する。
 
fxsaber:

マイクロ秒を使用する箇所もあります

  • 任意の(隣接するものだけでなく)Timeイベント間の距離が、与えられた時間の倍数になるようにOnTimerを調整すること。

次に、その誤差は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ミリ秒の誤差が追加される可能性があるからです。
しかし、夏時間への変更、タイムゾーンの変更、インターネット経由の時刻更新などでは、致命的な結果になることはないでしょう。

ファイル:
 
ニコライ・セムコ


残念なことに、
はこのバージョンの機能しか提供できません。

なぜアラスなのか?
ローカルタイムが変更されたり、ソフトウェアがハングアップした場合、RealMicrosecondCount 関数に最大16ミリ秒のエラーが追加されることがあるためです。
しかし、夏時間への切り替え、タイムゾーンの変更、インターネット経由の時刻更新などで致命的な影響が出ることはないでしょう。

まだ確認していませんが、16msはどうでしょう。 ググってみると、通常、システムタイマーの エラーは10ms程度、もしくは10-16msと出ています。

 

これは高解像度の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);
  }
}