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 не сработает, отобразив график без смещения.
Ладно, если бы функция выдавала ошибку. Но ее нет. Все вызовы проходят успешно, но именно при перезагрузке терминала смещение графика не происходит.

 
Вы применяете функцию, которая работает с графиком. Для индикатора гарантия создания графика - первый вход в OnCalculate, для советника - первый вход в OnTick(). Но ни как не ранее.
 
Vladimir Karputov:
Вы применяете функцию, которая работает с графиком. Для индикатора гарантия создания графика - первый вход в OnCalculate, для советника - первый вход в OnTick(). Но ни как не ранее.

Не вопрос. Если графика еще нет, то пусть функция вернет false и соответствующий код ошибки. Но этого нет, функция гордо рапортует об успешном выполнении. Обращаю внимание на то, что в документации не сказано о том, что это признак успешной отправки сообщения графику. Там четко написано: успешное выполнение функции.

Кроме того, это код для воспроизведения. На самом же деле еще до вызова ChartNavigate у меня идет обращение к таймсериям. И все они правильно заполнены, как оказывается. То есть график уже есть, есть его данные. Более того - с графика можно считать графические объекты, которые были помещены на него перед закрытием терминала.

Таким образом, по всем признакам график уже существует.

 

Странности какие-то. У меня отрабатывает без проблем.

И ещё одно замечание: Перед смещением графика надо отключить его автоматическое смещение CHART_AUTOSCROLL

 
Ihor Herasko:

Не вопрос. Если графика еще нет, то пусть функция вернет false и соответствующий код ошибки. Но этого нет, функция гордо рапортует об успешном выполнении. Обращаю внимание на то, что в документации не сказано о том, что это признак успешной отправки сообщения графику. Там четко написано: успешное выполнение функции.

Кроме того, это код для воспроизведения. На самом же деле еще до вызова ChartNavigate у меня идет обращение к таймсериям. И все они правильно заполнены, как оказывается. То есть график уже есть, есть его данные. Более того - с графика можно считать графические объекты, которые были помещены на него перед закрытием терминала.

Таким образом, по всем признакам график уже существует.

График и данные - две большие разницы. 

Все функции обращения к графикам - асинхронные: то есть путь в один конец - выстрелили и забыли. И в таком случае true означает всё лишь, что Вы правильно заполнили поля этой функции, не более.

Признак когда все данные готовы и графики построены это первый вход в Oncalculate/OnTick.

 
Vladimir Karputov:

График и данные - две большие разницы. 

Все функции обращения к графикам - асинхронные: то есть путь в один конец - выстрелили и забыли. И в таком случае true означает всё лишь, что Вы правильно заполнили поля этой функции, не более.

Признак когда все данные готовы и графики построены это первый вход в Oncalculate/OnTick.

Как тогда объясните тот факт что у меня работает безупречно??? В OnInit() именно так как в первом сообщении темы... Зачем ахинею сочинять?

 
Alexey Viktorov:

Странности какие-то. У меня отрабатывает без проблем.

Какой у Вас билд? У меня 1861.

И ещё одно замечание: Перед смещением графика надо отключить его автоматическое смещение CHART_AUTOSCROLL

Да, об этом я указал в первом шаге для воспроизведения.

 
Ihor Herasko:

Какой у Вас билд? У меня 1861.

Да, об этом я указал в первом шаге для воспроизведения.

У меня тоже 1861. Получилось воспроизвести только один раз. Все остальные попытки отработало нормально.

 
Vladimir Karputov:

График и данные - две большие разницы. 

Все функции обращения к графикам - асинхронные: то есть путь в один конец - выстрелили и забыли.

Нет, не все. Те, которые так устроены, специально прокомментированы. Например, тот же 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() создать объекты, которые затем успешно отобразятся на графике.

Во второй строке данные уже есть, но они неполные. Полнота данных достигнута на третьей итерации.

Резонно сделать вывод, что первый вызов OnCalculate не является гарантией подгрузки данных. Это просто первый тик по символу после открытия графика, который может прийти как после некоторого количества данных, так и без наличия других данных вообще.

Возвращаясь к проблеме, поднятой в теме, получаем, что функция ChartNavigate() не проверяет правильность параметров. Ведь если в OnInit() данных еще нет (0 баров), а в функцию передано значение -1000, то как же такое значение можно считать корректным, если баров нет? Ведь любая другая функция вернет ошибку при обращении к бару с несуществующим индексом. А здесь - успешно. Что же именно успешно?

 

Вот такой индикатор - специально поставил задержу в девять тиков, два вида перемещения графика и флаг принудительной перерисовки (вкл/откл)

//+------------------------------------------------------------------+
//|                                                      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:

Вот такой индикатор - специально поставил задержу в девять тиков, два вида перемещения графика и флаг принудительной перерисовки (вкл/откл)


Предварительно: CHART_BEGIN работает стабильно.

А если тиков нет, выходные? Тогда уже таймер придется подключать.

А нужно ведь решить один-единственный вопрос: как определить факт успешной отработки ChartNavigate? То, что она возвращает true,  это просто "для галочки", реальной работе никак не помогает.

Причина обращения: