Евгений Шибаев
Евгений Шибаев личный блог
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

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

     

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

  • Йонатан Берсон
    26 июня 2020, 17:48
    Спасибо за труд!
      • Йонатан Берсон
        26 июня 2020, 18:01
        Евгений Шибаев, тут же просто такая штука… много кто что говорит, но мало делает) 
      • Weddy
        27 июня 2020, 03:30
        Евгений Шибаев, вот бы еще пару дней назад, когда у меня был Д.Р., то заданный Вашим постом тон вообще бы смотрелся красиво:
        «Как я обещал — пользователь Смартлаба Weddy получает КО ДНЮ РОЖДЕНИЯ код бесплатно»  )))
        Ну а если серьезно, то большое спасибо за Ваш труд и помощь!!!
        Ну а если попытаться понаглеть, то хотел бы обратить внимание на нюанс из моего ТЗ :):
        чтоб в таблицу можно было выбрать интересующие инструменты и по ним отображалось по каждому инструменту изменение текущей цены по отношению к цене с задаваемым условием: за неделю, месяц, или особенно здорово например от последнего хай/лой за последние хх дней/ определенной даты.

        Т.е. источником моей мечты о сканере было то обстоятельство, что большинство он-лайн сканеров показывает изменение цены за те, или иные периоды по отношению к цене закрытия. И как-то не попадались сканеры, где изменение отражалось бы по отношению к high/low цены дня точки отсчета.
        Идея здесь простая. Вот 19.01.2020 был хай индекса ММВБ. Хотелось бы задать эту дату и увидеть в таблице изменение текущих цен инструментов по отношению к их хаям в заданный день. Посмотреть в сравнении кто на сколько больше/меньше упал.
        И наоборот. 15.03.2020 был лоу по индексу ММВБ. Посмотреть, сравнить кто на сколько отскочил со своих лоев на ту дату.
        Наверно для анализа акций удобней было бы задавать для таблицы вообще лишь класс TQBR, без вбивания кодов 260+ инструментов. Хотя у выборки с определенным набором инструментов есть своя ценность, при сужении акцента отслеживания.
        • Олайвир Стокс
          27 июня 2020, 03:37
          Weddy, 
          заменить можно указанием собственного ориентира, а внутредневной-недельный-квартальный саб бы подхватывался
          • Weddy
            27 июня 2020, 04:00
            Олайвир Стокс, сорри, но для меня написанное не понятно в практической реализации. В отличие от доброго автора топика я не владею луа
            • Олайвир Стокс
              27 июня 2020, 04:08
              Weddy, 
              это к выражению «самые дорогие ошибки — в неверной концепции», в данном случае, это выразилось в непрозрачности алгоритма что требуется — производитель реализовал алгоритм не тот, что представлял потребитель

              верна суть алгоритма? — отображение текущего отклонения от заданной цены, для удобства в окно сообщения отклонение от дневных\месячных\годовых экстремумов
              • Weddy
                27 июня 2020, 04:27
                Олайвир Стокс, 
                от дневных\месячных\годовых экстремумов
                от дневных экстремумов с возможностью указать тот день, с экстремумом которого сравнимается текущая цена. С месячными/годовыми наверное еще сложнее с заданием параметров точки отсчета
                • Олайвир Стокс
                  27 июня 2020, 05:50
                  Weddy, 
                  принимает на вход дату
                  выводит максимальные цены с отношением к текущей цене в виде таблицы нескольких инструментов, так?
          • Weddy
            27 июня 2020, 23:22
            Евгений Шибаев, 
            Все же не понял мысль здесь:
            задаете как сейчас период в количестве торговых сессий, скрипт вычисляет хай-лоу за этот период, а затем «расстояние в процентах» текущей цены от этих хай-лоу

            1) Если я задам days_before = {12}, то скрипт вычислит хай-лоу за весь период 12 дней, или в день 12 дней назад? Это разные варианты, каждый имеет свою ценность. Если можно задать переключатель, то здорово. А так я имел в виду вариант хай/лоу в 12-й день от текущего. чтоб можно было увидеть разницу с определенным днем (как писал например, с днем хаев индексов, див.отсечек, других ключевых дат).
            2) Как понимаю надо переключатель чтоб задать хай или лоу определять.
            3) Хорошо бы выводил в столбец определенное значение хай/лоу, чтоб легко проверить то ли сделал. По крайней мере на начальном тестовом этапе.
            4) Вычислить кол-во торговых дней до желаемой даты отсчета конечно можно. Хотя вбить конкретную дату было бы быстрее и безошибочнее.

            Поясните еще это:
            Насчет вбивания кодов — вы все равно будете «вбивать» имя тикера, скопируйте просто 260+ строк с уже готовым кодом и всё.

            — т.е луа не позволяет после указания кода класса самой заполнить таблицу имеющимися на бирже тикерами и надо именно указать каждый тикер?
            — откуда «скопируйте просто 260+ строк »? Мне пока пришло в голову лишь вывести через DDE в эксель таблицу текущих торгов, там уже удалить лишние столбцы, и формулами попытаться связать в требуемый синтаксис MGNT = «TQBR»,
              • Weddy
                28 июня 2020, 01:03
                Евгений Шибаев, да я понимаю что скрипт сам будет определять хай-лоу.
                Вы просто определите интервал, за который определять хай-лоу.

                Ну я же не об этом писал ранее:
                Вот 19.01.2020 был хай индекса ММВБ. Хотелось бы задать эту дату и увидеть в таблице изменение текущих цен инструментов по отношению к их хаям в заданный день.
                Т.е., я задал дату, это в примере 19.01.2020. И задал, что надо определять хай. Скрипт определил дневной хай цены по инструменту который был именно на этот день, а не в течение месяцев после.  Это например 224,5 руб. В условные 16:27 сегодняшних торгов цена по инструменту 194,56руб. Скрипт выводит относительное изменение между этими 2-мя ценами.
                Если же для даты 19.01.2020 задано определять лоу, а не хай, то соответственно скрипт отображает изменение цены от лоу дня 19.01.2020 до текущих 194,56руб.

                Не знаю насколько сложен переключатель задания определять хай или лоу нужного дня. Возможно проще скрипту определить и хай и лоу заданного дня (19.01.2020 в примере) и вывести в строке оба относительного показателя «хай 19.01.2020 к текущей цене» и «лоу 19.01.2020 к текущей цене»
                вы получите несколько тысяч тикеров одного кода класса
                я исходил из того, что на ММВБ всего 260+ акций, а не несколько тысяч. А так, скринер как раз для того и нужен, чтобы из большой массы выловить те инструменты, которые внимательнее рассмотреть, отслеживать. И как раз избежать ситуации, чтобы отслеживать тысячи.
  • Mezantrop
    26 июня 2020, 18:25
    Вот всегда интересовала мотивация кодеров — заморочиться, написать чего то и выложить в открытый доступ. Респект и уважуха, конечно, от профессионального халявщика. Но напуркуа? Кодеры живут вечно?
      • Mezantrop
        26 июня 2020, 18:37
        Евгений Шибаев, 
        АААА!
        Я памятник себе воздвиг нерукотворный
        К нему не зарастет народная тропа?
          • Mezantrop
            26 июня 2020, 21:16
            Евгений Шибаев, 
            Боюсь обидеть, извиняюсь, если что...
            Какое отношение сборник древнееврейских мифов имеет к народностям, проживающим исторически в лицемерии?
    • Олайвир Стокс
      27 июня 2020, 04:13
      Mezantrop, 
      тренируешься ожидая из вне благодарность?
      • Mezantrop
        27 июня 2020, 06:58
        Олайвир Стокс, 
        Да неее...
        У благодарности очень низкие котировки, а фундаментал вообще грустный...
        Пятничное…
        • Wallstep
          27 июня 2020, 15:12
          Mezantrop, 
          У благодарности очень низкие котировки

          Иисус вернул зрение 12 слепым, и только трое сказали спасибо.. .. 
          • Mezantrop
            27 июня 2020, 21:00
            Wallstep, 
            Это он Вам сам сказал?
            • Wallstep
              27 июня 2020, 23:17
              Mezantrop, конечно, вчера звонил.…. еще и смс скинул. .. 
              • Mezantrop
                28 июня 2020, 09:22
                Wallstep, 
                Вы по аккуратней...
                Расширенное сознание может назад не вернутся…
    • Валерий
      27 июня 2020, 07:16
      Mezantrop, ради саморазвития и спортивного интереса
      • Mezantrop
        27 июня 2020, 07:42
        Валерий, 
        Логичнее же все то же самое замутить в рамках коммерческого проекта? Напуркуа благотворительность? При чем это массово — полезного халявного кода — полинета.
        Если как оставить о себе память — более менее понятно — компенсация навязанной манипуляции. Если с другой целью — не понятно…
        • 4kk
          27 июня 2020, 19:58
          Mezantrop, вот такие как вы, никада не поймут таких как мы. Просто что-то взять и запилить покайфу. Чтоб работало. У вас адреналин только от денег выделяется?
          • Mezantrop
            27 июня 2020, 21:03
            4kk, 
            У меня много что,  много от чего, выделяется ...
            Но два безвозвратных ресурса: время и здоровье — обычно трачу с личной пользой…
  • Свой Мужик
    26 июня 2020, 18:52
    Ого кто-то Lisp вспомнил!!! Вот это круто!
      • Свой Мужик
        26 июня 2020, 19:44
        Евгений Шибаев, ой 20+ лет прошло уже кроме названия и то что под автокад который ещё тогда под DOS был по моему, писал не вспомню ничего :(
    • Носорог
      26 июня 2020, 19:09
      Свой Мужик, 

      Эх помница на автолиспе ваял я код под автокад.
      Бабули впрочем были против («био-копир наш был не рад») 
      Одно и то же рисовали толпой, годами — это скука! 
      Поставил плоттер (струйный правда), а мне сказали, что я — сука. :) 
      • Свой Мужик
        26 июня 2020, 19:44
        Носорог, да да да под автокад )))
      • Валерий
        27 июня 2020, 07:18
        Носорог, я и сейчас на автолиспе себе рутину на работе автоматизирую
        • Носорог
          27 июня 2020, 09:19
          Валерий, а у меня первая любовь — Паскаль. Понятно что до неё были бэйсик и даже программируемые калькуляторы. Из-за паскаля многие годы игнорировал си, а зря — в итоге все сиподобные нотации мне не заходят. Писать конечно могу, но как на неродном языке, а на Паскале я думал — сразу код себе представлял, оставалось его набить на клаве.

          И вот когда стал выбор между мультичартс и тс лабом, я выбрал первый как только прочитал, что его EasyLanguage — это Pascal.

          Выбор возможно иррациональный, уж как то долго я его осваиваю, куча граблей. Хочется верить что в тс лабе все проще. Но все равно какой это кайф было вспомнить первую любовь :) 
  • Alexandr
    27 июня 2020, 00:06
    отличная штука, а как сделать тоже самое но только применительно к объемам?
  • Олайвир Стокс
    27 июня 2020, 03:35
    Тимофею напомните по теме сосредоточения общеполезных материалов технического характера
  • Врач-бондиатОр
    27 июня 2020, 07:39
    Лисп -это жестко…
  • Andy
    27 июня 2020, 07:56
    за халяву большое спасибо. Но есть вопрос
    \Screener.lua:29: attempt to index field '?' (a nil value)
    это потому что сейчас торгов нет? или я что то не так сделал?
      • Andy
        27 июня 2020, 12:25
        Евгений Шибаев, спасибо, проверю во время работы биржи. Фьючи не пользую, посмотрю на акциях.
  • 4kk
    27 июня 2020, 19:55
    Хоть раз в месяц, что-то полезное можно на смарте найти. Кроме ежедневного нытья.
  • Alexandr
    08 июля 2020, 15:32
    Евгений, подскажите пжл, как изменить чтобы были фактические объемы? Если бы ещё ставилось дата и время в названии столбцов, то просто супер
  • Alexandr
    12 июля 2020, 18:47
    Евгений, а как сделать таблицу с открытым интересом?
  • SciFi
    21 ноября 2020, 18:01
    Огромное спасибо за хороший пример на Lua

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

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