В данном примере торгового робота рассмотрим создание собственных индикаторов технического анализа и вывод их на экран в окно графика.

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

Используя подход, описанный в файле «Создание индикаторов технического анализа.pdf», не получится получить доступ к двум инструментам и построить индикатор исходя из цен с двух инструментов. Ниже мы рассмотрим пример построения индикатора по двум графикам цены. Условие для скрипта торгового робота будет следующим. Нужно создать индикатор, который отображает разницу между ценой акции и ценой фьючерса, например для арбитражной торговли. В качестве инструментов возьмем акции Сбербанка и ближайший фьючерс на них SRH8.

Начнем. Создание индикаторов имеет ряд своих особенностей. Первое – это местоположение файла со скриптом торгового робота. Скрипт в обязательном порядке должен быть размещен в папке «LuaIndicators», которая в свою очередь находится в папке c программой QUIK. У меня на компьютере путь к папке выглядит следующим образом: C:\\QUIK_VTB24\\LuaIndicators. Если у Вас в папке программы QUIK нет папки «LuaIndicators», то ее необходимо сознать. Терминал QUIK считывает папку «LuaIndicators» и если находит скрипт на языке LUA, отвечающий минимально необходимым требованиям (о требованиях поговорим чуть позже), то сразу добавляет индикатор в список доступных индикаторов, список открывается, когда мы открываем окно «Добавление графика». Окно «Добавление графика» открывается из контекстного меню на графике пункт «Добавить график (индикатор)».

Еще один нюанс, если в коде индикатора допущена синтаксическая ошибка, то данный индикатор не будет отображаться в окне «Добавление графика».

Создадим новый файл для скрипта торгового робота с именем «023 График арбитраж.lua» и сохраним в папку LuaIndicators.

Перейдем к коду индикатора. Для индикатора существует, минимальный обязательный код, без которого терминал QUIK не сможет его распознать и работать с ним.

Минимальный код, на языке Lua выглядит следующим образом.

Разберем этот код.

Settings – это таблица, которая содержит настройки для графика. Настройки графика мы можем изменять в окне «Редактирование настроек графика». Здесь мы можем создать поля для различных настроек.

В строке кода 3 создана строка таблицы Settings с ключом Name в которую записано имя индикатора.

Далее, функция Init(), данная функция автоматически вызывается терминалом QUIK при добавлении индикатора на график и возвращает число линий на графике. В нашем случае будет одна линия, которая будет отражать разницу цены фьючерса и акций.

Функция OnCalculate(index), является основной функцией, она принимает на вход индекс свечи из источника данных и возвращает непосредственно значение индикатора для каждой свечки на графике, в ней же мы будем производить основной расчет значений для индикатора, хотя мы можем использовать и свои собственные функции для расчета значений индикатора.

Приступим к созданию индикатора. Первоначально разберемся с настройками. Наш индикатор уже имеет имя «Arbitrage_Stoсk_Fut». Далее нам понадобятся поля для ввода идентификаторов графиков, добавим их и сразу пропишем в них идентификаторы.

Строка кода 4. Создается строка таблицы Settings с ключом ID_Stock содержащая идентификатор графика цены акций.
Строка кода 5. Создается строка таблицы Settings с ключом ID_Fut содержащая идентификатор графика цены фьючерса.

Отлично, но это еще не все настройки для индикатора. Учитывая то, что мы будем использовать два разных графика цен для расчета индикатора, а конкретнее вычитать из цены одного цену другого, то возникает следующая проблема. Цены инструментов имеют разную разрядность, например акции Сбербанка торгуются по 230 руб., а фьючерсы по 23000 пунктов, если мы вычтем из цены фьючерса цену акций, то никакого вразумительного результата не получим, необходимо уровнять разрядность цен, для этого будем использовать множитель. Добавим в таблицу Settings еще одну строку с множителем и присвоим ему значение 100.

Строка кода 6. Создается строка таблицы Settings с ключом incr содержащая множитель на который будет умножена цена акции, для того чтобы получить значения цен одинакового порядка.

С таблицей настроек мы закончили, перейдем к функции OnCalculate().В теле функции добавим вызов функций getCandlesByIndex() для каждого графика цены. Работа функции getCandlesByIndex() была рассмотрена в разделе «13. Данные с графиков цен и индикаторов».

Рассмотрим параметры вызова функции на примере строки кода 14. Значение Settings.ID_Stock это идентификатор графика акций, следующее значение 0 это номер линии на графике, следующее значение index-1 это индекс свечи начиная с которого берутся значения цены. В данном случае получается, что функция берет предпоследнюю свечку, далее, в параметрах вызова функции стоит значение 1, указывающее взять одно значение. В итоге получается, что функция берет всего одну последнюю свечку с графика цены.

Функция getCandlesByIndex() возвращает таблицу, содержащую значения цен с графика, количество строк в данной таблице и легенду графика.

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

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

Количество строк в таблицах не должно равняться нолю, если одна из таблиц будет пустой, то вернем nil и закончим работу функции OnCalculate().

Переменные Num_Stock и Num_Fut содержат количество строк в соответствующих таблицах.

На данный момент скрипт, если его запустить, отработает следующим образом. Если условие истина, то функция вернет значение 1, стока кода 18 и на графике отразится прямая линия на уровне 1. Если условие ложь функция вернет nil.

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

Создадим переменные, в которые запишем значения цен с графиков.

Строка кода 17. Создается переменная, в которую записывается значение цены акции.
Строка кода 18. Создается переменная, в которую записывается значение цены фьючерса.

Обе таблицы Graph_Stock и Graph_Fut содержат лишь одну строку, поэтому значения цен берется из строки с индексом 0.

И так, у нас есть значения цен закрытия с двух инструментов, но прежде чем рассчитать разницу необходимо сделать еще пару проверок.

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

Первое, если цена фьючерса или акции на текущей свече равна ноль, то вернем nil и закончим работу функции.

Строка кода 19. Условие проверяет значение цен с графиков, если одна из цен равна ноль, возвращается nil и работа функции прекращается.
Строка кода 20. Возврат значения nil, остановка работы функции.

Второе условие, если цена акции или фьючерса равна nil, т.е. нет цены, то в этом случае также вернем nil, и завершим работу функции.

Строка кода 22. Условие проверяет значения цен с графиков, если одно из значений равно nil, то возвращается nil и работа функции прекращается.
Строка кода 23. Возврат значения nil, остановка работы функции.

Теперь все проверки пройдены, и можно добавить расчет индикатора. Расчет будем производить прямо в строке кода 25, с выводом значения индикатора.

Строка кода 25. В строке рассчитывается значение индикатора и возвращается из функции.

Скрипт торгового робота готов, сохраним его.

Перед тем как запускать скрипт торгового робота необходимо открыть графики цен и присвоить им идентификаторы.

Графики цен необходимо открыть в одном окне. Делается это следующим образом. Сначала открывается первый график, пусть это будет график фьючерса, далее в окне графика открываем контекстное меню и выбираем пункт «Добавить график (индикатор)…». Откроется окно «Добавление графика».

В окне нажмем кнопку «Новый», откроется окно «Выбор источника данных». В верхнем поле введем Сбербанк.

В разделе «МБ ФР: Т + Акции и ДР» выберем «Сбербанк» и нажмем кнопку «Выбрать». После в окне «Добавление график» нажмем добавить, обратите внимание галочка «Поместить график в новую область» должна стоять.

Два графика откроются в одном окне, установим интервал равный одной минуте.

Обязательно пропишем идентификаторы для графиков. Идентификаторы прописываются в окне «Редактирование настроек графика», окно открывается через контекстное меню пункт «Редактировать…».

Идентификатор для фьючерса.

Идентификатор для акций Сбербанка.

Далее, для того чтобы наш индикатор появился в окне «Добавление графика», необходимо поместить файл скрипта в папку «LuaIndicators», которая расположена в папе с программой QUIK. На моем компьютере путь к фалу скрипта выглядит следующим образом. «C:\\QUIK_VTB24\LuaIndicators\023 График арбитраж.lua», если на Вашем компьютере нет папки LuaIndicators, в папке с программой QUIK, то ее необходимо создать вручную.

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

Нажмем кнопку «Добавить».

В новой области окна появился график индикатора.

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

На этом мы закончим рассматривать примеры создания собственных индикаторов для торговых роботов.

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