2. Создание индикаторовпожалуй, сначала опишу основные сущности из чего состоит индикатор..
собственно, индикатор это программа с расширением mq4, которая должна находиться в каталоге experts\indicators вашего терминала
и так, индикатор определяется своими декларациями, а именно, обязательной декларацией является
- Код: выделить все
#property indicator_chart_window
или
- Код: выделить все
#property indicator_separate_window
соответственно, первая говорит о том, что индикация выводится в основное окно с графиком, а вторая в дополнительное окно
далее следует декларация количества используемых индикаторных буферов с указанием количества используемых буферов (от 1 до 8)
- Код: выделить все
#property indicator_buffers 1
эта декларация нужна, если данные для индикации предполагается выводить через индикаторные буферы, если же индикатор будет рисовать отдельные графические объекты (стрелки, линии и т.п.), то декларация не нужна
далее я буду писать только о параметрах и настройках применимо к использованию индикаторных буферов..далее следуют параметры цвета выводимой индикации indicator_colorN, где номер буфера (от 1 до 8) с названием цвета
- Код: выделить все
#property indicator_color1 Yellow
#property indicator_color2 Red
и т.д.
далее следуют какие-то глобальные и/или внешние параметры, например,
- Код: выделить все
extern int drawBegin = 1000;
extern int shiftPrice = 10;
далее обязательны double массивы, в которые будут заноситься данные цен (или еще какие данные), по которым будет выводиться графическая информация, например,
- Код: выделить все
double buff[];
теперь важный момент, все (почти все) начальные определения для используемых индикаторных буферов задаются в системной функции
init()
рассмотрим это подробнее, и так по порядку, допустим мы создаем индикатор, который будет рисовать линию закрытия цен в основном окне, сам индикатор не несет ничего полезного, разве что понимание того что и как в нем устроено..
для такого индикатора потребуется один буфер, и соответственно, один массив типа
double..
чтобы индикатор выводил нужную индикацию нужно задать настройки индикации - что есть что и как будет отображаться
назначаем 0-му индикаторному буферу массив, в котором будут храниться его данные
- Код: выделить все
SetIndexBuffer(0, buff);
устанавливаем индикаторному буферу все значение в 0, т.е. все значения в
buff будут нулями
это
необязательная опция, она приведена для информации, иногда требуются определенные начальные значения в буфере
- Код: выделить все
SetIndexEmptyValue(0, 0);
не обязательная опцияустанавливает номер бара, с которого необходимо начать рисовать индикацию
- Код: выделить все
SetIndexDrawBegin(0, drawBegin);
не обязательная опцияустанавливаем подпись - название индикации, она отображается во всплывающем окошке когда подводишь курсор к индикации
- Код: выделить все
SetIndexLabel(0, "наша цена");
устанавливаем тип отображаемой индикации, в данном случае линия, у функции
SetIndexStyle() есть еще три необязательных параметра,
которые здесь не использованы, после типа индикации (
DRAW_LINE) идут параметры стиль, толщина и цвет линии
кстати, наличие последнего параметра (цвета) отменяет необходимость объявлять параметр
indicator_colorN- Код: выделить все
SetIndexStyle(0, DRAW_LINE);
не обязательная опциясдвиг отображаемой индикации на
shiftPrice баров влево, т.е. вся индикация сдвигается как бы
shiftPrice становится нулевым для отображаемой индикации - иначе говоря смена центра координат,
но только для отображения, в
buff значения остаются на своих местах
- Код: выделить все
SetIndexShift(0, shiftPrice);
в итоге имеет функцию
init() вида
- Код: выделить все
int init(){
SetIndexBuffer(0, buff);
SetIndexEmptyValue(0, 0);
SetIndexDrawBegin(0, drawBegin);
SetIndexLabel(0, "наша цена");
SetIndexStyle(0, DRAW_LINE);
SetIndexShift(0, shiftPrice);
}
далее осталось написать код функции
start(), который будет обрабатывать данные и записывать их в массив buff, собственно, код простой
- Код: выделить все
int bars = 0, // количество не обсчитанных баров
i = 0; // индекс дальнего (от текущего нулевого бара) не обсчитанного бара
количество не обсчитанных баров на текущем тике, по приходу первого тика после прикрепления индикатора к графику
функция
IndicatorCounted() возвращает количество всех баров, которые доступны на текущем графике, т.к. их еще не считали
на последующих тиках функция возвращает 1, т.е. текущий не посчитанный бар, и только при появлении нового бара возвращает 2,
т.к. при закрытии бара и открытии нового и там и там было (могло быть) изменение цен
- Код: выделить все
bars = IndicatorCounted();
такого быть в нормальных условиях быть не должно, т.к. всегда есть 1 бар - текущий, на котором изменилось значение,
и поэтому этот бар считается не обсчитанным, возможно, такая ситуация случается при разрывах соединения с сервером (?!)
- Код: выделить все
if (bars < 0) return(-1);
здесь
Bars это общее число баров на графике, т.е. от начала справа и до конца по истории влево,
и здесь мы вычисляем индекс, с которого начинаются не обсчитанные бары, последний член выражения (-1) используется из-за того,
что индексы начинаются с нуля, поэтому на один меньше
- Код: выделить все
i = Bars - bars - 1;
// перебираем все не обсчитанные бары
- Код: выделить все
while(i >= 0){
// заносим в i-й элемент буфера цену закрытия на этом буфере
buff[i] = Close[i];
// уменьшаем индекс на единицу
i--;
}
вот собственно и все, что касается самой отрисовки индикации, то это происходит автоматически, т.е. терминал считывает значения буферов,
и в соответствии с заданным типом индикации и параметров индикации выводит соответствующее отображение
и так, получаем итоговый индикатор
- Код: выделить все
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Yellow
extern int drawBegin = 1000;
extern int shiftPrice = 10;
double buff[];
int init(){
SetIndexBuffer(0, buff);
SetIndexEmptyValue(0, 0);
SetIndexDrawBegin(0, drawBegin);
SetIndexLabel(0, "наша цена");
SetIndexStyle(0, DRAW_LINE);
SetIndexShift(0, shiftPrice);
}
int start(){
int bars = 0, i = 0;
bars = IndicatorCounted();
if (bars < 0) return(-1);
i = Bars - bars - 1;
while(i >= 0){
buff[i] = Close[i];
i--;
}
}
на этом пока все, надеюсь хоть какое-то мало-мальски понятное представление складывается об устройстве индикаторов, хотя бы таких простых как этот, пока что нет оппонентов и апологетов жаждущих познания ;)
если что непонятно излагаю, уж извините за косность языка, но думаю это поправимо встречными вопросами с конкретикой где и что не понятно..