Ошибки, баги, вопросы - страница 1391

 
Ilya Malev:

После нажатия на "обновить" все рассчиталось. Все таки в качестве пожелания - удобнее если бы данные индикаторов, созданных в ините рассчитывались до первого вызова OnCalculate/OnTimer etc.

Или чтобы была возможность после инита программно дождаться их просчета в цикле внутри индикатора. 

Чтобы рассчитать индикатор пользователю придется несколько раз жать "обновить" на графике. Надо ли ему это. Он вспомнит старый добрый МТ4 и останется на нем, не смотря на некоторые преимущества МТ5.

Любые расчёты в индикаторах НУЖНО делать только в OnCalculate().
 
Karputov Vladimir:
Любые расчёты в индикаторах НУЖНО делать только в OnCalculate().
Я говорю о показаниях индикатора Ишимоку в данном случае. Речь о показаниях индикаторов, которые используются в текущем, то есть в OnCalculate. Чтобы они рассчитывались до вызова OnCalculate, как это было в МТ4. Или чтобы можно было в OnCalculate дождаться их расчета. Иначе пользователям придется несколько раз нажимать на Обновить чтобы построить индикатор. Так как не все индикаторы строятся на всей истории за 1 секунду, бывают сложные индикаторы которые рассчитываются дольше. Все это время пользователю нужно будет куковать над кнопкой "Обновить", а в МТ4 нужно было просто ждать отрисовки.
 
Ilya Malev:
Я говорю о показаниях индикатора Ишимоку в данном случае. Речь о показаниях индикаторов, которые используются в текущем, то есть в OnCalculate. Чтобы они рассчитывались до вызова OnCalculate, как это было в МТ4.
В OnInit() осуществляется подготовка торгового окружения для индикатора. И только в OnCalculate() уже можно пользоваться данными индикатора.
 
Ilya Malev:
Я говорю о показаниях индикатора Ишимоку в данном случае. Речь о показаниях индикаторов, которые используются в текущем, то есть в OnCalculate. Чтобы они рассчитывались до вызова OnCalculate, как это было в МТ4. Или чтобы можно было в OnCalculate дождаться их расчета. Иначе пользователям придется несколько раз нажимать на Обновить чтобы построить индикатор. Так как не все индикаторы строятся на всей истории за 1 секунду, бывают сложные индикаторы которые рассчитываются дольше. Все это время пользователю нужно будет куковать над кнопкой "Обновить", а в МТ4 нужно было просто ждать отрисовки.

Периодически эта проблема всплывает на форуме. К сожалению вызов OnCalculate() в OnTimer() не решает проблему. 

Но всё же попробуйте. Пример есть в этой статье: Рецепты MQL5 - Разработка мультивалютного индикатора волатильности на MQL5.

Напишите потом, если не сложно, получилось или нет.

 
Karputov Vladimir:
В OnInit() осуществляется подготовка торгового окружения для индикатора. И только в OnCalculate() уже можно пользоваться данными индикатора.
Оказывается, что нельзя, не нажав кнопку "Обновить" на графике один или несколько раз (либо подождав 1/несколько тиков), если в индикаторе используются другие индикаторы с других символов и/или тф.
 
Anatoli Kazharski:

Периодически эта проблема всплывает на форуме. К сожалению вызов OnCalculate() в OnTimer() не решает проблему. 

Но всё же попробуйте. Пример есть в этой статье: Рецепты MQL5 - Разработка мультивалютного индикатора волатильности на MQL5.

Напишите потом, если не сложно, получилось или нет.

Спасибо за ссылку. Попробую и расскажу.
 
Ilya Malev:
Оказывается, что нельзя, не нажав кнопку "Обновить" на графике один или несколько раз (либо подождав 1/несколько тиков), если в индикаторе используются другие индикаторы с других символов и/или тф.

А если более внимательно просмотреть на работу кода, который я дал? И, в частности, в "Эксперты"? После перезапуска терминала на выходных:

2015.10.11 14:44:01.672 test (USDCAD,M5)        0
2015.10.11 14:44:01.681 test (USDCAD,M5)        1
2015.10.11 14:44:01.682 test (USDCAD,M5)        Расчитано 16518 баров за 0 секунд
2015.10.11 14:44:01.705 test (USDCAD,M5)        2
2015.10.11 14:44:01.705 test (USDCAD,M5)        Расчитано 16518 баров за 0 секунд

Отлично видно, что расчёт прошёл только на втором вызове OnCaalculate(). Таким образом никто не снимает с программиста ответственности по проверкам: проверяйте результат CopyBuffer() в OncalCulate() - если ничего не вернула функция, значит нужно проверить на следующем входе в OnCalculate().

 
Anatoli Kazharski:

Периодически эта проблема всплывает на форуме. К сожалению вызов OnCalculate() в OnTimer() не решает проблему. 

Но всё же попробуйте. Пример есть в этой статье: Рецепты MQL5 - Разработка мультивалютного индикатора волатильности на MQL5.

Напишите потом, если не сложно, получилось или нет.

Статью пока не прочитал, но прием с OnTimer работает отлично

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   0
int i_ich=INVALID_HANDLE;
double ind_buf[];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetTimer(1);
   i_ich=iIchimoku(Symbol(),PERIOD_H4,9,26,52);
   if(i_ich==INVALID_HANDLE)
     {
      Print("Невозможно создать индиктор Ишимоку!");
      return(INIT_FAILED);
     }
   SetIndexBuffer(0,ind_buf,INDICATOR_DATA);
   ArraySetAsSeries(ind_buf,true);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

void OnTimer(){
   datetime Arr1[];
   double Arr2[];
   long Arr3[];
   int Arr4[];
   OnCalculate(0, 0, Arr1, Arr2, Arr2, Arr2, Arr2, Arr3, Arr3, Arr4);
}

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[])
  {
   static int count=0;
   static datetime now=0;
   if(now==0)  now=TimeLocal();
   if(count>=0){
      Print(count);
      double temp[];
      int copied=CopyBuffer(i_ich,0,0,1,temp);
      if(copied>0){
         Print("Расчитано ",BarsCalculated(i_ich)," баров за ",int(TimeLocal()-now)," секунд");
         EventKillTimer(); // Индикаторы рассчитались, далее работаем только с OnCalculate
         count=-1;
      }else
         count++;
   }
   if(rates_total==0)   return(0); // Если это вызов из OnTimer, то возврат
   
   // ...
   return(rates_total);
}

В общем тут по-кривому показано, что вызов OnCalculate из OnTimer работает) Нужно добавить передачу правильных значений в таймсериях 

 
Ilya Malev:

Статью пока не прочитал, но прием с OnTimer работает отлично

В простых индикаторах вполне нормально. А вот в более сложных, почему-то иногда буксует. )
 
Ilya Malev:

Статью пока не прочитал, но прием с OnTimer работает отлично

Пользуйтесь Стилизатором - так лучше выявлять ошибки.

   if(count>=0)
     {
      Print(count);
      double temp[];
      int copied=CopyBuffer(i_ich,0,0,1,temp);
      if(copied>0)
        {
         Print("Расчитано ",BarsCalculated(i_ich)," баров за ",int(TimeLocal()-now)," секунд");
         EventKillTimer(); // Индикаторы рассчитались, далее работаем только с OnCalculate
         count=-1;
        }
      else
         count++;
     }
Увеличение переменной count нужно делать перед выходом из OnCalculate() -  в таком случае эта переменная будет правильно считать все заходы в OnCalculate.
Причина обращения: