В архиве по ссылке версия 8.6.0.0 от 10.02.2020. Так он "открывает" графики с Junior 9.3.1.11 Но если вы считаете, что так и должно быть, тогда ладно. Мне уже не надо.
Надо делать так, как надо. А как не надо - делать не надо.
В сообщении #41 опечатался. * в QUIK 8 скрипты торгуют, а в QUIK 9 режим торговли не включен, т.е. в 9 работы выполняется меньше, чем в 8. + в QUIK 8 на два скрипта больше. А нагрузка - сами видите.
Надо делать так, как надо. А как не надо - делать не надо.
Anton написал: Насколько это критично в реальном применении, а не в модельном примере, вопрос открытый.
А вот в реальном применении: загрузка CPU сегодня на открытии основной сессии в 10 ч. Слева - QUIK 9, справа - QUIK 8 при одинаковых настройках и одинаковом количестве открытых окон. Отличие только в том, что в QUIK 8 скрипты торгуют, а в QUIK 9 режим торговли не включен, т.е. работы выполняется меньше, чем в 9.
Надо делать так, как надо. А как не надо - делать не надо.
swerg написал: Деградация от версии к версии определённо печалит. Хоть я и поставил бы под сомнение корректность некоторых полученных результатов (v(0) больше, чем v(10000000) ??).
Anton написал: после каждого колбека lua_gc добавили. Не обратил внимания только, полный или шаг. Вот оно собсна и есть, пропорционально количеству потенциального мусора.
Тут надо отметить, что, если в скрипте есть таблица, в которой постоянно добавляются и убираются элементы, то фактически количество элементов в таблицы будет только расти и никогда не уменьшаться. Например, имеем таблицу активных заявок orders с ключом order_num. Когда заявка становится неактивной, убираем её: orders[order_num] = nil. Но для сборщика мусора этот элемент будет продолжать существовать со значением nil, он не сможет его очистить. Чтобы удалить элемент из таблицы, надо полностью удалить саму таблицу. Т.о., объём потенциального мусора будет только расти со временем работы скрипта.
Цитата
Anton написал: Насколько это критично в реальном применении
У каждого своё реальное применение. Кто-то торгует только один инструмент, а другой весь рынок отслеживает. Кому-то и 200 стаканов мало. Сами понимаете, в каждом случае количество событий будет отличаться кардинально.
Надо делать так, как надо. А как не надо - делать не надо.
Поправка к коду в сообщении #25: время надо фиксировать в самом колбеке. Но это не сильно влияет на итоговый результат: завышение результата на 0 - 0.5 сек.
Скрытый текст
Код
local function v(n)
for i = 1, n do
_G["v"..i] = i
end
end
v(0)
--v(10000000)
local run = true
function OnStop()
run = nil
end
local t
function OnAllTrade()
if getNumberOf("all_trades") == 1 then
local num = 1
function OnAllTrade(alltrade)
if not run then return end
num = num + 1
if num == 200000 then
t = os.clock() - t
run = false
end
end
t = os.clock()
end
end
function main()
while run do sleep(500) end
if t then message(tostring(t)) end
end
Надо делать так, как надо. А как не надо - делать не надо.
swerg написал: Давайте десятки миллионов глобальных переменных создадим
А давайте, чё мелочиться! Скрипт:
Скрытый текст
Код
local function v(n)
for i = 1, n do
_G["v"..i] = i
end
end
v(0)
--v(10000000)
local run = true
function OnStop()
run = nil
end
local t
function OnAllTrade()
if getNumberOf("all_trades") == 1 then
local num = 1
function OnAllTrade(alltrade)
if not run then return end
num = num + 1
if num == 200000 then run = false end
end
t = os.clock()
end
end
function main()
while run do sleep(500) end
if t then message(tostring(os.clock() - t)) end
end
Методика тестирования описана в сообщении #20. Только в этот раз я запускал только один экземпляр скрипта. Результаты тестирования в различных версиях QUIK при 0 и 10000000 глобальных переменных:
Даже просто создание локальной таблицы снижает производительность. Методика тестирования описана в сообщении #20
Код
local run = true
function OnStop()
run = nil
end
local t
function OnAllTrade()
if getNumberOf("all_trades") == 1 then
local num = 1
function OnAllTrade(alltrade)
num = num + 1
if num == 200000 then run = false end
end
t = os.clock()
end
end
function main()
local a = {}
local n = 0
--local n = 20000
for i = 1, n do a[i] = i end
while run do sleep(1) end
if t then message(tostring(os.clock() - t)) end
end
Получается, кеширование любых данных, например для расчётов индикаторов, снижает производительность при вызовах колбеков.
Надо делать так, как надо. А как не надо - делать не надо.
До кучи решил ещё одну тему проверить. swerg, то, что вы написали
Цитата
swerg написал: если вы просто возьмете Луа без привязки к квик - вызов среди десятков тысяч переменных тоже будет тормозить. Т.е. это такое вполне понятное свойство интерптетатора Луа.
- бред и не соответствует действительности: в чистом Lua время вызовов пустой функции никак не изменится даже после создания "десятков миллионов глобальных переменных". Коль ввязываетесь в спор, вы бы хоть проверяли, прежде, чем чё-то писать.
Надо делать так, как надо. А как не надо - делать не надо.
Пока биржа не тогует, решил проверить одну идею на демке. Junior, настройки по-умолчанию. Открыл три окна: ТОС, системные сообщения и доступные скрипты. В ТОС добавил неторговый класс SMS-оповещения, чтобы не мешала измерениям.
Далее запустил одновременно три копии скрипта:
Скрытый текст
Код
local function f(n)
for i = 1, n do
_G["f"..i] = function ()
return 0
end
end
end
local function r(n)
for i = 1, n do
local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
_G["f"..i] = function ()
return {a1, a2, a3, a4, a5, a6, a7, a8, a9, a10}
end
end
end
--f(150)
--r(150)
--require("socket")
--require("socket.smtp")
--require("iuplua")
local run = true
function OnStop()
run = nil
end
local t
function OnAllTrade()
if getNumberOf("all_trades") == 1 then
local num = 1
function OnAllTrade(alltrade)
num = num + 1
if num == 200000 then run = false end
end
t = os.clock()
end
end
function main()
while run do sleep(1) end
if t then message(tostring(os.clock() - t)) end
end
Перезаказал обезличенные сделки: Система / Настройки / Основные настройки... -> «Программа» / «Получение данных» / «Обезличенные сделки». Выбираю класс "Акции 1-го уровня (эмулятор)" -> "Перезаказать данные" По завершению работы скриптов запоминаю время.
Далее повторяю процедуру с f(150). Время работы скриптов выросло на 25%. С r(150) - на 80%-90%. При подключении socket время также увеличилось в 1,8 раза. А с iuplua в 3 раза.
Так что, дело тут не только в глобальных переменных.
Надо делать так, как надо. А как не надо - делать не надо.
swerg написал: Только сейчас разглядел создание 50 тыс глобальных переменных
Это количество было написано для саппорта, который проводит "нагрузочное тестирование" на демке, где количество событий на два порядка меньше, чем в реале. Чтоб потом не было разговоров, что все летает. На бою, естественно, и рядом нет тысячи переменных.
Конечно, я не учёл фактор теоретиков-флудеров.
Цитата
swerg написал: если вы просто возьмете Луа без привязки к квик - вызов среди десятков тысяч переменных тоже будет тормозить.
Пруф в студию.
Надо делать так, как надо. А как не надо - делать не надо.
Nikolay написал: о каких функциях речь? Любых пользовательских, или только о подписанных колбеках и функциях qlua?
Nikolay, В сообщении #2 уточнение: речь идёт о любых объявленных переменных. Возможно глобальных, но это не точно. Вы можете заменить блок создания переменных таким образом:
Код
_G["f"..i] = i
Естественно, в моменты низкой активности торгов, а тем более на демке, влияние на загрузку будет незначительно. Если только не увеличить количество переменных и/или скриптов. Можно ещё в скрипт добавить подписку на другие ликвидные инструменты, чтобы получать больше событий.
Цитата
swerg написал: А если колбеки убрать станет лучше?
Станет.
Цитата
swerg написал: какие именно колбеки убрать, от убирания которых становится лучше?
swerg написал: Чтобы масштаб проблемы был понятен.
swerg, сравните загрузку CPU при запущенном(ых) скрипте(ах) с блоком создания переменных
Код
_G["f"..i] = function () end
и без него. При открытых окнах (стаканы, ТТТ, ТОС) и при закрытии всех окон в квике.
Цитата
swerg написал: не особо слышно чтобы тормозил от колбеков
swerg, А кто догадается, что тормоза именно от вызова колбеков? Не от выполнения кода внутри колбека, а просто от вызова. В этой теме посмотрите #4 и #5 сообщения: https://forum.quik.ru/messages/forum10/message59837/topic6874/#message59837 Не факт, что там именно эта проблема. Но это легко проверить: 1) автору достаточно добавить в начало каждого колбека do return end и проверить загрузку 2) переименовать каждый колбек как-то так OnQuote -> OnQuote_ и снова проверить загрузку Если в 1-м случае нагрузка не изменится, а во 2-м уменьшится, то это - обсуждаемая здесь проблема.
Надо делать так, как надо. А как не надо - делать не надо.
Владимир, nikolz, господа флудеры, в демонстрационном скрипте нет никаких вычислений от слова совсем. Колбеки, вызываемые скриптом, пустые и не должны были бы оказывать на CPU абсолютно никакого влияния. Не надо искать подвох в скрипте, он написан лишь с одной целью: продемонстрировать в первую очередь разработчикам Арки существенный баг в организации вызовов колбеков скриптами. По факту получается, что время, затрачиваемое на вызов колбека, существенно больше, чем выполнение кода в колбеке. C Владимиром согласен в одном: "математика есть полное говно". Вот только это не моя математика, а квиковская, в котором есть прямая зависимость между количеством объявленных переменных и производительностью. Я, конечно, догадываюсь, в чём тут дело. Но так быть не должно. Предлагаю вам воздержаться от засирания темы. Хотя кому я это пишу...
Надо делать так, как надо. А как не надо - делать не надо.
Добавлю: даже если торговый счёт (поле А) каким-то чудом не слетел после подключения к серверу, то чтобы отображалась верная текущая позиция, надо поменять счет на другой и вернуть обратно. QUIK 9.3.1.11
Надо делать так, как надо. А как не надо - делать не надо.
Даже не так. Нагрузка на CPU пропорциональна количеству любых объявленных переменных (глобальных ?), в т.ч. функций (не обязательно выполняемых, а просто объявленных) в скрипте и/или подключаемых модулях и количеству колбеков, получаемых скриптом. Когда в QUIK открыты одна или несколько ТТТ с большим количеством бумаг, стаканы, ТОС, то скрипты, в которых есть колбеки по событиям из этих таблиц, при высокой активности торгов сильно тупят.
Надо делать так, как надо. А как не надо - делать не надо.
local n = 50000
for i = 1, n do
_G["f"..i] = function () end
end
local class = "SPBFUT"
local sec = "SiZ1"
local param = {"BIDDEPTHT", "OFFERDEPTHT"}
local run = true
function OnStop()
run = nil
end
function main()
assert(Subscribe_Level_II_Quotes(class, sec))
for i = 1, #param do
ParamRequest(class, sec, param[i])
end
while run do sleep(500) end
Unsubscribe_Level_II_Quotes(class, sec)
for i = 1, #param do
CancelParamRequest(class, sec, param[i])
end
end
function OnQuote(class_code, sec_code) end
function OnParam(class_code, sec_code) end
function OnAllTrade(alltrade) end
QUIK 9.3.1.11, Lua 5.4 Открыто, как минимум одно окно: стакан ликвидного инструмента. Конечно, никто не запускает скрипты с тысячами функций, но при нескольких запущенных скриптах с десятками функций при высокой активности на бирже получаем нихилую загрузку CPU.
ЗЫ: У кого "один скрипт на все случаи жизни" с парой функций, может игнорировать эту тему. Без флуда!
Надо делать так, как надо. А как не надо - делать не надо.
Vladimir Ivanov, Неоднократно писал, в т.ч. на форуме. Искать номер сейчас времени нет. Как помню, ваша основная рабочая версия была, что "виноваты Вайфай и Винда, поэтому ничё делать не будем." Сейчас я опровергаю вашу версию: Вайфай не виноват. Да даже, если допустить, что после выхода из спящего режима, у компьютера чудесным образом пропадают все сетевые интерфейсы - это не повод приложению зависать в ожидании от сервера ответа, которого никогда не будет. Да и не стоит винить дядю Билла в том, что при этом ваше приложение даже закрыть невозможно, нужно его прибивать через диспетчер задач.
Надо делать так, как надо. А как не надо - делать не надо.
Daniil Pozdnyakov написал: описать, как по-вашему должна быть реализована работа функций с номинальными порядковыми номерами
NUMBER row SetSelectedRow(NUMBER table_id, NUMBER row)
row >= 1 and row <= количества строк в таблице -- выделяет строку с номером row (здесь и далее под номером строки подразумевается номинальный порядковый номер) если строка с номером row отсортирована и не отображается в таблице, то выделение снимается, SetSelectedRow возвращает -1 row = 0 -- снимает выделение, SetSelectedRow возвращает 0 row = -1 -- выделяется последняя видимая строка в таблице (обратите внимание, что сейчас это не работает должным образом, если к таблице применены фильтры)
Если кто-то считает, что SetSelectedRow должен по-прежнему работать с видимым представлением таблицы, в котором учитываются пользовательские фильтры и сортировка, пусть напишет в этой теме, как это можно использовать.
Надо делать так, как надо. А как не надо - делать не надо.
Владимир написал: причём здесь избыточная точность не нужна и даже вредна.
Как я понял, ТС нужны данные для тестирования на истории. Действительно, 100% точность в этом случае не обязательна. Но не вредна точно. А вот, если встречаются пропуски в несколько минут (а у в экспорте финама такое встречается), то это - уже не гуд.
Цитата
Владимир написал: Графиков?! Я хоть слово сказал про графики?
А в чём разница?
Надо делать так, как надо. А как не надо - делать не надо.
Vladimir Ivanov, есть какие-то результаты? QUIK 9.3.1.11, Ethernet подключение Опять завис на этапе "идёт установление связи с сервером". После нажатия кнопки разорвать соединение обе кнопки становятся неактивными Остается только прибить процесс через диспетчер, потому что сам он выгружаться не хочет. Короче, ничего не поменялось. Причем Квики, которые с вечера были отключены от сервера, с утра успешно подключаются вручную.
Надо делать так, как надо. А как не надо - делать не надо.
Stanislav Tvorogov написал: Если по результатам дальнейшего анализа, включающего юридические аспекты, анализ на непротиворечивость с общей политикой компании, никаких возражений не возникнет, мы постараемся включить Ваши пожелания в план доработок при выпуске одной из следующих версий нашего ПО.
На какой стадии находится процесс анализа?
Надо делать так, как надо. А как не надо - делать не надо.
s_mike@rambler.ru написал: вы идете по строкам сверху вниз и ищете в каждой строке в скрытом столбце нужный вам ключ. как нашли - выделяйте эту строку по номеру строки перебора, не по ключу.
GetCell, если вы её имели ввиду, работает с ячейками по номинальному номеру строки (и это правильно, тут к ней претензий нет. Одна только SetSelectedRow оказалась с дефектом в этом плане). В вашем случае номер строки перебора всегда будет равен ключу.
Надо делать так, как надо. А как не надо - делать не надо.
Daniil Pozdnyakov написал: Касательно ответа на 2 вопрос. Привести пример, где в Lua-таблице с пользовательскими фильтрами выделяется строка функцией SetSelectedRow(), довольно сложно.
Это был скорее риторический вопрос. Потому что после применения фильтров и/или сортировки к таблице SetSelectedRow() становится бесполезной.
Цитата
Daniil Pozdnyakov написал: можем зарегистрировать пожелание на добавление признака, показывающего, что строка отфильтрована в таблице созданной через CreateWindow()
Мне нужно выделять строки по их номинальному порядковому номеру. Что я буду делать с этим признаком?
Надо делать так, как надо. А как не надо - делать не надо.
В целях улучшения взаимодействия и повышения информативности баг-репортов просьба более детально описать, что делали изначально и какие действия предприняли, что удалось получить ошибку.
Надо делать так, как надо. А как не надо - делать не надо.
Daniil Pozdnyakov написал: Перепроверили работу скриптов, на которые Вы ссылаетесь, уже с функцией CalcBuySell(). Они исправно выводят правильные данные.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: По данному обращению мы определили, что причиной множественных отправок сделок (более двух) на клиентские места является неоптимальность в серверном ПО QUIK. После ее устранения сделки могут быть отправлены на клиентское место максимум 2 раза - по получению сделки из торговой системы и по факту ее обновления.
Stanislav Tvorogov написал: По данному обращению мы диагностируем что заявки, отправляются пользователям столько раз, сколько раз они менялись на сервере (под изменением понимается, как изменение статуса, остатка, так и установка UID, trans_id). При этом по факту заявки могут быть отправлены сразу в последнем, актуальном, состоянии. Поэтому клиенты видят многократный апдэйт одной и той же заявки без ее видимых изменений. В одной из следующих версий серверного ПО QUIK мы постараемся исправить эту ситуацию, чтобы не дублировать отправку заявки в одном и том же состоянии несколько раз.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель написал: Сократить время можно, если обновлять лимиты не только после получения уведомления по заявке, но и после ответа от биржи по транзакции.
Предлагаем зарегистрировать такое пожелание. Регистрируем?
Это в ваших же интересах в первую очередь, учитывая, что
Цитата
Roman Azarov написал: Максимально сократить это время - является одной из наших основных задач.
Надо делать так, как надо. А как не надо - делать не надо.
local run = true
local id
function OnStop()
run = nil
local t = id
id = nil
if t then DestroyTable(t) end
end
function main()
id = AllocTable()
AddColumn(id, 1, "Row", true, QTABLE_INT_TYPE, 10)
AddColumn(id, 2, "Selected", true, QTABLE_INT_TYPE, 15)
CreateWindow(id)
for i = 1, 4 do
SetCell(id, InsertRow(id, i), 1, tostring(i), i)
end
SetTableNotificationCallback(id, function(t, event, row)
if event == QTABLE_VKEY then
message("SetSelectedRow: " .. tostring(SetSelectedRow(id, 2)))
elseif event == QTABLE_SELCHANGED then
SetCell(id, row, 2, tostring(row))
end
end)
while run do sleep(1000) end
end
Применить к таблице фильтр, как на скриншоте: "Row больше 1" При нажатии на любую клавишу, нужно выделить строку с фактическим порядковым номером 2. Но выделяется строка с номером 3, о чём сообщает событие QTABLE_SELCHANGED.
1. Как выделять строки по фактическому порядковому номеру, с учётом того, что скрипт понятия не имеет о применённых фильтрах и сортировках? 2. Да в руководстве указано: "Функция работает с видимым представлением таблицы, в котором учитываются пользовательские фильтры и сортировка." Но нафига оно онужно? Можете привести хоть один реальный пример, когда нужно выделить строку в таблице, в которой "учитываются пользовательские фильтры и сортировка", принимая во внимание, что скрипт понятия не имеет о применённых фильтрах и сортировках?
Надо делать так, как надо. А как не надо - делать не надо.
Daniil Pozdnyakov написал: Касательно неправильного отображения объёма на последней свече предыдущего дня. Данная проблема, которая была обнаружена в прошлых версиях терминала, была нами проверена на версии Quik 9.1. Она не воспроизвелась, объём последней свечи предыдущего дня отображается корректно, поэтому убедительная просьба прислать новые, актуальные скриншоты, на которых будет видно некорректное отображение объёма.
Надо делать так, как надо. А как не надо - делать не надо.
s_mike@rambler.ru написал: Сомн ительно, что это работало к вас в предыдущей версии.
Lua 5.3 / 5.4 имеет изменения в file:lines (···), добавляющие форматы, которые определяют, что читать. Т.о., функция ожидает строку в качестве аргумента, о чём и сообщает в ошибке. В Lua 5.1 переданный аргумент просто игнорировался.
Надо делать так, как надо. А как не надо - делать не надо.