Добрый день. Проблема не в том какой язык и как "прикручен" к терминалу. По большому счету нет разницы Lua это или MQL. Проводились тесты интерпретатора против JIT-компилятора, а в этом случае результаты вполне очевидны. Можно взять тесты из примера и провести сравнение Lua vs LuaJIT и получить примерно такое же соотношение времени выполнения.
При такой конструкции Вы уверены в правильности передаваемых параметров в функцию обратного вызова? ниже пример кода, который позволяет корректно передавать в колбек данные из DataSource:
Код
function cb(ds, index )
local t = ds:T(index)
message( string.format("%s, %s, %d", ds.class_code, ds.sec_code, index))
end
class_code = "SPBFUT"
sec_code = "RIZ6"
ds = CreateDataSource(class_code, sec_code, INTERVAL_M1)
assert(ds)
ds.update_func = cb
ds.sec_code = sec_code
ds.class_code = class_code
ds:SetUpdateCallback(function(index) ds:update_func(index) end)
Андрей 77 написал: А почему нельзя в CreateDataSource, SetUpdateCallback предусмотреть чтобы и class и security и ds были доступны cb ? Но только не переменные с такими именами, а их значения.
Просто это не было реализовано. Мы зарегистрировали от Вас пожелание на доработку. Мы постараемся рассмотреть его и сообщить Вам результаты анализа. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Это не было реализовано потому, что пользователи могут сделать реализацию самостоятельно. Предыдущий пример был не совсем корректный.
Код
function cb(owner, index )
local t = owner:T(index)
message( string.format("%s, %s, %d", owner.class_code, owner.sec_code, index))
end
class_code = "SPBFUT"
sec_code = "RIZ6"
ds = CreateDataSource(class_code, sec_code, INTERVAL_M1)
assert(ds)
ds.update_func = cb
ds.sec_code = sec_code
ds.class_code = class_code
ds:SetUpdateCallback(function(index) ds:update_func(index) end)
Основные затраты при поиске перебором используя getItem это передача структур данных из хост-программы через стек в скрипт. SearchItems дает возможность уменьшить эти расходы. Используя Ваш пример я написал похожую реализацию с помощью функции SearchItems. Исходный код я немного модифицировал для подсчета статистики. Исходный пример Пример реализации с SearchItems Результаты тестов на моей машине:
Андрей 77 написал: В данном случае замедления не будет, а удобство налицо - fn один раз приводится для любых проверок/выборок с любым набором параметров. А раз все равно getItem используется, то такой подход дает максимальное удобство при сохранении скорости. Конечно, если понадобится другой тип выборки (например qty > 1 and qty < 10) то придется отдельную функцию писать.
Добрый день. А не могли бы Вы привести законченный пример с использованием этой универсальной функции поиска?
Николай Камынин написал: Добрый день, Написал тест для исследования очередей заявок (стаканов). Пустил его на вашем демо-сервере. Понятно, что это тестовый сервер. Но уж больно интересная картинка. Если не военная тайна, может кто объяснит эти периодические зависания обмена на 40 секунд Вот картинка:
спасибо
Добрый день. Выше Вам уже предлагали выслать нам данные для анализа.
Вячеслав + написал: 1. Планируется ли менять тип min_price_step с number на string. 3. Те же вопросы для любой переменной типа number c вещественной частью, возвращаемой через QLua API (пока столкнулся только с min_price_step).
1. Нет, не планируется. 2. для любого другого значения точность определяется либо параметром scale на инструменте, либо точность равна 2 если речь идет о деньгах - лимиты, обороты и т.п.
Просто есть два подхода в использовании Lua: 1. Вы пишете на Lua и тогда корутины это то что Вам надо 2. Lua используете как язык для связки своих библиотек и QUIK. В этом случае реализация полностью на ваших плечах. Но я все еще не понимаю полностью как Вы хотите вызывать функции одного работающего скрипта из другого. Проблем и ограничений в таком подходе явно больше чем преимуществ.
Michael Bulychev написал: Сервер 10 секунд занимался тем, что отдавал вам очередь более приоритетных данных. По моему, наиболее адекватная оценка будет по времени последней сделки на ликвидном рынке.
так как ТВС - это приоритетные данные, а вечером особо ничего срочного нет, но получаем все теже 0.2-10 секунд, то Ваши рассуждения - это просто Ваши гипотезы, ничем не подтвержденные. -------------------------------------------------------- мечтать не вредно, но бесполезно.
Добрый день. 1. Исследования о задержках надо показывать не нам, а Вашему брокеру. 2. Если хотите что мы попробовали разобраться в проблеме, то присылайте нам информацию для анализа: - архив терминала без ключей; - исходники скриптов которые крутились в этот момент; - исходники Ваших библиотек, которыми вы измеряете время и все остальное; А так, "по фотографии", очень сложно дать какие-либо рекомендации
Если тиковый источник данных построен не по параметру торгов, то для него используются обезличенные сделки (все сделки). Какую задачу Вы решаете пытаясь сопоставить конкретную сделку тику в источнике данных?
тот самый написал: показывает наиболее загруженные IP брокера и предлагает переподключиться на другой канал.
Как это выглядит? мониторинг загрузки серверов на стороне брокера? Если так, то наверное это единственный надежный способ. Все остальные способы дают оценку некоторых несвязанных между собой параметров.
Добрый день. На мой взгляд в том что Вы предлагаете больше вопросов чем реальной пользы. Это касается и синхронизации времени в отдельном приложении и повышения приоритета данных. И о какой "приблуде" идет речь?
Сервер 10 секунд занимался тем, что отдавал вам очередь более приоритетных данных. По моему, наиболее адекватная оценка будет по времени последней сделки на ликвидном рынке.
Добрый день. Сейчас функция обратного вызова должна возвращать true/false, предлагаю интерпретировать ситуацию с возвратом функцией nil, как конец выполнения SearchItem. Такая реализация устроит?
DS={};
function DS_6(cl,se) -- создание источников тиков
local int=INTERVAL_TICK;
local x=cl..se..tostring(int);
if DS[x]==nil then
local ds,er=CreateDataSource(cl,se,int);ds:SetEmptyCallback();
if err then
Log(err,"err_ds");
else
message("ADD " .. x)
DS[x]=ds;
end
end
end
function OnStop(s)
stopped = true
end
function main()
local n=getNumberOf("securities")
for i=0, n-1 do
sec = getItem("securities", i)
if sec and sec.class_code == "SPBFUT" then
DS_6("SPBFUT", sec.code)
end
end
while not stopped do
sleep(500)
end
end
Этот код не приводит к зависанию ни на 6.17 ни на версии 7. Можете прислать нам архив терминала, либо самостоятельно снять полный дамп процесса после закрытия окна. Например с помощью ProcDump
Добрый день. Возможно он называется не совсем понятно, но показывает ровно то, для чего был сделан. Если не устраивают результаты - используйте стандартный пинг.
Добрый день. В чем-то действительно есть сходство со стандартным пингом. Разница только в уровне реализации. Я имею ввиду сетевую модель OSI. Еще раз повторю - приоритет у таких сообщений в протоколе минимальный. Поэтому большие задержки могут в случае если:
достаточно интенсивный поток торговых данных на сервере и серверу есть что отправить клиенту кроме ответа на пинг;
клиент недостаточно быстро выбирает данные по сети от сервера. Это может быть по причине плохой связи либо "тормозов" терминала;
В общем ничего особенно страшного в больших числах нет, при условии что терминал в это время не испытывает проблем с получением данных.
Добрый день. Пинг, который Вы смотрите в параметре LASTPINGDURATION, не является пингом в классическом понимании (ICMP протокол). Это определенные данные, которыми терминал и сервер обмениваются в процессе работы. Приоритет таких сообщений очень низкий. Это значит что ответные "понги" клиенту будут отправляться только в том случае, если больше нет торговых данных в очереди на отправку. Этим и объясняется разница между приведенными выше данными.
quio написал: Получается, единственное отличие в наличии автоматической отписки после останова скрипта? (после CreateDataSource терминал сам отписку не выполняет)
Добрый день. Отличие в том, что если нет соответствующей настройки в терминале, то не будет заказана история по параметру (тиковая или интервальная). Этот заказ предназначен для функции OnParam
1. Еще раз - "значение может быть nil" - в некоторых случаях это поле может отсутствовать в ответе на транзакцию. Если есть и оно не заполнено значит нечем его заполнять. 3. Возможно это проверяет торговая система. В транзакции нет привязки номера заявки к счету. 4. отдельный ответ от сервера QUIK.
Добрый день. 1. В документации написано "значение поля может быть nil" 3. Подать транзакцию на перестановку заявок с разных счетов можно, если у вас прав достаточно. 4. на каждую переставленную заявку приходит отдельный ответ.