- Основные характеристики индикаторов
- Главное событие индикаторов: OnCalculate
- Два типа индикаторов: для главного и отдельного окна
- Настройка количества буферов и графических построений
- Назначение массива в качестве буфера: SetIndexBuffer
- Настройка графических построений: PlotIndexSetInteger
- Правила сопоставления буферов и диаграмм
- Применение директив для настройки графических построений
- Установка названий для графических построений
- Визуализация пропусков данных (пустых элементов)
- Индикаторы с собственным подокном: размер и уровни
- Общие свойства индикаторов: заголовок и точность значений
- Поэлементное раскрашивание диаграмм
- Пропуск отрисовки на начальных барах
- Ожидание данных и управление видимостью (DRAW_NONE)
- Мультивалютные и мультитаймфреймовые индикаторы
- Отслеживание формирования баров
- Тестирование индикаторов
- Ограничения и преимущества индикаторов
- Создание заготовки индикатора в Мастере MQL
Назначение массива в качестве буфера: SetIndexBuffer
Роль индикаторных буферов могут выполнять любые динамические массивы типа double со временем существования от запуска программы и до её остановки. Самый распространенный способ определения такого массива — на глобальном уровне. Но в некоторых случаях удобнее делать массивы членами классов, после чего создавать глобальные объекты с массивами. Мы рассмотрим примеры такого подхода, когда реализуем мультивалютный индикатор (см. пример IndUnityPercent.mq5 в разделе Мультивалютные и мультитаймфреймовые индикаторы) и индикатор дельты объемов (см. IndDeltaVolume.mq5 в разделе Ожидание данных и управление видимостью).
Итак, опишем на глобальном уровне динамический массив buffer (без указания размера).
double buffer[]; |
Чтобы зарегистрировать его как буфер, в терминале существует специальная функция SetIndexBuffer. Как правило, она вызывается в обработчике OnInit, как и многие другие функции для настройки индикатора, которые мы рассмотрим позднее.
bool SetIndexBuffer(int index, double buffer[],
ENUM_INDEXBUFFER_TYPE mode = INDICATOR_DATA)
Функция связывает указанный по индексу (index) индикаторный буфер с динамическим массивом buffer. Значение index должно лежать в пределах от 0 до N - 1, где N — количество буферов, определенное директивой #property indicator_buffers.
Сразу после привязки массив еще не готов для работы с данными и даже не меняет свой размер, поэтому инициализацию и все расчеты следует выполнять уже в функции OnCalculate. Изменять размер динамического массива после его назначения в качестве индикаторного буфера нельзя. Для индикаторных буферов все операции по изменению размера производит сам терминал.
Направление индексации после связывания массива с индикаторным буфером по умолчанию устанавливается как в обычных массивах, но при необходимости его можно изменить с помощью функцию ArraySetAsSeries.
Функция SetIndexBuffer возвращает признак успешного выполнения (true) или ошибки (false).
Опциональный параметр mode указывает системе, каким образом будет использоваться буфер. Возможные значения собраны в перечислении ENUM_INDEXBUFFER_TYPE.
Идентификатор |
Описание |
---|---|
INDICATOR_DATA |
данные для отрисовки |
INDICATOR_COLOR_INDEX |
цвета отрисовки |
INDICATOR_CALCULATIONS |
внутренние результаты промежуточных вычислений |
По умолчанию индикаторный буфер предназначен для отрисовки данных (INDICATOR_DATA). Это значение привносит еще один эффект помимо отображения массива на графике: значение каждого буфера для бара под курсором мыши показываются в Окне данных. Правда, с помощью некоторых настроек индикатора это поведение можно изменить (см. свойство PLOT_SHOW_DATA в разделе Настройка графических построений). Большинство примеров в данной Главе относится к режиму INDICATOR_DATA.
Если для расчета индикатора требуется хранить промежуточные результаты для каждого бара, для них можно выделить вспомогательный неотображаемый буфер (INDICATOR_CALCULATIONS). Это более удобно, чем использование для тех же целей обычного массива, поскольку тогда программист должен самостоятельно управлять его размером. В данной Главе будет представлено два примера с INDICATOR_CALCULATIONS: IndTripleEMA.mq5 (см. раздел Пропуск отрисовки на начальных барах) и IndSubChartSimple.mq5 (см. раздел Мультивалютные и мультитаймфреймовые индикаторы).
Некоторые построения позволяют задавать для каждого бара цвет отображения. Для хранения информации о цвете используются цветовые буфера (INDICATOR_COLOR_INDEX). Цвет представлен целочисленным типом color, но все индикаторные буфера должны иметь тип double, и в них в данном случае хранится номер цвета из особой палитры, заданной разработчиком (см. раздел Поэлементное раскрашивание диаграмм и пример индикатора IndColorWPR.mq5 в нем).
Значения цветовых и вспомогательных буферов не отображаются в Окне данных, а также их нельзя получить с помощью функции CopyBuffer, которую мы изучим позднее в Главе про Использование встроенных и пользовательских индикаторов из MQL5.
Индикаторный буфер не инициализируется никакими значениями. Если какие-то его элементы не рассчитываются по тем или иным причинам (например, в настройках индикатора есть ограничение на максимальное количество баров или само графическое построение подразумевает редкие значащие элементы, между которыми должны быть пропуски, как между вершинами ZigZag-а), то их следует явным образом заполнить специальным "пустым" значением. "Пустое" значение не отображается на графике и не выводится в Окне данных. По умолчанию для него существует константа EMPTY_VALUE (DBL_MAX), но при необходимости его можно заменить на любое другое, например, на "обычный" 0. Это делается с помощью функции PlotIndexSetDouble.
С учетом новых знаний о функции SetIndexBuffer дополним наш очередной пример IndReplica1.mq5, который мы начали в предыдущем разделе. В частности, нам потребуется обработчик OnInit.
#property indicator_chart_window
|
Количество буферов определено директивой равным 1, поэтому назначение массива для единственного буфера использует индекс 0 (первый параметр SetIndexBuffer). Второй вызов функции является ошибочным и сделан только для демонстрации проблемы: поскольку индекс 1 подразумевает наличие двух объявленных буферов, он генерирует ошибку BUFFERS_WRONG_INDEX (4602).
В самом начале функции OnCalculate выведем размер массива еще раз. В этом месте он уже будет распределен под количество баров.
int OnCalculate(const int rates_total,
|
Теперь обратимся к вопросу, что наш индикатор будет считать. Как уже было сказано, мы пока не будем закладывать в него сложные формулы, а просто попытаемся скопировать переданную таймсерию из параметра data в буфер. Это отражено и в названии индикатора.
...
|
Теперь индикатор компилируется без предупреждений. Мы можем запустить на графике, и при настройках по умолчанию он должен дублировать в буфере значения цены закрытия баров. Это происходит благодаря краткой форме OnCalculate, мы рассматривали этот аспект в разделе Главное событие индикаторов: OnCalculate.
Однако мы обнаружим странную вещь: в Окне данных наш буфер действительно выводится и содержит правильные значения, однако на графике линии нет. Это следствие того, что за отображение отвечают графические построения, а не буфера. В текущей версии индикатора мы настроили только буфер. В следующем разделе мы создадим новую версию IndReplica2.mq5 и дополним необходимыми инструкциями.
Вместе с тем описанный эффект может быть полезен для создания "скрытных" индикаторов, которые не выводят свои линии на график, но доступны для программного чтения из других MQL-программ. При желании разработчик сможет скрыть даже упоминание индикаторных буферов из Окна данных (см. PLOT_SHOW_DATA в следующем разделе).
О том, как управлять индикаторами из MQL5-кода, будет рассказано в следующей главе.