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

 
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.
 
Ilya Malev:

...

В общем тут по-кривому показано, что вызов OnCalculate из OnTimer работает)

Нужно добавить передачу правильных значений в таймсериях 

В статье, как раз этот пример и показан. )

Вот ещё пример для тестов с таким же методом: Рецепты MQL5 - Разработка мультивалютного индикатора для анализа расхождения цен >>>

 
Karputov Vladimir:

Увеличение переменной count нужно делать перед выходом из OnCalculate() -  в таком случае эта переменная будет правильно считать все заходы в OnCalculate.

Там нужно было считать не все, а только до расчета Ишимоку. Все это время count было больше либо равно 0, а потом -1. Вообще это не имеет значения. Важно, что

1) При первом запуске индикатор запускался 1 раз (OnCalculate) и больше не запускается до следующего тика (на выходных и праздниках до нескольких суток), если не нажимать кнопку "Обновить"

2) При этом первом вызове индикатор Ишимоку не успел рассчитаться (что уж говорить о более сложных индикаторах)

3) Если использовать вместо OnCalculate OnTimer (либо вызывать OnCalculate из OnTimer), то пользователь может запустить индикатор, который построится сам, иначе ему придется нажимать на Обновить (возможно, несколько раз) либо ждать следующих тиков. Что является очевидным неудобством по сравнению с тем же МТ4.

Anatoli Kazharski:
В простых индикаторах вполне нормально. А вот в более сложных, почему-то иногда буксует. )
По-моему, проще всего вообще вместо OnCalculate использовать OnTimer.