- Дескрипторы и счетчики владельцев индикаторов
- Простой способ создания экземпляров индикаторов: iCustom
- Проверка количества просчитанных баров: BarsCalculated
- Получение данных таймсерии из индикатора: CopyBuffer
- Поддержка множества символов и таймфреймов
- Обзор встроенных индикаторов
- Использование встроенных индикаторов
- Расширенный способ создания индикаторов: IndicatorCreate
- Гибкое создание индикаторов с помощью IndicatorCreate
- Обзор функций управления индикаторами на графике
- Комбинирование вывода в главное окно и вспомогательное
- Чтение данных из диаграмм, имеющих сдвиг
- Удаление экземпляров индикаторов: IndicatorRelease
- Получение настроек индикатора по его дескриптору
- Определение источника данных для индикатора
Комбинирование вывода в главное окно и вспомогательное
Вернемся вновь к проблеме вывода диаграмм в главное окно и в подокно из одного индикатора, поскольку мы столкнулись с ней при разработке примера UseDemoAllSimple.mq5. Там мы выяснили, что индикаторы, предназначенные для отдельного окна, не подходят для визуализации на основном графике, а индикаторы для главного окна не имеют дополнительных окон. Существует несколько альтернативных подходов:
- Реализовать родительский индикатор для отдельного окна и выводить там диаграммы, а в главном окне использовать для отображения данных графические объекты. Это плохо, потому что данные из объектов нельзя считывать как из таймсерии, и множество объектов потребляет лишние ресурсы.
- Разработать для основного окна собственную виртуальную панель (класс), в которой в правильном масштабе отображать таймсерии, которые должны были бы выводиться в подокне.
- Использовать несколько индикаторов — как минимум один для главного окна и один для подокна — и обмениваться между ними данными через разделяемую память (требуется DLL), ресурсы или базу данных.
- Дублировать расчеты (использовать общий исходный код) в индикаторах для главного окна и подокна.
Мы представим один из вариантов решения, которое основывается на выходе за рамки одной MQL-программы: необходим дополнительный индикатор со свойством indicator_separate_window. Он у нас фактически уже есть — ведь мы создаем его расчетную часть, запрашивая дескриптор. Осталось лишь неким образом вывести его в отдельном подокне.
В новой (полной) версии UseDemoAll.mq5 мы будем анализировать метаданные запрошенного для создания индикатора в соответствующем элементе перечисления IndicatorType. Напомним, что там помимо прочего закодировано и рабочее окно каждого типа встроенного индикатора. Когда индикатор требует отдельное окно, мы будем создавать таковое с помощью специальных функций MQL5, с которыми еще предстоит познакомиться.
Для пользовательских индикаторов неоткуда взять информацию о рабочем окне. Поэтому добавим входную переменную IndicatorCustomSubwindow, в которой пользователь сможет указать, что требуется подокно.
input bool IndicatorCustomSubwindow = false; // Custom Indicator Subwindow |
В OnInit скроем буферы, предназначенные для подокна.
int OnInit()
|
После этой настройки нам придется воспользоваться парой функций, которые относятся не только к работе с индикаторами, но и с графиками. Мы подробно изучим их в соответствующей главе, а вводный обзор представлен в предыдущем разделе.
Одна из функций ChartIndicatorAdd позволяет добавить индикатор, заданный дескриптором, в окно, причем не только в главную часть, но и в подокно. Об идентификаторах графиков и нумерации окон мы поговорим в главе про графики, а сейчас достаточно знать, что следующий вызов функции ChartIndicatorAdd добавляет индикатор с дескриптором handle на текущий график, в новое подокно.
int handle = ... // получаем дескриптор индикатора, iCustom или IndicatorCreate
|
Зная о такой возможности, нетрудно выдвинуть идею о вызове ChartIndicatorAdd с передачей ей дескриптора уже готового подчиненного индикатора.
Вторая функция, которая нам потребуется, называется ChartIndicatorName. Она возвращает краткое имя индикатора по его дескриптору. Данное имя соответствует свойству INDICATOR_SHORTNAME, установленному в коде индикатора, и может отличаться от названия файла. Имя потребуется, чтобы подчистить за собой, то есть удалить вспомогательный индикатор и его подокно, после удаления или перенастройки родительского индикатора.
string subTitle = "";
|
В обработчике OnDeinit используем сохраненный заголовок subTitle для вызова еще одной функции, которую мы изучим позднее — ChartIndicatorDelete — она удаляет с графика индикатор с именем, указанном в последнем аргументе.
void OnDeinit(const int)
|
Здесь предполагается, что на графике работает только наш индикатор, и только в единственном экземпляре. В более общем случае для корректного удаления следует анализировать все подокна, но это потребовало бы ещё нескольких функций из тех, что будут представлены в главе про графики, поэтому ограничимся пока простым вариантом.
Если теперь запустить UseDemoAll и выбрать какой-нибудь индикатор из списка, помеченный звездочкой (т.е. требующий подокна), например, тот же RSI, увидим ожидаемый результат: RSI в отдельном окне.
RSI в подокне, созданном индикатором UseDemoAll