Блог им. bosco

On-Line получение данных из Quik в Java и не только

    • 14 ноября 2014, 23:51
    • |
    • П М
  • Еще
Как говорится, делай добро и бросай его в воду.
Выношу на свет плоды своих трудов. Трудов не одного дня. На текущий момент это же решение уже работает у меня в составе робота.
Проверено.

Что это такое: с помощью скрипта QApi.lua на стороне Quik организуется сервер, который умеет принимать команды с клиента и отдавать ему результаты выполнения этих команд.

какие команды и данные может выдавать скрипт
— получение стакана по заданной бумаге (class, security)
— получение последних N свечей по заданной бумаге   (class, security, interval, count)
— получение времени сервера
— получение торговой даты
— получение статуса квика — подключен он к серверу или нет

Зачем это надо: работает достаточно быстро — десятые доли секунды, стакан отдаётся с разной скоростью, т.к. скрипт для начала ждёт чтобы стакан изменился (гарантированно последние данные), не требует на стороне квика никаких настроек и открытых графиков. всё что надо — запустить скрипт.

Как это работает используется Windows Named Pipe, работа с которой происходит чере технологию FFI — foreign function interface, эта технология поддерживается для многих языков, таких как Java и Perl, например. Из VBA и C# можно работать с Windows Pipe напрямую, сделав объявления соответствующих функций из kernel32.

Похвастаюсь, в процессе работы с FFI я нашел существенную ошибку, которая не позволяла корректно работать с Trans2Quik.dll (да, это я тоже сделал на Java, но это уже отдельный проект), а именно — падала при переходе в Callback по обновлению статуса заявки. Я связался с разработчиком и он любезно это исправил. На форуме Quik разные люди в разное время не могли побороть эту проблему 3 года...

Что нужно чтобы запустить у себя 
  • ну во-первых Quik, во вторых, нужна скомпилированная библиотека ffi.dll, я брал отсюда: github.com/jmckaskill/luaffi. Там надо будет подшаманить с qlua.dll, чтобы получить из неё qlua.lib
  • затем, если вы будете работать на java, вам понадобиться jna, я брал отсюда https://github.com/twall/jna 
Где можно взять исходники 
а собственно вот: github.com/boscogh/quik_pipe

Честно скажу, это мой первый опыт опен-сорса, может я что-то сделал не так, исправлюсь.
Надеюсь это всё кому-то поможет.

Зачем я всё это выкладываю? Хочу найти работу в очень серьёзном трейдинге. «Ну ваааазьмите меня» 
Люблю системное программирование. И трейдинг.
★42
71 комментарий
да, немного про ограничения: сервер работает только с локальными клиентами (с этой машины), максимум одновременно только один клиент.

клиент может подключаться и отключаться, сервер это легко переживает.
avatar
ПBМ, а в случае многопоточной работы одного клиента? То есть мы создаём одного клиента, который из нескольких десятков потоков выставляет/снимает заявки, запрашивает данные из таблиц и т.п., сервер с подобным должен справиться? Сейчас у нас именно такая реализация, работает нестабильно, иногда виснет при запросах.
avatar
anovikov1992, о каких заявках речь?
в текущей реализации никакая многопоточность не поддерживается.
взаимодействие идёт по схеме: запрос -> ответ.
avatar
«получение времени сервера»

Вот эта штука, интересно, как реализована?
avatar
RIH2, в lua есть такое API,
см 183 строку github.com/boscogh/quik_pipe/blob/master/qapi.lua
avatar
Павел Bosco М, ага, спасибо.
avatar
RIH2, А время биржи есть там (не сервера квика)?
avatar
RIH2, так это и есть время биржи, нет?
т.е. это то время, которое отображается в квике снизу слева как «время сервера»
avatar
Павел Bosco М, не знаю, не уверен. Мне казалось что время сервера это время сервера QUIK, а время биржи это другое (собственно время биржи, по которому заключаются сделки). Так достоверно было на другом терминале и я думал что на квике так же, и поскольку моё мнение не было изменено за 5 лет, видимо и оснований для этого не было. Но мог и просто не заметить, давно уже не смотрел за этим всем.
avatar
RIH2, с другими терминалами не работал, но заявки регистрируются по времени сервера, у меня робот успевает вставать ровно на открытии следующей часовой свечи.
т.е. смотрю каждые 100 мс на время сервера, если уже хх:00:00, то читаю последние 3 свечи, разбираю для того часа который завершился и по необходимости выставляю заявку. В квике она отображается как xx:00:00,
насколько я понимаю, это уже время, когда она на биржу попала?

я скальпингом не баловался, насколько я могу понять, через квик это дело не самое быстрое. Сегодня у меня в районе 14:00 (для этого случая ставлю в 13:59:59, пораньше) была выставлена заявка, на покупку, но исполнилась она далеко не сразу, хотя цена уходила и чуть ниже. Исполнилась только через 5 минут. Не знаю почему, но дело точно было не во времени

UPD: пардон. это я уже глючу, заявка на продажу была. поэтому пока цена была ниже, она и не срабатывала… пора спать :)
avatar
Павел Bosco М, а кроме программирования вы ещё что-то умеете?
avatar
Mr. Bean, по работе? пишите в личку, может и умею.
текущий профиль работы у меня не связан с трейдингом. хотя связан с банками.
образование — инженерное, программист.
занимаюсь интеграцией банковских систем.
ну и не только банковских. любых где есть данные и интерфейсы по работе с ними.
avatar
Павел Bosco М, а почему через quik скальпить не быстро? Дело в отсутствии удобных инструментов или в медленной скорости самого quikа?
Спасибо за ваши примеры кода, как раз начинаю изучение построения роботов. Сам java программист, и думал что придется осваивать C# для этих целей.
avatar
gry, что нам программистам, сложно еще один язык освоить? =)
c# интересен когда переходите на другие системы типа TsLab
avatar
спасибо за примерчик.
дайте, пжлст, мыло — есть темка.
тханк ю.
avatar
Ринат Негметов, зайди ко мне в профиль, там первая ссылка «Написать письмо»
avatar
да с lua можно и наружу транслировать все пироги
а мне интересно, как можно из своей софтины связаться с серваком брокера, чтобы он думал что моя софтина — квик и отдавал данные, и принимал команды
avatar
velikan, наверное можно и так, но вряд ли получится быть квиком быстрее квика.
тогда уж лучше кардинально решить проблему и соединяться с сервером биржи напрямую, через Plaza. я так ещё не делал.
avatar
Павел Bosco М, быстрее — получится, квик потому что думает не только про купить/продать но и про кучу всего остального — комплексная софтина
а напрямую — да, тут никакой квик не поможет, только деньги :) наверное
avatar
velikan, попробуйте отснифить порт. заодно и нам расскажите про протокол =)
avatar
Андрей К, пробовал — основная проблема в том, что я нихера не понимаю в логах wireshark :(
avatar
> делай добро и бросай его в воду.
Больше нравится «делай добро и беги» :)
avatar
автор, dde то тебе чем не угодил?
avatar
GreenBear, передача данных через DDE по идее медленнее, чем через Lua.
avatar
Enfernuz, медленнее?
avatar
GreenBear, медленнее 100%.
плюс такие разработки могут привести к полноценной серверной части на qlua. Например двусторонний обмен данными и выполнение команд на сервере со стороны клиента
avatar
Андрей К, проясните этот момент на каком этапе медленне? Я на sql сервер передаю например все сделки и не заметил даже секундной задержки.

Я бы разработчиков квика заставил землю есть. LUA, QPile, DDE еще какая-то лажа… Все что необходимо это простой интерфейс с реализациями функций: connect, getHistory, trade. всё! такие разработки приведут только к потери времени.
avatar
GreenBear, вообщем дело такое.
Тут я бы разделил для себя вот что. Говорим про какой то автоматический вход в позицию. Выделяем такие параметры: моменты входа (какие то уровни со скопление ликвидности или просто вход свободный по рынку), возможный тейк, возможное время нахождение в сделке.

Если у нас осуществляется вход в сильно валотильный и сильно ликвидный момент на рынке, при этом тейк не более 500п (к примеру) и время сделки короткое (ну например 10-60сек), то коннект нам нужен быстрый. Я бы не сказал что могут решать микросекунды, но на dde при нынешнем рынке нас может легко просквозить на 100п (ри), в си и того сейчас больше. Если мы высиживаем до 500п, то такие потери конечно существены.
Если мы принимаем решение сидеть глобально (ну например отбой от какой нибудь сотой машки), сидеть пару часов и пару тысяч, то конечно можно и dde.
Это я все высказал свое мнение.
Далее. Существуют ряд приводов для quik. Я думаю все вы их знаете. И они когда то начинали с dde. Было достаточно много жалоб на такой вид коннекта от пользователей. И постепенно эти коннекты ушли.
avatar
Андрей К, так и думал, что на уровень миллисекунд спустимся. Я сильно сомневаюсь в вашей правоте. Посерфил инет на эту тему, в основном вопрос поднимается на S#. Делаю выводы:
— или у разрабов S# руки кривые.
— или старые версии quik были кривые.

на форуме quik'a обсуждают что срезы стакана в квик приходят 1-3 раза в секунду т.е. бороться за скрость < 10 мс. нет никакого смысла! а значит gate + plaza вам помогут, а не LUA.

Приводами квик не пользовался, их историю не знаю.
avatar
GreenBear, я поделился с вами своим опытом. Привел цифры. И примеры, когда они критичны. Вы захотели, чтобы я пояснил, я рассказал.
Я акцентировал внимание, на решаемые задачи. Когда то подходит dde и не стоит усложняться в qlua, когда то подходит qlua и не стоит тратиться и еще больше усложняться на плазу и тд. Всему свое место.

Что касательно старых версий quik. DDE — это отдельная разработка microsoft, вышедшая еще из 90-ых. Сам quik не особо имеет отношение к ней, просто средствами windows передает данные, некий такой блок внутри windows
avatar
Андрей К, ок. не буду больше флудить :)
avatar
GreenBear, для DDE надо делать гораздо больше манипуляций — создать таблицу, настроить вывод, включить его.
Мой вариант ничего этого не требует, даже для свечек.
Ещё, мне не нравилось что DDE — пассивный. Т.е. Quik решает, когда прислать тебе данные. В моём варианте, клиент сначала просит что ему надо, а сервер отвечает.
Потом lua универсальнее. Как узнать по DDE время сервера и статус подключения? Можно ли по DDE отправлять одновременно и свечи и стаканы?
Наверное тоже можно… но не легко.
Ну и, честно говоря, парсить данные из буфера в нужном тебе формате гораздо проще чем заморачиваться с парсингом достаточно не простой структуры данных в DDE.
DDE я тоже делал, начал с него. Получилось, но не понравилось.
Windows Pipe попроще будет. И да, может доказательств у меня нет, но по-моему всё-таки действительно быстрее.
Я действительно считаю на миллисекунды. Меньше чем на 100 миллисекунд — это уже не квик. А для квика это время вполне достижимо. И для крупных таймфреймов, типа 1 час — более чем достаточно.
avatar
Павел Bosco М, писать скрипт на LUA быстрее чем делать вывод на DDE? :)
делаете вывод на сервер SQL пишет запрос и ничего не надо парсить + сохраняете историю для анализа.
частота вывода указывается в настройках, а проверка — изменился ли стакан, увеличивает время доставки инфы ;)

ну не буду больше утраивать полемику. без перфоманса достижение кажется сомнительным.
avatar
GreenBear, устроил полемику и бежать? :)
вопросы:
1. как организовать вывод свечек по ДДЕ? никак, без вспомогательного скрипта.
2. можно ли выводить по одному каналу DDE несколько инструментов?
3. что делать, когда фьючерс истёк и надо переходить на следующий, можно ли перейти автоматически?
4. можете ли вы получить котировку, свечку, ровно в тот момент, когда она нужна вам? а не когда сервер решил её вам отдать?
и вообще, по-моему вы всё-таки говорите не про DDE в SQL, а про ODBC.
что касается перформанса. приводите ваши цифры, интересно.
возьмём свечи. закончился час. через какое время у вас появится новая свеча?
вообще подумайте немного логически, что быстрее, обратиться напрямую в квик за нужными данными, пусть и через pipe/lua или обратиться к серверу SQL через тот же самый pipe (сюрприз!), который получает данные из Quik тоже не посредством волшебства, а скорее всего через pipe?
avatar
Павел Bosco М,
1) таблицы настраиваются и экспортируются!
2) 1)
3) 1)
4) могу ). триггеры, таймеры...
ну да odbc.
когда я делал нужный мне индикатор, он обновлялся каждую секунду.
quik -> odbc -> робот. quik -> lua -> робот. не могу сказать точно, что быстрее.
и добавлю, организация автоматизации в квике меня сильно раздражает, ушел на transaq connector, больше свободы и больше контроля.
avatar
GreenBear, между odbc и роботом ещё ms-sql, я об этом
т.е.
quik -> odbc -> ms-sql -> odbc -> робот
а так, кому что удобнее.
avatar
quik -> odbc -> ms-sql -> odbc -> робот



avatar
Господи, 10/10!
Автор, как отблагодарить?

Написал свой алгоритм на Lua, но скрипт после некоторого времени вешает Quik. Написал на С# с использованием StockSharp — так там коннектор Quik Lua только недавно приделали, и кое-каких нужных вещей ещё нет. А покупать Plaza 2 пока жаба душит.
Сам Java-программист по текущему месту работы, поэтому такая библиотека очень кстати.
avatar
Enfernuz, есть яндекс кошелёк
410011439569740
avatar
Хотел было в личку вопрос отправить, но тут на СЛ практически во всём дискриминация по рейтингу, в том числе и на отправку личных сообщений.

Попытался по вашей схеме наладить передачу через qapi.lua и столкнулся с проблемой: после нескольких секунд работы скрипта qapi.lua терминал падает с ошибкой Windows:

[ Сигнатура проблемы:
Имя события проблемы: APPCRASH
Имя приложения: info.exe
Версия приложения: 6.14.0.12
Отметка времени приложения: 53b69afe
Имя модуля с ошибкой: StackHash_97c2
Версия модуля с ошибкой: 6.1.7601.17514
Отметка времени модуля с ошибкой: 4ce7ba58
Код исключения: c0000374
Смещение исключения: 000ce653
]

Что я делал до того, как:
1) Сбилдил ffi.dll и ffi.lib — положил их в %Path_to_Lua%/5.1/lib/
2) ffi.dll положил в %путь_до_терминала%/lua/
3) получил с помощью MSVC Command Prompt из qlua.dll (лежит в папке терминала) инфу для создания qlua.def
4) с помощью той же коммандной строки создал qlua.lib
5) положил qlua.dll и qlua.lib в %Path_to_Lua%/5.1/lib/ (зачем?)

Классический вопрос: что я делаю не так?
avatar
Enfernuz, вообще как-то не так.
надо сначала сделать 3) 4), потом для 1) указать qlua в качестве «lua.dll» и «lua.lib» в файле msvc_build — т.е. qlua.dll и qlua.lib, затем библиотечку ffi надо положить в каталог с info.exe, скрипт можно класть куда угодно, это не существенно.
у меня тоже не получилось с первого раза.
там есть в ffi тестовый пример «test.lua», он должен отрабатывать без violation. стартовать и заканчивать.
на нём проще потренироваться, т.к. для него надо только lua, без квика.
avatar
Павел Bosco М, спасибо, вроде разобрался.
А заявки вы как отправляете?
avatar
Enfernuz, через Trans2Quik.dll и FFI тоже
твои деньги на кошелёк упали? спасибо :)
avatar
Павел Bosco М, я пытаюсь сделать java-обёртку для trans2quik.dll с помощью JavaCPP (https://github.com/bytedeco/javacpp), но нифига что-то не выходит (туповат я, что ли, но тамошних примеров недостаточно). Внутрях она на JNI, а это выигрыш в быстродействии по сравнению с JNA (http://developers.opengamma.com/blog/2012/05/25/jna-jni-and-raw-java-performance).
Хотя, может, игра с JNI вместо JNA и не стоит свеч, т.к. Quik уже сам по себе режет быстродействие своей политикой получения данных с сервера. Но с этой обёрткой у меня уже принципиальный вопрос — «могу ли я?» :)
Если осилю — поделюсь.
avatar
Enfernuz, спасибо, у меня рабочий вариант, мне он нравится. Jna очень быстрый, там ведь ассемблер внутри. Ссылку гляну завтра.
avatar
Enfernuz, посмотрел статью. думаю не стоит тебе мучаться с JNI.
никаких больших матриц с последовательным доступом в методах не передаётся.
максимум 11 чтоли аргументов простого типа для работы с заявкой.
а график из статьи начинает отличаться для JNA и JNI только после матрицы 200х200
получение свечей например происходит за 1 милисекунду (при условии что труба уже создана) и то, я сравниваю через System.currentTimeMillis(), скорее всего там даже чуть быстрее всё.

сетевые задержки и задержки сервера Quik будут на несколько порядков больше.
avatar
а почему никто не пробует сделать все с zmq или подобными?
avatar
asteroid, а смысл? есть API ядра Windows, просто и быстро. зачем изучать какие-то сторонние вещи, написанные для прикладных (не системных) задач?
avatar
Вот здесь: forum.mql4.com/ru/3393#79641



Есть пример для МТ4 как организовать связь между двумя терминалами МТ4 (на одном компе)при помощи PostThreadMessageA() и соответственно GetMessageA().



В своё время я гнал котировки (тики) из одного терминала в другой (в той ветке мой последний пост с картинками). Полагаю что это точно быстрее DDE работает :)



P.S. Комп работал безостановочно с ночи понедельника до конца торгов в пятницу. Перегружал его только в выходные.



Это я к тому, что такой метод передачи очень надёжный… и ничего не вешает.
avatar
коллеги! можно попросить ffi.dll и ffi.lib или что там еще билдится и требуется проекту прикрепить или на файлообменник выложить? спасибо!
avatar
avatar
спасибо!
avatar
залил обновлённый код на GitHub, по результатам тестирования в бою. исправил проблемы при отключении-подключении сервера (только если вы пользуетесь скриптом круглосуточно без его выключения)
ну и ещё несколько мелочей.
avatar
ПBМ, спасибо за работу, помогает скрипт. Такой вопрос возник, по какой-то причине функции по получению времени сервера, торговый день, соединение с сервером работают исправно, а вот получение данных из таблицы текущих торгов (использование getParamEx() ) никак не удаётся запустить. Подскажите пожалуйста, может что-то поменялось с того времени или же какие-то настройки в терминале необходимо произвести?
avatar
anovikov1992, скорее всего не включен параметр в «поток котировок» «фортс» -> «гарантийное обеспечение покупателя»

avatar
ПBМ, в потоке котировок выбрал всё, что доступно. «Фортс» в нём не вижу

Может с моим подключением мне нельзя получать данные из этой таблицы? У меня сейчас тестовый доступ к учебному серверу
avatar
anovikov1992, возможно у вас это называется… Фьючерсы, но может быть там нет параметра «гарантийное обеспечение покупателя»
посмотрите что вам доступно в «фильтре параметров» для фьючерсов.
либо же вы указываете не тот класс или код инструмента.
avatar
Подскажите пожалуйста подобный способ возможно реализовать с помощью python? Есть ли возможность работать с заявками через pipe, не используя trans2quik? (я имею ввиду постановку, снятие, контроль исполнения заявок)
avatar
да, это я тоже сделал на Java, но это уже отдельный проект), а именно — падала при переходе в Callback по обновлению статуса заявки.
У меня такая же ерунда видимо в скрипте… запускаю скрипт (python)… выставляю заявки… снимаю, исполнение… все работает!  коллбеки приходят… все работает нормально… но затем просто отваливается скрипт (как будто выходит и цикла) у себя в скрипте все окутал логгированием и исключениями… но они все молчат. Я подозревал, что вылетает где то внутри длл… но событие это отследить не смог… причину воспроизведения ошибки тоже. Подскажите как Вы это победили?
avatar
4ypakabra, у меня была проблема в JNA библиотеке, FFI части, всё падало целиком при приходе ответа в колбек, связано было с тем что FFI некорректно формировало стек вызова. У вас явно другая проблема.

на python у меня мало опыта программирования, не знаю деталей вызова dll из него. 

вылет в dll приведёт к закрытию quik и формированию .dmp, который можно загрузить в MSVC и посмотреть где была ошибка. у вас явно не вылет.
avatar
ПBМ, Наверняка уже достал Вас вопросами и просьбами… Но все же рискну… Не могли бы помочь с компиляцией ffi.dll (64 bit). Я бы хотел научиться делать это сам, не могли бы не много пошаговой инструкции дать. Использую visual studio 2017. Раньше с такими задачами не сталкивался...(
avatar
4ypakabra, это ведь не моя программа.
разработчики снабдили её инструкцией, качаете исходник, открываете Makefile, там сразу слова

# For MSVC, please follow the instructions given in src/msvcbuild.bat.

открываете батник, читаете, настраиваете..

если будут сложности — спрашивайте. но нужно хотя бы начать.

avatar
ПBМ, Попробовал скомпилировать… Как прочитал выше в комментариях сделал qlua.lib. Взял файл qlua.lib, qlua.dll (из дистрибутива quik 8) и создал папку:
2) Прописал пути к файлам в батнике:


3) Попытался запустить батник...(


Сам Интерпретатор Lua брал отсюда: https://sourceforge.net (lua5_1_4_Win64_bin)

Подскажите пожалуйста в чем может быть проблема??


avatar
4ypakabra, ну как бы для того чтобы собирать исходники, нужны исходники.

в прошлом комментарии я ошибся и ссылался на исходники lua-jit, а не lua-ffi, т.е. другой проект. 

для lua-ffi инструкция собственно на сайте
https://github.com/jmckaskill/luaffi

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

ошибки, которые у вас вылетают, говорят что не найден самый первый файл с исходником
call_arm.dasc 

т.е. думаю, просто надо было перейти сначала в каталог с батником/исходниками.

avatar
ПBМ, я записал все свои действия пошагово вот тут https://github.com/facebookarchive/luaffifb/pull/13#issuecomment-509774274 
Если не сложно подскажите что я делаю не так… бьюсь уже 2 сутки не могу никак с мертвой точки сдвинуться! Понимаю, что оно Вам нафиг не надо… но надежда только на Вас

библиотека немного другая, но основа у нее та же самая… с luaffi по сути я делал аналогичное
avatar
4ypakabra, пардон, пропустил ваш коммент, 
я пересобрал ffi.dll, правда без отладочной информации, что-то там никак не подцеплялось, а разбираться было лень.
но думаю будет работать и так.
www.dropbox.com/s/mqtpqyhi4b35lcq/ffi.dll?dl=1
avatar
ПBМ, dll прицепилась все отлично! Только теперь при использовании Вашего старого скрипта handle у pipe = -1. (он не создается) Там поменялся синтаксис или  загвоздка в чем то другом? Проверил работоспособность функции int MessageBoxA(void *w, const char *txt, const char *cap, int type); из скрипта все получается… Может луа у меня какая нибудь не та с квиком лежит? 
avatar
Добрый День!
ПBМ
, Krl, вам удалось победить ошибку? У меня то же самое:

assert(ffi.C.ConnectNamedPipe(handle, poverlapped), «create connection error»)
--bad argument #1 to 'ConnectNamedPipe' (cannot convert 'number' to 'void *')

Если не трудно, подскажите, как исправить? ffi.dll скачал по вашей ссылке
avatar

теги блога П М

....все тэги



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