Блог им. morefinances

Qlua: пишем скринер акций Московской биржи

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

Нам понадобятся:

1. Таблица для вывода данных (строить уже умеем).

2. Получение данных из таблицы текущих торгов через getParamEx (проходили там же).

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

Через sec_list = getClassSecurities(«TQBR») можно получить строку с тикерами акций на Московской бирже, которые будут разделены запятыми. Чтобы пройтись по всем элементам и записать их в массив используем цикл:

for TIKER in string.gmatch(sec_list, "[^,]+") do
  tikers[#tikers + 1]=TIKER
end


Отслеживать будем параметр LASTCHANGE – процент изменения цены от цены закрытия:

local delta = getParamEx(«TQBR», tikers[i], «LASTCHANGE»)

В настоящий момент на фондовой секции Мосбиржи торгуются 248 бумаги (некоторые показываются только индикативно, реальных торгов по ним не ведутся). Создадим таблицу 25 х 10 в которой будем отражать тикер и полученный с таблицы торгов данные, если бумага торгуется в плюсе закрасим её зеленым, если в минусе красным цветом, если без изменений, то без цвета.

Qlua: пишем скринер акций Московской биржи
 

Файл: https://github.com/morefinances/qlua/blob/main/stockscreener_v1_0.lua

Вроде бы всё работает, но не очень удобно искать по тикеру конкретную бумагу: логичнее расположить вывод из массива не горизонтально, а вертикально, переделаем.

Здесь также можно улучшить алгоритм: после получения значений в первой итерации сложим их по тикерам в массив DELTA и если в следующем цикле цифра не будет отличаться, то мы и не будем обновлять её в таблице, что существенно сэкономит нам время на обновление данных. По этой же причине локальная переменная delta теперь стала глобальной, т.к. используется далее вне цикла for.

Результат:

Qlua: пишем скринер акций Московской биржи
Файл: https://github.com/morefinances/qlua/blob/main/stockscreener_v1_1_vertical.lua

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

Дополним скрипт, получим:

Qlua: пишем скринер акций Московской биржи
Файл: https://github.com/morefinances/qlua/blob/main/stockscreener_v1_2_columns.lua

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

function exc_tik(stock)  
  t = {
    "ACKO",
    "GAZC",
    "GAZS",
    "GAZT",
    "MGNZ"
  }

  for i, v in ipairs(t) do
   if v == stock then return 1 end
  end

  return 0

end

 

И отфильтруем с помощью этой функции массив тикеров, полученных с биржи.

Из нулевых по объему оставил только POLY, надеюсь, что они оперативно вернуться на торги. Остальные белым выделены бумаги, которые в моменте торгуются по цене закрытия вчерашнего дня.

Результат:

Qlua: пишем скринер акций Московской биржи
Файл: https://github.com/morefinances/qlua/blob/main/stockscreener_v1_3.lua

Скрипт можно еще улучшать (будем возвращаться к этому позже), но главное – даже с таким минимальным багажом знаний по qlua можно делать уже вполне себе полезные вещи.

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

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

Теги: qlua для начинающих, кружок авиамоделизма.

  • обсудить на форуме:
  • Quik Lua
★23
32 комментария
Респект кодерам QLUA 
avatar
 А слабо скинуть код сеточника бесплатно? 
avatar
Ухо спекулянта, так чего мелочиться-то?) нужно сразу просить кнопку "бабло" прикрутить)
avatar
alfacentavra, кнопка это одно, а бесплатный скрипт это другое, не надо передергивать понятия эти… Мне вот лень много кода писать а вот готовый код подпилить это можно
avatar
Ухо спекулянта, когда дойдем до рассмотрения различных элементов торговых роботов может что-то возьмете за основу, чтобы «подпилить» под себя.
avatar
Подскажите а есть варианты кроме как через квик это провернуть?
avatar
ЧунгаЧанга, так есть много сайтов, которые выводят эту информацию с небольшой задержкой к торгам. можно ими пользоваться, погуглите скринер акций.
avatar
Бизне$$ Ангел, посмотрю завтра. Сами индикаторы попозже будем рассматривать, это уже совсем прикладная такая задача.
avatar
Бизне$$ Ангел, https://smart-lab.ru/blog/928242.php
avatar
Спасибо, очень интересно. Но, я так понимаю, связать таблицу-скринер с графиком не получится? Ну, так как связываются стандартные таблицы квика с графиками… И, ещё, есть ли в квике возможность вместо скринера, как таблицы, запихнуть его код в график? То есть, например, на графике будет отображаться тот инструмент, который в данный момент соответствует определённым критериям…
avatar
Михаил К., квик вообще не очень дружелюбный в плане вывода графической информации. Связать/заякорить с графиком, как это в терминале работает с таблицей текущих торгов, чтобы была перерисовка графика при выборе другого инструмента не получится. Но можно использовать какие-то внешние решения (самое простое Excel/python), в этом случае скрипт сохраняет нужные данные в csv, а уже другой алгоритм делает любую отрисовку по любым условиям.
На график (любой) можно выводить метки. Т.е. если вас устроит, то на конкретный график (например индекса), можно через скрипт выводить тикеры, которые под конкретные условия попадают, и убирать их если условия уже не соблюдаются по ним. Это штатными средствами возможно. Но не отрисовка графика в зависимости от условий. Можно пробовать сделать индикатор с разными условиями, но чем больше мудрить в прорисовке тем грустнее это будет выполняться в квике. Лично я стараюсь графическую информацию не выводить в терминале: и квик более устойчиво работает, и, например, различные библиотеки python сделают вывод красиво и с нормальными гибкими настройками цветов/меток/дат и пр. самих графиков.
avatar
alfacentavra, спасибо, понял. 
avatar
alfacentavra, спасибо за кружок, очень познавательно 
avatar
Искал тут по сети как вытащить заявку айсберга из потока обезличенных сделок и наткнулся на Ваш пост. Похоже только Qlua мне поможет. Надо попробовать будет, задача определять наибольшую заявку из указанных и выводить ее на график текущего инструмента, помощник своего рода.
avatar
DennyV8, через одну тему коснемся меток на графике. Они делаются штатными методами как раз позволят выводить информацию, в т.ч., например, наибольшие заявки.
Но айсберг потому и айсберг, что «подводную» часть заявки не видно. А крупные заявки порой оперативно двигаются (так же роботами), не всегда показатель крупного игрока.
avatar
DennyV8, тема меток на графике: smart-lab.ru/blog/933582.php
avatar
DennyV8, сегодня рассмотрели близкий вариант: вывод на график крупных сделок: smart-lab.ru/blog/935919.php
avatar
Спасибо, принято. Сравню с тем что сам сваял, вроде как рабочий даже ))
avatar
Можно ли в скринере выводить в таблицу расчетные значения, полученные сначала через getParamEx и потом были произведены вычисления.
Хотелось бы добавить универсальный блок для дополнительного расчета полученных данных из таблицы значений, а то иногда мало того стандарта и нужно что-то посчитать, что-то типа этого : 

bid = getParamEx(«TQBR», tikers[i], «BID»)
offer = getParamEx(«TQBR», tikers[i], «OFFER»)
spread = (offer — bid) / bid * 100

и выводить в таблицу spread каждого тикера вместо delta, у меня в этом месте затык, чую что всего пара строк кода нужна))

delta = getParamEx(«TQBR», tikers[i], «LASTCHANGE»)
avatar
DennyV8, чтобы не переписывать скрипт и не заниматься заменой в названиях переменных поставьте просто вместо delta = getParamEx(«TQBR», tikers[i], «LASTCHANGE») свою формулу:
delta = (offer — bid) / bid * 100

Предварительно определив bid и offer.
И всё должно заработать. 
Ну и исключить получению 0 в bid.

Т.е. примерно так я бы сделал:

bid = getParamEx(«TQBR», tikers[i], «BID»)
offer = getParamEx(«TQBR», tikers[i], «OFFER»)

if bid ~=0 then
   delta = (offer — bid) / bid * 100
else
   delta = 0
end

Если со спрэдом далее никаких расчетов проводить не планируете, то можно так:

if bid ~=0 then
   delta = (offer — bid) / bid * 100
else
   delta = " "
end

В этом случае, если данные по биду не получены (например скрипт запущен до торгов), в таблице не будет ноль, а простой пропуск значения.
avatar
alfacentavra, Я примерно так и сделал сначала, только без проверки с 0, но выдает ошибку на строку с delta
lua:119: attempt to perform arithmetic on a table value (global 'offer')
avatar
DennyV8, да, он ругается, что скрипт пытается что-то сделать с таблицами.
Да, что-то я поторопился.
Чтобы работать с числом нужно добавить tonumber и указать параметр param_value полученной таблицы :

bid = tonumber(getParamEx(«TQBR», tikers[i], «BID»).param_value)
offer = tonumber(getParamEx(«TQBR», tikers[i], «OFFER»).param_value)

Но думаю логику скрипта нужно будет еще подправить, чтобы всё заработало.
avatar
DennyV8, ну и цветовые настройки еще можно убрать (либо подправить) т.к. спред не будет отрицательным и вся таблица позеленеет после заполнения.
avatar
alfacentavra,  Лишь бы таблица заработала, дальше разберемся, но пока все попытки тщетны ))

UPDATE
на просторах нашел часть кода, пишут что рабочий, но проверить не могу.

--Внутри колбека OnParam
--Считаем средний спред
         local tablebid = getParamEx(class_code,  fff, "bid") --получаем таблицу "bid"
         local bid=tablebid.param_value --из таблицы берём значение
         local tableoffer = getParamEx(class_code,  fff, "offer") --получаем таблицу "offer"
         local offer=tableoffer.param_value --из таблицы берём значение
         local p_spread = (offer - bid) / bid * 100 --считаем текущий спред по бумаге
         local elem = average_spreads[fff] --создаём таблицу для хранения расчётных данных
            if elem == nil then
               average_spreads[fff] = { Count = 1, Spread = p_spread, Avr = p_spread}
               elem = average_spreads[fff]
               else
               elem.Spread = p_spread
               elem.Avr = (elem.Avr * elem.Count + p_spread) / (elem.Count + 1)
               elem.Count = elem.Count + 1
               spread[fff]=elem.Avr
            end</code>
avatar
DennyV8, пробуйте, сделал, работает:



Файл: github.com/morefinances/qlua/blob/main/stockscreener_spred.lua

Не знаю, правда, чем полезны сами спреды в таком широком списке, но в качестве учебного примера почему бы и нет.
avatar
alfacentavra, Вроде работает, вот что значит руки мастера, оперативно сработали, благодарю. Теперь есть поле для маневра с кучей данных из таблицы.
avatar
alfacentavra, Хотел еще спросить по скринеру акций, я в Quik пытаюсь по коду акции из таблицы скринера вызвать стакан котировок определенной акции, но Quik почти все наши акции на русском языке выдает, может есть какой другой способ?
avatar
1. В таблице текущих торгов можно найти бумагу по коду (тикер). Добавьте себе этот столбец.
2. Самый простой вариант: это в терминале через поиск. Добавляете на панель «Поиск инструмента», вбиваете тикер, нажимаете enter. 

Выбираете из таблицы с результатами то, что вам нужно.


avatar
alfacentavra, Вот же я слепой, у меня оказывается это все есть в таблице, простите что отвлек.
avatar
Небольшой апгрейд скринера:
smart-lab.ru/blog/938450.php
avatar

теги блога alfacentavra

....все тэги



UPDONW
Новый дизайн