Написал dll, в которой одна функция: сложение двух чисел. Вот она внутри проекта C++ (пример взят с сайта quik2dde.ru)
Код
static int forLua_AddTwoNumbers(lua_State *L) {
// получаем первый и второй параметры вызова функции из стека с проверкой каждого на число
double d1 = luaL_checknumber(L, 1);
double d2 = luaL_checknumber(L, 2);
// помещаем в стек результат сложения
lua_pushnumber(L, d1 + d2);
return(1); // эта функция возвращает одно значение
}
Теперь тестирую эту функцию в Луа. Сравниваю скорость: 1) как быстро складывает dll 2) как быстро складывает Lua
Код
package.cpath = "C:\\runfast.dll"
require("runfast")
iterations=10000000
function main()
start=os.clock()
for i=1,iterations do
r = runfast.AddTwoNumbers(i, i)
end
finish=os.clock()-start
message ("C dll:"..tostring(finish), 1)
start=os.clock()
for i=1,iterations do
r = i+i
end
finish=os.clock()-start
message ("Lua:"..tostring(finish), 1)
end
результат: Луа быстрее в 3,6 раза. Почему? Из-за всех этих телодвижений со стеком? Но как тогда извлекать преимущество от скорости Си++? Мне надо переместить в dll из Луа кучу трудоёмких функций, чтобы быстро считалось.
А почему тогда string.find работает с русскими буквами? А есть ли риски, что string.find (reply.result_msg, "Снят" ) перестанет распознавать кириллицу? Придёт заявка со словом "Снято....", а он её увидит как абракадабру?
if string.find(reply.result_msg, "Снят") or string.find(reply.result_msg, "снят") then
end
Для этого использую string.lower(reply.result_msg) Но он не понимает русские буквы. Текст всё равно остаётся "Заявка 89900000 снята" или "Снято заявок". Большие буквы не становятся маленькими. Дело в русских буквах? Как с этим справиться?
Я заметил, что print не работает :) message меня не устраивает, потому что при быстром поступлении логируемых данных она подвешивает КВИК, например в колбеке OnQuote приходится выводить информацию в файл, а это неудобно
Поставил Visual Studio Community пытаюсь скомпилировать dll в примере Suntor --- Файлы заголовков включил
--- но он выдаёт такие ошибки 1>------ Сборка начата: проект: easy_c, Конфигурация: Release Win32 ------ 1>easy_c.cpp 1>d:\_c++\easy_c\easy_c\easy_c.cpp(41): fatal error C1010: непредвиденный конец файла во время поиска предкомпилированного заголовка. Возможно, вы забыли добавить директиву "#include "stdafx.h"" в источник. 1>Сборка проекта "easy_c.vcxproj" завершена с ошибкой. ========== Сборка: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========
Николай Камынин написал: ---------------- Оптимизируйте прием данных стакана в колбеке тогда не будет видимого торможения
под оптимизируйте вы что имеете в виду? -переписать логику на Си -перенести логику в main -оптимизировать расчёты внутри колбека или что то другое?
Я уже многое сделал, например стал отфутболивать слепки стакана, если изменения произошли в дальних котировках. Мне требуются только ближайшие. Плюс я думаю просто игнорировать избыточные слепки, которые являются излишними и не успевают быть обработанными. Это временно решит проблему пока я напишу dll под Си.
Если новый слепок стакана является избыточным и становится в очередь (квик обрабатывает предыдущие), значит он просто игнорируется и удаляется. Это должно быть опцией. Кто хочет такое выбрать, тот выбирает.
Возможна ли такая ситуация: в стакане произошли два изменения одновременно, и колбек OnQuote сработал только один раз? Или раз заявки идут одна за другой очередью, то будет гарантированно два срабатывания колбека?
Это было из-за колбека OnQuote там накапливалась очередь из большого числа слепков стакана. Такой вопрос. А если бы я отсылал заявки из main, то есть через другой поток, то мои заявки зависели бы тоже тормозили? Торможение в OnQuote влияет на main?
У меня сейчас стоит windows server 2003. Он потребляет меньше всего ресурсов. Может быть перейти на Windows server 2016? У него системные требования выше, но наверное и быстродействие выше. За 13 лет в плане скорости могли сделать большой шаг вперёд.
Я пытался воспроизвести ситуацию, когда видны лимиты за два session_status (№6 и №4). Но пока что показывает только один. Сейчас это статус №6. Попробую в другой раз. А каким способом я могу получить этот статус из текущей таблицы или ещё откуда нибудь? Чтобы робот, побегая "Позиции по клиентским счетам" брал правильный лимит. В четверг, когда эта проблема была, у меня была позиция x контрактов. Но робот её не видел, потому что обращался к неправильной строчке.
На просторах интернета есть скрипт на основе debug-библиотеки, встроенной в Луа. https://stackoverflow.com/questions/15725744/easy-lua-profiling Я - увы - ничего не понимаю в этом коде, но моих слабых способностей хватило, чтобы начать его использовать. До начала отслеживаемого куска ставится код:
Код
local calls, total, this = {}, {}, {}debug.sethook(function(event)
local i = debug.getinfo(2, "Sln")
if i.what ~= 'Lua' then return end
local func = i.name or (i.source..':'..i.linedefined)
if event == 'call' then
this[func] = os.clock()
else
local time = os.clock() - this[func]
total[func] = (total[func] or 0) + time
calls[func] = (calls[func] or 0) + 1
end
end, "cr")
--изучаемый код
Концовка:
Код
debug.sethook()
-- print the results
for f,time in pairs(total) do
print(("Function %s took %.3f seconds after %d calls"):format(f, time, calls[f]))
end
вместо print я вывожу эту строку в файл.
Скрипт работает и внутри колбека OnQuote показывает мои "личные" функции:
Но самое ценное - функцию получения стакана getQuoteLevel2 не показывает. Видимо, он понимает только пользовательские функции. Прошу подсказать, как в этот дебаггер добавить другую полезную информацию: --функции QLUA --пробегание циклов --переменные Спасибо за советы.
Николай, спасибо, за ответ. Такой вопрос. Два одинаковых скрипта. В одном РТС, в другом Си. Как лучше сделать: 1. Запускать два скрипта в 1 квике? 2. Или открыть два КВИКа и включить по одному скрипту в каждом КВИКе?
Не нужно внутри колбека делать вычисления, потому как это тормозит основной поток терминала. Нужно выставить сигнал о том, что данные изменились (возможно отложить их куда-то) и покинуть колбэк, а в майне уже делать нужные дела.
Я постепенно делаю это, но всё равно кое-что придётся оставить в колбеке. Я же не могу крутить main в диком безостановочном цикле, который постоянно будет ловить новые изменения. Если сделать по вашему, то main при 50 инструментах не сразу обработает изменение. У меня внутри main стоит sleep(1). При 50 инструментах это довольно долгая задержка. Поэтому интересны советы как раз по многопоточности и по разумному использованию ядер. Если надо, я куплю 10 ядер, лишь бы всё работало.
Здравствуйте. Последние дни на рынке паника. Активность резко возросла. Я в КВИКе подписываюсь на стаканы 5 фьючерсов и 50 акций. Обрабатываю их в OnQuote. В июне-июле не было никаких проблем из за вялого рынка. Но в среду-четверг-пятницу пошла жесть. КВИК подвисает намертво. Пришлось отказаться от акций, оставил два фьючерса Si и RTS, но даже их пришлось разнести по разным КВИКам. Два фьючерса в одном скрипте в одном КВИке всё равно вешали КВИК. Сейчас на 1 квик у меня по 1 скрипту, в котором 1 инструмент. Благодаря этому удалось вернуться к работе. --- Прошу дать совет, как решить эту проблему. 1. Я уже перенёс из OnQuote много функций, которые теперь обрабатываются в main, но там по прежнему остаётся обработка таблиц, несколько циклов и немного математики. Время, за которое проходит одна итерация внутри OnQuote около 20 миллисекунд. 2. На виртуалке поставил более быстрые ядра. Сейчас конфигурация такая: Обидно, что даже в моменты пиковой нагрузки загрузка процессора даже близко не подходила к 100%, то есть были свободные ядра. При этом более быстрые ядра не решили проблему, квик всё равно подвисал. 3. Работает сборщик мусора луа, проблем с памятью не наблюдалось. --- Можно ли OnQuote направлять на разные ядра процессора? например с помощью модуля многопоточности луа LuaLanes? --- Можно ли запустить в одном скипте несколько OnQuote? В один принимать фьючерсы, в другой акции например? --- Буду благодарен за любые советы и подсказки.
Здравствуйте. Это позиции по фьючерсам. Вопрос про поле этой таблицы session_status=6 На одном из серверов моего брокера транслируется не только текущая сессия (№6 - это вечорка), но и предыдущая с номером 4 Поэтому когда робот бегает по этой таблице, он может взять значение другой сессии и будет ошибка. Как можно получить этот параметр? И какие номера каким сессиям соответствуют? Спасибо.
Добрый день. Пытаюсь победить странную проблему с роботом. После того как робот поработает час, заявки на биржу улетают очень долго: между отправкой и получением реплая до 5 секунд. Стоит выключить робота и включить по новой, как проблема решается, заявки улетают быстро. --- В функции main стоит collectgarbage Она чистит мусор везде? Может быть нужно поставить её в другие колбеки, которые открывают новый поток? У меня из трудоёмких колбеков работают OnQuote (60 инструментов) и OnAllTrade.
Сегодня в течение дня тоже был обрыв. Тики перестали приходить. Я это связываю с параллельной работой другого робота, который сильно грузит процессор. Загрузка ядер доходила до 100% и могла что-то испортить. Возможно из-за этого перестали приходить тики.
Хорошо, проверю. Подобная проверка является ли эффективной в случае обрыва?
Код
if ds_tick[sec]:Size()==nil or ds_tick[sec]:C(ds[sec]:Size())==nil or ds_tick[sec]:Size()==0 or ds_tick[sec]:C(ds[sec]:Size())==0 then
ds_tick[sec] = CreateDataSource(class_code[sec],sec,INTERVAL_TICK)
ds_tick[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class_code[sec],sec,...) end)
mm(sec.." обрыв. Перезаказ тиков")
end
П.С. Естественно, речь идёт про отсутствие сделок после 10:00. Я указал время 9:57, потому что это возможно что-то значит. Возможно в это время нельзя заказывать сделки или ещё что то в этом духе.
Я заказываю ленту всех сделок через CreateDataSource вот так:
Код
ds_tick[sec] = CreateDataSource(class_code[sec],sec,INTERVAL_TICK)
ds_tick[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class_code[sec],sec,...) end)
ds[sec] = CreateDataSource(class_code[sec],sec,INTERVAL_M1)
ds[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class_code[sec],sec,...) end)
while ds[sec]:Size()==nil or ds[sec]:C(ds[sec]:Size())==nil or ds[sec]:Size()==0 or ds[sec]:C(ds[sec]:Size())==0 do
sleep (1)
end
Этот кусок кода находится в начале функции main и выполняется единожды при запуске скрипта. Всё работает, жалоб не было до сегодняшнего дня. Утром я запустил робота примерно в 9:57. Робот начал работать, но сделки не приходили. Робот не получал ни одной сделки, в том числе по супер-ликвидам, которые точно торговались. Остановил скрипт, запустил по новой. Всё стало работать штатно, сделки начали приходить. Подскажите пожалуйста что это могло быть и как с этим бороться в будущем?
Добрый день. При торговле я использую огромную библиотеку функций на луа. Там около 3000 строчек, десятки функций. Далеко не все они нужны. Я эту библиотеку подключаю с помощью
Код
require "TradeLib"
Можно ли импортировать не все функции, а только часть? Наподобие того как в питоне делается:
Цитата
fr om TradeLib import (SendLim it, GetPrice)
И второй вопрос. Если я загружаю всю эту библиотеку в 3000 строчек, то происходит ли чрезмерная загрузка памяти, замедление работы или ещё что-нибудь плохое? Может быть не стоит и волноваться? Спасибо.
Let_it_go написал: Как мне грамотно передать её в функцию индикатора? Нужно сделать как в примере, выкинуть все поля, кроме нужного поля close?
Не совсем понятен вопрос... В коде примера, можно просто поменять в трёх местах tbl на tbl[6] и всё... разве нет?
Я написал такой парсер для котировок.
в функцию, рассчитывающую индикатор, будет запихиваться таблица t_small, а таблица t_big нужна, чтобы брать из неё дату, время, High,Low. table.remove(t,3) нужна, чтобы выбросить цену открытия. Она не используется.
Добрый день. Осваиваю работу с сайтом финама. https://www.finam.ru/profile/moex-akcii/sberbank/export/ Беру оттуда архив котировок, к примеру в таком виде: теперь я хочу воспользоваться замечательной библиотекой INDICATORS.ZIP (спасибо огромное её автору, эти функции верно служат мне несколько лет). В описании библиотеки такое предусмотрено:
Код
--Пример расчета индикатора Moving Average по произвольному набору чисел:
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua")
tbl = {[1]=2587.5, [2]=2588.5, [3]=2585.1, [4]=2583.7, [5]=2582.6, [6]=2581.2, [7]=2579.2, [8]=2574.7,
[9]=2571.5, [10]=2570.8, [11]=2569.9, [12]=2569.7, [13]=2567.2, [14]=2569.3, [15]=2566.1, [16]=2567,
[17]=2563.3, [18]=2565.2, [19]=2564.3, [20]=2565.9, [21]=2568.5, [22]=2572.2, [23]=2572, [24]=2572, [25]=2571.3}
function main()
func = MA()
t_id = AllocTable()
AddColumn(t_id,1,"Price",true,QTABLE_INT_TYPE,10)
AddColumn(t_id,2,"MA",true,QTABLE_INT_TYPE,10)
CreateWindow(t_id)
SetWindowCaption(t_id,"MA")
for i=1,#tbl do
ma_out=func(i, {Period=3, Metod = EMA, VType=ANY}, {[i]=tbl[i]})
tmp=InsertRow(t_id,-1)
SetCell(t_id,tmp,1,tostring(tbl[i]),tbl[i])
SetCell(t_id,tmp,2,tostring(ma_out),ma_out)
end
end
Строить буду по ценам закрытия Close. Вопрос касается таблицы tbl, которая передаётся в функцию. Она будет иметь вид: дата, время, open,high,low,close.
Господа, прошу помочь. Уже долгие часы сжёг на эту проблему. Пытаюсь установить модуль Lunatic Python. Он позволят из скрипта луа вызывать питоновские функции. Вот он https://pypi.org/project/lunatic-python-universal/ --- У меня установлен питон 3.7.0 Установщик pip обновлён до текущей версии. Он благополучно устанавливает пакеты питона, например математическую библиотеку matplotlib --- Установлена Луа 5.1.5 --- Коды на питоне пишу в PyCharm от JetBrains --- Пытаюсь установить lunatic python, но безуспешно Текст ошибки Command "python setup.py egg_info" failed with error code 1 in C:\Users\A\AppData\Lo cal\Temp\pip-install-ley5xara\lunatic-python-universal\ --- попытка установить пакет прямо из папки куда он распакован, тоже неудачная: --- easy_install тоже не даёт результата... Спасибо за любые подсказки
Господа, медленно пополняю ряды питоно-кодеров. (я неуч в программировании, не судите строго) Читаю эту ветку и не могу понять. Неужели нет нормального способа подключиться к данным КВИКа с помощью внешней программы? На луа всё легко: любую циферку можно получить скриптом. А тут приходится какие-то ухищрения делать. Сначала с помощью луа экспортировать в файл, и из этого файла читать питоном. Или по ДДЕ в эксель. Хм... но это неудобно. Неужели нет простого способа прочитать питоном стакан или текущую таблицу?
Я нашёл библиотеку lualanes Она даёт многопоточность http://lualanes.github.io/lanes/ Но не могу разобраться, где мне запускать эти потоки? Внутри функции main или за её пределами? Если запускать длительный процесс ДО запуска main, то будет подвисание скрипта.
Прошу дать совет. У меня работает скрипт, обрабатывающий большой объём данных. На расчёт уходит много времени. Прошу подсказать, можно ли в луа реализовать многопоточность, чтобы эффективно задействовать все ядра виртуальной машины. В нынешнем виде скрипт работает так:
Код
f_ticker_list="GAZR,SBRF,MIX,Si,RTS"
for instrument in string.gmatch(f_ticker_list,"%w+") do
--утомительные расчёты на основе анализа множества файлов с рыночной информацией
end
Он задействует только 1 ядро виртуальной машины. Как разбросать этот процесс на другие свободные ядра виртуалки? Спасибо
Я не планировал перекидывать этот файл. Мне нужно его прочитать с помощью dofile (Соседняя виртуалка\papam.txt) Вопрос в том как правильно в коде выразить мысль "Соседняя виртуалка"
Сергей, спасибо за ответ. Всё получилось. Следующий вопрос. Запускаю оба скрипта с одинаковым кодом, но в одном по старинке требуется открытая таблица обезличенных сделок, а в другом она заказывается через INTERVAL_TICK. таблица обезличенных сделок ЗАКРЫТА. Тем не менее оба скрипта работают нормально и выдают идентичный результат. Почему? Второй подписался на тики, и они передаются на первый?