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

 

さて、皆さん、最初の部分は完了しました(すべてのペアのレートを読む)。

今私はRSIのようないくつかのグラフィック指標をポットする関数ArrayCopyRatesでコピーされたすべてのパリのレートを使用する必要があります...私は下の画像に描画するように。

私の最初の質問では、私はこれを行う方法を知っているつもりです...とレートを読み取ることについてではありません。私はそれを描画する前に、レートをコピーする必要があるとは思わないが、行う方法を知って良かった...今私はちょうどすべてのペアをプロットするための指標領域を分割する方法を発見する必要がある...

 

インジケータ領域を分割する方法はありません。すべて別々に描画する必要があり、バッファも自動スケーリングもありません。ご覧ください。

こんな絵があったんですか?(MetaQuotes Software Corp.) - MQL4 forum - Page 12
こんな絵があったんですか?(MetaQuotes Software Corp.) - MQL4 forum - Page 14
こんな写真見たことある?(MetaQuotes Software Corp.) - MQL4 forum - Page 36

 
WHRoeder:

インジケータ領域を分割する方法はありません。すべて別々に描画する必要があり、バッファも自動スケーリングもありません。ご覧ください。

こんな絵があったんですか?(MetaQuotes Software Corp.) - MQL4 forum - Page 12
こんな絵があったんですか?(MetaQuotes Software Corp.) - MQL4 forum - Page 14
こんな写真見たことある?(MetaQuotes Software Corp.) - MQL4 forum - Page 36

理解することができます。そうすると、すべての要素がオブジェクトとして描画される必要があります。
 

これはどこかで拾ったIndicatorだが、解読しようとしたことはない。現在のチャートの3つのタイムフレームを表示しています。面白いのはローソク足がヒストグラムで描かれていること。かなりきれいですが、私が今興味のあるものではありません。

ベストウィッシュ

ファイル:
 
OK、ありがとうございます。私は仕事で出張中ですが、帰ったらテストしてみます。
 
Fernando Carreiro:

このスレッドを見ている人たちに、最新情報をお知らせします

彼は英語が苦手で、私たちはポルトガル語を話すので、私はPMでOPのコードの修正を手伝っています。テストでは、"ArrayCopyRates() "関数で起こっている別の "おかしい "ことに気づきました。EAでMqlRates 配列を"ArrayCopyRates() "で使用する場合、データ配列は常に現在の状態を報告する仮想のものであり、データは常に新鮮である。

しかし、Indicatorの場合はそうではないようです。配列は仮想的なコピーではなく、「ArrayCopyRates()」が呼ばれた瞬間に設定された静的なコピーになっています。シンボルがチャートシンボルと異なる場合、データが更新されない。チャートと同じシンボルであれば、配列データは「ライブ」で期待通りに更新されますが、別のシンボルであれば、静的コピーとなります。

したがって、インジケータで動作させるためには、OnCalculate()イベントを呼び出すたびに、新しいデータが必要であれば、"ArrayCopyRates()"関数を呼び出さなければなりません。

Fernandoの知見を拡大すると、シンボルがチャートシンボルと同じであっても、タイムフレームが異なれば、配列は静的なものになります。

ですから、インジケータで仮想コピーを持つには、同じシンボルかつ同じタイムフレームでなければなりません。それ以外は静的です。

 
honest_knave: シンボルがチャートシンボルと同じであっても、タイムフレームが異なれば、配列は静的なものとなります。ですから、インジケータで仮想コピーを持つには、同じシンボルと同じタイムフレームでなければなりません。それ以外は静的です。
更新をありがとうございました。
 
こんにちは。

この問題の解決策をくまなく探していたのですが、このスレッドで議論している皆さんに感謝したいと思います。

このフォーラムでは初めてのメッセージなので、何かプロトコルを見逃していたら教えてください。

私は非常にシンプルなインジケータを開発しようとしていますが、私のロジックは、チャートが完全に最新であることに敏感であるようです。

私のインジケータは、前日のレンジ(高値から安値、または安値から高値)にフィブを描き、現在の日にフィブの高値、安値、50%に線を引くようなものです。このインディケータがGMTブローカー(日曜日の日足)で使用される場合、ユーザーは入力パラメータを設定し、月曜日に金曜日または日曜日のレンジのみを使用するか、金曜日+日曜日のレンジを使用するかを選択することができます。NYクローズブローカー(GMT+2)では、日曜日のローソク足がないため、違いはありません。

このインディケータのもう一つの特徴は、ユーザーがfibを移動させることができ、現在の日のライン(高値、50%、安値)はfibによって設定された新しい範囲に調整されることです。これにより、レンジが収縮している場合に、レンジを調整することができます。

このインジケータは主に複数の1時間足チャートで使用されますが、ユーザーはファイバーで行われた変更を失うことなく時間枠を切り替えることができるはずです。

フィブを描くためには、前日の高値と安値だけでなく、これらのポイントの時刻を見つける必要があります。

アイデアは簡単ですが、私はいくつかの難題に直面しています。

週半ばと仮定して、前日の高値と安値を見つけるために、私は単に使用します。

       Hi = iHigh(NULL, PERIOD_D1, 1);
       Lo = iLow(NULL, PERIOD_D1, 1);

それはいいのですが、今度は前日の最高値と最安値が何時だったかを調べる必要があります。そこで、iHighestとiLowestを使って、1時間足のローソク足の高値と安値の時刻を推定することにした。そこで問題が発生しました。


iHighestとiLowestを使うには、最初の1時間のローソク足とレンジの大きさを指定する必要がある。したがって、私の場合、それは前日の最初の1時間と最後の1時間のローソク足になる。だから、私は前日の開始のために前の日の日足ロウソクのオープンを使用し、前日の終わりを見つけるために、現在の日の日足ロウソクのオープン-1、。

       PrevDayBegin = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 1));                
       PrevDayEnd = iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1);

そして、PrevDayBeginは0:00 1hローソクのインデックスになり、PrevDayEndは23:00 1hローソクのインデックスになるので、通貨にだけこのインディケータを使用するなら、うまくいきます(再び週半ばと仮定します)。問題は、先物(指数、金、原油など)の場合です。毎日のローソク足の始まりは常に0:00ですが、先物の最初のローソク足はGMT+2ブローカーの午前1時なので、PrevDayBeginを計算する上記のコード行は前日23時の1時間足ローソク足を返します。

そこで、この状況に対応するために、PrevDayBeginをPrevDayEndと同じ週の日に移動させるコードを含めることにしました。

       if(TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayBegin)) != TimeDayOfWeek(iTime(NULL, PERIOD_H1, PrevDayEnd)))
         PrevDayBegin--;  

このロジックは、1時間足のローソク足がすべて最新の状態であれば問題なく動作しますが、以下のログを見ると、今日起こったことがいくつか印刷されています。参考までに、私は前日の夕方にMT4を閉じて、今日の朝(英国の午前7時頃)に再び開いたので、チャートに欠けているデータは数時間しかなかったのです。

2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OTHER DAY OF WEEK==.
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.08 19:00) (Prev_Day_Range_LRT_50_v0.6 SPX500,H2: PDR PrevDayEnd = 1 (2017.02.08 19:00) ) 。
2017.02.09 06:56:20.613 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 20 (2017.02.08 00:00)

ログを見ると、1hチャートの最新のローソク足は2017.02.08 20:00 (インデックス0)なので、iBarShift(NULL, PERIOD_H1, iTime(NULL, PERIOD_D1, 0)-1) は (インデックス 1) 2017.02.08 19:00 に近接しているように見えます。その結果、iHighestとiLowestが間違った範囲を使用するため、インジケータのすべての計算が混同されます。

以前の議論に基づいて、私は計算を行う前にすべてのローソクがロードされるのを待つように提案されたいくつかの解決策を試して使用しましたが、どうやらまだ動作していません。

例えば、OnInit()で、1時間足、日足、現在のタイムフレームのチャート更新をトリガーするために、以下のコード行を含めました(チャートが別のタイムフレームで開いているときにプラットフォームが閉じていた場合に備えて)。

   // Triggers history update
   MqlRates mqlrates_array_d1[];
   MqlRates mqlrates_array_h1[];
   MqlRates mqlrates_array[];
  
   ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1);
   ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1);
   ArrayCopyRates(mqlrates_array,NULL,0);  
もう一つ気づいたことは、MT4は、不足している履歴をすべて読み込む前に、チャートで開いている時間枠の最新のローソク足Time[0]を更新するようなので、Time[1]も有効な価格かどうかをテストすることにしました。

このコードはOnCalculate()に挿入され、@whroeder1(こちら)と@Fernando Carreiro&@Wemerson Guimaraes(こちら)のコードに基づいている。

bool isHistoryLoading;

OnInit();
:
isHistoryLoading = true;
:

OnCalculate( ... )
:
      MqlRates mqlrates_array_d1[];
      MqlRates mqlrates_array_h1[];
      MqlRates mqlrates_array[];
      
      if(isHistoryLoading)
        {      
         ResetLastError();        
        
         if(ArrayCopyRates(mqlrates_array_d1,NULL,PERIOD_D1)>0)
           {
            if(GetLastError() == 0)
              {
               if((iTime(NULL,PERIOD_D1,0) > 0) && (iTime(NULL,PERIOD_D1,1) > 0))
                 {
                  ResetLastError();
  
                  if(ArrayCopyRates(mqlrates_array_h1,NULL,PERIOD_H1)>0)
                    {
                     if(GetLastError() == 0)
                       {
                        if((iTime(NULL,PERIOD_H1,0) > 0) && (iTime(NULL,PERIOD_H1,1) > 0))
                          {
                           ResetLastError();
      
                           if(ArrayCopyRates(mqlrates_array,NULL,0)>0)
                             {
                              if(GetLastError() == 0)
                                {
                                 if((iTime(NULL,0,0) > 0) && (iTime(NULL,0,1) > 0))                            
                                   {
                                    isHistoryLoading = false;
                                
                                    if(DebugLog)
                                      Print("Chart up-to-date!");        
                                    }
                                }
                             }
                          }
                       }
                    }                      
                 }
              }
           }
        }
        
      if(isHistoryLoading)
        {
         if(DebugLog)
           Print("Waiting for chart to update!");
         return(rates_total);
        }    

:

そして、これはプラットフォームを開き、インジケータを初めてロードしたときのログです。

2017.02.09 06:56:18.492 カスタムインジケータ Prev_Day_Range_LRT_50_v0.6 SPX500,H1: ロードに成功しました。
2017.02.09 06:56:18.630 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: 初期化されました。
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Chart up-to-date!
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Indicator doesn't exist!作成中です。
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OTHER DAY OF WEEK==.
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 20 (2017.02.07 23:00) (Prev_Day_Range_LRT_50_v0.6 SPX500,H2: PDR PrevDayEnd = 20 (2017.02.07 23:00
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayBegin = 42 (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR 曜日 = 3
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Candle = 28) (Price = 2299.33) (Time = 2017.02.07 14:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iLowest (Candle = 20) (Price = 2287.88) (Time = 2017.02.07 23:00:001)
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Time1=2017.02.07 14:00 Price1=2299.33 から Time2=2017.02.07 23:00 Price2=2287.88 まで Fibが発生。
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: トレンドライン 'PDRTrend1 131296489639296384' from Time1=2017.02.08 00:00 Price1=2299.33 to Time2=2017.02.09 00:00 Price2=2299.33
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend2 131296489639296384' from Time1=2017.02.08 00:00 Price1=2293.605 to Time2=2017.02.09 00:00 Price2=2293.605
2017.02.09 06:56:18.639 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend3 131296489639296384' from Time1=2017.02.08 00:00 Price1=2287.88 to Time2=2017.02.09 00:00 Price2=2287.88

ローソク足0と1への参照やArrayCopyRates関数は、すでにチャートに読み込まれている情報にアクセスしているだけなので、ArrayCopyRatesはコピーした有効な要素数を返しているようで、iTime(..., 0) と iTime(..., 1) は前日のプラットフォーム停止時に保存した直近2本のローソクの有効価格を返しているようですね。

つまり、昨日(PERIOD_D1 [0] = (2017.02.08 00:00))であるかのようにインジケータがプロットされたことになります。

このインジケータは、ユーザーがfibを動かしても、高値、50%、安値のラインが常に現在の日にプロットされるように作られています(上のログに表示されている3本のトレンドラインがそれです)。そのため、OnCalculate()に、トレンドラインの中間が現在の日にプロットされているかどうかをテストするコードを書いています(ユーザーは上下のラインを無効にする入力オプションを持っているので、常にプロットされるのは中間ラインだけです)。

OnCalculate( ... )
:

      if(ObjectFind(Trend2Name) != -1)                // Check whether mid range line exists
        {
            
         if((TimeDay(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeDay(TimeCurrent()))
           && (TimeMonth(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeMonth(TimeCurrent()))
           && (TimeYear(ObjectGetInteger(0,Trend2Name,OBJPROP_TIME,0))==TimeYear(TimeCurrent()))) // Indicator has already been ploted today        
           {
            return(rates_total);
           }
         else     // Indicator exists but in a past date, so delete it and plot it on current day
           {
            if(DebugLog)
               Print("Indicator in a past date! Deleting it and creating it today!");
              
            if(ObjectFind(FibName) != -1)
              FiboLevelsDelete(0,FibName);              
            // Indicator will be created by the OnChartEvent() when it detects the fib was deleted.
           }
        }
      else        // Indicator doesn't exist, so create it
        {
         if(DebugLog)
            Print("Indicator doesn't exist! Creating it.");
         CreateIndicator();
        }
:

数ティック後にデータが部分的にロードされ、上記のコード片はラインが前日にプロットされたことを検出し、fibを削除し、範囲の再計算とオブジェクト(すなわちfib、トレンドラインなど)の再描画をトリガーします。


2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: インジケータが過去の日付に!削除して今日作成!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRFibo 131296489639296384 削除しました!
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRRectangle 13129648639296384 を削除しました。
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRTrend1 131296489639296384 を削除する。
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRTrend2 131296489639296384 を削除しました。
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDRTrend3 131296489639296384 を削除する。

そして、このメッセージの冒頭で触れていた問題に戻ってきます。私が上で実装したテストは、インジケータが履歴を完全にロードするのを待たず、そのため、部分的なデータに基づいて範囲が計算されるのです。

これはメッセージの冒頭で示したログの完全版で、1hチャートの2本目のローソク足(インデックス1)が(2017.02.07 21:00)なのでPrevDayEndが誤計算されているだけでなく、1hチャートの当日の1本目であるはずのCurrDayBeginがiBarShiftによって(2017.02.08 06:00)にアプライドされていることを示しているものです。

CurrDayBegin = iTime(NULL, PERIOD_D1, 0);
      
while(TimeDayOfWeek(iTime(NULL, PERIOD_H1, iBarShift(NULL, PERIOD_H1, CurrDayBegin))) != TimeDayOfWeek(TimeCurrent()))

     // If iBarShift can't find the 0am candle and returns the 11pm candle of prev day.

  CurrDayBegin = CurrDayBegin + 3600;        // Move 1h until you find the 1st candle of today.                                        

2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: == OTHER DAY OF WEEK====.
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PrevDayEnd = 1 (2017.02.07 21:00) (Prev_Day_Range_LRT_50_v0.6 SPX500,H2: PDR PrevDayEnd = 1 (2017.02.07 21:00
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1:PDR PrevDayBegin = 22 (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR CurrDayBegin = (2017.02.08 06:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [0] = (2017.02.08 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [1] = (2017.02.07 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR PERIOD_D1 [2] = (2017.02.06 00:00)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR 曜日 = 3
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: PDR iHighest (Candle = 8) (Price = 2299.33) (Time = 2017.02.07 14:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1:PDR iLowest (Candle = 19) (Price = 2288.57) (Time = 2017.02.07 03:00:001)
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Time1=2017.02.07 03:00 Price1=2288.57 から Time2=2017.02.07 14:00 Price2=2299.33 まで Fibが発生。
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend1 131296489639296384' from Time1=2017.02.08 06:00 Price1=2288.57 to Time2=2017.02.09 06:00 Price2=2288.57
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend2 131296489639296384' from Time1=2017.02.08 06:00 Price1=2293.95 to Time2=2017.02.09 06:00 Price2=2293.95
2017.02.08 06:53:53.252 Prev_Day_Range_LRT_50_v0.6 SPX500,H1: Trendline 'PDRTrend3 131296489639296384' from Time1=2017.02.08 06:00 Price1=2299.33 to Time2=2017.02.09 06:00 Price2=2299.33

要するに、チャートにすべてのヒストイがロードされているかどうかをテストする理由はあるのでしょうか?それとも、私のコードに何か欠けているのでしょうか?

この長いメッセージにお付き合いいただき、ありがとうございました。

もし、全体のコードとログをご覧になりたい場合は、ご連絡ください。ここにコードを添付したくないのですが、個人的に送ることができたら嬉しいです。

以下はインジケーターのスクリーンショットです。

(1) 不完全な履歴を使って計算したもの (水平線が日の初めから始まっていないことに注意してください)

不完全な履歴で算出された指標

(2) 完全な履歴を使用して再計算したもの(水平線が日の始めから始まっている)。

フルヒストリーを用いて再計算された指標

Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
Problems with ERR_HISTORY_WILL_UPDATED (4066 ) & weekends
  • www.mql5.com
Hi i m building a custom indicator and got problems with the 4066 Error...