SetUpdateCallback - не срабатывает после первого запуска скрипта
Пользователь
Сообщений: Регистрация: 13.05.2022
21.11.2022 16:12:34
Кто встречался с такой ситуацией ?
Заказываю тики через CreateDataSource:SetUpdateCallback().
Запускаю Квик: -Загружаю скрипт. -Запускаю скрипт. -Скрипт вызывает CreateDataSource. -CreateDataSource возвращает нулевую таблицу, что говорит о том, что данные придут позже в колбек. -Колбек больше НИКОГДА не вызывается.
Выгружаю Скрипт и СРАЗУ же его запускаю - данные сразу же начинают приходить.
Кто косячит ? Я или криворукие разрабы ?
Пользователь
Сообщений: Регистрация: 30.01.2015
21.11.2022 18:14:16
Цитата
Quikos написал: Кто встречался с такой ситуацией ?
Заказываю тики через CreateDataSource:SetUpdateCallback().
Запускаю Квик: -Загружаю скрипт. -Запускаю скрипт. -Скрипт вызывает CreateDataSource. -CreateDataSource возвращает нулевую таблицу, что говорит о том, что данные придут позже в колбек. -Колбек больше НИКОГДА не вызывается.
Выгружаю Скрипт и СРАЗУ же его запускаю - данные сразу же начинают приходить.
Кто косячит ? Я или криворукие разрабы ?
Скрипт запускаете руками или автоматом с запуском квика? Если автоматом, то в скрипте надо делать ожидание. ---------------- Проще, если вам нужны тики, то просто подпишитесь на них через меню и они будут приходить при старте квика без проблем.
Пользователь
Сообщений: Регистрация: 13.05.2022
21.11.2022 19:10:29
Цитата
nikolz написал: Скрипт запускаете руками или автоматом с запуском квика? Если автоматом, то в скрипте надо делать ожидание. ---------------- Проще, если вам нужны тики, то просто подпишитесь на них через меню и они будут приходить при старте квика без проблем.
Скрипт запускается полностью вручную.
Это хорошо, что можно подписаться через меню. Но это явный косяк в API.
написал: Скрипт запускаете руками или автоматом с запуском квика? Если автоматом, то в скрипте надо делать ожидание. ---------------- Проще, если вам нужны тики, то просто подпишитесь на них через меню и они будут приходить при старте квика без проблем.
Скрипт запускается полностью вручную.
Это хорошо, что можно подписаться через меню. Но это явный косяк в API.
написал: Скрипт запускаете руками или автоматом с запуском квика? Если автоматом, то в скрипте надо делать ожидание. ---------------- Проще, если вам нужны тики, то просто подпишитесь на них через меню и они будут приходить при старте квика без проблем.
Скрипт запускается полностью вручную.
Это хорошо, что можно подписаться через меню. Но это явный косяк в API.
чтобы понять причину надо смотреть ваш скрипт.
Скрипт простейший:
Код
function my_callback_CreateDataSource(my_table_data_, code_class_, code_paper_, interval_, cntr)
message(code_paper_)
end
-----------------------------------------------------------------------------------------------------------int main:-----------------------------------------------------------------------------------------------------
function main()
local code_class1 = "TQBR"
local code_paper1 = "GAZP"
local interval1 = INTERVAL_TICK
local code_class2 = "TQBR"
local code_paper2 = "SBER"
local interval2 = INTERVAL_TICK
local my_table1, error_desc1 = CreateDataSource(code_class1, code_paper1, interval1) --Вызываем собсвенно CreateDataSource
------------------------Проверка на ошибки:-------------------
if error_desc1 ~= nil then
message("Error")
end
--------------------------------------------------------------
message(tostring(my_table1.Size()))
if my_table1.Size() == 0 then
message("data requested from the server")
end
local my_table2, error_desc2 = CreateDataSource(code_class2, code_paper2, interval2) --Вызываем собсвенно CreateDataSource
------------------------Проверка на ошибки:-------------------
if error_desc2 ~= nil then
message("Error")
end
--------------------------------------------------------------
message(tostring(my_table2.Size()))
if my_table2.Size() == 0 then
message("data requested from the server")
end
my_table1:SetUpdateCallback(function(idx)my_callback_CreateDataSource(my_table_data1, code_class1, code_paper1, interval1) end)
my_table2:SetUpdateCallback(function(idx)my_callback_CreateDataSource(my_table_data2, code_class2, code_paper2, interval2) end)
-------------------------
while not stopped do
sleep(1)
end
-------------------------
end -- end main()
И если бы была ошибка в скрипте - то на второй раз запуска скрипта, колбек так же бы не вызывался, НО на второй раз все рабоатет, как и ожидается. Но только на второй раз.
Пользователь
Сообщений: Регистрация: 30.01.2015
22.11.2022 18:31:54
Переписал Ваш скрипт , но действительно, если таблица обезличенных сделок не открыта, то руками запускается со второго раза, а автоматом - с первого. Очевидно это какая-то особенность или ошибка библиотеки QLUA.
Код
local code_class1 = "TQBR"
local code_paper1 = "GAZP"
local interval1 = INTERVAL_TICK
local code_class2 = "TQBR"
local code_paper2 = "SBER"
local interval2 = INTERVAL_TICK
------------------------
local function my_cb_CDS(idx,tabl)
message(tostring(tabl.sec)..","..tostring(idx),1)
Sleep(100);
end
--------int main:---------------
function main()
if tab1==nil then tab1 = CreateDataSource(code_class1, code_paper1, interval1);
if tab1 then
tab1.clas=code_class1; tab1.sec=code_paper1; tab1.int=interval1;
tab1:SetUpdateCallback(function(idx) my_cb_CDS(idx,tab1) end)
end
end
if tab2==nil then tab2= CreateDataSource(code_class2, code_paper2, interval2);
if tab2 then
tab2.clas=code_class2; tab2.sec=code_paper2; tab2.int=interval2;
tab2:SetUpdateCallback( function(idx) my_cb_CDS(idx, tab2) end)
end
end
-------------------------
while not stopped do
-- message(tostring(my_table1:Size()),1)
sleep(1000)
end
-------------------------
end -- end main()
function OnInit(script_path)
end
Пользователь
Сообщений: Регистрация: 30.01.2015
22.11.2022 18:34:35
поправил код скрипта
Код
local code_class1 = "TQBR"
local code_paper1 = "GAZP"
local interval1 = INTERVAL_TICK
local code_class2 = "TQBR"
local code_paper2 = "SBER"
local interval2 = INTERVAL_TICK
------------------------
local function my_cb_CDS(idx,tabl)
message(tostring(tabl.sec)..","..tostring(idx),1)
Sleep(100);
end
-----------------------------------------------------------------------------------------------------------int main:-----------------------------------------------------------------------------------------------------
function main()
while not stopped do
if tab1==nil then tab1 = CreateDataSource(code_class1, code_paper1, interval1);
if tab1 then
tab1.clas=code_class1; tab1.sec=code_paper1; tab1.int=interval1;
tab1:SetUpdateCallback(function(idx) my_cb_CDS(idx,tab1) end)
end
end
if tab2==nil then tab2= CreateDataSource(code_class2, code_paper2, interval2);
if tab2 then
tab2.clas=code_class2; tab2.sec=code_paper2; tab2.int=interval2;
tab2:SetUpdateCallback( function(idx) my_cb_CDS(idx, tab2) end)
end
end
-------------------------
-- message(tostring(my_table1:Size()),1)
sleep(1000)
end
-------------------------
end -- end main()
function OnInit(script_path)
end
Пользователь
Сообщений: Регистрация: 13.05.2022
22.11.2022 23:46:27
Цитата
nikolz написал: Переписал Ваш скрипт , но действительно, если таблица обезличенных сделок не открыта, то руками запускается со второго раза, а автоматом - с первого. Очевидно это какая-то особенность или ошибка библиотеки QLUA.
Причем для некоторых акций - запускается с первого раза, а для некоторых со второго. Навряд ли такое поведение можно называть "особенностью" - это явный косяк.
Пользователь
Сообщений: Регистрация: 13.05.2022
23.11.2022 00:15:53
Я правильно понял, что нужно дождаться пока появится таблица заполнится и только потом вызвать SetUpdateCallback ?
Пользователь
Сообщений: Регистрация: 03.03.2016
23.11.2022 14:13:15
Я после ds=CreateDataSource(...) ставлю
while ds:Size()>0 do sleep(50) end И следом назначение колбэка
Пользователь
Сообщений: Регистрация: 03.03.2016
23.11.2022 14:18:56
Пардон, очепятка
while not ds or ds:Size()==0 do sleep(50) end
Ну еще счетчик циклов для повторной попытки загрузки
Ну еще счетчик циклов для повторной попытки загрузки
Не лучшее решение, оно блокирует исполнение кода. Запросы где время ответа неизвестно, лучше решать через очереди задач ожидания. Потоков в lua нет, но, как минимум, не блокировать весь код. Если, например, скрипт обрабатывает много инструментов и потоков данных, то ждать после каждого заказа - много времени пройдет пока до последнего дойдет. Или надо что-то другое постоянно контролировать, пока по другому инструменту заказ сделали. То что долго идет ответ - это не повод для уже работающих инструментов ждать.
Ну еще счетчик циклов для повторной попытки загрузки
в приведенном выше скрипте эта проблема решается циклом там же записываются доп параметры в таблицу ds
Пользователь
Сообщений: Регистрация: 30.01.2015
23.11.2022 14:49:23
Цитата
Quikos написал: Я правильно понял, что нужно дождаться пока появится таблица заполнится и только потом вызвать SetUpdateCallback ?
я в настоящее время не использую тики, Но для таблице обезличенных сделок (тиков) я сделал DDE клиента который стартует всегда при загрузки квика и позволяет получать в фоновом режиме любые таблицы квика , например доску опционов, или таблицу обезличенных сделок. -------------- еще использовал колбек onAllTrade , тоже работает нормально.
Пользователь
Сообщений: Регистрация: 03.03.2016
23.11.2022 18:10:30
Цитата
Nikolay написал: Не лучшее решение, оно блокирует исполнение кода. Запросы где время ответа неизвестно, лучше решать через очереди задач ожидания. Потоков в lua нет, но, как минимум, не блокировать весь код. Если, например, скрипт обрабатывает много инструментов и потоков данных, то ждать после каждого заказа - много времени пройдет пока до последнего дойдет. Или надо что-то другое постоянно контролировать, пока по другому инструменту заказ сделали. То что долго идет ответ - это не повод для уже работающих инструментов ждать.
Не от хорошей жизни, данные не всегда успевают. Поскольку, как вы заметили, потоков в луа нет, пришлось на каждый инструмент(тикер) сделать по скрипту. Ну а в отдельном скрипте без базы никаких задач нет. К стати, пока ни при какой нагрузке ожидание начала загрузки больше секунды-двух не встретил, а базы подгружается в основном либо при запуске, либо на открытии сессии. Как и повода жаловаться на SetUpdateCallback. Хотя в основном как колбэк используется OnAllTrade, база больше для расчетов.
написал: Не лучшее решение, оно блокирует исполнение кода. Запросы где время ответа неизвестно, лучше решать через очереди задач ожидания. Потоков в lua нет, но, как минимум, не блокировать весь код. Если, например, скрипт обрабатывает много инструментов и потоков данных, то ждать после каждого заказа - много времени пройдет пока до последнего дойдет. Или надо что-то другое постоянно контролировать, пока по другому инструменту заказ сделали. То что долго идет ответ - это не повод для уже работающих инструментов ждать.
Не от хорошей жизни, данные не всегда успевают. Поскольку, как вы заметили, потоков в луа нет, пришлось на каждый инструмент(тикер) сделать по скрипту. Ну а в отдельном скрипте без базы никаких задач нет. К стати, пока ни при какой нагрузке ожидание начала загрузки больше секунды-двух не встретил, а базы подгружается в основном либо при запуске, либо на открытии сессии. Как и повода жаловаться на SetUpdateCallback. Хотя в основном как колбэк используется OnAllTrade, база больше для расчетов.
В квике можно создавать сколько угодно потоков При этом надо использовать общий глобальный стек. В нем решены проблемы синхронизации для main и для любых других. ---------------- я приводил пример с пулом потоков Использовал его для обработки колбеков по 200 инструментов. в итоге максимальное количество потоков которые были открыты пулом составило 12. Никаких проблем с синхронизацией не было.
Пользователь
Сообщений: Регистрация: 13.05.2022
23.11.2022 19:30:15
Цитата
Kolossi написал: Как и повода жаловаться на SetUpdateCallback.
Хотите сказать - у Вас описываемого мной косяка разрабов не наблюдается ?
написал: Как и повода жаловаться на SetUpdateCallback.
Хотите сказать - у Вас описываемого мной косяка разрабов не наблюдается ?
Нет не наблюдается. Просто может быть потому что я сразу подстраховался и забил. Жалко времени на это тратить. Реальная функция из скрипта, была написана на ранних версиях квика и с тех пор не трогалась:
Код
function GetDS(p) -- функция закачки данных
local error_desc=""
if p==1 then -- дневные
...
elseif p==2 then -- тиковые
dsa,error_desc=CreateDataSource(p_classcode, trw.p_seccode, INTERVAL_TICK)
while not dsa or dsa:Size()==0 do
local n=100
while n>0 do
sleep(100)
if dsa and dsa:Size()>0 then break end
n=n-1
end
if not dsa or dsa:Size()==0 then
dsa,error_desc=CreateDataSource(p_classcode, trw.p_seccode, INTERVAL_TICK) -- повтор
end
if error_desc~=nil and error_desc~="" then
message("TICK, "..p_classcode.."/"..trw.p_seccode.."/".."Source2 error==>" .. error_desc)
return 0
end
end
dsa:SetEmptyCallback()
return dsa:Size()
else
return 0
end
end
Полагаю счетчик и повтор решили возможную проблему.
Пользователь
Сообщений: Регистрация: 03.03.2016
24.11.2022 09:55:02
Цитата
nikolz написал: В квике можно создавать сколько угодно потоков При этом надо использовать общий глобальный стек. В нем решены проблемы синхронизации для main и для любых других. ---------------- я приводил пример с пулом потоков Использовал его для обработки колбеков по 200 инструментов. в итоге максимальное количество потоков которые были открыты пулом составило 12. Никаких проблем с синхронизацией не было.
Спасибо, посмотрю. Однако сейчас уже это не совсем актуально поскольку каждый скрипт и есть отдельный поток, а переменные между скриптами можно передавать через общее пространство переменных. Жаль только что нет возможности запускать дерево скриптов.
local code_class1 = "TQBR"
local code_paper1 = "GAZP"
local interval1 = INTERVAL_TICK
local code_class2 = "TQBR"
local code_paper2 = "SBER"
local interval2 = INTERVAL_TICK
------------------------
local function my_cb_CDS (idx,tabl)
message (tostring(tabl.sec) .. "," .. tostring(idx), 1 )
Sleep( 100 );
end
-----------------------------------------------------------------------------------------------------------int main:-----------------------------------------------------------------------------------------------------
function main ()
while not stopped do
if tab1 = = nil then tab1 = CreateDataSource (code_class1, code_paper1, interval1);
if tab1 then
tab1.clas = code_class1; tab1.sec = code_paper1; tab1.int = interval1;
tab1: SetUpdateCallback ( function (idx) my_cb_CDS(idx,tab1) end )
end
end
if tab2 = = nil then tab2 = CreateDataSource (code_class2, code_paper2, interval2);
if tab2 then
tab2.clas = code_class2; tab2.sec = code_paper2; tab2.int = interval2;
tab2: SetUpdateCallback ( function (idx) my_cb_CDS(idx, tab2) end )
end
end
-------------------------
-- message(tostring(my_table1:Size()),1)
sleep ( 1000 )
end
-------------------------
end -- end main()
function OnInit (script_path)
end
Данный код так же Не работает с Первого раза, ТОЛЬКО со Второго раза.
написал: Как и повода жаловаться на SetUpdateCallback.
Хотите сказать - у Вас описываемого мной косяка разрабов не наблюдается ?
Нет не наблюдается. Просто может быть потому что я сразу подстраховался и забил. Жалко времени на это тратить. Реальная функция из скрипта, была написана на ранних версиях квика и с тех пор не трогалась: Полагаю счетчик и повтор решили возможную проблему.
С вероятностью 99,9% - Вы просто ее не замечаете, так как она наблюдается именно сразу после запуска Квика и после Первого запуска скрипта, на второй, третий и последующий разы - данная пробелма не наблюдается до тех пор пока Вы не перезапустите Квик заново.
При этом разработчики - собаки сутулые - в течении годов ничего с этим не делают.