Просто напоминаю, что аварийные падения терминала продолжаются, а на отосланные дампы приходит ответ разработчиков:
Цитата
К сожалению, нам не удалось точно установить причину возникшей ошибки. Однако, в ближайшей версии мы изменим работу с коллбэками Lua. Ожидаем, что изменения исключат возникающую ошибку.
Приносим извинения за причинённые неудобства.
При этом новой версии уже давно нет. Как-то плохо это выглядит со стороны пользователей.
Есть список слушателей, которых надо уведомлять о коллбэках (каждого слушателя о своём подмножестве коллбэков) как можно быстрее. При этом в main() время от времени возникают вычислительно тяжёлые задачи (заранее нельзя контролировать время их выполнения и разбивать на мелкие подзадачи).
Если пробрасывать события из потока коллбэков в поток main(), то будут возникать задержки, чего не стоит допускать.
Есть потребность в отключении слушателей по таймауту (а не когда придёт очередной коллбэк) и подключении новых вне зависимости от приходящих коллбэков. При этом итерирование по таблице с добавлением/удалением сразу в двух потоках без должной синхронизации как-то плохо выглядит.
Выходит, что удобно иметь возможность инициировать какой-то коллбэк из потока main, не надо думать про синхронизацию. Пункты 1 и 2 были обсуждением таких возможностей.
Антон, спасибо за предложенные варианты по п.1. Опасения по поводу п.2 понял. Получается, что лучше просить разработчиков реализовать п.1.
swerg, я же не просто так написал, что
Цитата
Надо всё это для того, чтобы можно было выполнять в потоке коллбэков регулярные задачи, которые удобнее и архитектурно правильнее делать там, а не в main.
1) Добавить функцию обратного вызова OnTimer(), которая будет вызываться терминалом с некоторой периодичностью. Надо понять, как указывать период срабатывания. Конкретно для моих задач хватит срабатывания раз в секунду, но мало ли кому чаще надо. Предлагаю обсудить, кому интересно.
Пускай первый раз функция OnTimer() запускается сразу после OnInit() и возвращает число число миллисекунд, через которое будет сделан следующий вызов функции OnTimer(). Если возвращается не число, то пусть следующий вызов будет через 1 секунду.
Реализация на стороне терминала кажется несложной.
2) Дать пользователю возможность из main-потока подать команду на запуск своей функции в потоке коллбэков. Нормальное название не придумал, но надо что-то типа
Код
executeAsCallback(function() ... end)
В принципе, имея п.2, пользователь сможет самостоятельно реализовать п.2, если только в main-потоке не выполняются тяжёлые вычислительные задачи.
Надо всё это для того, чтобы можно было выполнять в потоке коллбэков регулярные задачи, которые удобнее и архитектурно правильнее делать там, а не в main.
Функция возвращает таблицу Lua с параметрами таблицы «Позиции по деньгам».
В случае ошибки функция возвращает «nil».
Что за ошибка у вас или не у вас возникает -- неясно, но раз в документации написано, что может быть nil, это надо предусматривать. Но осадочек остаётся, согласен.
Про особенности национальной DestroyTable и, вообще, о корректной работе с окнами в QLua написал бы кто-нибудь хороший мануал с примерами и объяснениями, почему именно так надо. И на форум выложить на память и для начинающих. Или уже есть где такое в интернете?
Ваше пожелание зарегистрировано, мы постараемся его рассмотреть. Впоследствии, по результатам анализа, будет приниматься решение о реализации пожелания в будущих версиях ПО.
Вот тоже самое хочется сказать. Похоже, очередной выпуск на пенсию состоялся. Варились в собственном соку 40 лет да так, что протухли уже.
Я только одним утешаюсь: если начать торговать по-крупному на свои деньги, то с таким психологическим бэкграундом разорение будет весьма быстрым, после чего посты на форуме закончатся.
Можно довольно простую программку сделать для приема дде-соединения ради только имен столбцов.
Я не умею, да и разбираться с устаревшими технологиями как-то не хочется.
Цитата
А давайте другого пожелаем, чтоб нам дали функцию в луа типа STRING getClassParameters(STRING classcode). А то как-то непорядочек, количество параметров в getClassInfo есть, а самих их негде взять.
Цитата
Я другое хотел предложить: возвращать таблицу вида: {["Имя параметра"] = "Формальный заголовок", } Но не знаю, насколько это юзабельно, поэтому не стал
Наверное, это неплохие варианты. Надобность в таком, по-видимому, будет редкая (один раз запустил и всё). Как сделать по уму и наиболее просто, пусть разработчики подумают.
при временных остановках никто о них не думает и не меняет в них 1 на что-то другое
Да, бирже пофиг на это. В крайнем случае, она вас за неэффективные транзакции оштрафует. Трейдер за всё в ответе, даже если не виноват. :)
А если серьёзно, то для ликвидных инструментов можно отслеживать количество сделок по классу или по классу+инструменту. И если в последние, скажем, 10 секунд нет ни одной сделки, полагаем, что торговля остановлена. Для неликвидных инструментов это будет плохо работать, понятное дело.
Похоже, что параметры "Мин." и "Макс." -- это что-то непонятное, а для акций TQBR и облигаций TQOB параметры "Мин. возм. цена" и "Макс. возм. цена" просто не транслируются.
Ещё вопрос, почему при запросе параметра last для TQBR и SBER за 10 минут до начала торгов мы видим нули:
Во прямо сейчас я вижу в ТТТ для класса RTSIDX и инструмента RTSI значения Мин. 1151,45 и Макс. 1165,58, но внутри QLua эти значения пока не смог получить.
А в потоке котировок для Акций вообще нет параметров Макс. и Мин. (есть Максимальная цена сделки и Минимальная цена сделки, но это же не то, кажется), при том, что сервер квик на аутсорсинге у Арки стоит и должен быть настроен как надо.
И как понять название параметра на английском, если в справке они перечислены в разделе про QPile, а он уже не обновляется? Как называются параметры "Мин." и "Макс." внутри Qlua?
Не пора ли перенести эти описания в справку QLua и актуализировать?
Продолжим тему. Получается, что в Lua-скрипте для получения верхней границы цены надо писать примерно так:
Код
local paramName = "priceMax"
if classCode == "TQBR" or classCode == "RTSIDX" then
paramName = "Max" -- тут точно такое название параметра???
end
local param = getParamEx(classCode, secCode, paramName)
Какие ещё коды классов помимо TQBR и RTSIDX надо указать, чтобы это всё работало корректно?
Я понимаю, что нельзя гарантировать, что в терминале есть вся последняя информация с биржи. Но трудно писать код, когда ты проверил в if условие, что всё должно быть хорошо, а после then всё сразу стало плохо (ситуация поменялась). Нет атомарности.
Вот и приходится без проверки всяких условий isConnected() делать какой-нибудь getXXX(), а потом проверять заполненность полей таблицы внутри результата, потому, что с очень малой вероятностью "что-то пошло не так".
Может, я что-то не до конца понимаю, и мне кто-нибудь прояснит ситуацию по приведённым ниже пунктам.
1) isConnected(), конечно, хорошая функция, но мне кажется, что её корректное использование таково: если она вернула 0, то разработчик может предусмотреть запрет на выполнение каких-то действий в скрипте, поскольку информация в терминале не соответствует действительности (устарела). А вот если isConnected() вернула 1, то это ничего не гарантирует: может, нужные шлюзы ещё не подключены, может информация не до конца загрузилась с сервера. Т.е. мы можем избежать гарантированных ошибок при isConnected() == 0, но не сделать ошибок при isConnected() == 1 эта функция не помогает.
2) При разрыве соединения и повторном подключении терминала к серверу в какой-то момент происходит пропадание информации в ТТТ (и других) и её повторное появление. При работе скриптов в момент "пропадания" информации справочные функции типа getSecurityInfo() могут вернуть пустые таблицы. Это приводит к тому, что скрипт, скажем, читает информацию о размере лота, а там его нет. Неприятно.
По второму пункту хотелось бы понять, как избежать постоянных проверок, что информация отсутствует. Возможно, что при перезагрузке данных в таблицах имеет смысл блокировать запросы к функциям типа getSecurityInfo(), пока они не могут вернуть данные. Пусть скрипты подождут на этой блокировке.
Может кто поделиться своим опытом по данному поводу? Из каких ещё функций, кроме getSecurityInfo(), будут получаться пустые таблицы в моменты перезагрузки данных? Могут ли разработчики прокомментировать это (и отразить в документации, что возвращается, если нет данных)?
В начало функции поставьте проверку на nil и выводите сообщение (через message, например, или в лог, если он у есть). При работе со вложенными массивами/таблицами часто бывает, что забыли внутренние структуры инициализировать.
Цитата
Я уже до ручки дошёл: перед вызовом функции обуваю аргумент в tostring, а внутри функции переворачиваю его в tonumber - пофиг: "attempt to concatenate a nil value (local 's')".
Тут же явно на nil намёк.
Можно ещё всё в xpcall завернуть и печатать стек, чтобы было понятно, откуда вы попали со значением nil. Пример, как это обычно делается в моём коде приведён ниже. При любой ошибке видно, где она произошла.
Код
logger:info("STARTED")
local status, errMessage = xpcall(function()
if isConnected() ~= 1 then
local msg = config.name .. " is not connected on start. Shutdown."
logger:error(msg)
else
initialize()
run()
end
end, function(err)
logger:error(tostring(err))
logger:error(debug.traceback())
end)
if not status and errMessage ~= nil then
logger:error(errMessage)
end
Владимир, рекомендую прежде чем возмущаться, ознакомиться с учебниками по языку Lua, раз уж приходится на нём программировать в терминале. Также можно почитать информацию о динамически типизируемых языках и зачем так сделали их создатели.
Хотите узнать тип переменной -- есть функция type(переменная), которая возвращает строку с названием типа.
Если tonumber возвращает nil, значит аргумент не может быть представлен в виде числа.
Если вы, как программист, пишете что-то в переменную, то из логики приложения должно быть понятно, что именно туда записывается.
Винить кого-то в своих ошибках -- самый простой способ, конечно.
1) Некорректная работа кнопки «max» в специализированной форме ввода заявки.
2) Фильтр по времени в настройках графика теперь недоступен при использовании интервалов длительностью в «День», «Неделю» и «Месяц».
3) Зависание программы при вызове функции QLUA DestroyTable.
4) В некоторых случаях создание таблиц «Позиции участника по деньгам» и «Позиции участника по инструментам на выбранных счетах» было недоступно.
5) В некоторых случаях в таблицах «Позиции по инструментам» отображались дубликаты позиций.
6) Некорректное автозаполнение полей торгового счета и кода клиента в панели торговли таблицы котировок.
7) В некоторых случаях программа аварийно завершала работу при запуске.
8) Некорректная работа фильтра классов и инструментов Таблицы обезличенных сделок.
9) Программа аварийно завершала работу в некоторых случаях после разрыва связи с сервером QUIK и последующим восстановлением соединения.
10) В некоторых случаях оценка позиций в таблице «Состояние счета» выполнялась по инструменту некорректного класса.
11) В некоторых случаях на форме ввода заявки рассчитывался некорректный объём комиссии.
12) На форме ввода заявки FX-плагина рассчитывался некорректный объём комиссии.
13) В некоторых случаях программа аварийно завершала работу.
14) Для индикаторов на LUA значения параметров свечей не учитывали младшие разряды, если они равны «0».
15) Некорректная работа программы на Windows Server 2003.
16) В некоторых случаях не отображались имеющиеся позиции по деньгам и инструментам.
17) Программа аварийно завершала работу при работе скриптов на LUA с данными графиков. Набор функций для работы с данными графиков описан в пункте 3.10 Руководства пользователя LUA – Интерпретатор языка LUA / 3. Функции взаимодействия скрипта LUA и Рабочего места QUIK / 3.10 Функции для работы с графиками.
Поэтому для таких задач все же рекомендуем рассмотреть вариант работы с таблицей обезличенных сделок, она в этом плане точнее и актуальнее. Биржа гарантирует хронологический порядок записей в данной таблице. Если же наблюдается обратное, это повод обратиться к брокеру, потому что такое поведение некорректно.
Если в таблицу обезличенных сделок добавить классы TQBR и SPBFUT, то можно убедиться, что время не будет монотонным. Внутри класса TQBR -- да, а всё вместе -- нет, т.к. эти классы торгуются в разных биржевых системах.
Я не проверял ещё, что после нововведений на срочном рынке внутри класса SPBFUT время останется монотонным. Возможно, что сейчас это пока так, но сохранится ли это в будущем -- неясно.
Интересует, исправлены ли ошибки, упомянутые тут: https://forum.quik.ru/messages/forum10/message48049/topic5119/#message48049 Хоть это и не мои ошибки, внимательное чтение сообщений на форумах подсказывает, что основные причины проблем именно там. Потом эти проблемы могут по-разному проявляться у разных пользователей.
Повторю, что я сам не знаю, как стабильно воспроизвести ошибку. Поэтому высылать код скрипта не имеет смысла.
В дополнение могу лишь свои домыслы высказать. Терминал несколько раз аварийно завершал свою работу с дампами памяти (вам отосланы). Вполне возможно, что в эти моменты были испорчены данные по графикам. После перезаказа данных и отработки логики, описанной вами выше в теме, "битая" часть графиков ушла в архив. Пока она не будет удалена руками или по превышению 65 тыс. свечей, будет проявляться описанная мною выше проблема.
Резюмируя гипотезу: из-за ошибки в другом месте (аварийные завершения работы терминала) получаются "битые" графики, которые потом портят нормальную работу.
Есть косвенные признаки того, что в терминале 8.8.4.3 (и, возможно, других версий) могут получаться "битые" графики при склейке 3000 свечей, которые выдаёт сервер, и архива свечей, накопленных в терминале.
Проявляется это как ошибки в скриптах при работе с данными, получаемыми из объектов DataSource. Выходят сообщения типа
Код
attempt to perform arithmetic on a nil value (field '?')
хотя код до этого нормально работал несколько дней.
Как стабильно воспроизвести ошибку я не знаю. Помогает закрытие терминала, удаление dat-файлов из папкок archive и archive\bak, повторный запуск терминала. История сбросится до 3000 свечей в этом случае.
Перезаказ данных с указанием всех галочек не помогает.
Вопрос к разработчикам: когда будет очередной релиз терминала или нам придётся торговать 14 сентября с помощью 8.8.4.3, про который ТОЧНО известно, что там РЕГУЛЯРНО происходят аварийные завершения работы из-за QLua?