Погружаемся в особенности индикаторов MetaTrader 5 - страница 5

 
Yedelkin:
Вместо передачи готового хендла искать этот хендл из индикатора № 2?
Про передачу готового хэндла в другой индикатор не скажу, с этим не экспериментировал. Могу сказать определенно, что если все полученные хэндлы индикатора удалить как положено, то уже не следует заботиться о выделенной для него памяти, это забота терминала.
А потом что будет? Увеличится счетчик ссылок на единственную копию индикатора № 1, которая и будет вести расчёты? А память, занятая второй копией индикатора №1, освободится?

Вопрос возник потому, что в индикаторе № 1 у меня используются классы, и чёрт меня дёрнул выводить на печать сигналы о запуске конструкторов этих классов. Когда смотрел логи, обнаружил, что конструкторы классов индикатора №1 запускаются дважды, из под обоих индикаторов, несмотря на одинаковые входные параметры, указываемые для iCustom(). Вот и ищу способы избавиться от лишних запусков второй копии индикатора №1.
Попробуйте посмотреть, сколько раз и в какой последовательнсоти срабатывают события OnInit/OnDeinit индикатора. Мало ли, что там не так с классами и их конструкторами.
 
alxm:  если все полученные хэндлы индикатора удалить как положено, то уже не следует заботиться о выделенной для него памяти, это забота терминала.

Так ведь озабоченность вызывает возможное лишнее потребление памяти во время работы индикатора (и его копий?), а не по окончании его работы :)

alxm: Попробуйте посмотреть, сколько раз и в какой последовательнсоти срабатывают события OnInit/OnDeinit индикатора. Мало ли, что там не так с классами и их конструкторами.

По ходу, komposter оказался прав. У меня предусмотрено, что на печать выводится как запуск Oninit() основного индикатора, так и запуск конструктора и деструктора класса из этого индикатора. При одном основном и трёх вспомогательных индикаторах четыре раза распечатывается связка "запуск OnInit() + запуск конструктора". Сейчас просмотрел, когда именно запускается деструктор класса. Выяснилось, что у трёх вспомогательных индикаторов запуск конструктора и деструктора класса, относящегося к основному индикатору, происходит в одну и ту же секунду. Т.е., скажем так, объект класса для основного индикатора создаётся и уничтожается одномоментно. Видимо, осуществляется тот самый "однократный расчёт основного индикатора".

Спасибо за поддержку! 

 
Yedelkin:

Так ведь озабоченность вызывает возможное лишнее потребление памяти во время работы индикатора (и его копий?), а не по окончании его работы :)

Мне непонятно, что Вы называете лишним потреблением памяти. Индикатор память занимает, копии - нет. По крайней мере, не появляются дополнительные буферы индикатора и его переменные. Если есть несколько хэндлов для индикатора с одинаковыми параметрами, то память может выделяться только для нужд учета этих хэндлов, и вряд ли много.

 
alxm:

Мне непонятно, что Вы называете лишним потреблением памяти. Индикатор память занимает, копии - нет. По крайней мере, не появляются дополнительные буферы индикатора и его переменные. Если есть несколько хэндлов для индикатора с одинаковыми параметрами, то память может выделяться только для нужд учета этих хэндлов, и вряд ли много.

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

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

Не берите в голову. 

 

Не смог найти ответ на такой вопрос:

если индикатор создаётся только для осуществления вычислительных операций (т.е. без графических построений), то почему вот такой код

#property indicator_buffers 2
#property indicator_plots 0

double aaa[],bbb[];

int OnInit()
  {   
   ResetLastError();
   if(!SetIndexBuffer(0,aaa,INDICATOR_CALCULATIONS)) Print("aaa[] _LastError = ",_LastError); return(-1);
   ResetLastError();
   if(!SetIndexBuffer(1,bbb,INDICATOR_CALCULATIONS)) Print("bbb[] _LastError = ",_LastError); return(-1);
   return(0);
  }

возвращает ошибку "bbb[] _LastError = 4602" ("Ошибочный индекс своего индикаторного буфера")? Т.е почему первое связывание с индексом 0 и типом данных INDICATOR_CALCULATIONS осуществляется нормально, а на втором связывании с индексом 1 и тем же типом данных возникает ошибка?

 
Yedelkin:

Не смог найти ответ на такой вопрос:

если индикатор создаётся только для осуществления вычислительных операций (т.е. без графических построений), то почему вот такой код

возвращает ошибку "bbb[] _LastError = 4602" ("Ошибочный индекс своего индикаторного буфера")? Т.е почему первое связывание с индексом 0 и типом данных INDICATOR_CALCULATIONS осуществляется нормально, а на втором связывании с индексом 1 и тем же типом данных возникает ошибка?

Во первых в коде написано "выйти по return(-1) после первого объявления", но даже если взять в скобки, всё равно это советник а не индикатор тк нет функции OnCalculate. Но даже если её поставить то всё равно ошибка тк нет директивы #property indicator_chart_window, либо в отдельном окне.

MQL5 определяет индикатор по наличию этой директивы предпроцессору и наличию функции OnCalculate. При чём оба условия должны быть.


Но даже при соблюдении всех условий баг действительно есть, я так же столкнулся с ним с неделю назад.

при #property indicator_plots 0 имеем баг уже на буффере b1[]. При наличии объявленной хоть одной линии plots баг исчезает.

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 0

double b0[],b1[],b2[];
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   ResetLastError();
   if(!SetIndexBuffer(0,b0,INDICATOR_CALCULATIONS)) {Print("b0[] _LastError = ",_LastError);}
   ResetLastError();
   if(!SetIndexBuffer(1,b1,INDICATOR_CALCULATIONS)) {Print("b1[] _LastError = ",_LastError);}
   ResetLastError();
   if(!SetIndexBuffer(2,b2,INDICATOR_CALCULATIONS)) {Print("b2[] _LastError = ",_LastError);}
   
   return(0);
  }
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {return(rates_total);}
//+------------------------------------------------------------------+



 
Urain: MQL5 определяет индикатор по наличию этой директивы предпроцессору и наличию функции OnCalculate. При чём оба условия должны быть.

Этот код - часть индикатора, вызвавшая вопросы. Оба условия в самом индикаторе есть. Согласен про отсутствие необходимых скобок для return(-1) - набивал на форуме вручную, пропустил. В индикаторе фигурные скобки имеются (иначе бы не распечатывалась сама ошибка). Но суть Вы уловили.

Urain: при #property indicator_plots 0 имеем баг уже на буффере b1[]. При наличии объявленной хоть одной линии plots баг исчезает.

 Да, речь именно об этом. Первое связывание с индексом 0 и типом данных INDICATOR_CALCULATIONS осуществляется нормально, а на втором связывании с индексом 1 и тем же типом данных возникает ошибка.

Может, по замыслу разработчиков, это - не баг, а третье необходимое условие для определения индикатора (ненулевой плотс)?   :) 

 
Yedelkin:

Этот код - часть индикатора, вызвавшая вопросы. Оба условия в самом индикаторе есть. Согласен про отсутствие необходимых скобок для return(-1) - набивал на форуме вручную, пропустил. В индикаторе фигурные скобки имеются (иначе бы не распечатывалась сама ошибка). Но суть Вы уловили.

 Да, речь именно об этом. Первое связывание с индексом 0 и типом данных INDICATOR_CALCULATIONS осуществляется нормально, а на втором связывании с индексом 1 и тем же типом данных возникает ошибка.

Может, по замыслу разработчиков, это - не баг, а третье необходимое условие для определения индикатора (ненулевой плотс)?   :) 

Вероятно так и есть, (ненулевой плотс) третье условие.

Вы когда делаете нерисуемый расчёт подразумеваете что им будет пользоваться советник либо другой индикатор, но даже если линия объявлена как INDICATOR_DATA то при вызове этого индикатора из советника или другого индикатора линия ведь не рисуется (и это уже оптимизировано на уровне ядра MQL5).

 
Urain: Вы когда делаете нерисуемый расчёт подразумеваете что им будет пользоваться советник либо другой индикатор, но даже если линия объявлена как INDICATOR_DATA то при вызове этого индикатора из советника или другого индикатора линия ведь не рисуется (и это уже оптимизировано на уровне ядра MQL5).
Да, линию объявил как INDICATOR_DATA в качестве каламбура, т.к. если plots == 0, то какие могут быть "данные для отрисовки"? Тем не менее, компилятор скушал это. В итоговой же версии моего индикатора все типы данных объявлены как INDICATOR_calculations.
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Свойства пользовательских индикаторов
Документация по MQL5: Стандартные константы, перечисления и структуры / Константы индикаторов / Свойства пользовательских индикаторов
  • www.mql5.com
Стандартные константы, перечисления и структуры / Константы индикаторов / Свойства пользовательских индикаторов - Документация по MQL5
Причина обращения: