Макс Крутой пишет: Как сделать чтобы при выходе из программы с работающими скриптами, они не запускались вновь при запуске программы? Получается так что программа ещё не очухалась а скрипт уже вовсю торгует.
Сейчас средствами терминала никак, но Вы можете эту логику реализовать самостоятельно в скрипте.
Дмитрий пишет: Месяцвозился с проблемой. При обращении к функции CreateDataSource из внешней dll периодически падал quik. В цикле 100000 раз обращался к полю Size(). Причём падал совершенно в разных местах и воспроизвести однозначно проблему не получалось. Слинковал dll с qlua.dll падения прекратились, но quik просто стал намертво зависать. В ходе манипуляций выяснил, что обращаться к полям CreateDataSource нужно по стеку (lua_state), полученному из функции main, а например, не в каком-нибудь OnInit(). Сохранил указатель lua_state *L в функции main и падения квика прекратились. Ничего тут не спрашиваю, просто предупреждаю. Ребята, имейте это ввиду, чтобы не мучались.
Добрый день. Сообщите версию терминала, на которой проводили исследования.
Сергей Иваницкий пишет: Удалось четко локализовать условия, при которых терминал вылетает с ошибкой при запущенном скрипте. Происходит это только в двух случаях: а) при открытии одной из вкладок; б) при двойном щелчке левой кнопкой мыши по графику в другой вкладке. Если избегать этих действий, связка терминал-скрипт работает стабильно без ограничения по времени.
Так что тем, кто использует скрипт "Intraday LUA" и сталкивался с такой же проблемой, можно порекомендовать опытным путем выявить, какие действия служит триггером сбоя, и после запуска данного скрипта воздерживаться от них, если, конечно, они не критичны для работы.
Добрый день. Проблема в использовании vcl.dll Подробности можно почитать тут
asteroid пишет: Michael Bulychev , еще вопрос. А почему dependency walker не показывает зависимость квиковской lua5.1.dll не показывает зависимость от qlua.dll
Если я правильно понял, то эта реализация для LuaJIT, и библиотека lua5.1 собраны для нее
Сомневаюсь что все это взлетит в терминале, особенно если там есть еще какие-либо модули. А lua5.1.dll, которая идет в комплекте с терминалом, является прокси библиотекой для qlua.dll
Если есть какая-то конкретная проблема, то можно попытаться разобрать ее. Иначе кроме как почитать MSDN что-то предложить трудно. Слишком обширная тема для форума и несколько не по теме.
Дмитрий пишет: Спасибо! Я правильно понимаю, что это стандартное поведение для Lua? Или все же не исключено, что в разных версиях/реализациях языка поведение в данном случае может быть различным?
Это всего лишь оптимизация на уровне виртуальной машины, не рекомендуется использовать подобные тонкости как часть своего алгоритма.
Дмитрий пишет: Здравствуйте! Хотелось бы узнать, всегда ли интерпретатор Lua (и в частности QLua) вычисляет логические выражения полностью в операторах if, while и repeat, или же он прерывает их вычисление в том случае, когда результат уже заведомо известен? В качестве примера можно привести такой оператор: if (t_id ~= nil) and not IsWindowClosed(t_id) then ... Если t_id == nil, то будет ли в данном случае осуществляться вызов функции IsWindowClosed(t_id)? Ведь и без этого ясно, что данное выражение будет равно false. В компиляторах языков программирования типа Pascal или C (уже не помню точно какого из них) для управления поведением программы в таком случае была опция, которая называлась кажется "complete boolean eval", поскольку иногда этот вопрос имеет большое значение. А как с этим обстоят дела в (Q)Lua?
Добрый день. проверить можно самому:
Код
function foo1()
print("in foo1")
return false
end
function foo2()
print("in foo2")
return false
end
print("--- OR")
if (foo1() or foo2()) then
end
print("--- AND")
if (foo1() and foo2()) then
end
Дмитрий Минеев пишет: Michael Bulychev , спасибо за развернутый ответ. Но, в вашем случае призойдет то же самое, что и у меня: На первой итерации, при расчете EMA(3) на 2 баре (например), мы получим корректное значение, но рассчет ЕМА(4) на том же баре затрет кешированное значение для ЕМА(3) и на следующей итерации оно посчитается не коррекно. В вашем методе реализиции необходимо в функцию ЕМА() передавать переменную Line и поменять вычисление на:
Код
p = line[index-Settings.startPeriod] or C(index)
n = k*C(index)+(1-k)*p
вот так должно заработать.
Добрый день. не затрет. Для каждого такого замыкания будет создана своя копия локальных данных cache{} и параметра period. Вот пример попроще:
Код
function counter_from(i)
local x=i
return function ()
x=x+1
return x-1
end
end
c1 = counter_from(1)
c2 = counter_from(100)
for i=1, 10 do
print("c1 = " .. c1() .. ", c2 = " .. c2())
end
Settings= {
Name = "averEMA",
startPeriod = 3,
endPeriod = 6,
line =
{
{
Name = "AverEMA",
Type = TYPE_LINE,
Width = 2
}
}
}
function Init()
return 1
end
function average(_start, _end)
local sum=0
for i = _start, _end do
sum=sum+C(i)
end
return sum/(_end-_start+1)
end
function cached_EMA(__period, __k)
local cache={}
local period = __period
local k = __k or 2/(period+1)
return function(ind)
local n = 0
local p = 0
--local period = _p
local index = ind
if index == 1 then
cache = {}
end
if index < period then
cache[index] = average(1,index)
return nil
end
p = cache[index-1] or C(index)
n = k*C(index)+(1-k)*p
cache[index] = n
return n
end
end
function OnCalculate(index)
local s=0
if index == 1 then
line = {}
for i=Settings.startPeriod, Settings.endPeriod do
line[i - Settings.startPeriod + 1] = cached_EMA(i)
end
end
s = 0
for i = 1, #line do
local res = line[i](index)
if res == nil then
return nil
else
s = s + res
end
end
return s/#line
end
asteroid пишет: Прошу прощения! А мое сообщение ктонить прокомментирует? Это мой косяк или все же разработчики подтвердят что косяк гдето на их стороне и я буду ждать фикс?
Если исключить из кода строку
Код
local zmq = require("zmq")
то ошибка не воспроизводится.
Добрый день. Наших "косяков" тут нет. Попробуйте воспользоваться функцией getScriptPath()
Код
gPath = do_smth_with_path(getScriptPath()) -- настраиваете пути как Вам надо относительно скрипта
package.cpath = gPath .. "\\?.dll;" .. package.cpath
package.path = gPath .. "\\?.lua;" .. package.path
Дмитрий пишет: Здравствуйте! 1) Если в скрипте для вывода на экран создавалась таблица t_id, окно которой еще до завершения работы скрипта было закрыто вручную, то нужно ли после этого использовать вызов функции Clear(t_id) для очистки содержимого таблицы t_id и освобождения памяти, занятой этой таблицей? Если ответ на этот вопрос утвердительный, то еще один вопрос: 2) Если после закрытия окна вручную скрипт сразу завершает свою работу, то есть ли смысл и в этом случае использовать функцию Clear(t_id) или же вся занятая скриптом (и в том числе таблицей t_id) память автоматически освободится после остановки скрипта?
Добрый день. данные в таблице очищаются при ее закрытии, вызове Clear() или Destroy() Если скрипт остановлен и таблица осталась открыта, то данные очистятся после ее закрытия. Вызов Destroy() включает в себя вызов Clear()
Максим пишет: Здравствуйте! Довольно чайниковский вопрос, но разобраться не могу. Возникает проблема со сравнением двух чисел и арифметическими операциями. Есть цена из стакана qt.bid.price=91.702700. И есть цена current_order_price_buy=91.7027 (визуально совпадают) Однако их сравнение tonumber(qt.bid.price)==tonumber(current_order_price_buy) не происходит! При этом разность этих чисел равна diff=-1.4210854715202e-014 Как сделать так, чтобы они все же совпадали, т е какими видятся, такими были и фактически.
sam063rus пишет: между нами говоря - мы оба прекрасно знаем чем является t_id и что никакой это не HWND, что сильно усложняет задачу. t_id - это всего лишь некий индекс в QLUA и не более. поэтому нет возможности сказать windows, что это "папа" контрола. грешным делом была задумка одно время сделать невидимую таблицу нулевого размера, чтоб состряпать из неё базовый класс для контролов но и эту затею можно спустить в унитаз.
Насчёт интерфейсов классов - я просто начинаю отчаиваться в затее прямого диалога с разработчиками. Михаил, если вы по-прежнему в этом заинтересованы - то я буду продолжать.
1. Никто Вам напрямую HWND без оберток не отдаст, это совершенно лишнее. К тому же никто его легко найти самому. 2. Продолжайте, просто пока я не вижу что там обсуждать.
я думаю, лучше было бы, если разработчики определили бы так называемый класс QScript, имеющий одним из родителей класс CWnd, либо, обладающий возможностью создавать окна, который мы потом назовём главным и который будет владельцем всех окон порождённых от него. это значительно упростит написание/управление контролами.
Считайте что функции для работы с таблицами являются методами такого класса, а table_id идентификатор объекта. Что это меняет? Кстати, Вы так и не дописали интерфейсы объектов в одной из веток форума.
Такая возможность действительно закладывалась. Отработал скрипт один раз и оставил таблицу, дальше она живет отдельно от скрипта.к коду она не привязана.
Michael Bulychev пишет: Что такое дочерний стейт я не понимаю.
имеется ввиду контекст созданный lua_newthread. просто по Вашим словам можно именно так понять, что закрывая скрипт - мы на самом деле не уничтожаем его VM.
lua_newthread тут не причем. речь шла о совершенно другом. VM Lua закрывается.
Michael Bulychev пишет: Вся штука в том, что окно привязано не к текущему инстансу VM Lua, а к загруженному скрипту.
а разве для каждого загруженного скрипта не создаётся виртуальная машина? т.е. получается, остановив скрипт - мы на самом деле ничего не останавливаем, а закрываем дочерний стейт?
Создается. Что такое дочерний стейт я не понимаю. В связи с какой проблемой подобный вопрос?
Добрый день. Вся штука в том, что окно привязано не к текущему инстансу VM Lua, а к загруженному скрипту. Как только скрипт снова запускается, то он начнет получать нотификацию от своих ранее созданных окон. Чтоб бы избежать такого придется закрывать все окна созданные скриптом после его остановки. Можно рассмотреть такое пожелание если оно устроит пользователей.
получается, если верить Вашим словам - то у Вас должно быть так: #define lua_register(L,n,f) (lua_pushcfunction(L, (getNumberOf)), lua_setglobal(L, ("getNumberOf" ;) ))
Дмитрий пишет: Добрый день. Перечитал старый форум, но внятного ответа так и не нашёл. Наверняка уже многие делали то же, что и я, и многие ещё будут делать. Поэтому хочу уточнить один важный момент. Есть Lua - скрипт, в котором подключается своя библиотека на c++. В этой библиотеке создаётся несколько потоков.Например, 1 поток будет отправлять заявки в Quik, другой поток будет читать таблицу параметров, ещё несколько потоков будут подписываться на ТВС и перебирать все сделки через CreateDataSource (а их может быть миллионы). В общем каждый поток будет одновременно запускать какие-то Lua-функции. А Lua - стек у нас только один. Вопрос: нужно ли синхронизировать эти потоки и гарантировать вызов lua функций из dll в одно время только однажды ? Если да, то получается, что пока какой-то поток, например перебирает все сделки в цикле (миллион), то заявки отправлять нельзя ? Параметры читать нельзя ? Все задачи будут ждать завершения какого-то одного потока ? А если нужно одновременно в разных потоках вызвать CreateDataSource, каждый со своим инструментом, и одновременно их записывать в какие-либо массивы ?
Добрый день. Я бы настоятельно советовал Вам посмотреть в сторону coroutine в Lua. Уверен, что их возможности полностью покроют описанные Вами задачи. Но если желание наплодить потоков в своей библиотеке непреодолимо, то рекомендации ниже: 1. Линкуйте свою библиотеку с qlua.dll 2. Если пункт два вызывает вопросы, то убедитесь что в папке с терминалом (там же, где лежит info.exe и qlua.dll) присутствует файл lua5.1.dll собранный нами. Проверить это можно в свойствах файла:
3.Для каждого отдельного потока, который работает с Lua перед его запуском необходимо проделать примерно следующее:
4. При завершении работы поток не должен вызывать lua_close(thread_L), это приводит к закрытию всей Lua для скрипта. 5. для того чтобы сборщик мусора при завершении все корректно убрал необходимо сделать:
Код
lua_unref(L, thread_L_ref);
Вроде все. Но я бы все таки настоятельно рекомендовал использовать Lua coroutine
Эти примеры я привел к тому, что не всегда более длинный код работает медленнее. А пример с test_table1 показывает что заранее продуманный способ хранения данных позволяет выиграть и в размере кода и в скорости работы. Если у Вас стоит задача в таблице сохранять строки а затем проверять их наличие, то третий способ самый оптимальный. Используйте строки в качестве ключа таблицы. Это дает максимальную скорость при минимальном количестве кода.
Дмитрий пишет: Тут стоит вопрос не об оптимизации скорости работы скрипта, а о минимизации и упрощении его текста. Ну и по работе со строками как таковыми мне все более-менее понятно, а вот о средствах Lua для поиска среди элементов таблицы я пока мало что знаю (кроме тупого перебора их в цикле).
Во многом это зависит от используемых алгоритмов обработки и хранения данных. В каждом случае можно придумать вариант оптимальный по скорости работы и объему кода.
Код
test_table={"qwe", "1qweasd", "zxc"}
test_table1={["qwe"]=true, ["1qweasd"]=true, ["zxc"]=true}
str = "1qweasd"
function check1(t, str)
return (string.find("|"..table.concat(t,"|").."|", "|"..str .. "|") ~=nil)
end
function check2(t, str)
for k, v in pairs(t) do
if v == str then return true end
end
return false
end
function check3(t, str)
return (t[str] or false)
end
max_count=1000000
_s=os.clock()
for i=1, max_count do
res = check1(test_table, str)
end
_e = os.clock()
print("check1 took "..tostring(_e-_s))
_s=os.clock()
for i=1, max_count do
res = check2(test_table, str)
end
_e = os.clock()
print("check2 took "..tostring(_e-_s))
_s=os.clock()
for i=1, max_count do
res = check3(test_table1, str)
end
_e = os.clock()
print("check3 took "..tostring(_e-_s))
--[[
check1 took 0.752
check2 took 0.261
check3 took 0.116
--]]
Sergey Gorokhov пишет: из материалов с других форумов - мы знаем, что "main" запускается (а вместе с ней и создаётся отдельный поток) после колбека "OnInit" - значит ли это , что, если в скрипте не будет прописан колбек OnInit - то и для функции "main" не будет создан отдельный поток???
------------------------- Нет не значит.
Правильный ответ: проверяем есть ли в скрипте OnInit - если есть и он завершился без ошибки то, можно смело запускать поток и вызывать в нём "де-факто"-колбек "main". Если же OnInit нет то, просто пытаемся создать поток и запустить в нём "main" ----------------------- А вообще-то, с проверок и надо было начинать: если нет "майна", то и не должно быть создания потока. Это одна из Ваших ошибок.
Вы не правы, ошибка была совсем в другом. Никакого потока в Вашем коде не создается.
Добрый день. Давайте немного успокоимся и сбавим тон. Есть ошибка - при завершении скрипта с ошибкой не освобождаются ресурсы Lua. Ровно эту картину Вы и наблюдаете - main отсутствует, но ресурсы не освобождены, библиотека не выгружена. Именно она и обрабатывает все события на этой форме. Эта ошибка будет исправлена.
Если мы вызываем код из скрипта, то биндить ничего не надо
Код
lua_getglobal(L, "OnAllTrade")
lua_pushtable(L, trade) //псевдокод
lua_pcall(L, 1, 0, 0) //зависит от вашей функции и наличия обработчика ошибок
//обработка результатов если они есть
Серж пишет: при обращении к x, произойдет блокировка, изменение данных и разблокировка.
значит ли это, что Вы в qlua переопределили стандартные макросы lua_lock/lua_unlock с пустышек на критические секции или, что/то в этом духе? и если да - то и нам можно теперь ими пользоваться?
Да, значит. Пользоваться можно на свой страх и риск. никакой гарантии далее мы дать не можем.