Мне нравится 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 тоже дает некоторое преимущество в скорости, т.к. диск порой занят не только вашими, но и другими делами, и временами скорость обмена может существенно падать.
Да и Lua-машина в квике запускается в отдельном потоке, кроме того, в отдельном потоке запускаютя каллбеки.
Проще всего использовать нативное апи. В котором можно создавать свои собственные потоки.
Максим ТХАБ, Есть например LuaSockets github.com/diegonehab/luasocket
В интернете можно найти бинарники. Можете грузить по сети.
Если вы знакомы си++ или делфи, то реализовать такую фичу можно будет легко.
Можно писать любое количество, которое нужно.
просто вы сказали, что замеряли и добились высокой скорости — дак вот сколько у себя строк та пишите? явно там не одна сотня?
скажем 1500 строк в 4 столбца на инструмент и так по 4 инструментам и так раз 5 в секунду это будет анриал или все переварится?
по опыту C# в csv несколько тысяч строк в 2 столбца пишет менее 50 мс на сколько помню.
Ну, а реал-тайм передается по разному — и одной строкой, и сразу несколько или много строк. Это не измерялось, но существенно падать скорости там не с чего. Это же файл в памяти.
Снйчас я использую ДЛЛ. Файловый обмен ранее использовал, и предлагаю только как простой и быстрый способ связи с внешним ПО. А для многих стратегий и даже скорости записи на диск выше крыши.
Что касается роботов, то квик просто не приемлем, если надо что-то делать быстро. При всех недостатках МТ5 он очень быстр. Хотя в идеале нужен свой собственный софт, а еще лучше свой собственный девайс работающий с биржей по быстрым протоколам.
Я работаю с Альфой в Квик, и если не грузить потоки Lua, а уходить из Квик наружу, то даже для интрадей роботов вполне приемлемо. Было бы неприемлемо, давно бы ушел в какой нибудь коннектор.
В Квике скорее всего выделен отдельный поток на события Lua.
И этот поток будет тоже «потоком терминала», как и все другие потоки.
Обычно делают так.
В 4-ке вроде есть API, но документация на него отсутствует, а самому разбираться, как это делают на Alfadirect4.ru, — эт на любителя.
Могу процитировать доки своими словами, написано как-то так — функции событий терминала работают в потоке терминала и после чтения данных поток функции должен быть по возможности быстрее освобожден.
Вы сами можете попробовать повесить туда длинный цикл и посмотреть что будет с терминалом. Лучше в понедельник.))
Я уже не буду обсуждать, что все события работают в очереди в одном потоке с соответствующими последствиями.
Полагаю, что внешние dll — библиотеки не помогут, если само тело ТС перегружено.
Использую SSD, ноут.
Сейчас мы занимаемся записью файлов из Луа. Файловые операции записи оч быстрые, т.к. осуществляются и буферизуются непосредственно ОС. Практически мы пишем в память. Так что поток событий освобождается мгновенно и почти не грузится.
Что касается чтения файлов из Квик, то это будет производиться в функции main(), а откуда непосредственно — из памяти ли с диска, это уже ОС решает. Т.к. реал-тайм объемы небольшие, то чтение будет скорее всего производится из буфера ОС, т.е. мы скорее всего, будем обмениваться файлами через память. Но это все-таки ОС решать.)
https://smart-lab.ru/blog/550216.php
Ну, а связь любая — именованные каналы, сокеты, ДЛЛ, файлы и что хотите.
Для проектирования меня вполне устраивают файлы. Потом уже, когда все отлажено, можно ДЛЛ писать.
И какие у вас предложения эффективного расширения Луа? В смысле доступа к различным библиотекам — математическим, статистическим, машинного обучения и прочим?
Обмен через файлы мне нравится своей простотой и доступностью. Далеко не каждый владеет С++/C#.
А Питон вообще незаменим, в частности, своими библиотеками. Сам по себе он конечно далеко не простой язык, но порог вхождения оч низкий — можно начинать что-то делать практически сразу, на нулевом уровне.
Если разговор про HFT, то это другая песня.
А для всего остального файловый обменник — самое то.
На луа пишем только прием-передачу данных между брокером и своим софтом.
Далее — всё остальное на чем захочется.
Даже на Турбо Паскале :)
за полтора года пару раз видел как глючит получение данных в квике, и соответственно та же кривая муть из квика пихается в dll...
а вот сам lua (нонстоп пихающий всё мне в dll-ку) за всё это время ни заглючил ниразу(я по крайней мере не заметил)...
Эх… этому lua в квике нормальный бы блеать юзер-френдли отладчик…
в функции мейн в цикле вызываю что-то вроде
if getItem(«FUTURES_CLIENT_HOLDING»,i).sec_code == security then
return getItem(«FUTURES_CLIENT_HOLDING»,i).totalnet;
а данные для LUA все-таки получаете с графика по идентификатору через getCandlesByIndex или создаете подписку в самом LUA на поток данных с сервера?getCandlesByIndex
offer1 = tostring(getParamEx(«SPBFUT», ticker1, «offer»).param_value)
bid1 = tostring(getParamEx(«SPBFUT», ticker1, «bid»).param_value)
Для того чтобы они работали, должен быть открыт соответствующий стакан. я это расцениваю как дополнительный контроль/предохранитель, а не как неудобство(всё равно нужно квик открытым держать).
Со свечами я думаю работал бы примерно так же. То есть держал бы график открытым и с него уже получал бы через getCandlesByIndex.
В языке АД4 имеются только оч хилые функции записи данных в файлы, и, в принципе, их можно с некоторыми поправками использовать для обмена данными… Функций чтения файлов в языке АД4 я не нашел, т.е., штатными средствами языка АД обеспечить обмен данными невозможно.
Но есть одна лазейка — в основной функции (Evaluate() для индикаторов, или OnUpdate() для стратегий) мы можем вызвать библиотечный NET объект, и с помощью него обеспечить чтение файла из стратегии или индикатора. Таким образом обмен данными с АД4 обеспечить все-таки можно. Я это когда то пробовал делать, и результаты выложены где-то на просторах инета. Если кого такой подход заинтересует, поищу и выложу сюда или в отдельный пост.
Для реализации достаточно иметь некоторые представления о С#.
А Базы Данных вас не смущают? Они все, так или иначе, постоянно пишут на диск. И через них, кстати, осуществляется обмен данными.
Про TCP/IP из Луа расскажите людям, которые не знают С++, не умеют писать ДЛЛ — а таких большинство. Дайте им вашу ДЛЛ с сокетами, и они с ней не справятся, и ее можно будет использовать не более чем игрушку
Алготрейдеры если и неплохо программируют, в большинстве не являются проф программистами. И предложенный метод не для вас, а для них. И в блоге это написано. И хорош он приемлемой скоростью для большинства ТС, простотой и общедоступностью.
Думаю, что, как, и зачем пишут БД я знаю лучше многих.))
Для простоты положим что все написано на с++. Спс.
Понятно, что Феррари быстрее Ниссана, но, для большинства применений, кроме как для выпендрежа, в феррари нет надобности.
Использовать DDE я бы не советовал. Если действительно скорости обмена не хватает, то для ТС нужна связь через ДЛЛ или сокеты и пр., и файловый обмен вам не подойдет.
Один раз сделаете и куча плюсов:
-ни тебе брокер корявый не помешает со своим «рубильником»;
-ни провайдер;
-и даже Вася Пупкин — тоже мешать не будет.
разницы по нагрузке, вот что я имел ввиду.
Замеряете, сравниваете, делаете выводы. До сервера квик у меня заявка летит от 20 ms до 260 ms, в среднем 130 ms. про transaq не знаю ничего, кто-то кричал, что 18 ms, в чем я сильно сомневаюсь. Может раньше так и было в транзаке, но раньше и через квик 20-40 ms летели заявки, пока арка не ввела в плагин qlua функцию isDarkTheme (сарказм)