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

 
Artyom Trishkin #:

従来から、if(limit>1) limit=rates_total-1というチェックが入っています。これは、計算上i+somethingが存在しない場合に対応するものです。もしあるならば、これらの「何人何役」をlimit=rates_total-1-some-somethingという構成に含める必要がある。

これがないと、必ずアレイのオーバーランが発生します。rates_total は Bars() 以外の何物でもないからです。したがって、5000本のバーがあるときにインデックス5000を指定すると、配列の限界から外れることになります(バーの計算はゼロから始まります)。

あなたの例では、限界値の計算が誤っています。

こんな感じでいいんじゃないでしょうか。

そして、その後に limit>1 をチェックします。

また、limitが1より大きい場合は、limit = rates_total-1 とする。

アルテムさん、ありがとうございます! そして、お騒がせしてすみません。
そうですね、チェックがあるはずなんですが、つい忘れてしまいました。
やはり、コードにコメントが入っています
//Check and calculate bars number.
どうやら、コピーペーストのせいで誤解が生じたようです。
チェックですべて正常に動作します。ありがとうございます。

 
Roman #:

Artemさん、ありがとうございます!
そうですね、チェックがあるはずなんですが、忘れてました。
チェックですべて正常に動作します。ありがとうございます。

どういたしまして。計算を修正する。正しくはありません - 上記で強調しました。

int limit = rates_total-1-prev_calculated;

-1はここにいるべきでは ない。

rates_total が 5000 で、前の OnCalculate() の呼び出しで計算されたバーも 5000 (prev_calculated) である場合、制限は -1 に等しくなります。従って、ループは全く実行されない。

もし、インジケーターの読み方を選択したい場合(ゼロバーでのティック、または新しいバーのオープニング時のみ)、その方法を指定する変数を入力してください。

int end = (every tick ? WRONG_VALUE : 0);

ループは以下のようになります: for(int i=limit; i>end; i--) { //...}

を実行すると、リミット計算が正しく行われ、ループが思い通りになります。

 

正しいコードです。

各ティックでi>=0

新しいバーの場合は i>0

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,       
                 const int prev_calculated,   
                 const int begin,             
                 const double& price[])      
{
   ArraySetAsSeries(price, true);
   ArraySetAsSeries(IndBuff, true);
   
   //-------------------------------------------------------------------------
   //Расчёт и проверка количества просчитываемых баров
   int limit = rates_total-prev_calculated;
   
   if(limit>1) 
      limit = rates_total-1;
   

   //-------------------------------------------------------------------------
   //Расчёт индикатора
   for(int i=limit; i>=0; i--)
   {

      IndBuff[i] = price[i]; 

   }
   

   return(rates_total);
}
 
Nikolai Semko #:
または

どうしたらいいのかも聞かずに...。テレパスは休暇から戻ったのか?;)

 
Roman #:

正しいコードです。

各ティックでi>=0

i>0 で新しいバー

ArraySetAsSeries(IndBuff, true);

これは、OnInit()に移した方がよいでしょう。

 
Artyom Trishkin #:

どうしたらいいのかも聞かずに...。テレパスは休暇から戻ったのか?;)

:)
アルテムさん、テレパスでなくても、この人が数分前に登録して、最初に見たのが「バグ、バグ、質問
明らかに、無料でお金がもらえるかどうか、あまり迷惑をかけないようにということなんですが......。

 
Nikolai Semko #:

:)
アルテムさん、テレパスでなくても、この人が数分前に登録して、最初に見たのが「エラー、バグ、質問」だったということはわかりますよね
明らかに、「無料でお金がもらえるなら、頑張り過ぎないで...」とお願いしているのです。

家庭教師に投資してベントレーで小遣い稼ぎをしようと思ったのかも?:)

 
Artyom Trishkin #:

ベントレーのために、家庭教師に投資して、プログラマーとして苦労してお金を稼ごうと思ったのかもしれません。:)

そんなことはないだろう、アルテム。
プログラマーとしてのポテンシャルがあれば、曖昧さや不確実性は許されなかったはずだ。
:)
 
Roman #:

何が一番迷惑かわかる?どんな行動も、何の前触れもなく黙ってごまかされること。
そして、人が傷つくのです。このメタトレーダーにはうんざりです。

インジケータサイクルの設計は、何も考えずにコピーペースト方式(と曲がったオートコンプリート)で昔からのものを借りているだけです。

現在のインターフェースでは、すべてがシンプルです。

for(int bar=prev_calculated>0?prev_calculates-1:0 ; bar<rates_total; bar++) {

   int i=rates_total-1; // i используем если обращения как ArraySetSeries(x,true), иначе bar

   ....

}

return rates_total;

この場合のprev_calculated-1によるプッシュは、各コールで最後のバーを再計算する必要がある場合に必要です。

 
Maxim Kuznetsov #:

ただ、指標となるサイクルの設計が、何も考えずにコピーペースト(と曲がったオートコンプリート)で昔取った杵柄になっているのが気になるところです。

現在のインターフェースでは、すべてがシンプルです。

for(int bar=prev_calculated>0?prev_calculates-1:0 ; bar<rates_total; bar++) {

   int i=rates_total-1; // i используем если обращения как ArraySetSeries(x,true), иначе bar

   ....

}

return rates_total;

この場合のprev_calculated-1によるクラウディングは、各コールで最後のバーを再計算する必要がある場合に必要です。

はい、この発言でちょっと興奮しました。
以前は動作していたものが動作しなくなっただけで、神経質なチックが始まる ))
そして、すべてをダブルチェックし始め、もちろん覚えていないいくつかの特殊性を忘れて、根拠のないクラッシュを非難する。
そして、コピーペーストは非難される。多くの方が直面したことがあると思います。

インジケータやEAのカスタム テンプレートを作ることを開発者に提案したい。
ウィザードで選択できるようになるそうです。

m

C/C++のエディタには、この機能を持つものがあります。
主に作業する基本的なテンプレートを追加しておき、ウィザードで読み込むと非常に便利です。
標準的なMQLのテンプレートは、まったく同じではありません。
明らかに、テンプレートを書いて、それをコピーすることができると言えるでしょう。
そしてまた、「コピーペースト」という陰湿な言葉に戻ってくるのです。そして、それを自動化してプログラマーを楽にするということは、考慮されていないのです。