エラー、バグ、質問 - ページ 3027

 
Сергей Таболин:

指標は一番苦手です ))))

でも!

全く理解できていないのか、それとも少し勘違いしているのか、どちらかです。

私の知る限り、prev_calculatedは未計算のデータのカウンタです。そして、受信データをカウントしたら、そのカウンターをリセットする...。もういいや、男、新しいデータは計算しなくていいや...みたいな。)))

そして、そのような場合にインジケータが完全に 再計算されるべき理由は何なのか、私にはわかりません。

---------------

ちょっとだけ嘘をつきました )))

再計算されるのは指標ではなく、履歴上で「見栄え」を良くするために「指標」が再計算されるのです ;)

プログラマーがコントロールできない理由でカウンタがリセットされた場合、インジケータが初めて起動したときのようになります。

訳の分からない説明で、私のメッセージが伝わらなくなるのは困るのですが、やっと開発者に届きました。



OnCalculate()が返す値と2番目の入力パラメータprev_calculatedの関係に注目する必要があります。この関数を呼び出すと、prev_calculatedパラメータには、前回の呼び出し時にOnCalculate()が返した値が格納されます。これにより、この関数の前回の呼び出し以降に変更されていないバーについて、計算を繰り返すことを避けるために、カスタム・インジケータを 計算するための経済的なアルゴリズムが可能になります。

-これはドキュメントからの引用です。 正しく機能しないcalcは、経済的な計算の概念全体を壊してしまうのです。
 
Andrey Dik:
プログラマーがコントロールできない理由でカウンターがリセットされ、あたかもインジケーターが初めて動作したかのようになるのです!

訳の分からない拍手の中で、私のメッセージが伝わらなければと思いましたが、尊敬する開発者の方々に届きました。

新しいバーでは毎回こうなのでしょうか?安心させられてるんですね。

すべてのバーでない場合、pre_calcをリセットするためのさまざまな理由があります。

 

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

バグ、バグ、質問

アンドレイ・ディク 2021.05.27 13:53

つまり、新しい タイムフレームのバーが 表示されると同時に、事前に計算されたカウンターがゼロになります。これは、インディケータが最初に起動したときと同じように、再度計算さ れることを意味します。

は、このような構造が身近にあるのでしょうか?

if (rates_total == prev_calculated) return rates_total;
  
int startInd = rates_total - prev_calculated;

for (int i = startInd; i >= 0; i--)
{
  //тут считаем индикатор, который обращается к другому индикатору на старшем ТФ
}

問題はEAのロジック(再描画、非再描画、過少描画など)ではなく、誰もそんなことを要求していないのにprev_calculatedがリセットされていることです。

問題だと思います。

if (rates_total == prev_calculated) return rates_total;

他のTFで呼び出されたインジケータに1ティックごとに計算させず、呼び出したら履歴が同期してそのインジケータのゼロからの計算


呼び出されたインジケータはすべてをカウントし、prev_calculated==0にリセットされません。

インジケータでクローズを描き、新しいバーでイベントを巻き戻し、prev_calculated == 0 :

// tst.mq5

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   int start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }
   
   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

このインジケータを呼び出し(バッファの最後の2つの値を取得)、さらにTFでクローズを描画します。

input ENUM_TIMEFRAMES TF = PERIOD_M5;
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   ind_handle = iCustom(NULL, TF, "NewFolder\\tst");
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   int start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }

   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
   double buf[];
   if(CopyBuffer(ind_handle, 0, 0, 2, buf) < 0) Print("Error CopyBuffer # ",GetLastError());
//--- return value of prev_calculated for next call
   return(rates_total);
}


は、M1 の最後の指標であるログを実行しました。

2021.05.27 21:48:34.196 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:48:00

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) tst_tf prev_calculated == 0

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) Error CopyBuffer # 4806

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst 新しいバー 2021.05.27 21:45:00

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst prev_calculated == 0

2021.05.27 21:49:01.636 tst_tf (EURUSD,M1) tst_tf new bar 2021.05.27 21:49:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M1) tst_tf 新しいバー 2021.05.27 21:50:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M5) tst 新しいバー 2021.05.27 21:50:00

2021.05.27 21:51:01.789 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:51:00

2021.05.27 21:52:02.832 tst_tf (EURUSD,M1) tst_tf 新しいバー 2021.05.27 21:52:00

2021.05.27 21:53:00.920 tst_tf (EURUSD,M1) tst_tf 新しいバー 2021.05.27 21:53:00

2021.05.27 21:54:02.778 tst_tf (EURUSD,M1) tst_tf New bar 2021.05.27 21:54:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M1) tst_tf 新しいバー 2021.05.27 21:55:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M5) tst 新しいバー 2021.05.27 21:55:00

2021.05.27 21:56:00.118 tst_tf (EURUSD,M1) tst_tf 新規バー 2021.05.27 21:56:00

2021.05.27 21:57:00.419 tst_tf (EURUSD,M1) tst_tf 新規バー 2021.05.27 21:57:00

 
Andrey Khatimlianskii:

新しいバーはどこもこんな感じなんですか?過剰な保険をかけているのか、それとも何か...。

すべてのバーでない場合、pre_calcをリセットするためのさまざまな理由があります。

は、メジャーTFの新しいバーごとに正確に表示されます。

例えば、M1でインジケータが動作し、M5でインジケータにアクセスした場合、5分ごとにインジケータが完全に再計算されることになります。

 
Igor Makanu:

問題だと思います。

他のTFで呼び出されたインジケータを1ティックごとに計算させず、呼び出したらそのインジケータのゼロからの履歴同期と計算がある状態です


呼び出されたインジケータはすべてをカウントし、prev_calculated==0にリセットされません。

インジケータでクローズを描き、新しいバーでイベントを巻き戻し、prev_calculated == 0 :

このインジケータを呼び出し(バッファの最後の2つの値を取得)、さらにTFでクローズを描画します。

要求された上位TF(M5)のデータの同期と、その上のインジケータの準備状況を確認し、準備不足なら終了。

その結果、このインジケータはM1バーのオープン時に一度だけ動作し、毎ティックで動作するわけではありません。


//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

//проверка на наличие нового бара
if (rates_total == prev_calculated) return rates_total;

開発者の方々には、私の訴えを聞いてほしい。

 
Andrey Dik:

要求された上位TF(M5)のデータ同期と、その上のインジケーターの準備状況を確認し、準備不足であれば終了します。

その結果、このインジケータはM1バーの開始時に一度だけ動作し、毎ティックでは動作しません。


開発者の方々には、私の訴えを聞いてほしい。

というのは、インジケータでは正しく動作しないはずです。

if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))

もし私が間違っていなければ、ヘルプにすべてのTFのデータをページングするスクリプトの内訳があり、インジケータが非同期で動作するため、インジケータからヒストリデータを要求することができないという警告があるはずです。

で、ハンドルをバインドした後に BarsCalculated() を一度使うことが推奨されています。


UPD: ヒストリーページング用スクリプトと、インディケータで動作しない理由の説明: https://www.mql5.com/ru/docs/series/timeseries_access

 
Andrey Dik:

要求された上位TF(M5)のデータ同期と、その上のインジケーターの準備状況を確認し、準備不足であれば終了します。

その結果、このインジケータはM1バーの開始時に一度だけ動作し、毎ティックでは動作しません。


カスタムプリクラを使わなければならないのでしょうか? 開発者の方々の嘆願を聞いてほしいです。

何のためのチェックなのか?

//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

条件なしでreturn 0;と書く方がよほどシンプルである。

新しいバーが出るたびに、条件が満たされ、同期に関係なくすべてのバーが再計算されます。配慮のないコードを書き、末端のバグを装う...。

 
コンパイルエラーです。
union X1 { //(1) нормально
        char x11[INT_MAX/2+1];
};
union X2 { //(2) Error: 'X2' - struct is too large
        char x21[INT_MAX/2+1];
        char x22[INT_MAX/2+1];
};
(1)と(2)の根本的な違いは何でしょうか?
 
単一フィールドでのユニオンは不思議なものです。
 
Alexey Viktorov:

そんなチェックに何の意味があるのでしょうか?

条件なしでreturn 0;と書いてしまえば簡単なのですが...。

この条件は新しいバーごとに満たされ、同期に関係なくすべてのバーが再計算されます。無茶なコードを書いて、末端のバグとして受け流す...。

をもう一度考えてみてください。

理由: