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

 
Marat Sultanov #:
以前は(古いコンパイラでも)、宣言される前にクラスを使用することが可能だった:
しかし、今はコンパイル時にエラーが出る:
未定義のクラス 'A' は使用できません。

もし動かなくなったら、それが正しいかどうかわかるといいですね。

オブジェクトの代わりにポインターを作れば、古いバージョンでも動く。

 
fxsaber #:

もし動かなくなったのなら、それが正しいことなのかどうかを知るのはいいことだ。

オブジェクトの代わりにポインターを作れば、古いバージョンでも動く。

素晴らしいご指摘、ありがとうございます!

はい、確かにポインターを使えば状況は完璧に解決します:

class A;

class B
{
   public: A * a;
   public: int Val;
};

class A
{
   public: B * b;
   public: int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   A a;
   
   b.a = GetPointer(a);
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}
 

高速アルゴリズムのファン。ナノ秒を争う人 :)


タスク: 与えられた時刻とTFに従って、バーが開く時刻を 求める。例えば、始値と終値の時間によって。

ほとんどのプログラマーは、iTime と iBarShift の組み合わせを使用します。これは最も遅い実装であり、特にこのような実装では、アップロードされたデータや結合された配列の最新の履歴が必要になります。さらに、この方法では、必要な履歴が欠落している場合にエラーが発生する可能性がある。

より高度なプログラマーは、MqlDateTime構造体とTimeToStruct()関数によってこの問題を解決するでしょう。これは悪い解決策ではないし、十分速い。

しかし、3番目の解決策があり、これは前の解決策よりも数倍生産的である:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

このアルゴリズムの主な難点は、月初めの時刻を計算することです(緑色でハイライトされています)。そこには、単純なものから複雑なものへと変化するマジックがある。複雑なものから単純なものへの逆パスはもっと難しいだろう。

パフォーマンスの向上は、標準のPeriodSeconds()関数の代わりにTFからバー内の秒を取得するアルゴリズムによってももたらされます。


3つのメソッドすべてのパフォーマンスを計算し、比較するテスト・スクリプトを添付します:

2023.11.14 12:15:29.145 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 21.20 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.10 наносекунд - Быстрый расчет
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 142.00 наносекунд - Расчет через iBarShift
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:34.226 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 19.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.70 наносекунд - Быстрый расчет
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 127.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_W1========
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 98.30 наносекунд - Расчет через iBarShift
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:52.770 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 4.10 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    контрольная сумма - 0, время выполнения 1 иттерации = 148466.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 3.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000017286960, время выполнения 1 иттерации = 110555.70 наносекунд - Расчет через iBarShift
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    ========================================================================

iBarShiftは 実際のバーで 動作するため、iBarShiftとのチェックサムは 一致 しません。チェックサムが一致するのは、 MN1 と W1 のタイムフレームだけです。なぜなら、そのようなバーの履歴には穴がないからです。
アルゴリズムが動作を開始するときに、ループ内で小さな時間ステップ(1日未満)を使用して以前の計算を保存すると、パフォーマンスが高くなります:

2023.11.14 12:14:10.714 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:10.722 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 8.03 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:10.723 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 136.80 наносекунд - Расчет через iBarShift
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:14:17.502 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:17.510 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 7.70 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:17.511 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 137.54 наносекунд - Расчет через iBarShift
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    ========================================================================


iBarShift 経由のアルゴリズムで過剰な値(青くハイライトされている)は、現在必要な履歴または配列によって計算された TF がないために発生し、それらのアップロードを開始します。
アップロード後の結果は以下のようになります:

2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 4.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 2.60 наносекунд - Быстрый расчет
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000009103200, время выполнения 1 иттерации = 129.10 наносекунд - Расчет через iBarShift
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 1.40 наносекунд - Быстрый расчет
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000038634480, время выполнения 1 иттерации = 381.30 наносекунд - Расчет через iBarShift
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    ========================================================================

ファイル:
 
Nikolai Semko #:

高速アルゴリズムのファン。ナノ秒を争う人たち :)

...

😮😲😳🥴🤪

...

ああ...

mmm....

oooh....

gkghm...。私の素朴な疑問がこんな風に出てくるとは思わなかった。

そんな感じだ。

 
Artyom Trishkin #:

😮😲😳🥴🤪

...

ああ...

うーん

ああ...

えっへん。私の素朴な疑問がこんな形で出てくるとは思わなかった。

ああ。

そうだよ、アルテム、しばらく騙されたよ。
スポーツ的な興味だったんだ。
僕も含めて、誰かの役に立てばいいな。:))

 
Nikolai Semko #:

そう、アルテム、君はしばらく僕をだましたね。
僕はスポーツの興味に取り組んだんだ。
誰かの役に立つことを願っているし、他の人の中でも僕の役に立つことを願っている。:))

もちろんだよ。素晴らしい。ありがとう!

S.F.これは面白かった。

その後どうするんだ?

 
Artyom Trishkin #:

もちろん重宝するよ素晴らしい。ありがとう!

S.F.これには驚かされました:「28.02.2100までしか正しくカウントされない!!」。

その後どうするんだ?


このアルゴリズムが75年間も需要があるとは思えない。
正直なところ、グレゴリオ暦を考慮に入れるのは怠慢だった。2000年はハイステだったが、2100年はもう違う。

 
Nikolai Semko #:


このアルゴリズムが75年も需要があるとは思えない。
正直なところ、グレゴリオ暦を完全に考慮に入れるのは怠慢だった。2000年は高嶺の花だったが、2100年はもう違う。

MNについては、事前に計算された配列を使うことができる。

Ln2(12ヶ月*100年)...11のif`とバイナリサーチでの比較、しかし他の計算はない。

 
Maxim Kuznetsov #:

MNには事前に計算された配列を使えばいい。そこにデータはほとんどない。

Ln2(12ヶ月*100年)...11のif`とバイナリサーチでの比較、しかし他の計算はない。

難しいことはない。実装方法はわかっている。
ただ、100%絶対に役に立たないと確信できるようなことはしたくないんだ。
 
Maxim Kuznetsov #:

MNには事前に計算された配列を使えばいい。そこにデータはほとんどない。

Ln2(12ヶ月*100年)...11のif`とバイナリサーチでの比較、ただし他の計算はなし。


いや、それは間違いだ。パフォーマンスを上げても効果はない。計算が滞ってしまいます。また、配列要素へのアクセスはアルゴリズムを非常に遅くする。

理由: