Основы написания пользовательских индикаторов


Введение

Целью данной статьи является объяснение принципов построения пользовательских индикаторов на одном примере и рассмотрение «подводных камней», с которыми могут встретиться программисты, делающие первые шаги в освоении языка NTL+.


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


В качестве примера создадим индикатор, который будет показывать разность между количеством баров с ценой закрытия больше цены открытия и количеством баров с ценой закрытия меньше цены открытия; эти разности накапливаются за последние n интервалов. Будем отображать наш индикатор в отдельном окне и показывать в виде гистограммы.


Написание кода скрипта

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

Рассмотрим код такого индикатора.


Для начала нужно объявить все переменные, которые будут использоваться в нашем индикаторе.

#set_indicator_separate double ExtMapBuffer1[]; int ExtCountedBars=0; extern int period = 10;

Директива препроцессора #set_indicator_separate указывает, что мы будем выводить график в отдельным окне и он не будет накладываться на основной график цены. В следующей строке объявляется глобальный массив ExtMapBuffer1, в котором будут храниться значения индикаторного буфера. Обратите внимание, что мы не указываем размер этого массива, так как компилятор самостоятельно определит необходимый объем выделяемой памяти.


В массиве ExtMapBuffer1 фактически хранятся координаты ординат точек, участвующих в отображении, а их абсциссы определяются индексом элементов массива. Затем мы инициализируем переменную ExtCountedBars значением 0. В этой переменной будет храниться количество уже рассчитанных баров. Таким образом, нам не нужно каждый раз производить вычисления для всех баров, что значительно ускоряет вычисление значений индикатора; передвижение графика индикатора будет происходить быстрее. В следующей строке объявлена глобальная переменная period для хранения количества интервалов, на которых индикатор вычисляет заданную статистику. Обратите внимание на то, что использование модификатора extern дает нам возможность менять параметр period через свойства индикатора без необходимости перекомпиляции.


Рассмотрим функцию Initialize(), в которой будем указывать базовые настройки для нашего индикатора.


Метод SetIndexCount объекта Indicator устанавливает количество буферов значений индикаторов. Буфер со значениями ExtMapBuffer1 у нас один, поэтому указываем единицу в качестве единственного параметра. Также нам будет нужно связать номер буфера и массив со значениями буфера. Эта связка задается в строчке Indicator.SetIndexBuffer(0,ExtMapBuffer1), где определено, что свойства нулевого индикатора используются для отрисовки значений из буфера ExtMapBuffer1.


В следующей строке мы задаем свойства для нашего индикатора. Первый параметр метода SetIndexStyle задает номер буфера; это значение 0, которое мы указали в SetIndexBuffer. Второй параметр определяет тип отрисовки: гистограмма. В третьем параметре задаем стиль линий lsSolid (фактически тут можно задать любое значение, так этот параметр влияет только на линии и гистограммы с единичной толщиной). В следующих параметрах задаем толщину линии 5 и цвет синий в виде константы clrBlue (цвет можно также задавать в RGB формате, например, 0x0000FF).


Затем идет функция Run(), которая выполняет базовые проверки и запускает пользовательскую функцию draw(). Функция draw() выполняет весь расчет.