При возникновении стандартной ситуации смены рабочего тикера для робота довольно просто подписатся/отписатся на/от свечных баз данных. В случае же с обезличенными сделками ситуация выглядит иначе. Я предположил, что подписка на тиковую базу при помощи CreateDataSource решает эту проблему. Тестовый скрипт:
Код
is_run=true
function main()
ds,error_desc=CreateDataSource("TQBR", "GAZP", INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
message("Data "..tostring(ds:Size()))
ds:SetEmptyCallback()
while is_run do
sleep(100)
end
end
function OnStop(stop_flag)
ds:Close()
is_run=false
end
Запускаю скрипт и , о чудо(!), в фильтре Основные_настройки/Программа/Получение_данных/Обезличенные_сделки появляется Газпром. Т.е. задача подписки на ленту сделок успешно решена и данные заказаны. Но... - ничего не появляется в фильтре таблицы обезличенных сделок - убрать эту подписку можно только вручную после похода в меню настроек.
В связи с вышеописанным имею два вопроса:
1. Достаточно ли такой подписки для корректной работы в скрипте колбэка OnAllTrade и выборки SearchItems("all_trades", .....) не имея этого инструмента в таблице обезличенных сделок? 2. Как отписаться от этого счастья средствами Qlua при следующей смене иструмента?
В теории да, я так тоже делаю. Правда не советую так ждать прихода данных. Тиковые данные могут приходить долго, очень долго. В прошлых версиях данные приходили и без открытой таблицы обезличенных сделок. В текущих - уже нет, по крайней мере, по моим наблюдениям. Отписаться как и от обычного потока данных - закрыть. Собственно Вы это и делаете OnStop. Хотя, если говорите, что не убирается (как я понял), то, возможно, что-то опять изменилось между версиями. В последнее время мажорные релизы выходят как кролики.
Nikolay написал: В теории да, я так тоже делаю. Правда не советую так ждать прихода данных. Тиковые данные могут приходить долго, очень долго. В прошлых версиях данные приходили и без открытой таблицы обезличенных сделок. В текущих - уже нет, по крайней мере, по моим наблюдениям. Отписаться как и от обычного потока данных - закрыть. Собственно Вы это и делаете OnStop. Хотя, если говорите, что не убирается (как я понял), то, возможно, что-то опять изменилось между версиями. В последнее время мажорные релизы выходят как кролики.
Субъективно вроде работает, затыки появляются при смене даты торговой сессии на следующий день. Close() из меню подписку не убирает.
Еще есть такой глюк. Если Вы запустите КВИК и потом запустите скрипт, в котором есть подписка на обезличенные сделки, то ничего не получите. Если скрипт снять и снова запустить, то все заработает . Раньше уже про это писали, но воз вроде и ныне там.
nikolz написал: Еще есть такой глюк. Если Вы запустите КВИК и потом запустите скрипт, в котором есть подписка на обезличенные сделки, то ничего не получите. Если скрипт снять и снова запустить, то все заработает . Раньше уже про это писали, но воз вроде и ныне там.
После смены даты много чего происходит - теперь индексы установленных меток еще изменяются. Такое ощущение, что какой-то колбек, например OnCleanUp, теперь приводит к такому-же эффекту как старт с нуля терминала.
Цитата
Close() из меню подписку не убирает
Т.к. подписка на тиковые данные добавляет, то закрытие должно удалять. Иначе это надо рассматривать как ошибку утечки памяти.
- ничего не появляется в фильтре таблицы обезличенных сделок
Если речь идет о том, что инструмент не добавляется в фильтр отдельной Таблицы обезличенных сделок, такое поведение корректно.
Цитата
- убрать эту подписку можно только вручную после похода в меню настроек.
Воспроизвели данное поведение при условии, что в терминале присутствует открытая Таблица обезличенных сделок. Проблема изучается. Постараемся в ближайшее время дать ответ.
Цитата
1. Достаточно ли такой подписки для корректной работы в скрипте колбэка OnAllTrade и выборки SearchItems("all_trades", .....) не имея этого инструмента в таблице обезличенных сделок?
Достаточно, наличие инструмента в открытой Таблице обезличенных сделок не обязательно.
Цитата
2. Как отписаться от этого счастья средствами Qlua при следующей смене иструмента?
Если в терминале нет открытых Таблиц обезличенных сделок, при вызове ds:Close() исключается получение обезличенных сделок по инструменту.
- ничего не появляется в фильтре таблицы обезличенных сделок
Если речь идет о том, что инструмент не добавляется в фильтр отдельной Таблицы обезличенных сделок, такое поведение корректно.
Цитата
- убрать эту подписку можно только вручную после похода в меню настроек.
Воспроизвели данное поведение при условии, что в терминале присутствует открытая Таблица обезличенных сделок. Проблема изучается. Постараемся в ближайшее время дать ответ.
Цитата
1. Достаточно ли такой подписки для корректной работы в скрипте колбэка OnAllTrade и выборки SearchItems("all_trades", .....) не имея этого инструмента в таблице обезличенных сделок?
Достаточно, наличие инструмента в открытой Таблице обезличенных сделок не обязательно.
Цитата
2. Как отписаться от этого счастья средствами Qlua при следующей смене иструмента?
Если в терминале нет открытых Таблиц обезличенных сделок, при вызове ds:Close() исключается получение обезличенных сделок по инструменту.
Антон, спасибо за ответ! Раз уж вы решили разобраться то посмотрите пожалуйста этот баг когда данные по обезличенным сделкам не получаются после запуска терминала со скриптом при закрытой сессии. Т.е. потом, когда сессия открывается, данные не поступают. При смене даты то же самое. Это при условии, что подписка оформлена в Настройках, но таблица обезличенных сделок не открыта. Если ТОС открыта и там прописан инструмент, то все работает корректно. Т.е. надо либо пофиксить этот баг, либо дать возможность CreateDataSource(..... INTERVAL_TICK) одновременно с внесением выбранного тикера в заказ данных вносить его и в открытую таблицу обезличенных сделок. В этом случае мы бы просто держали ТОС открытой и туда добавлялся бы и убирался тикер по CreateDataSource и Close(). Сейчас, для корректной работы скриптов, приходится после CreateDataSource(..... INTERVAL_TICK) руками вносить тикер в ТОС и потом после Close() руками же его убирать из Настроек и ТОС
В общем, как не искал, ничего не нашел. Все работает как надо за исключением отписки. Полагаю в последних версиях (у меня 11.0.0.92) эта проблема пофиксилась с чем-то вместе "за компанию". Либо я не учел какой-то дополнительный фактор. В любом случае дальше искать черную кошку в темной комнате смысла нет. Проявится снова, продолжу.
Kolossi написал: - убрать эту подписку можно только вручную после похода в меню настроек.
Действительно, в настоящий момент реализация такова, что в случае, когда открыта хотя бы одна таблица обезличенных сделок, даже по другому классу, то при отписке от обезличенных сделок через скрипт они не исчезнут из фильтра и продолжат заказываться терминалом.
Приносим свои извинения за длительное ожидание ответа.
В итоге я таки поймал этот баг за хвост. Вот скрипт, который его ловит:
Код
-- Скрипт проверки корректности получения данных обезличенных сделок.
-- Терминал запускается вместе со скриптом ДО начала сессии.
-- Таблица обезличенных сделок не открыта
-- Тикера нет в Таблице текущих торгов.
--
ticker="MAGN"
status,t_status=0,0
old_size=0
n=0
is_run=true
SessionDate=""
function main()
message("Script's start local time: "..os.date("%d-%b-%Y %X"))
SessionDate=getTradeDate().date
message("Session date "..SessionDate)
ParamRequest(p_classcode,ticker,"TRADINGSTATUS")
--
while is_run==true do
if SessionDate~=getTradeDate().date and status==1 then -- новая сессия
SessionDate=getTradeDate().date
message("New session date "..SessionDate)
n=0
end
t_status=tonumber(getParamEx2("TQBR",ticker, "TRADINGSTATUS").param_value) -- текущий статус
if status~=t_status then -- изменение статуса сессии
status=t_status
if status==3 or status==1 then
if not ds or type(ds)~="table" then
ds,error_desc=CreateDataSource("TQBR", ticker, INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
ds:SetEmptyCallback()
message(os.date(" %X").." Ready. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
while n<10 and status==1 do
local size=ds:Size()
if size~=old_size then
message(tostring(n)..os.date(" %X").." Get data. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
old_size=size
n=n+1
end
sleep(50)
end
end
end
end
sleep(100)
end
end
function OnStop(stop_flag)
message("Script's stop local time(MSK-1): "..os.date("%d-%b-%Y %X"))
if ds then ds:Close() end
is_run=false
end
Скрипт был запущен вместе с терминалом до начала сессии (status==0), после открытия предторговой (status==3) отработали функции CreateDataSource и SetEmptyCallback. После открытия основной сессии (status==1) должны были начать поступать данные по обезличенным сделкам и показаны первые 10 изменений базы. Однако данные по сделкам в терминал НЕ поступали:
20.12.2023 08:00:10 Script's start local time: 20-Dec-2023 08:00:10 20.12.2023 08:00:10 Session date 20.12.2023 20.12.2023 08:00:34 Соединение установлено. Предыдущий вход был 20.12.2023 07:57:31 с адреса 92.62.58.114. 20.12.2023 09:50:10 09:50:10 Ready. Session status:3.0 Data size:0 20.12.2023 10:05:35 Script's stop local time: 20-Dec-2023 10:05:35
В 10-05 скрипт был перезапущен и отработал корректно:
20.12.2023 10:06:05 Script's start local time: 20-Dec-2023 10:06:05 20.12.2023 10:06:05 Session date 20.12.2023 20.12.2023 10:06:05 10:06:05 Ready. Session status:1.0 Data size:406 (406 записей базы было пропущено при первом запуске) 20.12.2023 10:06:05 0 10:06:05 Get data. Session status:1.0 Data size:406 20.12.2023 10:06:05 1 10:06:05 Get data. Session status:1.0 Data size:418 20.12.2023 10:06:05 2 10:06:05 Get data. Session status:1.0 Data size:421 20.12.2023 10:06:06 3 10:06:06 Get data. Session status:1.0 Data size:424 20.12.2023 10:06:12 4 10:06:12 Get data. Session status:1.0 Data size:425 20.12.2023 10:06:14 5 10:06:14 Get data. Session status:1.0 Data size:426 20.12.2023 10:06:16 6 10:06:16 Get data. Session status:1.0 Data size:428 20.12.2023 10:06:20 7 10:06:20 Get data. Session status:1.0 Data size:429 20.12.2023 10:06:20 8 10:06:20 Get data. Session status:1.0 Data size:430 20.12.2023 10:06:24 9 10:06:24 Get data. Session status:1.0 Data size:431
Не знаю насколько важно - терминал запускался на "тихоходном" компе c Intel Core i5
nikolz написал: То что тики подписываются со второго пинка было указано давно, но воз и ныне там.
Наткнулся на интересную фишку: если тики не едут после подписки при открытой сессии, то подписка на другой тикер даже в другом скрипте толкает все подписки и они приходят в чувство.
nikolz написал: То что тики подписываются со второго пинка было указано давно, но воз и ныне там.
Наткнулся на интересную фишку: если тики не едут после подписки при открытой сессии, то подписка на другой тикер даже в другом скрипте толкает все подписки и они приходят в чувство.
именно в другом скрипте, либо перезапуск этого же, что как бы запуск другого скрипта.
function main()
message("Script's start local time: "..os.date("%d-%b-%Y %X"))
SessionDate=getTradeDate().date
message("Session date "..SessionDate)
ParamRequest(p_classcode,ticker,"TRADINGSTATUS")
--
while is_run==true do
t_status=tonumber(getParamEx2("TQBR",ticker, "TRADINGSTATUS").param_value) -- текущий статус
if status~=t_status then -- изменение статуса сессии
status=t_status
if status==3 or status==1 then
if not ds or type(ds)~="table" then
ds,error_desc=CreateDataSource("TQBR", ticker, INTERVAL_TICK)
if error_desc~=nil and error_desc~="" then message(" Source error==>" .. error_desc) end
local nn=0
while ds:Size()<5 and nn<100 do
sleep(100) nn=nn+1
end
ds:SetEmptyCallback()
message(os.date(" %X").." Ready. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
end
while n<10 and status==1 do
local size=ds:Size()
if size~=old_size then
message(tostring(n)..os.date(" %X").." Get data. Session status:"..tostring(status).." Data size:"..tostring(ds:Size()))
old_size=size
n=n+1
end
sleep(50)
end
end
end
sleep(100)
end
end
Ничего не изменилось, данные поступают только после перезапуска скрипта.
Kolossi написал: Поправил main() что бы отсечь возможные варианты:
Код
function main ()
message ( "Script's start local time: " .. os.date ( "%d-%b-%Y %X" ))
SessionDate = getTradeDate ().date
message ( "Session date " .. SessionDate)
ParamRequest(p_classcode,ticker,"TRADINGSTATUS")
--
while is_run = = true do
t_status = tonumber( getParamEx 2( "TQBR" ,ticker, "TRADINGSTATUS" ).param_value) -- текущий статус
if status~ = t_status then -- изменение статуса сессии
status = t_status
if status = = 3 or status = = 1 then
if not ds or type(ds)~ = "table" then
ds,error_desc = CreateDataSource ( "TQBR" , ticker, INTERVAL_TICK)
if error_desc~ = nil and error_desc~ = "" then message ( " Source error==>" .. error_desc) end
local nn = 0
while ds: Size () < 5 and nn < 100 do
sleep ( 100 ) nn = nn + 1
end
ds: SetEmptyCallback ()
message ( os.date ( " %X" ) .. " Ready. Session status:" .. tostring(status) .. " Data size:" .. tostring(ds: Size ()))
end
while n < 10 and status = = 1 do
local size = ds: Size ()
if size~ = old_size then
message (tostring(n) .. os.date ( " %X" ) .. " Get data. Session status:" .. tostring(status) .. " Data size:" .. tostring(ds: Size ()))
old_size = size
n = n + 1
end
sleep ( 50 )
end
end
end
sleep ( 100 )
end
end
Ничего не изменилось, данные поступают только после перезапуска скрипта.
подтверждаю, проверялось много раз и не только мною.
nikolz написал: как решаете обмен данными между скриптами?
конкретно эти два не требуют обмена между собой. Для отрисовки результатов каждого из них написал индикатор, туда передаю из скриптов данные через lua_share.
Для более новой пары скрипт+индикатор уже всё пишу в одной dll на плюсах, там boost::lockfree::queue для сообщений индикатора в сервер (требующих синхронизации и долгой обработки), и std::atomic переменные для использования в индикаторе данных из сервера, типа atomic<MyData*>, чтобы знать, есть уже данные или нет, и atomic<std::size_t> size_of_shared_data , чтобы индикатор не лез в данные, которые сервер начал, но не закончил, писать, или atomic<double> price для цен других инструментов (берутся в сервере через update callback). В ситуации реконнекта приходится всё-таки юзать один mutex (в скрипте в OnConnected и в while (is_run), не индикаторе), вырубать все 28 экземпляров индикатора, перезаказывать данные, обновлять все указатели, и только потом разрешать индикаторам работать.
Kolossi написал: данные поступают только после перезапуска скрипта.
Проверьте, пожалуйста, удастся ли воспроизвести поведение на версии Рабочего места QUIK 11.0.1?
Если ситуацию удастся воспроизвести, просим Вас прислать для анализа копию используемого Рабочего места QUIK (без файлов ключей .txk) и файл с Lua-скриптом. Файлы можно поместить в архив и разместить на любом удобном для Вас файлообменном сервисе, затем прислать ссылку на загрузку на нашу почту quiksupport@arqatech.com. В письме просим указать ссылку на данную тему форума.