3Qu
3Qu личный блог
14 декабря 2019, 20:42

Коммуникации Quik Lua с внешним миром.

Мне нравится Lua. Lua хороший компактный язык на котором можно сделать индикаторы, различные вспомогательные программы, помогающие трейдеру и даже несложные торговые системы (ТС, роботы). Пожалуй единственная книга по Lua — Роберту Иерузалимски: Программирование на языке Lua. Ее можно найти в интернете.

Lua имеет также несложный C-API позволяющий связать программы Quik Lua с внешним миром через DLL и получить доступ практически ко всему, в том числе к любым математическим библиотекам обработки данных, что необходимо для сколь-нибудь сложным ТС. Однако, для этого уже необходимо знание не только Lua, но и Lua C-API, языка С/С++, а также умения писать DLL. При этом надо будет решить еще ряд проблем, которые возникнут по ходу пьесы в процессе этой деятельности. Далеко не каждый пользователь Quik и Lua может все это реализовать в обозримое время.
У Quik Lua (QLua) есть еще недостатки — все события терминала в Lua работают в потоке терминала, и получив из них данные надо как можно быстрей завершать функции обработки этих данных и освобождать поток терминала, иначе терминал просто повиснет. Единственная функция QLua работающая в собственном потоке — это main() и вся сколь-нибудь сложная обработка может находиться только в ней.
Кроме того, для Lua крайне мало библиотек, а существующие работают оч не быстро. В принципе, это и не нужно, если можно организовать связь с внешним миром через C-API. Но нам от этого легче не становится.) Короче, для написания хорошей сложной ТС нам надо выйти за пределы QLua и установить связь с внешним миром, и сделать это доступными средствами.
Сейчас наиболее продвинутым языком, включающим в себя массу библиотек обработки данных является Python. По применимости для обработки данных он, пожалуй, занимает первое место в мире, а по распространенности входит в первую пятерку. В числе библиотек — математические, статистические, машинного обучения и пр., и пр. Таких библиотек более тысячи только в Anaconda, большинство из которых устанавливается при ее инсталяции. Вы можете не использовать Anaconda и скачать Python с сайта python.org, в этом случае, вам придется добавлять нужные вам библиотеки (пакеты) самостоятельно. Этот подход сложнее, но имеет некоторые преимущества.
Эти библиотеки в основном написаны на С++ и работают очень быстро, а сам Python при этом выполняет роль языка сценариев. И хотя сам Python язык не очень быстрый, его доля в исполняемой программе невелика и существенного влияния на быстродействие он не оказывает. Во всяком случае, для большинства ТС, включая интрадей, быстродействия систем на Python вполне хватает. Python, кстати, на начальном уровне, когда уже можно работать, легко осваивается за пару недель. Литературы в интернете много и не буду что-либо рекомендовать.
Итак, мы будем связывать QLua с Python. И делать это через обмен файлами с данными.
Сам я этот способ связи сейчас не применяю и работаю через DLL. Однако, ранее много использовал для самых разных целей, в том числе для проверки и отладки различных торговых программ. Писать DLL, все-таки, достаточно муторно, а опробовать обработку данных со связью через файлы не представляет сложности, да и всякие изменения вносятся очень просто. А DLL — это уже на последнем этапе, когда все уже готово.
Итак, файловый обмен. Код приводить не буду, он элементарен, файловые операции все знают. Опишу только принципы обмена данными. Но, если будут просьбы опубликовать экземпл, то со временем сделаю.
Пусть мы получили данные из события терминала в функцию OnAllTrade(alltrade). Для обмена с DLL функция выглядит так:

-- получение обезличенных сделок в Lua
function OnAllTrade(alltrade)
if alltrade.sec_code == FUT_S or alltrade.sec_code == FUT_L then
--message("Обезлич сделка beg " .. alltrade.sec_code)
at ={alltrade.datetime, alltrade.sec_code, alltrade.trade_num, alltrade.flags, alltrade.price,
alltrade.qty, alltrade.value, alltrade.period}
CCS.AllTrade2DB(at) -- вызов функции DLL
--message("Обезлич сделка end " .. alltrade.sec_code)
end
end

В этом коде мы должны вместо функции вызова DLL написать и подставить другую функцию, преобразующую данные at к текстовому формату CSV. Получим строку букв и чисел разделенных запятыми. Данные готовы для передачи во внешний мир.
Теперь для передачи данных нам потребуется два файла:
AllTradeD — служит для передачи данных, и
AllTradeF — пустой файл, служит флагом для индикации готовности данных к считыванию.

На первом шаге мы открываем и записываем данные at в файл AllTradeD, закрываем файл, после чего создаем пустой файл AllTradeF, индицирующий приемной стороне, что данные готовы к считыванию, и закрываем его. Данные преданы.
Теперь обратимся к приемной стороне, уже Python, в нашем случае.
В программе Python организуем цикл, проверяющий наличие файла AllTradeF. Как только файл обнаружен, данные готовы к чтению. Читаем данные из файла AllTradeD и обязательно закрываем файл. Теперь удаляем файл AllTradeF, что будет означать для передающей стороны (QLua), что приемник готов к получению следующей порции данных. Далее процесс повторяется до полного одержания.
Да, передающая сторона должна открывать файл AllTradeD для записи, а не для дополнения.
Собственно, передача данных из Python в QLua делается аналогично.

Теперь о быстродействии такой системы.
Мне удалось получить скорость передачи ~1Gb/s c RAM-Disk. Разумеется с HDD такую скорость обмена не получить, но если у вас есть SSD, то скорость обмена будет вполне удовлетворительной. Даже если у вас нет SSD, то сейчас уже на многих компьютерах появились порты USB 3.0 и 3.1. Имея соответствующую флешку и осуществляя запись на нее также получаем очень приличную скорость обмена.
Использование для записи флешки USB 2.0 вместо HDD тоже дает некоторое преимущество в скорости, т.к. диск порой занят не только вашими, но и другими делами, и временами скорость обмена может существенно падать.

89 Комментариев
  • Karim
    14 декабря 2019, 21:09
    Зачем такие сложности. Проще передавать данные через память, а не через файл. Да и быстрее.
    Да и Lua-машина в квике запускается в отдельном потоке, кроме того, в отдельном потоке запускаютя каллбеки.
      • Александр
        15 декабря 2019, 09:38
        3Qu, Самый плохой способ. При этом диск будет нагружаться сильно. И работает это достаточно медленно. Тогда уж по TCP передавать данные, такие библиотеки есть и в lua и питоне.
        Проще всего использовать нативное апи. В котором можно создавать свои собственные потоки.
        • Максим
          15 декабря 2019, 14:18
          Александр, А пример, как это реализовать, написать можете ? 
          • Александр
            15 декабря 2019, 21:16

            Максим ТХАБ, Есть например LuaSockets github.com/diegonehab/luasocket

            В интернете можно найти бинарники. Можете грузить по сети.

            Если вы знакомы си++ или делфи, то реализовать такую фичу можно будет легко.

      • Виталий
        15 января 2020, 13:12
        3Qu,  а сколько строк пишите в файл?
          • Виталий
            15 января 2020, 13:45
            3Qu, в примере я понимаю, что 1 строка)
            просто вы сказали, что замеряли и добились высокой скорости — дак вот сколько у себя строк та пишите? явно там не одна сотня?

            скажем 1500 строк в 4 столбца на инструмент и так по 4 инструментам и так раз 5 в секунду это будет анриал или все переварится?

            по опыту C# в csv несколько тысяч строк в 2 столбца пишет менее 50 мс на сколько помню.
  • ICWiener
    14 декабря 2019, 21:12
    Да сам то квик медленный, а тут еще навесить все это
      • ICWiener
        14 декабря 2019, 21:28
        3Qu, из всех терминалов, с которыми я работал, самый стремный, долгий и кривой — это квик. Истинный Франкенштейн. Даже терминал 3.5 у Альфы, был гораздо лучше, что у говорить про 4 версию. 
        Что касается роботов, то квик просто не приемлем, если надо что-то делать быстро. При всех недостатках МТ5 он очень быстр. Хотя в идеале нужен свой собственный софт, а еще лучше свой собственный девайс работающий с биржей по быстрым протоколам.
  • _sg_
    14 декабря 2019, 23:04
    У Quik Lua (QLua) есть еще недостатки — все события терминала в Lua работают в потоке терминала, и получив из них данные надо как можно быстрей завершать функции обработки этих данных и освобождать поток терминала, иначе терминал просто повиснет. Единственная функция QLua работающая в собственном потоке — это main() и вся сколь-нибудь сложная обработка может находиться только в ней.

    В Квике скорее всего выделен отдельный поток на события Lua.
    И этот поток будет тоже «потоком терминала», как и все другие потоки.
    Обычно делают так.
      • _sg_
        14 декабря 2019, 23:16
        3Qu, может быть документацию Квика посмотреть…
      • Technotrade
        14 декабря 2019, 23:18
        3Qu, а для альфадиректа вы пробовали писать тс? И как успехи?
        • ICWiener
          14 декабря 2019, 23:27
          Technotrade, альфадирект вообще не применима для чего-то алго, не знаю даже зачем они затеяли роботов на своем терминале. Хотя в АД есть интересные решения для ручной торговли — типа исполнение ордера при пробитии нарисованной руками линии.
          • Technotrade
            15 декабря 2019, 11:44
            ICWiener, а почему не применима для алго? Можете объяснить на пальцах?
            • ICWiener
              15 декабря 2019, 13:58
              Technotrade, очень слабый задел. Штатных функций не хватает даже для простых роботов, а ковырять их недокументированный API — к чему, если есть МТ5 (быстрый, с документацией и С-подобным языком)
          • Technotrade
            15 декабря 2019, 11:50
            3Qu, а что, то что вы писали на  С# для АД4 с ним не работало вообще, или какие проблемы возникли ??? У них же прямо в самой программе можно код писать. Там на каком языке коды ? 
  • Eugene Bright
    14 декабря 2019, 23:25
    Совсем не спец по QLUA (стаж общения — 1 год). Написал ТС. Сначала грузила память на 2Гб (50%), но после изменения структуры (организация сопрограмм/функций) вне основного потока main() загрузка стала не более 4%, а время — считанные мс. 
    Полагаю, что внешние dll — библиотеки не помогут, если само тело ТС перегружено.
    Использую SSD, ноут.
      • Eugene Bright
        15 декабря 2019, 00:13
        3Qu, да, я согласен на песочницу. Куличики — наше всё.
      • Eugene Bright
        15 декабря 2019, 00:46
        3Qu, логично, чо!
  • GVS
    14 декабря 2019, 23:53
  • dnmsk ☮
    15 декабря 2019, 00:21
    Все уже давно написано за вас. Ищите реализацию через сокеты. 
      • dnmsk ☮
        15 декабря 2019, 00:38
        3Qu, Насколько быстрее эта реализация чем на lua?
  • PSH
    15 декабря 2019, 01:09
    В качестве практикума по процедурному программированию интересно, наверное. Сама идея прикручивать к луа сбоку питон и обмениваться данными через файлы видится мне не самой эффективной
  • PSH
    15 декабря 2019, 01:10
    Lua как язык, безусловно, шыкарен :)
  • PSH
    15 декабря 2019, 01:24
    3Qu, ну лично я бы, конечно, работал с луа-машиной из c# напрямую, быстро, удобно
  • PSH
    15 декабря 2019, 01:26
    Но у меня брокер itinvest с их smartcom — тоже достаточно кривая поделка
  • Turbo Pascal
    15 декабря 2019, 04:02
    Поддерживаю.
    Если разговор про HFT, то это другая песня.
    А для всего остального файловый обменник — самое то.
    На луа пишем только прием-передачу данных между брокером и своим софтом.
    Далее — всё остальное на чем захочется.

    Даже на Турбо Паскале :)
    • Niktesla (бывш. Бабёр-Енот)
      15 декабря 2019, 13:58
      Turbo Pascal, на вашем этом турбо паскале токо студентов Вирту учить… вот Delphi 7 это реальная тема! 
  • day0markets.ru
    15 декабря 2019, 07:52
    Есть связка квик/python на сокетах. В стадии тестирования, кто хочет потыкать велкам в личку
    • Vadim Ch
      24 декабря 2019, 15:33
      day0markets, К сожалению не могу в личку написать :( Можете поделиться связкой? Хочу на новогодних каникулах поиграться 
    • vvt
      05 февраля 2020, 22:46
      day0markets, тоже не могу написать в личку, а хотелось бы потыкаться )
  • GoodBargains
    15 декабря 2019, 11:09
    Что подразумеваете под сложным роботом?
  • GoodBargains
    15 декабря 2019, 11:13
    Правда пишут, что в самом квике есть косяк, который до сих пор не починили. Если происходит сигнал на вход или выход в момент зависания квика, то после возобновления работы квика сделки могут дублироваться по несколько раз? Теряется айди какое то там..??
  • GoodBargains
    15 декабря 2019, 11:14
    Есть ли тут спецы, которые могут написать робота по стратегии из ТСлаб? Точь в точь.Сколько?
  • Niktesla (бывш. Бабёр-Енот)
    15 декабря 2019, 13:36
    а я в dll-ку всё сгружаю...
    за полтора года пару раз видел как глючит получение данных в квике, и соответственно та же кривая муть из квика пихается в dll...

    а вот сам lua (нонстоп пихающий всё мне в dll-ку) за всё это время ни заглючил ниразу(я по крайней мере не заметил)...

    Эх… этому lua в квике нормальный бы блеать юзер-френдли отладчик…
    • Пафос Респектыч
      15 декабря 2019, 16:45
      Niktesla (бывш. Бабёр-Енот), а что мешает запускать луа-скрипты отдельно от квика? Ничего ) Если есть вообще в природе юзер-френдли отладчики для луа, конечно. Наверное есть.
    • Виталий
      15 января 2020, 13:00
      Niktesla (бывш. Бабёр-Енот), привет! не понял поясни как ты в LUA получаешь отдельно данные? через создание подписки в коде на данные?
      • Niktesla (бывш. Бабёр-Енот)
        15 января 2020, 17:47
        Виталий, не совсем понял что значит отдельно... 
        в функции мейн в цикле вызываю что-то вроде

        if getItem(«FUTURES_CLIENT_HOLDING»,i).sec_code == security then 
          return getItem(«FUTURES_CLIENT_HOLDING»,i).totalnet;

        • Виталий
          15 января 2020, 18:18
          Niktesla (бывш. Бабёр-Енот), не так понял ваш коммент первый, уловил теперь)
          а данные для LUA все-таки получаете с графика по идентификатору через getCandlesByIndex или создаете подписку в самом LUA на поток данных с сервера?getCandlesByIndex
          • Niktesla (бывш. Бабёр-Енот)
            15 января 2020, 18:35
            Виталий, я честно говоря графики не гружу, обхожусь бидами и офферами.

            offer1 = tostring(getParamEx(«SPBFUT», ticker1, «offer»).param_value)
            bid1 = tostring(getParamEx(«SPBFUT», ticker1, «bid»).param_value)

            Для того чтобы они работали, должен быть открыт соответствующий стакан. я это расцениваю как дополнительный контроль/предохранитель, а не как неудобство(всё равно нужно квик открытым держать).

            Со свечами я думаю работал бы примерно так же. То есть держал бы график открытым и с него уже получал бы через getCandlesByIndex.

  • billy
    15 декабря 2019, 16:35
    теоретически, если через файлы, то и через базу, а она автоматом дает синхронизацию.
      • billy
        15 декабря 2019, 18:38
        3Qu, ну а что проще sql, даже не знаю, те же csv вроде все поддерживают
  • Niktesla (бывш. Бабёр-Енот)
    15 декабря 2019, 17:53
    меня вообще корежит от мысли об обмене потоковыми данными в реальном времени через запись в файлы… рука не подымается так жесткий диск насиловать ^^'
      • Александр
        15 декабря 2019, 21:24
        3Qu, У баз данных хорошая система кеширования, плюс данные пишутся в память и диск они не насилуют. Ваш вариант называется «как изнасиловать диск». Самый простой из рабочих вариантов — это передавать данные по TCP/IP, можно реализовать двухнаправленное соединение и передавать данные в/из питона.
          • Александр
            16 декабря 2019, 11:53
            3Qu, Не сравнивайте то, как базы пишут и ваш вариант. В интернете есть библиотеки для lua, которые реализовывают TCP/IP, легки в использоании. Я такой пользуюсь, друзья пользуются. Если вы не можете использовать, это наверное ваши проблемы. Говорить за других я бы не стал.
  • Кашников Александр
    16 декабря 2019, 10:57
    Что-то тут вы фигней занимаетесь. Половину из того, что народ пытается впихнуть из луа в другой ЯП, решается на самом луа, гораздо быстрее и надежнее. Да и квик + скорость нужно забыть вообще, не важно сколько по времени будет считать алгоритм на луа или на том же С++, когда дело дойдет до транзакции, то, собственно и всё, супер-пупер быстрый расчет на С++ сводится в 0. 3Qu обмен данными через файл не потокобезопасен и как «метод» — фуфло.
  • Andrew Morozov
    16 декабря 2019, 14:06
    Уважаемые участники дискуссии, можете ли кто-то поделиться информацией, если обладает таковой, насколько быстрее работает конструкция клиентское приложение-> transaq api, чем связка клиентское приложение — > какой то костыль — >quik.

    Для простоты положим что все написано на с++. Спс.
  • Andrew Morozov
    16 декабря 2019, 14:32
    Кашников Александр, сорри, но так там все про квик… Интересно сравнить скорость доставки транзакций, в основном.
    • Кашников Александр
      16 декабря 2019, 15:27
      Andrew Morozov, а зачем? Эта скорость изменчива у обоих методов и зависит от многих внешних факторов. Если нужна скорость, то копайте сразу в сторону ко-локации.
      Один раз сделаете и куча плюсов:
      -ни тебе брокер корявый не помешает со своим «рубильником»;
      -ни провайдер;
      -и даже Вася Пупкин — тоже мешать не будет.

  • Andrew Morozov
    16 декабря 2019, 15:00
    Я не этот вопрос задал, извините. При чем здесь файлы, или ДДЕ, мне интересно, насколько более отзывчивы сервера системы transaq, чем квиковские, какие
    разницы по нагрузке, вот что я имел ввиду.
  • Andrew Morozov
    16 декабря 2019, 15:02
    Скорость самого квика не устраивает даже без всяких торговых систем, руками невозможно торговать внутри дня.
  • Andrew Morozov
    16 декабря 2019, 17:04
    Кашников Александр, прямой доступ, оно понятно. Если б не геморрой с сертификацией, сделал б уже. И факторы, которые влияют на работу бэкэнда тоже понимаю, не понятно есть ли существенная разница в этом влиянии между квиком и транзаком.
    • Кашников Александр
      16 декабря 2019, 19:00
      Andrew Morozov, опять же, в чем вопрос, не понятно. Отправляете заявку из квик раз 30, в цикле со sleep(1000) и без него и точно так же через transaq.
      Замеряете, сравниваете, делаете выводы. До сервера квик у меня заявка летит от 20 ms до 260 ms, в среднем 130 ms. про transaq не знаю ничего, кто-то кричал, что 18 ms, в чем я сильно сомневаюсь. Может раньше так и было в транзаке, но раньше и через квик 20-40 ms летели заявки, пока арка не ввела в плагин qlua функцию isDarkTheme (сарказм)
  • Andrew Morozov
    16 декабря 2019, 21:26
    Вопроса бы не было, если б у моего брокера транзак. Так то да, придётся сделать именно то Вы советуете, и не один раз, но придётся открыть ещё один счёт либо забить на это и сертифицировать свой софт на бирже. Поэтому и пытаюсь найти просвещенных людей, прояснить, чтобы не делать лишних движений
    • Andrew Morozov
      16 декабря 2019, 21:29
      20 или 50 миллисекунд, в моем случае это не имеет значения, квик, на пару секунд иногда лагает.

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

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