初期化中のChartNavigate

 

ChartNavigate関数で 問題に遭遇しました。何か間違ったことをしているのか、それとも本当に機能に問題があるのか。よく使っている人は書き込んでください。

問題の核心は、ChartNavigateがチャートを移動しないことです。 端末を起動するとき この関数が OnInit() の中で呼ばれた場合。意図的に何度もドキュメントを読み返しました。初期化中に関数を呼び出すことができないとはどこにも書いてありません。

コード インジケーター を再生することができます。

#property indicator_chart_window 
int OnInit()
{
   if (ChartNavigate(0, CHART_END, -1000))
      Alert("Успешно");
   else
      Alert("Ошибка №", GetLastError());

   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
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[])
{
   return(rates_total);
}

プレイまでの手順

  1. チャートの自動再生をオフにする。
  2. インジケーターをチャートに貼り付けます。ChartNavigateは、チャートを希望する位置に移動させることで起動します。
  3. 端末をアンロードする。
  4. 端末を読み込む。オフセットなしでチャートを表示すると、ChartNavigateは動作しません。
関数がエラーを出すようであればOK。でも、そうじゃないんです。すべての呼び出しは成功しますが、チャートのオフセットが発生しないのは、ターミナルを再読み込みしたときです。

 
チャートと連動する関数を適用するのです。インジケーターの場合、チャート作成の保証はOnCalculateの 最初のエントリ、EAの場合はOnTick()の最初のエントリになります。でも、それまではダメ。
 
Vladimir Karputov:
チャートと連動する関数を適用するのです。インジケーターの場合はOnCalculateの最初の入力、Expert Advisorの場合はOnTick()の最初の入力がチャート作成の保証となります。でも、それまではダメ。

問題ありません。グラフがまだない場合は、false とそれに対応するエラーコードを返すようにします。しかし、これはそうではなく、この関数は誇らしげに実行の成功を報告しています。なお、ドキュメントには、グラフへのメッセージ送信が成功したことを示すとは書かれていない。機能実行の成功」とはっきり書いてあります。

また、これは再生のためのコードです。実は、ChartNavigateの呼び出しの 前にも、timeseriesの呼び出しがあるんです。そして、そのすべてが正しく記入されていることがわかった。つまり、すでにチャートがあり、そのデータがある。また、端末を閉じる前にチャートに配置されたグラフィックオブジェクトをチャートから読み出すことも可能です。

したがって、どう考えても、このチャートはすでに存在している。

 

それは変ですね。私には何の問題もなく使えています。

さらに、グラフをオフセットする前に、自動オフセットCHART_AUTOSCROLL を無効にする必要があります。

 
Ihor Herasko:

問題ありません。グラフがまだない場合は、false とそれに対応するエラーコードを返すようにします。しかし、これはそうではなく、この関数は誇らしげに実行の成功を報告しています。なお、ドキュメントには、グラフへのメッセージ送信が成功したことを示すとは書かれていない。機能実行の成功」とはっきり書いてあります。

また、これは再生のためのコードです。実は、ChartNavigateの呼び出しの 前にも、timeseriesの呼び出しがあるんです。そして、そのすべてが正しく記入されていることがわかった。つまり、すでにチャートがあり、そのデータがある。また、端末を閉じる前にチャートに配置されたグラフィックオブジェクトをチャートから読み出すことも可能です。

したがって、どう考えても、このチャートはすでに存在している。

チャートとデータは、2つの大きな違いです。

グラフを参照するすべての関数は非同期です。つまり、一方通行で、撮影して忘れてしまうのです。そしてこの場合のtrueは、この関数のフィールドに正しく入力されたことを意味するだけで、それ以上の意味はない。

すべてのデータが揃い、グラフがプロットされたときの符号がOncalculate/OnTickへの最初の入力となる。

 
Vladimir Karputov:

グラフとデータは、大きく分けて2つの違いがあります。

グラフアクセス機能はすべて非同期です。つまり、撮影して忘れるという片道旅行です。この場合、trueはこの関数のフィールドに正しく入力されたことだけを意味し、それ以上の意味はありません。

すべてのデータが揃い、グラフがプロットされたときの符号がOncalculate/OnTickへの最初の入力となる。

では、私にとっては完璧に機能するという事実をどう説明するのですか?スレッドの最初の投稿と全く同じようにOnInit()で...なぜ無意味なことをするんだ?

 
Alexey Viktorov:

それは変ですね。私には何の問題もなく使えています。

どのようなビルドをお持ちですか?1861年を持っています。

さらに、グラフをオフセットする前に、自動オフセットCHART_AUTOSCROLL を無効にする必要があります。

はい、再生するための最初のステップでその点を指摘しました。

 
Ihor Herasko:

あなたの体型は?1861年を持っています。

はい、それはリプレイの最初のステップで指摘したことです。

1861も持っています。一度だけ再現することができた。他の試みはすべてうまくいっています。

 
Vladimir Karputov:

グラフとデータは、大きく分けて2つの違いがあります。

グラフアクセス機能はすべて非同期です。つまり、撮影して忘れるという片道旅行です。

いいえ、全部ではありません。そのようなものは、特にコメントアウトされています。例えば、同じChartApplyTemplate.

この場合、trueはこの関数のフィールドに正しく入力されたことだけを意味し、それ以上の意味はありません。

チャート自体がまだ存在しないのに、この関数はどうやってチャート ID が正しいと判断したのでしょうか?

すべてのデータが揃い、グラフがプロットされたときの符号がOncalculate/OnTickへの最初の入力となる。

残念ながら、そうではありません。以下はそのコードです。

#property indicator_chart_window 
int OnInit()
{
   Print(__FUNCTION__, ", баров: ", Bars(Symbol(), PERIOD_CURRENT));

   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
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[])
{
   Print(__FUNCTION__, ", баров: ", Bars(Symbol(), PERIOD_CURRENT));
   return(rates_total);
}

仕組みはこうです。

16:01:31.765    Test (XBNUSD,M1)        OnInit, баров: 0
16:01:33.531    Test (XBNUSD,M1)        OnCalculate, баров: 37026
16:01:34.010    Test (XBNUSD,M1)        OnCalculate, баров: 46484

チャートがまだ開かれていない、つまりデータがまだ生成されていない新しいシンボルでインジケータを実行します。

最初の行(OnInit)では、確かにデータはありません。しかし、チャートIDがあり、OnInit()でオブジェクトを作成すれば、正常にチャートに表示されます。

2行目にはすでにデータがありますが、不完全なものです。3回目の反復でデータは完成する。

OnCalculateの最初の呼び出しは、データのロードを保証するものではないと結論付けるのが妥当である。これは、チャートを開いた後のシンボルの最初のティックであり、ある程度のデータの後に来ることも、他のデータが全くない状態で来ることもあります。

トピックで提起された問題に戻ると、ChartNavigate()関数が パラメータの正しさをチェックしないことがわかります。OnInit()でまだデータがない(バーが0本)状態で、関数に-1000という値が渡された場合、バーがないのであれば、この値を正しいと考えることはできるでしょうか?結局のところ、他のどの関数も、存在しないインデックスでバーにアクセスすると、エラーを返します。しかし、ここでは成功している。具体的に何が成功しているのでしょうか?

 

ここでは、特別に9ティックの遅延、2種類のチャートの動き、強制再描画のフラグ(オン/オフ)を入れています。

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property indicator_chart_window 
#property indicator_plots 0
//--- input parameters
input bool redraw=true;
input ENUM_CHART_POSITION position=CHART_BEGIN;
//---
long count=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   count=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
   count++;
   Comment(count);
   if(count==9)
     {
      ResetLastError();
      if(position==CHART_BEGIN)
        {
         if(ChartNavigate(0,CHART_BEGIN,100))
            Print("Успешно. redraw ",redraw,". position ",EnumToString(position));
         else
            Print("Ошибка №",GetLastError(),". redraw ",redraw,". position ",EnumToString(position));
        }
      if(position==CHART_END)
        {
         if(ChartNavigate(0,CHART_END,-100))
            Print("Успешно. redraw ",redraw,". position ",EnumToString(position));
         else
            Print("Ошибка №",GetLastError(),". redraw ",redraw,". position ",EnumToString(position));
        }
      if(redraw)
         ChartRedraw();
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+


予備:CHART_BEGINは 安定しています。

ファイル:
Test.mq5  6 kb
 
Vladimir Karputov:

ここでは、特別に9ティックの遅延、2種類のチャートの動き、強制再描画のフラグ(オン/オフ)を入れています。


速報:CHART_BEGINは 安定して動作しています。

でも、ダニがいなかったら、週末はどうでしょう?そうすると、タイマーを接続する必要があります。

そして、解決すべき問題はただ一つ、ChartNavigateが正常に実行されたかどうかを判断する方法です。trueを返すということは、ただ「カチカチ」やっているだけで、実作業では何の役にも立たない。