Как сохранить ссылку или указатель на массив, полученный в OnCalculate() ? Что сейчас предлагают разработчики ?

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Georgiy Merts
9191
Georgiy Merts  

Очередной раз сталкиваюсь со старой проблемой - в OnCalculate() передаются массивы, с которыми работает индикатор.

Как сохранить указатели или ссылки на них, чтобы затем обращаться к необходимым данным ?

Как я понимаю, по-прежнему есть только два не больно приятных варианта.

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

2. На каждом OnCalculate() сперва копировать данные массивов в свой массив типа CArrayDouble - и сохранять указатель на него, в дальнейшем использовать именно его.


Мне оба варианта совершенно не нравятся.

В первом - невозможно использовать структуру классов. (Скажем, у вас есть класс, вычисляющий канал, который получает данные с помощью виртуальных функций - как передать в него указатели на массивы OHLC ?)

Во втором - на каждом вызове OnCalculate() происходит совершенно излишнее копирование всего массива (ну или по крайней мере, той его части, которая будет пересчитана).


Изменилось ли сейчас что-то в этом плане ?

Было бы неплохо иметь функцию int OnCalculate(const int rates_total,const int prev_calculated,const CArrayDatetime* time, const CArayDouble* open, CArrayDouble* high...) - в общем, аналог функйи OnCalculate(), работающий с объектами Стандартной Библиотеки, на которые можно сохранять указатели, а не с массивами, на который ни указателей, ни ссылок нет.  


Вобще, хотелось бы знать, как народ работает с этими массивами в сложных многуровневых вложенных функциях и классах ?

fxsaber
16830
fxsaber  
George Merts:

аналог функйи OnCalculate(), работающий с объектами Стандартной Библиотеки

Категорически против встроенности СБ в язык.

Делайте Calculate-буферы для Open, High и т.д. В OnCalculate только дописывайте rates_total-prev_calculated. И работайте с буферами уже, которые видны везде. 

Georgiy Merts
9191
Georgiy Merts  
fxsaber:

Категорически против встроенности СБ в язык.

А никто ничего встраивать не предлагает.

Я говорю, что было бы хорошо иметь ДОПОЛНИТЕЛЬНО такую функцию. Чтобы копирование сразу было в объекты типа CArrayDouble.

Кому необходимы обычные массивы - старую функцию, безусловно, следует оставить.

fxsaber:

Делайте Calculate-буферы для Open, High и т.д. В OnCalculate только дописывайте rates_total-prev_calculated. И работайте с буферами уже, которые видны везде. 

И как обойтись без лишнего копирования ?

Вопрос как раз в том, чтобы обойтись без копирования. А то, что ты предлагаешь - я так и делаю, это второй вариант, который мне не нравится.

Vasiliy Sokolov
30029
Vasiliy Sokolov  

George Merts: 

Очередной раз сталкиваюсь со старой проблемой - в OnCalculate() передаются массивы, с которыми работает индикатор.

Как сохранить указатели или ссылки на них, чтобы затем обращаться к необходимым данным ?

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

George Merts:

Было бы неплохо иметь функцию int OnCalculate(const int rates_total,const int prev_calculated,const CArrayDatetime* time, const CArayDouble* open, CArrayDouble* high...) - в общем, аналог функйи OnCalculate(), работающий с объектами Стандартной Библиотеки, на которые можно сохранять указатели, а не с массивами, на который ни указателей, ни ссылок нет.  

Этого никогда не будет. Стандартные классы не в части у MQ, в том смысле что весь API к МТ написан без единого класса. Более коцептуально правильным решением было бы ввести третий формат iCustom:

//+------------------------------------------------------------------+
//| Accumulation/Distribution                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int prev_calculated,
                const MqlRates &rates[]
                )
  {
  }

Сразу куча проблем решается с тасканием этих бесконечных массивов между функциями.

Также есть вариант забить на то, что дает сама iCustom и работать с котировками через функции Copy*, но этот вариант тоже имеет свои недостатки.

fxsaber
16830
fxsaber  
George Merts:

А то, что ты предлагаешь - я так и делаю, это второй вариант, который мне не нравится.

Нет, я предлагаю дописывать в специально созданные индикаторные буферы для этого.

Т.е. не в свой массив, а именно в индикаторные буферы. 

Georgiy Merts
9191
Georgiy Merts  
Vasiliy Sokolov:
 
//+------------------------------------------------------------------+
//| Accumulation/Distribution                                        |
//+------------------------------------------------------------------+
int OnCalculate(const int prev_calculated,
                const MqlRates &rates[]
                )
  {
  }

Сразу куча проблем решается с тасканием этих бесконечных массивов между функциями.

Где ж "решается", если мы не можем сохранить ни эту ссылку, ни указатель на этот массив ?

В данном случае - просто массивы значений заменены массивом структур, но дополнительное копирование необходимо все равно.

Georgiy Merts
9191
Georgiy Merts  
fxsaber:

Нет, я предлагаю дописывать в специально созданные индикаторные буферы для этого.

Т.е. не в свой массив, а именно в индикаторные буферы. 

А как иметь доступ к ним "при высокой вложенности" функций ? Предлагаешь опять же - тянуть ссылки через все вложенные функции ?
fxsaber
16830
fxsaber  
George Merts:
А как иметь доступ к ним "при высокой вложенности" функций ? Предлагаешь опять же - тянуть ссылки через все вложенные функции ?
Нет, это же индикаторные буферы. Ссылки на них незачем тянуть. Видны, как ::-массивы.
Georgiy Merts
9191
Georgiy Merts  
fxsaber:
Нет, это же индикаторные буферы. Ссылки на них незачем тянуть. Видны, как ::-массивы.

А... Понял. Да. Видны отовсюду.

А с копированием как ? Надо же, чтобы туда данные кто-то копировал ? Терминал копирует данные в исходные массивы, а потом мы еще их и в индикаторные передаем ? Неэффективно, по-моему.

Кстати, это тоже вариант - чтобы просто массивы, передаваемые в OnCalculate() - были бы глобальными. Тогда их никуда "тащить" не надо, они везде были бы видны.  Действительно. Тоже вполне годный.


А !!! Или ты предлагаешь создать индикаторые буффера, и именно их и использовать в OnCalculate(), чтобы терминал сразу их заполнял ? А они уже, видны везде, и мы используем данные из них ? А ну, а ну... попробуем... Хотя, интересно, как быть с буффером времени, объема и спреда... Ну, сейчас поглядим.

Что-то пишет "declaration of 'Open' hides global declaration at line 13 Buffers_Core.mq5" - похоже, не получается подсунуть в OnCalculate созданный буффер...
fxsaber
16830
fxsaber  
George Merts:

А !!! Или ты предлагаешь создать индикаторые буффера, и именно их и использовать в OnCalculate(), чтобы терминал сразу их заполнял ? А они уже, видны везде, и мы используем данные из них ? А ну, а ну... попробуем... Хотя, интересно, как быть с буффером времени, объема и спреда... Ну, сейчас поглядим.

Индикаторные буферы для этой цели годятся больше, чем просто массивы, т.к. не нужно контролировать размер массива, сдвиги цен и т.д. Надо только в OnCalculate  в начале прописать дописывание в индикаторный буфер N (rates_total - prev_calculated) значений.

Но, честно говоря, не сталкивался с навязанной тягой хвостов. Наверное, сложных индикаторов не писал.

Georgiy Merts
9191
Georgiy Merts  
fxsaber:

Индикаторные буферы для этой цели годятся больше, чем просто массивы, т.к. не нужно контролировать размер массива, сдвиги цен и т.д. Надо только в OnCalculate  в начале прописать дописывание в индикаторный буфер N (rates_total - prev_calculated) значений.

Но, честно говоря, не сталкивался с навязанной тягой хвостов. Наверное, сложных индикаторов не писал.

Не, гляди. Есть класс, который, скажем, рассчитывает канал регрессии. Только не первой степени (как стандартный), а, скажем, третьей степени, чтобы получились две красивые кубические параболы. В нем есть функция double GetCubic(int Idx) - которая возвращает точки этих парабол в соответствующих барах. Вызываешь ее, и возвращаемые значения - и есть канал регрессии третьей степени.

Внутри класса данные запрашиваются с помощью виртуальной функции double GetPrice(int iIdx). То есть, когда ты хочешь построить этот самый канал регрессии третьей степени - тебе достаточно пронаследовать класс, и перегрузить в нем эту самую виртуальную функцию, возвращая значения цены по указанному индексу. После чего вызываешь GetCubic() - и рисуешь свои параболы.

Как передать в функцию GetPrice(int iIdx) значения из массива Close[iIdx] ?

Был бы массив виден везде - никаких вопросов бы не возникло. Можно было бы запомнить указатель или ссылку на него - опять же, никаких вопросов. А так - приходится сперва переписывать значения в промежуточный буффер, и потом отдавать их в виртуальной функции GetPrice().

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий