mql5言語の特徴、微妙なニュアンスとテクニック - ページ 88

 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

バグ、バグ、質問

fxsaber さん 2016.07.19 12:41

ENUM_DEAL_PROPERTY_INTEGER::DEAL_TICKET を適用する場所が HistoryDealGetInteger(TicketDeal, DEAL_TICKET) だけなら、何の意味があるのでしょうか?

ORDER_TICKETの例で、その考え方は明らかでしょう。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

MQL5でOrderCloseTime()?

fxsaber さん 2018.07.18 03:51

datetime OrderCloseTime( const ulong Ticket )
{
  return((HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) || HistoryOrderSelect(Ticket) ? (datetime)HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE) : 0);
}

そこで、HistorySelect-functionによって事前に生成された現在の履歴テーブルが、必要なレコードを含んでいるかどうかをチェックすることができます。DEAL_TICKETも同様です。

 

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

クリアリングでポジションの価格水準を保存する(可能か?)

fxsaber さん 2018.07.17 20:45

// Возвращает цену открытия выбранной позиции без учета клиринга
double GetSummaryPositionPrice()
{
  double TotalVolume = 0;
  double TotalDealPrice = 0;
  
  if (HistorySelectByPosition(PositionGetInteger(POSITION_IDENTIFIER)))
  {
    const int DealsTotal = HistoryDealsTotal();
    
    for (int i = 0; i < DealsTotal; i++)
    {
      const ulong DealTicket = HistoryDealGetTicket(i);
      
      if (HistoryDealGetInteger(DealTicket, DEAL_ORDER))
      {
        const double DealVolume = (HistoryDealGetInteger(DealTicket, DEAL_TYPE) ? -1 : 1) * HistoryDealGetDouble(DealTicket, DEAL_VOLUME);
        const double DealPrice = HistoryDealGetDouble(DealTicket, DEAL_PRICE);
  
        if (TotalVolume * DealVolume >= 0)
          TotalDealPrice = (TotalDealPrice * TotalVolume + DealPrice * DealVolume) / (TotalVolume + DealVolume);
        else if (MathAbs(DealVolume) - MathAbs(TotalVolume) > 0.005)
          TotalDealPrice = DealPrice;
          
        TotalVolume += DealVolume;
      }      
    }
  }
  
  return(TotalDealPrice);
}
 

GetMicrosecondCount関数は、GetTickCountと異なり、ローカルコンピュータの時刻に リンクしていることをご存知の方は少ないでしょう。 つまり、この時刻が変化すると(例えば、インターネット時刻との同期)、GetMicrosecondCount値も対応する値で変化するのです。一方、GetTickCountにはこのような問題はない。

デモとして、このコードを実行し、実行中にコンピュータの時刻を変更することができます。

  datetime time= TimeLocal();
  ulong    microsec= GetMicrosecondCount();
  uint     ticks= GetTickCount();
  
  while(!IsStopped())
  {
    Comment(int(TimeLocal()-time),"   ",(GetMicrosecondCount()-microsec)/1000000,"   ",(GetTickCount()-ticks)/1000);
    Sleep(10);
  }
 
アレクセイ・ナヴォイコフ

GetMicrosecondCount関数は、GetTickCountとは異なり、ローカルコンピュータの時刻に連動していることをご存知の方は少ないかもしれません。

知りませんでした、ありがとうございます

 

オーバーフローを回避するGetTickCount関数の 変形版(ただし、関数の呼び出し間隔が50日を超えないことが条件)

ulong GetTickCountLong()
{
  static ulong sum=0;
  static uint  lasttickcount=0;
  uint tickcount= GetTickCount();
  if (tickcount<lasttickcount) sum+=0x100000000;
  lasttickcount= tickcount;
  return sum + tickcount;
}
 
Alexey Navoykov:

GetMicrosecondCount関数は、GetTickCountと異なり、ローカルコンピュータの時刻にリンクしていることをご存知の方は少ないでしょう。 つまり、この時刻が変化すると(例えば、インターネット時刻との同期)、GetMicrosecondCount値も対応する値で変化するのです。一方、GetTickCountにはこのような問題はない。

これを実証するために、このコードを実行し、コードの実行中にコンピュータの時刻を変更することができます。

まあ、これは開発者が直すべきバグなんだけどね。その場合、その機能は説明にそぐわない。

Функция GetMicrosecondCount() возвращает количество микросекунд, прошедших с момента начала работы MQL5-программы.
GetTickCountと 比較すると、この関数の値はミリ秒ではなくマイクロ秒です(1000倍の精度があります)。また、非膨張性であることも特徴です。
だから、代替性というのはちょっと正しくないんです。
 
アレクセイ・ナヴォイコフ

GetMicrosecondCount関数は、GetTickCountと異なり、ローカルコンピュータの時刻にリンクしていることをご存知の方は少ないでしょう。 つまり、この時刻が変化すると(例えば、インターネット時刻との同期)、GetMicrosecondCount値も対応する値で変化するのです。一方、GetTickCountにはこのような問題はない。

これを実証するために、このコードを実行し、実行中にコンピュータの時刻を変更することができます。

もう一つ重要な観察があります。それは、GetMicrosecondCountの代わりにGetTickCount関数を使用することは絶対に不適切であるということから導かれるものです。
多くの人が驚かれると思います。

簡単なスクリプトの動作を検証することで

void OnStart()
  {
   uint i=GetTickCount();
   uint i0=GetTickCount();
   while(i==i0) i0=GetTickCount(); 
   
   int N1=1;
   ulong t1=GetMicrosecondCount();
   uint i1=GetTickCount();
   uint i2=GetTickCount();
   while(i1==i2) { i2=GetTickCount(); N1++;}
   t1=GetMicrosecondCount()-t1;
   
   ulong t=GetMicrosecondCount();
   ulong t0=GetMicrosecondCount();
   while(t==t0) t0=GetMicrosecondCount(); 
   int N2=1;
   ulong t2=GetMicrosecondCount();
   ulong t3=GetMicrosecondCount();
   while(t2==t3) { t3=GetMicrosecondCount(); N2++;}
   ulong t4=t3-t2;

   Print("1 значение в милисекундах:  " +(string)i1+", следующее значение   "+ (string)i2 + ", разница - " +(string)t1 + 
   " микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = " +DoubleToString((double)t1*1000.0/N1,3)+ " наносекунды");
   
   Print("1 значение в микросекундах: " +(string)t2+", следующее значение   "+ (string)t3 + ", разница - " +(string)t4 + 
   " микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = " +DoubleToString((double)t4*1000.0/N2,3)+ " наносекунды");
  }

作品の出来栄え

2018.07.27 00:23:02.261 TestTimeCount   1 значение в милисекундах:  25225093, следующее значение   25225109, разница - 15663 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.323 наносекунды
2018.07.27 00:23:02.261 TestTimeCount   1 значение в микросекундах: 20247, следующее значение   20248, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 33.333 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в милисекундах:  25226421, следующее значение   25226437, разница - 15586 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.324 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в микросекундах: 22835, следующее значение   22836, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 30.303 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в милисекундах:  25227750, следующее значение   25227765, разница - 15657 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.309 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в микросекундах: 23701, следующее значение   23702, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 27.027 наносекунды

は、次のような結論を導き出すことができる。

  • GetTickCount()関 数の値はミリ秒 ごとではなく、15.625ミリ秒(1秒の1/64、64=2^6)ごとに変化し、GetMicrosecondCount()関数の値は、1ミリ秒ごとに変化します。 マイクロ の2つです。GetMicrosecondCount関数はGetTickCountの1000倍ではなく、15625倍の精度を持つという意味です。
  • が、GetTickCount()関数は、GetMicrosecondCount()に比べて約12~15倍高速になります。
 
ニコライ・セムコ

それなら、このバグは開発者が修正したほうがいい。なぜなら、その場合、機能は説明文に対応しないからです。

GetTickCountと比較して、この関数の値は、ミリ秒ではなくマイクロ秒です(1000倍正確)。また、非膨張性であることも特徴です。
だから、代替性というのはちょっと正しくないんです。

プログラム区間の実行時間を測定する場合、システム性能の変動によって精度が平準化され、ミリ秒や数十ミリ秒の誤差が生じる。 1ミリ秒以下の非常に小さなセグメントを測定する場合は意味がない。 測定誤差の割合が非常に高くなるのだ。

 
アレクセイ・ナヴォイコフ

マイクロ秒の実用的な使い方はまだ見たことがありません。 プログラムの一部の実行時間を測定する場合、システムの性能変動によってすべての精度が平準化され、ミリ秒、あるいは数十ミリ秒の誤差になります。 1ミリ秒未満の非常に小さなセグメントを測定する場合は、意味がありません。 測定誤差は非常に大きくなります。

  1. 前号を見る
  2. マイクロ秒を使った実用的な例もたくさんあるんですよ。

 
ニコライ・セムコ

もう一つ重要なことは、GetMicrosecondCountの代わりにGetTickCount関数を使用することは絶対に不適切であるということです。
多くのプログラマーにとって、驚きの連続になると思います。

簡単なスクリプトの動作を検証することで

は、次のような結論を導き出すことができる。

  • GetTickCount()関数の 値がミリ秒 毎ではなく15.6ミリ 秒毎に変化し、GetMicrosecondCount()関数の値がミリ秒毎ではなく15.6ミリ 秒毎に変化します。 マイクロ の2つです。GetMicrosecondCountはGetTickCountの1000倍ではなく、15600倍の精度を持つということです。
  • が、GetTickCount()はGetMicrosecondCount()に比べて約12~15倍高速になります。

重要な論点

理由: