Доступ к графикам осуществляется с помощью функций интерпретатора QLua. Получить данные с графика цены можно двумя разными функциями. Рассмотрим, для начала, как в QUIK идентифицируются графики. Идентификация графика, говоря простым языком, это присвоение графику уникального имени, по этому имени мы сможем обращаться к графику, используя функции QLua, а в ответ получать с него данные. И так начнем, для примера откроем график цены и объема фьючерса на индекс RTS (в данном примере фьючерс RIZ7, интервал графика 60 мин.). Щелкнем правой кнопкой мыши на область графика и выберем пункт меню «Редактировать». Откроется окно «Редактирование настроек графика».

В левой части окна видим раскрывающийся список «Диаграмма» подпункт «Область1» подпункт «RIZ7 [Price]», выберем данный подпункт в правой части окна выберем вкладку «Дополнительно», в нижней части вкладки есть поле «Идентификатор». В данном поле прописывается идентификатор выбранного графика, по этому идентификатору мы будем обращаться к графику с помощью функций, введем идентификатор «RTSPrice».

Графику или индикатору необходимо присваивать уникальный идентификатор.

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

1.Идентификатор графика.
2.Номер линии на графике. Если мы обращаемся к графику цены, то данный параметр всегда будет 0. Если мы обращаемся к графику индикатора и индикатор имеет несколько линий на графике, например индикатор ADX, то необходимо будет указать с какой именно линии мы хотим получить данные.
3.Индекс свечки, с которой мы начнем получать данные. В основном, будет использоваться получение данных, с самой первой свечки на графике (самая левая свечка), в этом случае данный параметр будет иметь значение 0, поскольку нумерация свечей на графике начинается с ноля. Но также можно взять любую другую свечку в качестве начала, главное чтобы этот параметр не был больше чем всего свечей на графике.
4.Количество запрашиваемых свечек. Этот параметр указывает, сколько взять свечек с графика начиная от первой запрашиваемой свечки. В основном мы будем брать сразу все свечки на графике.

И так, если с первыми тремя пунктами все понятно, в них мы сами прописываем заранее известные значения, то вот с пунктом 4 не все так однозначно. Прежде чем запрашивать определенное количество свечей, нам необходимо узнать, а сколько вообще свечей на нашем графике. Тут на помощь придет функция QLua, которая выдает количество свечей на графике, а именно getNumCandles(). Работает эта функция просто, в нее передаем идентификатор графика и в ответ получаем количество свечек на графике.

Создадим новый проект скрипта Lua, под названием «015 Данные с графика getCandlesByIndex.lua», и объявим переменную RTSNCandles, вызовем функцию getNumCandles() передав в нее идентификатор графика «RTSPrice».

Теперь, в нашем распоряжении имеется, количество свечей на графике и далее мы можем получить с него данные с помощью функции getCandlesByIndex().

Вызовем функцию getCandlesByIndex().

Так выглядит вызов функции getCandlesByIndex(). Одновременно с вызовом функции объявляется таблица и две переменные:

RTSPrice – таблица, которая содержит все данные с графика;
RTSN – количество запрошенных свечей, этот же параметр указывает на количество строк в таблице RTSPrice;
RTSName – название графика.

Рассмотрим еще раз значения, передаваемые в функцию для ее вызова.
«RTSPrice» – идентификатор графика.
0 – номер линии графика (используется, если график состоит из нескольких линий, например индикатор ADX, состоящий из трех линий, в остальных случаях значение всегда 0).
0 – номер свечки, с которой необходимо взять данные с графика (в терминале QUIK все данные цен хранятся в таблицах, нумерация таблиц начинается с 0, т.е. самая левая свеча на графике имеет номер 0).
RTSNCandles – количество свечек, которое необходимо взять с графика.

Получается, мы говорим функции взять с графика с определенным идентификатором определенное количество свечей, от такой до такой, в нашем случае от нулевой до последней.

Рассмотрим подробнее таблицу RTSPrice, которая содержит данные с графика. В таблице несколько колонок, каждая из которых содержит определенный параметр. В нашем примере взят график фьючерса на индекс RTS с исполнением в декабре 2017 г. код RIZ7, интервал графика 60 минут.

В таблице приведены первые 3 строки из таблицы RTSPrice.

Таблица содержит 11 столбцов. В данной таблице есть одна особенность столбцы (year, month, day, hour, min, sec) содержащие дату и время объединены под одним именем datetime. Для того чтобы нам обраться, например к столбцу year сначала необходимо указать объединяющий столбец datetime а после столбец year. Чуть ниже Вы увидите как это работает.

Мы можем обратиться к любой строке таблицы и взять необходимое значение, указав определенную строку, явно прописав ее номер или с помощью цикла найти необходимое значение. Рассмотрим, как работать с таблицей содержащей данные с графика. Количество строк в таблице содержится в переменной RTSN. Здесь есть небольшой нюанс. Поскольку нумерация строк в возвращаемой таблице начинается с 0, то номер последней строки в таблице и количество строк в таблице будет различаться на единицу. Для наглядного примера рассмотрим теоретическую таблицу:

Первый столбец нумерация строк, второй столбец значение в строках. Количество строк 5, а номер последней строки 4. В переменной RTSN содержится количество строк, следовательно, чтобы обратиться к последней строке, то переменную RTSN необходимо уменьшить на 1. Если обратиться к несуществующей строке таблице, то получим значение nil. Исходя из этого, формат обращения к последней строке таблице будет иметь вид RTSN-1.

Создадим переменные и поместим в них соответствующие значения из последней свечки на графике.

Разберем подробнее, как обратится к данным из таблицы RTSPrice, на примере строки 3 нашего скрипта.
В этой стоке мы сначала объявляем переменную Year, далее присваиваем ей значение из таблицы RTSPrice берем строку [RTSN-1] из строки берем сначала общий столбец datetime, а далее уже нужный нам столбец year.

В результате мы имеем, переменные содержащие все значения последней свечи нашего графика. Точно таким же образом можно взять значения с любого индикатора, отличия заключаются в том, что переменные Open, High, Low, Close будут иметь одинаковое значения, а переменная Vol будет всегда равна 1.

Для наглядности выведем все значения последней свечи в таблицу терминала QUIK. Из предыдущего примера «014 Пользовательские таблицы.lua» мы знаем, как ее создать. В нашей таблице будет 12 столбцов. Первый столбец будет отображать название графика, название мы возьмем из переменной RTSName (напомню, в переменную RTSName присваивается название графика, функцией getCandlesByIndex()). Далее пойдут следующие столбцы «Год», «Месяц», «День», «Час», «Минута», «Секенда», «Открытие», «Максимум», «Минимум», «Закрытие», «Объем». Название для нашей таблицы укажем «Данные с графика RIZ7». Местоположение на экране оставим как в предыдущем примере, а вот длину таблицы увеличим до 900 пикселей. А также весь наш код поместим в функцию main. В итоге должен получиться следующий код.

Запустим скрипт в терминале QUIK и посмотрим на результат.

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

Поскольку все данные с графика содержаться в таблице RTSPrice, а с таблицей RTSPrice, мы можем совершать все действия, доступные для таблиц Lua, то для примера найдем с помощью цикла максимальное значение цены за последние 200 свечек. Создадим переменную, в которую будет записываться максимальное значение и переменную, которая будет содержать количество свечек.

Создадим цикл for который будет перебирать значения с конца таблицы RTSN-1 до значения RTSN-N.

Рассмотрим цикл подробнее. Строка кода 36. Цикл начинает перебор значений с RSTN-1, (i = RTSN-1) т.е. с самой последней строки, до строки RTSN-N (N – переменная содержащая количество строк из которых нужно найти максимальное значение), параметр «-1» указывает, что переменную «i»нужно уменьшить на единицу после каждой итерации.
Строка кода 37. В строке прописано условие сравнения значений. Из таблицы RTSPrice берется строка с индексом «i», из этой строки берется столбец с именем high. Далее полученное значение сравнивается с переменной MaxN. Если условие истина, то выполняется строка кода 38. В этой строке в переменную MaxN присваивается значение RTSPrice[i].high. Если условие ложь, цикл переходит к новой итерации.

Выведем максимальное значение в колонку таблицы. Для этого создадим еще одну колонку с именем «Макс N» при помощи функции AddColumn() и заполним колонку при помощи функции SetCell().

В строке кода 15 мы прописываем код для еще одного столбца в таблице QUIK. В строке кода 56 выводим в таблицу QUIK значение переменной MaxN.

Сохраним и запустим скрипт в терминале QUIK.

В колонке «Макс N», отобразилось максимальное значение за последние 200 свечек. На данном графике мы можем визуально проверить корректность работы скрипта, наведя курсор на недавнюю самую высокую свечку.

Максимальное или минимальное значение можно найти также при помощи цикла while. Для примера разберем, как найти минимальное значение за 200 свечей при помощи цикла while.

Создадим переменную MinN и присвоим ей значение минимума цены последней свечки RTSPrice[RTSN-1].low. Это необходимо сделать, поскольку если мы присвоим ей значение 0, как в случае с максимумом, то минимальное значение так и останется 0, цена не может быть меньше нуля.

Создадим переменную «j», которая будет считать количество итераций и заодно являться индексом для строки таблицы, присвоим данной переменной значения последней строки в таблице RTSPrice.

Далее запишем цикл while, который перебирает последние 200 строк таблицы RTSPrice и находит минимальное значение в колонке low.

В условии цикла (строка кода 46) необходимо поставить знак «>=» по следующей причине. Если поставить знак «>», то цикл переберет 199 строк вместо 200. Это связанно с нумерацией строк в таблице RTSPrice, нумерация начинается с нуля. Также мы можем записать это условие следующим образом

while j > RTSN – 1 – N do

в этом случае мы используем знак «>» и цикл переберет ровно 200 строк. В данном курсе будет использоваться запись

while j >= RTSN — N do.

Рассмотрим подробно данный цикл while. И так, строка кода 46, в данной строке прописывается условие выполнения цикла, а именно пока переменная «j» больше или равна разнице RTSN – N, то наш цикл выполняется. Строка кода 47. В строке прописано условие сравнения значений. Из таблицы RTSPrice берется строка с индексом «j», из этой строки берется столбец с именем low. Далее полученное значение сравнивается с переменной MinN. Если условие истина, то выполняется строка кода 48. В этой строке в переменную MinN присваивается значение RTSPrice[j].low. Если условие ложь, цикл переходит к новой итерации. Строка кода 50. В этой строке мы уменьшаем переменную «j» на единицу тем самым переходя на строку выше в таблице RTSPrice.

Выведем минимальное значение в колонку таблицы. Для этого создадим еще одну колонку с именем «Мин N» при помощи функции AddColumn() и заполним колонку при помощи функции SetCell().

В строке кода 16 мы прописываем код для еще одного столбца в таблице QUIK. В строке кода 67 выводим в таблицу QUIK значение переменной MinN.

Сохраним и запустим скрипт в терминале QUIK.

В колонке «Мин N», отобразилось минимальное значение за последние 200 свечек. На данном графике мы можем визуально проверить корректность работы скрипта, наведя курсор на недавнюю самую низкую свечку.

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

Добавим на наш график индикатор скользящая средняя (Moving Average), количество периодов 20 свечек, метод Simple, поле цены Close. Для данного индикатора введем идентификатор RTSMA.

В строках кода 23 и 24 заменим идентификатор RTSPrice на идентификатор RTSMA.

Заменим идентификатор графика в строке вызова функции на «RTSMA». Сохраним и запустим скрипт.

В таблицу вывелись данные с графика скользящей средней с идентификатором RTSMA. Обратите внимание, столбцы «Открытие», «Максимум», «Минимум» и «Закрытие» имеют одинаковые значения, индикатор скользящая средняя имеет лишь одно значение для каждой свечки.

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

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

Чтобы подробно рассмотреть работу функции CreateDataSource(), создадим новый проект под названием «016 Данные с графика CreateDataSource.lua». Скопируем код, из проекта «015 Данные с графика getCandlesByIndex.lua», относящийся только к выводу таблицы Lau на экран. Должен получиться следующий код.

Далее добавим строку вызова функции CreateDataSource(), передадим в нее необходимые параметры, а результат выполнения функции поместим в таблицу RTSPrice. Важным отличием функции CreateDataSource() от getCandlesByIndex() является то, что функция CreateDataSource() сама заказывает данные графика с сервера QUIK, для нее нет необходимости держать открытым график инструмента с заданным интервалом данных.

Рассмотри подробнее формат вызова функции CreateDataSource(), строка кода 23. Для вызова данной функции в нее необходимо передать Код класса в нашем случае это «SPBFUT», далее Код бумаги это «RIZ7» и интервал данных это INTERVAL_H1. Функция вернет данные в таблицу RTSPrice.

Код класса – все фьючерсы относятся к классу SPBFUT. Посмотреть Код класса для любого инструмента можно в «Текущей таблице» выбрав соответствующий столбец в настройках.

Код бумаги – краткое наименование инструмента. Посмотреть код бумаги возможно также в «Текущей таблице» выбрав соответствующий столбец в настройках.

Интервал данных, он же интервал графика задается следующими значениями:

Функция CreateDataSource() возвращает таблицу Lua следующего вида:

T – время,
O – цена открытия свечи,
H – цена максимума свечи,
L – цена минимума свечи,
С – цена закрытия свечи,
V – объем свечи.

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

local RTSN = RTSPrice:Size()

Запись RTSPrice:Size() по сути, говорит следующее, возьмем таблицу RTSPrice и применим к ней функцию Size(). Функция Size() – возвращает количество строк в таблице RTSPrice, причем нумерация строк в таблице RTSPrice начинается с 1 (в отличии от getCandlesByIndex()).

Обращение к строкам таблицы, возвращаемой функцией CreateDataSource(), отличается от стандартного обращения. Например, чтобы взять значение цены открытия из последней свечи, нам необходимо ввести следующий код:

local Open = RTSPrice:O(RTSN)

Знак «:» вызывает параметр «O» класса «свечи» и объекта «свеча». Все это взято из Объектно-ориентированного программирования (ООП). Язык Lua не является объектно-ориентированным языком программирования, но в нем можно создавать подобие методов для классов. Мы не будем углубляться в изучение данных возможностей, просто примем за данность, чтобы обратиться к значениям свечи необходимо соблюдать такой синтаксис. Если Вам будет интересен этот вопрос, то Вы сможете самостоятельно разобраться в нем. Для создания торговых роботов это не обязательные знания.

Вкратце. Свеча является объектом, у объекта есть параметры: Время, Открытие, Максимум, Минимум, Закрытие, Объем. У каждой свечи есть идентификатор – это порядковый номер в таблице Lua. Класс объектов, например класс «свечи», описывает параметры объекта, именно в классе указывается, какие параметры будут у объектов данного класса.Для примера использования функции CreateDataSource(), возьмем данные с последней свечи на графике и выведем их в таблицу.

Запишем все параметры последней свечи в соответствующие переменные.

Рассмотрим, как берется данные времени свечи, на примере строки кода 25. Для таблицы RTSPrice вызывается функция T() в функцию передается значение RTSN, далее из таблицы, которую вернет функция T() берется строка с идентификатором year. Таким же образом берутся все остальные параметры времени свечи, строки кода с 26 по 30 включительно.

Параметры цены и объема берутся с графика следующим образом, рассмотрим на примере строки кода 31.

Для таблицы RTSPrice вызываем функцию О() и передаем в функцию значение RTSN, функция возвращает параметр Open свечи с индексом RTSN.

Скрипт почти можно запускать. Поскольку функция CreateDataSource() не возвращает Легенду (название) графика, то эту колонку таблицы заполним вручную, строка кода 38. Также закомментируем строки кода, относящиеся к выводу в таблицу максимальной и минимальной цены, строки кода 50 и 51, они нам понадобятся чуть позже.

Сохраним и запустим, получившейся скрипт, в терминале QUIK.

Функция CreateDataSource() запросила данные с сервера QUIK и выдала их в указанном виде.

К таблице содержащей данные с графика, можно применять любые действия доступные для таблиц Lua. Найдем максимальное и минимальное значение, за 200 предыдущих периодов. Для этого необходимо создать цикл, который будет перебирать предыдущие значения в таблице RTSPrice и находить максимальные и минимальное значение. Когда мы делали такую же операцию с таблицей RTSPrice, которую вернула функция getCandlesByIndex(), мы использовали два цикла, первый for находил максимум, второй while, находил минимум, это было сделано, для того, чтобы показать, как с помощью обоих циклов сделать перебор значений в таблице. Сейчас, мы сделаем иначе. Один цикл будет искать максимальное и минимальное значение одновременно. Не большое отступление. Чем больше различных циклов в скрипте тем медленнее скрипт работает. Для улучшения быстродействия необходимо минимизировать использование циклов. Один цикл, находящий сразу минимум и максимум, из одной таблицы данных, будет работать в два раза быстрее по сравнению с двумя циклами, которые по отдельности ищут максимальное и минимальное значение.

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

Строка кода 36, в переменную MaxN будет записываться максимальное значение за период. Строка кода 37, в переменную MinN будет записываться минимальное значение, по умолчанию в переменную записывается минимальное значение последней свечи на графике, поскольку если мы запишем 0 то это и будет минимальное значение цены, поскольку цена всегда выше ноля. Строка кода 38, в переменной N задается количество свечей, за которое мы хотим найти минимальное и максимальное значение. Строка кода 39, в данной строке создается управляющая переменная, с помощью которой мы будем перебирать строки таблицы, начальное значение устанавливается на последней строке в таблице, поскольку мы перебираем строки начиная с последней.

Создадим цикл while, который будет перебирать значения строк в поисках максимального и минимального значения. Цикл будет перебирать строки начиная с самого последнего значения, до расчетного.

Разберем работу цикла.
Строка кода 40, в данной строке прописывается цикл и условия его работы. Пока переменная «j» больше или равна разнице между значениями RTSN (кол-во строк в таблице RTSPrice, количество свечей на графике) и N (заданный интервал, за который необходимо найти минимальное и максимальное значение), то цикл выполняется.
Строка кода 41, в данной строке прописывается условие сравнения максимума текущей свечи и существующего максимального значения.
Строка кода 42, если условие в строке кода 41, истина то в переменную MaxN записывается новое максимальное значение.
Строка кода 44, в строке приписывается условие сравнения минимума текущей свечи и существующего минимального значения. Строка кода 45, если условие в строке кода 44 истина, то в переменную MinN записывается новое минимальное значение.
Строка кода 47, в этой строке переменная «j» уменьшается на единицу, тем самым мы переходим на строку выше в таблице RTSPrice.

Перед запуском раскомментируем строки кода 63 и 64, в данные колонки будут выводится наши значения минимума и максимума за 200 свечек.

Сохраним и запустим скрипт в терминале QUIK.

Как видим в колонках «Макс N» и «Мин N», отобразились искомые значения. Теперь давайте запустим наш предыдущий скрипт «015 Данные с графика getCandlesByIndex.lua», и сравним результаты их работы.

В обеих таблицах выводятся идентичные значения. В самом верху отображена таблица из скрипта «016 Данные с графика CreateDataSource.lua», ниже из скрипта «015 Данные с графика getCandlesByIndex.lua».

В программировании существует множество различных вариантов выполнения одной и той же задачи. Для своих торговых роботов вы можете составить свой алгоритм вычисления того или иного значения.

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

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