Евгений Шибаев
Евгений Шибаев личный блог
26 июня 2020, 16:47

QLua скринер в 10 строк кода. Или "за базар отвечаю".

Всем привет!
Никогда не давайте обещаний которые не можете выполнить. Во-первых — это портит карму. Во-вторых, за сказанное нужно отвечать. В далеких (не очень) 90-х, если человек не держал слова, к нему приезжали «санитары» с электроприборами, типа дрель, паяльник, утюг — все перечислять не буду, чтобы не пугать читателя, т.к. пост многие найдут полезным не только для торговли, но и для написания собственного кода. Так вот, пообещал я человеку, дело было так:
QLua скринер в 10 строк кода. Или "за базар отвечаю".
Мой родной язык, помимо русского, Common Lisp. С недавних пор породнился с Питоном. А тут луа, да еще с Квиком вперемешку. Не фиг было обещания давать. Больше времени потратил на изучение структур данных луа и особенностей QLua. Сам код был написан за пару часов, как увидите ниже — чё там писать-то...
Как я обещал — пользователь Смартлаба Weddy получает код бесплатно, как и остальные участники тусовки. Ну а я, в качестве вознаграждения получаю приобретенный опыт. Проверял сегодня — работает с любым Квиком (6, 7, 8). Конечно дополнительных «наворотов» я не делал, как в идеале желал Weddy, но это уже детали.
Сам код отображает изменение цены в процентах для любого количества тикеров, которые вы запишите в переменную tickers в виде пар (код-бумаги и код-класса) за N-последних дней (переменная days_before). Все обновляется в режиме онлайн и работает очень быстро (Квик не замечает нагрузки этого скрипта). Инструментами могут быть любые торгуемые на МОЕХ тикеры — акции, облигации, фьючерсы, опционы и т.д. В таблице показаны изменения текущей цены к цене закрытия «вчера», «позавчера», три дня, неделю назад, 10, 30, 44, 67, 90 торговых сессий назад.
«Вживую» выглядит так:

QLua скринер в 10 строк кода. Или "за базар отвечаю".
Ну и сам код:
-- ©2020 by Evgeny Shibaev
-- Таблица, отображающая в процентах рост(падение) инструмента финансового рынка за определенное количество дней
-- Какие инструменты(тикеры) отслеживаем. Таблица пар тикер - площадка
tickers = {SiU0 = "SPBFUT", RIU0 = "SPBFUT", BRN0 = "SPBFUT", GZU0 = "SPBFUT", SRU0 = "SPBFUT", GAZP = "TQBR", SBER = "TQBR", YNDX = "TQBR",
           GMKN = "TQBR", MGNT = "TQBR", SU26207RMFS9 = "TQOB"}
-- За ппоследние n-дней
days_before = {1, 2, 3, 5, 10, 30, 44, 67, 90} -- эквивалентно "вчера", "позавчера", 3-дня назад, 7 и 30 торговых сессий назад.
sources = {} -- Список источников данных по количеству тикеров
rows = {} -- Список строк в таблице по количеству тикеров
screener = AllocTable() -- Указатель на саму таблицу
stopped = false -- Остановка скрипта
     
-- Функция вызывается перед вызовом main
function OnInit(path)
   -- "Ticker"- название первого столбца в таблице
   AddColumn(screener, 0, "Ticker", true, QTABLE_STRING_TYPE, 15)
   -- Названия остальных столбцов в таблице по количеству days_before
   for column, days in ipairs(days_before) do
       AddColumn(screener, days, days.." day(s)", true, QTABLE_STRING_TYPE, 11)
   end
   CreateWindow(screener)
  -- Даем название  таблице
   SetWindowCaption(screener, "Percent change for last days")
   for ticker, board in pairs(tickers) do
       --Для каждого тикера создаем источник данных - "дневки"
       sources[ticker] = CreateDataSource(board, ticker, INTERVAL_D1)
       --Устанавливаем коллбэк функцию для каждого тикера. Она вызывается при изменении цены тикера. "А что, так можно было?"
       sources[ticker]:SetUpdateCallback(function(index) InvalidateCallback(index, ticker) end)
       --Для каждого тикера определяем строку в таблице и запоминаем ее в rows
       rows[ticker] = InsertRow(screener, -1)
       --В первом столбце каждой строки будет имя тикера
       SetCell(screener, rows[ticker], 0, ticker)
   end
end

-- Коллбэк функция вызывается при изменении значения текущей цены тикера. Обновляет строку тикера в таблице сразу, как происходит изменение.
function InvalidateCallback(index, ticker)
   for column, days in ipairs(days_before) do
      -- Определяем процентр изменения цены тикера за days-дней
      percent = Change(ticker, days)
      -- Выводим в соответствующую ячейку таблицы процентр изменения
      SetCell(screener, rows[ticker], days, string.format("%.2f", percent).."%")
      -- Подкрашиваем ячейку соответственно росту(падению) и величины роста(падения)
      SetColor(screener, rows[ticker], days, BCellColor(percent), FCellColor(percent), BCellColor(percent), FCellColor(percent))
   end
end

--Функция определяет на сколько процентов выросла или упала бумага относительно N-дней назад
function Change(ticker, days_before)
  len = sources[ticker]:Size() --Сколько всего "дневных" свечей в источнике данных конкретного тикера
  --Возвращаем рост(падение) в процентах текущей цены от цены закрытия days_before-торговых сессий назад
  return (sources[ticker]:C(len) - sources[ticker]:C(len - days_before)) / sources[ticker]:C(len - days_before) * 100
end

-- Цвет текста в ячейке. Если рост - то цвет "зеленый", падение - "красный"
function FCellColor(change) if change > 0 then return RGB(0,128,0) else return RGB(158,0,0) end end

-- Маленькая "тепловая карта". Делает фон ячейки более интенсивным, взависимости от величины роста(падения)
function BCellColor(change)
  bright = math.floor(255 - math.min(math.abs(change*10), 110),1)
  if change > 0 then return RGB(bright,255,bright) else return RGB(255,bright,bright) end
end

-- Функция вызывается перед остановкой скрипта
function OnStop(signal) stopped = true end

-- Функция вызывается перед закрытием квика
function OnClose() stopped = true end;

-- Основная функция выполнения скрипта
function main()
  while not stopped do sleep(1) end
end  	  

Всем хороших выходных, и постарайтесь выполнить все данные вами обещания!
Код вы можете также найти в конце страницы https://www.jatotrade.com/download
Или по прямой ссылке. Подписаться на мой канал в ютьюбе можно здесь. Там много чего интересного.

ЗЫ: точный способ узнать код класса бумаги спросить на iss.moex например для опциона на RI127500BG0A
https://iss.moex.com/iss/securities.xml?q=RI127500BG0A В ответе найдете в поле primary_boardid=«ROPD»:
<row id=«411357163» secid=«RI127500BG0A» shortname=«RTS-9.20M020720CA127500» regnumber="" name=«Нед. марж. амер. Call 127500 с исп. 2 июля на фьюч. контр. RTS-9.20» isin="" is_traded=«1» emitent_id="" emitent_title="" emitent_inn="" emitent_okpo="" gosreg="" type=«option» group=«futures_options» primary_boardid=«ROPD» marketprice_boardid=""/>


 





55 Комментариев
  • Kot_Begemot
    26 июня 2020, 16:54
    Да, смартлабовцы они такие, на что хочешь разведут и без всякых паяльников)))
  • 3Qu
    26 июня 2020, 17:00
    А чё ты говорить? И так все ясно.)
  • Александр
    26 июня 2020, 17:03
    Запилить еще можно средний дневной объем. И среднее движение от открытия до закрытия.
  • Replikant_mih
    26 июня 2020, 17:24

    Ииии Евгений врывается в топ самых полезных авторов Смарт-лаба))

     

    Скринер штука полезная для некоторых стилей торговли.

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн