Блог им. morefinances
Сегодня рассмотрим:
1. Получение биржевых данных через функцию getParamEx
2. Выгрузка списка параметров функции getParamEx через DDE из торгового терминала
3. Создание пользовательских таблиц в торговом терминале
Одна из особенностей работы через квик это то, что можно получать достаточно большой объем биржевой информации по интересуемым инструментам. Большинство других платформ для алгоритмической торговли и терминалов в РФ будут выдавать только цену открытия, максимум/минимум дня, последнюю цену, цену закрытия, объемы по инструментам и максимум еще 3-5 каких-то дополнительных пунктов. В распоряжении тех, кто использует qlua огромная матрица параметров таблицы текущих торгов.
Получить их можно через функцию getParamEx:
getParamEx(код класса актива, инструмент, параметр), где:
код класса: например в случае акций это «TQBR», а в случае срочного рынка «SPBFUT».
инструмент: тикер.
параметр – один из параметров для соответствующей группы инструментом (об этом подробнее ниже).
Функция возвращает таблицу со следующими полями:
param_type– показывает тип возвращаемых данных.
1: число с точкой (обычно цены).
2: целое число (количество заявок, сделок и пр.).
3: текстовые данные (наименование бумаги, тикер, класс бумаги и пр.).
4: значения из ограниченного списка (статус сессии: открыта, статус бумаги: торгуется, тип: ао и пр.)
5: время (время последней сделки, начало и окончание аукциона открытия и пр.)
6: дата (дата последних торгов, дата расчетов, дата торгов и пр.)
param_value – числовое значение параметра (вернет конкретную цену или количество, с которыми далее можно работать).
Для текстовых данных параметр будет равен нулю, для перечисляемых типов значение равно порядковому значению в списке.
param_image– строка в том виде как данный параметр выглядит в таблице текущих торгов в самом терминале (т.е. с учетом целой и дробной части, разделителей разрядов и пр.).
Пример:
last_type = getParamEx("TQBR", "GAZP", "LAST").param_type last_value = getParamEx("TQBR", "GAZP", "LAST").param_value last_image = getParamEx("TQBR", "GAZP", "LAST").param_image message("Цена последней сделки по Газпрому: ") message("тип: "..last_type) message("значение : "..last_value) message("строка: "..last_image)
Получим:
В основном мы будем работать с числовыми параметрами.
Примеры таких запросов:
offer = getParamEx("TQBR", "GAZP", "OFFER").param_value bid = getParamEx("TQBR", "GAZP", "BID").param_value change = getParamEx("TQBR", "GAZP", "CHANGE").param_value lastchange = getParamEx("TQBR", "GAZP", "LASTCHANGE").param_value numoffers = getParamEx("TQBR", "GAZP", "NUMOFFERS").param_value numbids = getParamEx("TQBR", "GAZP", "NUMBIDS").param_value wprice = getParamEx("TQBR", "GAZP", "WAPRICE").param_value message("Лучшая цена предложения OFFER: "..offer) message("Лучшая цена спроса BID: "..bid) message("Разница цены последней сделки к предыдущей сессии CHANGE: "..change) message("% изменения от закрытия LASTCHANGE: "..lastchange) message("Количество заявок на продажу NUMOFFERS: "..numoffers) message("Количество заявок на покупку NUMBIDS: "..numbids) message("Средневзвешенная цена WAPRICE: "..wprice)
Список всех параметров функции можно найти в хелпе терминала (в терминале нажимаем F1, в строке поиска забиваем «GET_PARAM_EX», выбираем Функции для получения значений Таблицы текущих торгов и в самом низу описания находим «См. также Значения параметров функций», нажав на которую мы получаем полный список возможных кодов классов инструментов и список возможных идентификаторов параметров):
Но даже на форуме разработчиков терминала указано, что лучше брать их экспортом DDE из квика, т.к. сама таблица варьируется от класса инструмента и может меняться от брокера к брокеру.
Поэтому стоит разобраться с тем как можно сделать полную выгрузку списка параметров этой функции из терминала (далеко не все пригодятся в дальнейшем, но знать какие есть в распоряжении стоит).
Рассмотрим это на примере акций Московской Биржи (код класса TQBR).
Для начала откроем в терминале таблицу текущих торгов и получим полный список доступных параметров: создать окно, текущие торги.
Выбираем Акции:
И далее добавляем все доступные параметры:
В полученной таблице текущих торгов нажимаем правую клавишу мышки и выбираем «Вывод через DDE сервер». Откроется окно, в котором нужно выбрать пункт «Запускать приложение DDE сервера автоматически»:
Нажимаем «Начать вывод» и у нас начинают выгружаться в excel данные с таблицы.
Нажимаем «Остановить вывод». Копируем всю строку заголовков и перемещаем их в отдельную вкладку. Для удобства можно транспонировать, чтобы было далее в табличном формате работать:
Возвращаемся в терминал, в окно «Вывод через DDE-сервер» и теперь выбираем «Формальные заголовки»:
Опять нажимаем вывод и уже замечаем, что в excel названия столбцов отражаются только на английском.
Останавливаем вывод, копируем все названия столбцов и уже к ранее сохраненным названиям добавляем только что полученные:
Всё, мы получили полный список названий (первый столбец) и параметров (второй столбец) для акций функции getParamEx.
Сохраняем файл, он еще в дальнейшем пригодится.
После этого в самом терминале нужно отключить вывод в окне «Вывод через DDE-сервер» (поле «запускать приложение DDE сервера автоматически»), чтобы в дальнейшем при открытии терминала не начинался автоматический вывод данных в excel.
Помним, что таблица может меняться со временем, в т.ч. по этой причине ориентируясь только по форумам и сайтам можно встретить старые параметры, которые уже не будут работать.
Детальное описание значений параметров можно также найти в хелпе квика (в терминале нажимаем F1, в поисковой строке забиваем «Приложение 2», в числе первых в поисковой выдаче будет то, что нам нужно):
Отсечение лишних нулей в числах.
Если посмотреть, что нам выдал в окно сообщений второй пример, с которого мы начали рассмотрение функции, то можно заметить, что вывод идет с лишними нулями:
Это особенность самого терминала. Чтобы их отсечь можно использовать различные функции округления. Например, такого плана:
function mprint(numb) return math.floor(numb*100)/100 end
Получим:
При желании можно эту функцию усовершенствовать с учетом необходимого разряда округления (числа нулей после запятой).
Пользовательские таблицы в терминале
В торговом терминале через qlua можно создавать собственные таблицы (не путать с таблицами/массивами, которые мы рассматривали ранее при погружении в синтаксис языка). Это более удобный инструмент вывода данных, чем постоянно спамить в таблицу сообщений (хотя последнее тоже не исключаем для вывода данных, плюс помним про возможности PrintDbgStr (касались этого ранее).
В таблице можно структурировано выводить необходимую информацию и подсвечивать необходимые данные (менять как цвет шрифта, так и фон), и даже можно через таблицу менять какие-то параметры скрипта в процессе его работы (вариант диалоговых окон, это будет рассматривать позднее).
Следующий код создаст таблицу из 3 столбцов и 1 строки:
if m_t==nil then -- если таблица не создана, то m_t=AllocTable() -- создаем таблицу AddColumn(m_t, 1, "Тикер", true, QTABLE_STRING_TYPE, 15) -- добавили столбец шириной в 15 символов AddColumn(m_t, 2, "Бумага", true, QTABLE_STRING_TYPE, 20) -- добавили столбец шириной в 20 символов AddColumn(m_t, 3, "Цена", true, QTABLE_STRING_TYPE, 10) CreateWindow(m_t) -- создание окна таблицы SetWindowPos(m_t,0,430,700,110) -- позиционирование (x,y от левого верхнего угла) -- и размеры (ширина, высота) SetWindowCaption(m_t, "Вывод данных через таблицу") -- показать таблицу, пишем заголовок InsertRow(m_t,-1) -- добавить строку end
Чтобы разместить данные в конкретных ячейках используется SetCell:
SetCell(id таблицы, id или номер строки, id или номер столбца, данные для вывода)
Выведем информацию по Газпрому, например: цену последней сделки, суммарный спрос и предложение (количество инструментов во всех выставленных заявках на покупку и продажу соответственно (в лотах) — добавим для этого еще 2 столбца):
if m_t==nil then -- если таблица не создана ранее, то m_t=AllocTable() -- создать таблицу m_t AddColumn(m_t, 1, "Тикер", true, QTABLE_STRING_TYPE, 10) AddColumn(m_t, 2, "Бумага", true, QTABLE_STRING_TYPE, 20) AddColumn(m_t, 3, "Цена", true, QTABLE_STRING_TYPE, 10) AddColumn(m_t, 4, "Суммарное предложение", true, QTABLE_STRING_TYPE, 25) AddColumn(m_t, 5, "Суммарный спрос", true, QTABLE_STRING_TYPE, 25) CreateWindow(m_t) -- создание окна таблицы SetWindowPos(m_t,100,430,700,110) -- позиционирование (x,y от левого верхнего угла) SetWindowCaption(m_t, "Вывод данных через таблицу") -- показать таблицу, пишем заголовок InsertRow(m_t,-1) -- добавить строку end tikers = {"GAZP"} local tName = getParamEx("TQBR", tikers[1], "SHORTNAME").param_image local tLast = getParamEx("TQBR", tikers[1], "LAST").param_image local tOffer = getParamEx("TQBR", tikers[1], "OFFERDEPTHT").param_image local tBid = getParamEx("TQBR", tikers[1], "BIDDEPTHT").param_image SetCell(m_t, 1, 1, tikers[1]) SetCell(m_t, 1, 2, tName) SetCell(m_t, 1, 3, tLast) SetCell(m_t, 1, 4, tOffer) SetCell(m_t, 1, 5, tBid)
Теперь можно сделать цикл и добавить еще пару бумаг, изменив только тикеры в массиве tikers и добавив соответствующее количество строк таблицы:
tikers = {"GAZP", "SBER", "VKCO"} if m_t==nil then m_t=AllocTable() AddColumn(m_t, 1, "Тикер", true, QTABLE_STRING_TYPE, 10) AddColumn(m_t, 2, "Бумага", true, QTABLE_STRING_TYPE, 20) AddColumn(m_t, 3, "Цена", true, QTABLE_STRING_TYPE, 10) AddColumn(m_t, 4, "Суммарное предложение", true, QTABLE_STRING_TYPE, 25) AddColumn(m_t, 5, "Суммарный спрос", true, QTABLE_STRING_TYPE, 25) CreateWindow(m_t) -- создание окна таблицы SetWindowPos(m_t,100,430,700,110) -- позиционирование SetWindowCaption(m_t, "Вывод данных через таблицу") -- добавляем количество строк равное размеру массива tikers for u = 1, #tikers do InsertRow(m_t,-1) end end for i = 1, #tikers do local tName = getParamEx("TQBR", tikers[i], "SHORTNAME").param_image local tLast = getParamEx("TQBR", tikers[i], "LAST").param_image local tOffer = getParamEx("TQBR", tikers[i], "OFFERDEPTHT").param_image local tBid = getParamEx("TQBR", tikers[i], "BIDDEPTHT").param_image SetCell(m_t, i, 1, tikers[i]) SetCell(m_t, i, 2, tName) SetCell(m_t, i, 3, tLast) SetCell(m_t, i, 4, tOffer) SetCell(m_t, i, 5, tBid) end
Получаем:
В следующий раз мы продолжим работу с пользовательскими таблицами в терминале: встроим их в скрипт (сейчас мы только разово статично выводили информацию, в следующий раз в скрипте таблицы будут обновляться онлайн), научимся выделять цветами нужные нам данные и уже напишем своего первого советника.
Сегодняшние примеры доступны на github: https://github.com/morefinances/qlua
Упражнения:
1. Получите список полей для функции getParamEx() по срочному рынку.
2. Создайте пользовательскую таблицу и выведите в ней таблицу умножения.
3*. Напишите скрипт, который будет создавать таблицу и каждую секунду обновлять через getParamEx() значение последней сделки по базовому активу (например акции Газпрома), по аналогичному фьючерсу (ближайший фьючерс на акции Газпрома, в данном случае) и рассчитывать в отдельном столбце контанго/бэквордацию.
Теги: qlua для начинающих, кружок авиамоделизма.
В предыдущих сериях:
Qlua: введение
https://smart-lab.ru/blog/917696.php
Настраиваем торговый терминал и редактор кода
https://smart-lab.ru/blog/918869.php
Основы qlua, часть 1:
message, конкатенация
фильтрация по сообщениям в терминале
PrintDbgStr, комментарии
типы данных, type
операции с числами
операции со строками
операции с таблицами
условные операторы
https://smart-lab.ru/blog/920031.php
Основы qlua, часть 2:
Циклы for … do … end, while do … end, repeat … until.
sleep, break, goto.
как пройти весь массив циклом, как пройти таблицу по ключам
локальные и глобальные переменные, функции
получение даты и времени
получение данных через getInfoParam
https://smart-lab.ru/blog/921366.php
Qlua: структура скрипта.
Структура типового скрипта qlua с примерами.
Обработка скриптом «обрыва связи» с сервером и возобновления работы.
Работа с файлами: запись, перезапись и чтение файла.
getScriptPath, getWorkingFolder
https://smart-lab.ru/blog/922044.php