多通貨対応のインジケータを開発する方法をご存知の方はいらっしゃいますか?

 
多通貨対応のインジケーターの 開発方法をご存知の方はいらっしゃいますか?

1~10種類の通貨を選択し、各通貨に5本のバーを表示させたいと思っています。

しかし、私はこれを行う方法を知りません。

 

標準的なインジケータでは、OnCalulate( ... ) イベント関数を通じて送信されたパラメータからのデータでバッファアレイを構築することになります。しかし、多通貨や 多時間枠の 場合、2つのソリューションのうち1つを使用する必要があります。

  • iTime()iVolumeiOpeniCloseなどの「iFunction」バリエーションの古いメソッドを使用しますが、デフォルトの_Symbol またはSymbol() の代わりに「EURUSD」「JPYUSD」などの異なるシンボルを使用しています。
  • ArrayCopyRates() 関数の最初のバリエーションの新しいメソッドを MqlRatesの 配列ポインタと一緒に使用します。 コピーされた」配列は、実際にはスペースを取らず、様々なシンボルと時間枠の既存のデータへのポインタと なります。

しかし、これが機能するためには、マルチシンボルやマルチタイムフレームが機能するために、2つの条件のうちの1つが存在しなければなりません。

  • シンボルとタイムフレームのそれぞれのチャートがすでに開かれていて、エラーが発生しないかどうか。
  • を使用すると、最初にデータを要求したときに4066エラー(ERR_HISTORY_WILL_UPDATED)が発生し、データのダウンロードを待って再度データを要求するために、スリープと再試行のループを コーディングする必要があります。

私が提案する解決策は、4066エラーを処理する最も効率的で簡単な方法として、ArrayCopyRates()MqlRates メソッドを使用することです。

これについては、MQL4のドキュメントとヘルプファイルに詳細な情報があります。

PS!NB! iMA()iATR() など、様々なシンボルや時間枠の組み込みインジケーター関数にアクセスする際は、4066エラーにならないよう、スリープとリトライのループを実装することを忘れないでください。以下は、MQL4ドキュメントからの引用です。

Any indicator can be calculated on the data of not only current chart, but also on the data of any available symbol/period. If data (symbol name and/or timeframe differ from the current ones) are requested from another chart, the situation is possible that the corresponding chart was not opened in the client terminal and the necessary data must be requested from the server. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - the requested history data are under updating) will be placed in the last_error variable, and one will has to re-request (see example of ArrayCopySeries())
 
OPはインジケータについて質問していることを忘れないでください。Sleep()はインジケータでは無視されます。
 
GumRai:
OPはインジケータについて質問していることを忘れないでください。Sleep()はインジケータでは無視されます。

すみません、知りませんでした。私はEAではこの方法を多用していますが、Indicatorでは使用していませんので、スリープのハンディキャップについては知りませんでした。

その場合、OnCalculate() 関数へのティックコール ごとに連続したコールの周りに再試行ループを構築する必要があります(ここでArrayCopyRates() の使用がより良い解決策です)。

あるいは、OnInit() 関数で動作するのであれば、インジケータ用のデータを準備する方法として、このケースでは非常に長いリトライ回数(スリープなし)が望ましいかもしれません。

 
FMIC:

...

  • でないと、最初にデータを要求したときにエラー4066(ERR_HISTORY_WILL_UPDATED) が発生し、データのダウンロードを待って再度データを要求するために、スリープと再試行のループを コーディングしなければならなくなります。

PS!NB! iMA()iATR() など、様々なシンボルや時間枠の組み込みインジケーター関数にアクセスする際は、4066エラーにならないよう、スリープとリトライのループを実装することを忘れないでください。以下は、MQL4ドキュメントからの引用です。


最近何か変更されない限り、条件やヒストリの更新の進行に関係なく、最初の関数 呼び出しから(そしてこの最初の呼び出しからのみ)毎回4066エラーが発生します。実用性はありません。
 
Ovo:
最近何か変更されたのでなければ、条件や履歴の更新の進捗に関係なく、最初の関数呼び出しから(この最初の呼び出しからだけ)毎回4066エラーになります。実用性は皆無です。
私の場合、そのようなことはありませんでした。データがすでに完全に利用可能な場合は、4066エラーは出ません。しかし、データが直接利用できない場合、その特定のシンボルとtime.frameの関数を 最初に呼び出すときだけエラーが発生します。その後、そのデータを要求する他のどの関数でも、もはやエラーは発生しません。
 

FMIC:

その場合、OnCalculate() 関数へのすべてのティックコールで連続したコールの周りに再試行ループを構築する必要があります(ここで、ArrayCopyRates() の使用がより良い解決策となります)。

あるいは、OnInit() 関数で動作するのであれば、今回のように非常に長いリトライ回数(スリープなし)で、インジケータのデータを準備する方法が望ましいかもしれません。

  1. インジケータ内のループ(長いかそうでないか)は機能しません。インジケータが動作している間、ターミナルでは他のことは何も 起こりません。これが、Sleepがインジケータで動作しない理由です。そして、ArrayCopyRatesが非同期である理由です(インジケーターの場合。)
  2. initでレート配列を有効にします。OnTickで テストし、そこでリトライを 処理します。また、チャートによって、新しいバーを作成するタイミングが異なる ことを忘れないでください。
    string pairs[] = {"EURUSD", "GBPUSD" ...}
    MqlRates pair0[], pair1[], ...
    bool initial;
    OnInit(){ initial=true;
       ArrayCopyRates(pair0, pairs[0], _Period);   
       ArrayCopyRates(pair1, pairs[1], _Period);
       :
    }
    OnCalculate( ... ){
       int count = IndicatorCounted();
       if(initial){
          if(pair1[0].time == 0) return;
          if(pair2[0].time == 0) return;
          :
          initial=false; count = 0; // process all bars
       }
       for(int i = Bars - 1 - MathMax(lookback, count); i >= 0; --i){
          int shift0 = iBarsShift(pairs[0], _Period, Time[i]);
          int shift1 = iBarsShift(pairs[1], _Period, Time[i]);
          buffer[i] = pair0[shift0].close - pair1[shift1].close;

  3. もしArrayCopyRatesを 使いたくなければ使う必要はありませんが、それでも[if(initial)]のpairN[0].timeを iTime() に置き換えることによって他のペアをロードしなければなりません。
 
   if(pair1[0].time == 0) return;

これは決して真実ではありません。

シンボルと時間枠に対して読み込まれた履歴がある場合、この関数は最新の値を取得します。

もしヒストリーがロードされていなければ、Array out of range エラーを受け取ります。

iTimeなどでも同じです。

 
GumRai:

これは決して真実ではありません。

シンボルと時間枠に対して読み込まれた履歴がある場合、この関数は最新の値を取得します。

もしヒストリーがロードされていなければ、Array out of range エラーを受け取ります。

iTimeなどでも同じです。

私もそう思います。

個人的には、"ArrayCopyRates() "の戻り値を確認し、それ以降は配列のサイズを把握してから配列データにアクセスするようにしています。

iTime()」などについては、必ず「iBars()」の方を先にチェックしています。

 
GumRai:

これは決して真実ではありません。

  if(pair1[0].time == 0) return;

シンボルと時間枠に対して読み込まれた履歴がある場合、この関数は最新の値を取得します。

履歴が読み込まれていない場合は、Array out of rangeエラーになります。

iTime等と同様です。

ACRを見るには、多くのヒストリ(ビルド600以前)の例があります。それ以外の方法はありません。その後、ACRやiTimeを呼び出しても4066は返ってきませんので、データがダウンロードされたかどうかを知ることはできません。

iTimeは常にエラー時にゼロを返します。

 
WHRoeder:

ACRを見るには、歴史的な(600年前の)例がたくさんあります。それ以外の方法はありません。ACRやiTimeのその後の呼び出しは4066を返さないので、データがダウンロードされたかどうかを知ることはできません。

iTimeは常にエラーでゼロを返してきました。

他に方法がない」とはどういう意味でしょうか?

ArrayCopyRates」からのリターンカウントをチェックし、配列のサイズをチェックすることは、「Array index isout of range」エラーを簡単に返してしまう「pair1[0].time == 0」よりも、強固なチェック方法であるように思われます。

EDIT: あなたの投稿をよく読んで、私の発言のいくつかを削除しました。

理由: