Обсуждение статьи "Как перенести расчетную часть любого индикатора в код эксперта"

 

Опубликована статья Как перенести расчетную часть любого индикатора в код эксперта:

Причины для переноса кода индикатора в советник могут быть различными. Но как оценить плюсы и минусы такого подхода? В данной статье предлагается технология переноса кода индикатора в советник. Проведены несколько экспериментов по оценке скорости работы советника.

Вот что нам предстоит сделать для переноса расчетной части индикатора в советник.

  1. Организовать работу индикаторных буферов. Для этого мы создадим класс CArrayBuffer, а в нем — методы для хранения данных и удобного доступа к ним. Позже мы создадим массив таких классов по количеству буферов в индикаторе.
  2. Расчетную часть индикатора из функции OnCalculate перенесем в функцию Calculate нашего класса.
  3. Доступ к таймсериям индикатор получает из параметров функции OnCalculate, чего нет у функций советника. Поэтому организуем загрузку необходимых таймсерий в функции LoadHistory.
  4. Чтобы унифицировать доступ к пересчитанным данным индикатора, создадим в классе CIndicator функцию CopyBuffer с необходимыми параметрами. 

Всю предстоящую работу можно обобщить в нижеследующую схему.

Автор: Dmitriy Gizlyk

 

Спасибо, хорошо сделано.

bool CIndicator::LoadHistory(void)
  {
   datetime cur_date=(datetime)SeriesInfoInteger(m_Symbol,m_Timeframe,SERIES_LASTBAR_DATE);
   if(m_last_load>=cur_date && ArraySize(m_source_data)>=m_history_len)
      return true;

Из этого кода получается, что на тиках пересчета не будет. Только на появлении новых баров. Или я плохо въехал в реализацию?

 
fxsaber:

Спасибо, хорошо сделано.

Из этого кода получается, что на тиках пересчета не будет. Только на появлении новых баров. Или я плохо въехал в реализацию?

Да, в статье сразу написано, что расчет делается по закрытым свечам. Для расчета на каждом тике нужно из кода убрать проверку открытия нового бара и копировать историю с "0" бара, а не с "1", как сейчас.
 
Dmitriy Gizlyk:
Да, в статье сразу написано, что расчет делается по закрытым свечам. Для расчета на каждом тике нужно из кода убрать проверку открытия нового бара и копировать историю с "0" бара, а не с "1", как сейчас.

Жаль, не сделали сравнение в потиковом.

Как дополнение, в этом режиме не обойтись без CopyTicks в реализации, чтобы "индикаторы" отрабатывали полноценно.

 
fxsaber:

Жаль, не сделали сравнение в потиковом.

Как дополнение, в этом режиме не обойтись без CopyTicks в реализации, чтобы "индикаторы" отрабатывали полноценно.

Я не знаю, о каком индикаторе идет речь. Но обычно индикаторы работают по ценам баров и перерисовывают последний бар. В таком случае можно и не загружать CopyTicks, а использовать туже загрузку исторических данных. Правда, в таком случае нужно будет в классе добавить пересчет последнего значения.

 
Dmitriy Gizlyk:

Я не знаю, о каком индикаторе идет речь. Но обычно индикаторы работают по ценам баров и перерисовывают последний бар. В таком случае можно и не загружать CopyTicks, а использовать туже загрузку исторических данных. Правда, в таком случае нужно будет в классе добавить пересчет последнего значения.

Встроенный в советник индикатор будет пропускать тики. Чтобы этого не происходило, и требуется CopyTicks для получения тиков между соседними вызовами OnTick, OnTimer и т.д.

Иначе можно серьезно терять инфу

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотеки: HistoryTicks

fxsaber, 2018.04.10 17:53

Боевой советник на высокочастотном символе (200-350 тиков в минуту) с частыми торговыми приказами (несколько раз в минуту) и пингом 100 ms в стандартном режиме работы теряет ~5% тиков.

 
fxsaber:

Встроенный в советник индикатор будет пропускать тики. Чтобы этого не происходило, и требуется CopyTicks для получения тиков между соседними вызовами OnTick, OnTimer и т.д.

Иначе можно серьезно терять инфу

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

 

Здравствуйте! Спасибо за Вашу статью.

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

К сожалению в тестовых примерах не понятна и не видна именно организация связи между элементами массива и барами на графике, все остальное понятно. Как именно расставить и увидеть нужные точки(или символы) на графике? Хотелось бы прояснить этот момент. Спасибо еще раз!!

 
IuriiPrugov:

Здравствуйте! Спасибо за Вашу статью.

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

К сожалению в тестовых примерах не понятна и не видна именно организация связи между элементами массива и барами на графике, все остальное понятно. Как именно расставить и увидеть нужные точки(или символы) на графике? Хотелось бы прояснить этот момент. Спасибо еще раз!!

Добрый день, Юрий.
В первую очередь, прошу прощения за задержку с ответом. В MQL при доступе к таймсериям принято считать текущий бар с индексом "0", а исторические данные идут с увеличением индекса. Подробнее об этом можно прочитать в документации по ссылке. Аналогичный подход был организован и при доступе к расчетным данным индикатора. Т.е. в любой момент при доступе к данным последней закрытой свечи Вы указываете индекс "1".

 

DMITRIY GIZLYK, спасибо за статью.

Интересует вопрос многопоточности, можно ли как-то класс запустить параллельно, на отдельном ядре процессора? Вы упомянули в конце статьи "преимущество может быть нивелировано многопоточной архитектурой MetaTrader 5".

Dmitriy Gizlyk
Dmitriy Gizlyk
  • www.mql5.com
Опубликовал статью Нейросети - это просто Каждый раз, когда речь заходит об искусственном интеллекте, в голове всплывают какие-то фантастические образы и кажется, что это очень сложное и непостижимое. Но мы все чаще и чаще слышим об искусственном интеллекте в повседневной жизни. В новостных лентах все чаще пишут о каких-либо достижениях с...
 
Dmitriy Gizlyk:
Да, в статье сразу написано, что расчет делается по закрытым свечам. Для расчета на каждом тике нужно из кода убрать проверку открытия нового бара и копировать историю с "0" бара, а не с "1", как сейчас.

Я правильно понял, для работы с полным набором данных таймсерий нужно добавить массивы кроме этого:

массив исходных данных для расчета (m_source_data);

То есть если индикатор обращается к разным данным по барам - времени time[], максимальной и минимальной цене high[] low[], то нужно добавить еще 3 массива аналога m_source_data и скопировать туда данные в  CIndicator::LoadHistory,

а так как функция виртуалка, то можно её переписать прямо в индикаторе?

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