Блог им. morefinances
Продолжаем погружение в основы qlua.
Идентификатор инструмента
Получаем количество свечей через getNumCandles
Получаем свечные данных через getCandlesByIndex
Читаем данные с индикатора SMA
Данные с верхней и нижней линии Price Channel
Графики с таблицы текущих торгов
Сравнение получение данных через CreateDataSource и через getCandlesByIndex
Торговый терминал позволяет получать данные по биржевым свечкам непосредственно из открытых графиков. Причем можно получать данные не только с котировок цены, но и с объемов, с индикаторов, а также, как мы увидим позже, с любых графических данных выведенных, например, с таблицы текущих торгов.
Получение данных котировок с графика цены.
Для начала на самом графике цены необходимо установить идентификатор.
Создаем график в торговом терминале, нажимаем правую клавишу мышки, выбираем «Редактировать», выбираем график цен:
Проваливаемся во вкладку «Дополнительно», и присваиваем id, например: SBER_ID:
В случае если мы хотим получать данные не только по котировкам инструмента, но и с индикаторов, то аналогично нужно будет проставить идентификаторы и для них. На примере скользящей средней:
Если в дальнейшем окно с графиком закроется, то для корректной работы скрипта идентификатор потребуется прописать заново. Также если мы скопирум график (Действия / Создать копию), то новый график не будет содержать идентификатора.
Теперь привязываемся к данному id в скрипте и можем запросить, например, через getNumCandles количество свечей с графика:
function main() tiker_id = "SBER_ID" number_of_candles = getNumCandles(tiker_id) message("Количество свечей в источнике данных: "..number_of_candles) end
Получить данные по идентификатору с графика поможет функция getCandlesByIndex, запрос будет выглядеть следующим образом:
mprice, a, b = getCandlesByIndex(tiker_id, line, first, number_of_candles)
где:
tiker_id – наш идентификатор.
line – номер линии графика. Если индикатор имеет несколько линий, то они нумеруются от 0 и далее. Если работаем с ценами, то указываем 0.
first – индекс первой свечи: особенность нумерации при получения данных через графики: первая свечка имеет индекс не 1, а 0. first не может быть больше общего количества свечей на графике.
number_of_candles – количество запрашиваемых свечей. В наших примерах мы будем запрашивать все, но бывают случаи, когда нужны только несколько последних свечек.
При этом, кроме таблицы свечей (mprice) мы получаем с функции еще и:
a – количество свечей в таблице mprice и
b – легенда инструмента (подпись в терминале под графиком).
Получим последнюю свечку с графика Сбербанка:
function hhmmss(date_time) local Hour = date_time.hour if Hour<10 then Hour = "0"..Hour end local Min = date_time.min if Min<10 then Min = "0"..Min end local Sec=date_time.sec if Sec<10 then Sec="0"..Sec end return Hour..Min..Sec end function DDMMYYYY(date_time) local DD = date_time.day if DD<10 then DD = "0"..DD end local MM = date_time.month if MM<10 then MM = "0"..MM end local YYYY = date_time.year return DD..MM..YYYY end function main() tiker_id = "SBER_ID" number_of_candles = getNumCandles(tiker_id) mprice, a, b = getCandlesByIndex(tiker_id, 0, 0, number_of_candles) i = number_of_candles - 1 openprice = mprice[i].open highprice = mprice[i].high lowprice = mprice[i].low closeprice = mprice[i].close volume = mprice[i].volume localtime = hhmmss(mprice[i].datetime) localdata = DDMMYYYY(mprice[i].datetime) message(number_of_candles.." "..localdata.." "..localtime.." OPEN="..openprice.." HIGH="..highprice.." LOW="..lowprice.." CLOSE="..closeprice.." VOLUME="..volume) message(a.." "..b) end
Результат:
Видим, что текущая, последняя свечка имеет номер number_of_candles — 1.
Чуть скорректируем код, чтобы получить последнюю и первую свечку:
for i = 0, number_of_candles, (number_of_candles - 1) do
И можем сравнить с результатом по скрипту выгрузки котировок, который писали ранее:
Получаем данные с индикатора
Чтобы получить данные с индикатора, в нашем случае простая средняя, достаточно просто поменять идентификатор:
tiker_sma_id = "SBER_SMA_ID"
Получим последних 10 значений обычной средней:
function main() tiker_sma_id = "SBER_SMA_ID" number_of_candles_sma = getNumCandles(tiker_sma_id) SMA_from_graph, a, b = getCandlesByIndex(tiker_sma_id, 0, 0, number_of_candles_sma) for i = number_of_candles_sma-10, number_of_candles_sma-1 do message("Свеча : "..number_of_candles_sma .." SMA с графика: "..SMA_from_graph[i].close) end message(a.." "..b) end
Результат:
Можно проверить значения по графику, но можно сделать проверку самостоятельным расчетом средней:
Здесь в формуле средней использую свойство, когда новое значение получается через удаление последнего и добавления нового числа последовательности, деленных на период средней (в нашем случае 10). Особенно удобно, если период средней большой, ускоряет расчет. Получаем:
Данные с Price Channel
Получим данные с индикатора Price Channel (максимум и минимум цен за выбранный период).
Аналогично предыдущим вариантам указываем id:
Запрашиваем данные с верхней (0) и нижней (2) линии индикатора:
function main() tiker_price_channel_id = "SBER_PRICECHANNEL_ID" number_of_candles = getNumCandles(tiker_price_channel_id ) message(""..number_of_candles) rsi_upper, m, n = getCandlesByIndex(tiker_price_channel_id, 0, 0, number_of_candles) rsi_lower, k, s = getCandlesByIndex(tiker_price_channel_id, 2, 0, number_of_candles) summ = 0 for i = number_of_candles-10, number_of_candles-1 do message(i.." "..DDMMYYYY(rsi_upper[i].datetime).." "..hhmmss(rsi_upper[i].datetime).." upper="..rsi_upper[i].close.." lower="..rsi_lower[i].close) sleep(10) end message(m.." "..n) message(k.." "..s) end
Получаем:
Профессионалы, конечно, не будут так привязываться к стандартным индикаторам в терминале, а если даже им нужно использовать какие-то индикаторы в расчетах будут встраивать соответствующий код расчета функцией внутри своего скрипта, а не привязываться по идентификатору к графику. Во-первых, потому что тестирование стратегий может проходить в среде, где никаким образом к графику терминала не привязаться, во-вторых, всегда лучше понимать природу индикатора и делать собственный расчет, чем полагаться на реализацию (пусть и стандартную) третьих лиц. Даже расхождение в округлении внутри расчета индикатора может сильно исказить результаты работы скрипта.
Но на начальном этапе это вполне удобный и наглядный вариант работы со стратегиями на индикаторах, в т.ч. для того, чтобы визуально подтвердить или отфильтровать какие-то гипотезы для своей торговли.
Графики с таблицы текущих торгов.
Не все знают, что в торговом терминале можно настроить не только графики котировок, объема и различных индикаторов, но также квик позволяет просматривать динамику некоторых данных с таблицы текущих торгов. Выведем, например, суммарный спрос и предложение, которые ранее использовали в качестве фильтра при рассмотрение простого торгового советника:
Для этого на графике Сбербанка нажимаем Insert (либо правая клавиша мыши/ Добавить график (индикатор)), далее выбираем Новый.
Не меняя бумагу (Сбербанк) нажимаем Изменить:
Нажимаем последовательно кнопки Выбрать, Выбрать, Добавить.
Получаем график:
Мне удобнее смотреть его не в барах или свечках, а в форме простой линии по закрытию минуты, поэтому я еще меняю представление графика:
В дополнительных параметрах графика прописываем id: SBER_BID
Аналогично проделываем для параметра «Суммарное предложение», id: SBER_OFFER.
Выводим оба графика на одну область:
Если графики после этих манипуляций не появились, необходимо зайти в меню терминала Система / Настройки / Основные настройки / Сохранение данных, выбрать «Данные, отражающие текущее состояние и всю историю изменений» и «Получать пропущенные данные»:
Вернуться на сам график и нажать F5. После чего график должен уже нормально отразиться.
Сам терминал при этом сообщит о том, что был перезаказ пропущенных данных:
Если графики не отразились, то делаем стандартный перезаказ данных: Система / Заказ данных / Перезаказать данные:
После этого всё должно работать нормально.
Теперь по id можно будет запрашивать данные по выбранным графикам:
Здесь я обращаюсь к цене закрытия свечи по каждой минутке, но можно по аналогии со свечными данными работать с ценой открытия, high/low и в каких-то случаях с volume.
Все сегодняшние примеры требуют соответствующих графиков и корректного прописания идентификаторов на них. Иначе терминал выдаст ошибку.
Теперь у нас есть 2 варианта обращения к свечным данным. Можно сравнить их.
Сравнение получение данных через CreateDataSource и через getCandlesByIndex
Плюсы:
Работа со свечными данными через CreateDataSource:
1) Не требуется никаких графических настроек.
2) Можно запускать скрипт с разных терминалов/рабочих мест сразу, без дополнительных настроек.
3) Нельзя случайно выбрать не тот инструмент, таймфрейм, индикатор, т.к. всё прописывается в самом коде скрипта.
4) Можно реализовывать алгоритмы, которые торгуют не одну бумагу, а отфильтровывают по критериям инструменты, например с высоким потенциалом движения, и далее ведут торговлю по ним.
Минус:
1) Могут быть на начальном этапе подгружены не все данные, для корректной работы требуется их перезакать. Но ровно этот же минус есть и у второго способа.
Работа со свечными данными через getCandlesByIndex (по идентификатору графика):
Плюсы:
1) Работа с графиками, очень легкий вариант написания советников и торговых роботов, особенно завязанных на индикаторы.
2) Не нужно вникать в логику расчетов самих индикаторов, в коде которых новичок может вполне себе наделать ошибок (хотя код всех стандартных индикаторов представлены самими разработчиками, можно покопаться желающим).
3) Можно использовать графики по данным из таблицы текущих торгов.
4) Вполне хороший вариант выгрузки данных по цене и индикатору, когда нужно считать значения с графика и, например, сохранить их в файл для дальнейшего анализа или тестирования стратегии.
Минусы:
1) Но при этом подход требует настройки нужных графиков, правильных таймфреймов, прописания идентификаторов (это не сделать кодом, только ручная работа). Если торговых терминалов несколько, то такие настройки нужно сделать на каждом.
2) Если машинально случайно на графике сменили таймфрейм – летит вся стратегия.
3) Подход требует чаще находиться у терминала, чтобы дозаказать данные, если график перестал их отражать (случается периодически у кого чаще, у кого реже, даже у крупных брокеров).
4) Если по стратегии используются разные таймфреймы, то должны быть открыты сразу несколько соответствующих графиков.
5) При небольших неточностях скрипт становится на два порядка более ресурсозатраным. Так, например, если мы сделаем скрипт с ожиданием минутных данных, по аналогии с тем, что мы рассматривали ранее по CreateDataSource и запустим два скрипта одновременно, то мы увидим:
Здесь мы обращаемся в цикле while ко всему диапазону свечек графика. Но стоит скорректировать и загружать только последнюю закрытую свечку, как скрипт становится вполне соразмерным по нагрузке:
Упражнения:
1. Сделайте вывод цены закрытия по выбранному инструменту и двум любым индикаторам в файл. Последние 10 значений выведите в таблицу.
2*. Попробуйте написать торгового советника на индикаторах с графика.
Теги: qlua для начинающих, кружок авиамоделизма.
Ранее:
Qlua: введение
Доля клиентов, использующих алгоритмическую торговлю
«Кружок авиамоделизма»
Разные торговые терминалы, почему Quik
Основной функционал qlua
Настраиваем торговый терминал и редактор кода
Установка торгового терминала
Подготовка терминала
Вкладки в терминале
Сохранение и загрузка настроек
Таблица системных сообщений
Отключение окна сообщений
Редактор Notepad++
Настройка русского языка в редакторе
Выбор синтаксиса языка и кодировки
Цветовые настройки
Дублирующий просмотр
Запуск первого скрипта
Основы qlua, часть 1:
message, конкатенация
фильтрация по сообщениям в терминале
PrintDbgStr, комментарии
типы данных, type
операции с числами
операции со строками
операции с таблицами
условные операторы
Основы qlua, часть 2:
Циклы for … do … end, while do … end, repeat … until.
sleep, break, goto.
как пройти весь массив циклом, как пройти таблицу по ключам
локальные и глобальные переменные, функции
получение даты и времени
получение данных через getInfoParam
Qlua: структура скрипта.
Структура типового скрипта qlua с примерами.
Обработка скриптом «обрыва связи» с сервером и возобновления работы.
Работа с файлами: запись, перезапись и чтение файла.
getScriptPath, getWorkingFolder
Qlua: получение данных из таблицы текущих торгов, создание таблиц в торговом терминале.
Получение биржевых данных через функцию getParamEx
Выгрузка списка параметров функции getParamEx через DDE из торгового терминала
Создание пользовательских таблиц в торговом терминале
Qlua: работа с таблицами (продолжение). Пишем своего советника (начало).
Интегрируем таблицы в структуру скрипта qlua.
Удаляем таблицы через DestroyTable.
Останавливаем скрипт через IsWindowClosed.
Обработка события закрытия таблицы через коллбэк.
Работа с цветом SetColor, Highlight, SetSelectedRow.
Пишем простого советника.
Qlua: дополняем скрипт советника таймингом:
Устанавливаем время старта работы скрипта,
Ставим тайминг на получение сигналов на вход,
Устанавливаем таймер на приостановку скрипта.
Qlua: завершаем апгрейд советника:
Пропуск «поздних» сигналов на старте.
Обработка советником обрыва связи.
Сохранение сигналов и логов в файл.
Qlua: пишем скринер акций Московской биржи
Qlua: получение данных биржевых свечей с сервера брокера, обработка данных, пишем скрипт выгрузки котировок
Функция CreateDataSource
Получение количества свечек данных
Пауза для подгрузки данных
Получение по инструменту OPEN, HIGH, LOW, CLOSE, VOLUME
Обработка времени и даты
Закрытие источника данных
Примеры: получение данных последних 10 свечей, выгрузка новой минутной свечки после её закрытия, текущее значение простой средней SMA10 по минуткам
Простой скрипт выгрузки котировок