Старатель написал: если открыто два одинаковых (инструмент, таймфрейм) графика на диаграмме (или через CreateDataSource)
Если первый график отрыт на диаграмме или через CreateDataSource, то индикатор, переставляющий метки на втором графике (с тем же инструментом и таймфреймом), теряет свои метки.
Надо делать так, как надо. А как не надо - делать не надо.
Есть такой баг (CQ01954637), добавленный после v.7.5: если открыто два одинаковых (инструмент, таймфрейм) графика на диаграмме (или через CreateDataSource), то на втором (тот, который открыт вторым) при попытке изменить метку через SetLabelParams, индикатор теряет свою метку. Возможно, есть связь с одной из ваших проблем.
Надо делать так, как надо. А как не надо - делать не надо.
TGB написал: вариант нейтрализации этой ошибки на уровне разработчика скриптов (все же, требующий нетривиального анализа и, возможно, дополнительного изменения кода скрипта при каждой его редакции)
Часто ли вам требовалось использовать этот вариант?
Старатель написал: Это позволяет скриптеру писать байткод-циклы (в текущей версии QLua 5.3/5.4), выполняющиеся атомарно (читай потокобезопасно). При реализации вашего пожелания на уровне QLua скриптер лишится такой возможности.
Я не против, если скриптер будет иметь контроль, например заданием переменной из скрипта: если счетчик задан, то снимать лок, через заданное количество циклов. Если не задан, то - без изменений. Как то так.
Надо делать так, как надо. А как не надо - делать не надо.
Тогда правильно ли я понимаю, что первичными ключами для таблиц являются: для заявок: order_num, class_code для сделок: trade_num, order_num, sec_code для обезличенных сделок: trade_num, sec_code, class_code ?
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: На некоторых рынках есть классы в которых нумерация заявок идет в разрезе инструментов, а не классов. Т.е. есть ситуации когда у разных инструментов одного класса номера заявок могут совпадать. И при этом это совершенно разные заявки
Получается для корректной работы функции getOrderByNumber нужно было добавить ещё код бумаги.
Надо делать так, как надо. А как не надо - делать не надо.
TGB написал: Вопрос по существу может быть таким: «упрощают ли предлагаемые средства разработки программ жизнь пользователя или нет? И в какой степени?».
По моему мнению все "нововведения", которые удаляют или затрудняют работу текущего функционала, только ухудшают "жизнь пользователя". https://forum.quik.ru/messages/forum10/message40996/topic4921 https://forum.quik.ru/messages/forum13/message40352/topic4830 Кому-то захотелось так сделать, потому что он посчитал, что ему лично так будет удобно. Программисты выполнили его хотелку, и в результате ухудшили жизнь другим. Если что-то радикально менять, то это должен быть опциональный вариант.
Надо делать так, как надо. А как не надо - делать не надо.
Дмитрий написал: 2) Есть еще проблема, которая тянется с предыдущих версий. При запущенном терминале если долго не пользоваться компом и при уходе его в какой-либо из режимов энергосбережения (например Гибернация), то при последующем выводе из режима Квик либо оказывается подключенным к серверу, либо нет. Если нет, то висит окно: "Net error: Удаленный хост принудительно разорвал существующее подключение". При этом в меню программы вместо "Установить соединение" остается доступным только вариант "Разорвать соединение" (словно оно по прежнему еще установлено). И никаких вариантов кроме как перезагрузить Квик нет. Но это еще не все. Кликнув на закрыть Квик, имеем исчезнувшее окно программы. Но в Диспетчере задач Win10 по прежнему продолжает висеть сколь угодно долго процесс "Рабочее место информационно-торговой....". И если его принудительно не завершить, то Квик больше не запустить.
Старая проблема. В информационном окне в состоянии соединения пишет: "устанавливается". Но раньше, вроде, можно было хоть вручную подключится. Теперь, если нажать кнопку "Разорвать соединение", то кнопки "Установить соединение", "Разорвать соединение" становятся неактивными. Если попытаться открыть какое-либо окно, то QUIK повесится.
Надо делать так, как надо. А как не надо - делать не надо.
Проблема в том, что перед добавлением/удалинием элементов происходит перебор элементов таблицы в цикле для поиска нужного индекса. Если нужный элемент найден, а другой поток удалит элемент с меньшим индексом, то индексы сдвинутся и получится ерунда, т.е. нужно синхронизировать потоки.
Поскольку вы используете потокобезопасные функции, то добавление элемента в конец таблицы (именно такая запись без указания индекса table.sinsert(Trades, trade)) не влечет каких-то неприятных последствий.
Надо делать так, как надо. А как не надо - делать не надо.
Если функция передается в качестве аргумента, то в debug.getinfo(1).name будет имя не самой функции, а имя аргумента.
Код
local function local_comparator(lhs, rhs)
local t = debug.getinfo(1)
message('local_comparator name is ' .. (t.name or 'nil'))
return true
end
function f(arg) arg() end
f(local_comparator) -- MSG: local_comparator name is arg
Есть способ узнать имя функции?
Надо делать так, как надо. А как не надо - делать не надо.
Андрей написал: обеспечьте надежный способ отличать, заполнено поле уже или нет. Незаполненное поле не должно иметь значение, валидное для заполненного.
Цитата
Андрей написал: для незаполненных тогда просто не возвращать поле (=nil).
Sergey Gorokhov, надёжный способ вам предложили, отрицать очевидное бессмысленно. Теперь вы врёте, всячески изворачиваетесь и бросаетесь из крайности в крайность, пытаясь оправдать своё безделие.
Цитата
Sergey Gorokhov написал: сам терминал подключен к серверу тоже до начала торгов
Так это существенное ограничение. А в 9-10 часов теперь подключать нельзя?
Тогда уж указывайте в Руководстве "идеальные условия", для которых предназначен QLua, и соответствующие ограничения.
Надо делать так, как надо. А как не надо - делать не надо.
TGB написал: Бывают ситуации зависания в QLua, когда основной поток обслуживания колбеков всех скриптов пользователя, а также таблиц QUIK (это не таблицы Lua), блокируется выполнением длинного цикла пользовательской программы на «чистом» Lua, в котором нет ни вызова seep ни вызова других C-функций.
Держите и вы от меня "шайбу":
Цитата
Старатель написал: чтобы не было зависаний, можно вставить внутрь цикла любую с-функцию (не обязательно sleep). Причём, вставлять можно не на каждую итерацию, а через заданное количество циклов. Это позволит не подвешивать основной поток и при этом сохранить скорость вычислений байткода в циклах.
Надо делать так, как надо. А как не надо - делать не надо.
TGB написал: В документе разработчика QUIK: «Использование Lua в Рабочем месте QUIK.pdf», в разделе «2. Взаимодействие потоков Lua скрипта» описана рекомендуемая схема обработки колбеков.
Иногда в скрипте требуется что-то большее, чем просто в одном потоке засунуть значение в табличку и вытащить его в другом.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Данные не появились - сидим ждем дальше.
Цитата
Sergey Gorokhov написал: Почему не рабочий? Ведь им пользуются значит рабочий.
Именно таким вариантом не пользуется никто. Эта моделька, где скрипт рвется в бой сразу после получения хотя бы одной позиции в depo_limits. В результате в большинстве случаев получает фальстарт. В вашем варианте в большинстве случаев вы так и будете сидеть ждать на старте, пока вам не дадут хорошего пинка, т.е. пока кто-то не откроет позиции (или хотя бы не выставит заявки) по всем инструментам, которыми торгует скрипт.
Цитата
Sergey Gorokhov написал: В идеальных условиях и вопроса о признаке бы не возникло, не так ли.
Не так. Что такое "идеальные условия" в данном контексте? Это когда позиции загружены на сервер до начала торгов, они верные, не требуют корректировки. Можем ли мы сейчас определить их при "идеальных условиях". Надёжно - нет, вы сами признали. Возможно ли допилить QUIK таким образом, чтобы позиции можно было бы надёжно определить в "идеальных условиях". Да:
Цитата
Старатель написал: Уведомление надо посылать клиенту после прокачки лимитов, тогда скрипт узнает об окончании прокачки по этому уведомлению.
Цитата
Sergey Gorokhov написал: Вопрос был что надежней. Только внештатные ситуации и могут дать ответ на этот вопрос.
Сравнивать надежность во внештатных ситуациях имело бы смысл, если бы ваш вариант надёжно работал в штатной ситуации или, по крайней мере, не хуже предложенной ТС.
Надо делать так, как надо. А как не надо - делать не надо.
Sergey Gorokhov написал: Да благодаря sys_events скрипт будет знать что на сервере все лимиты есть и опять же скрипту придется ждать прокачки данных (то что и сейчас) Но опять же скрипт не узнает когда эта прокачка закончится
Уведомление надо посылать клиенту после прокачки лимитов, тогда скрипт узнает об окончании прокачки по этому уведомлению.
Цитата
Sergey Gorokhov написал: Для примера, "плохие" варианты уже были озвучены:
Цитата
Sergey Gorokhov написал: Допустим брокер загрузил пачку, isLimitsLoaded вернет true, а именно Ваши лимиты брокер не загрузил, а загрузит их чуть позже. Ваш код в этой ситуации примет решение что лимитов нет (нулевые) а на самом деле они будут позже.
Если брокер загружает лимиты посреди сессии, то - это внештатная ситуация.
Sergey Gorokhov написал: А значит, Вам легко может приехать строка содержащая 0, а потом через некоторое время нормальное значение.
Это скорее исключение, чем правило. У подавляющего числа пользователей этого не случится никогда. А вообще "плохие примеры" притянуты за уши и абсолютно ничего не доказывают.
Цитата
Sergey Gorokhov написал: Вариант которые уже сейчас решает вопрос уже был предложен Ждите колбек или смотрите в цикле. Данные появились - хорошо работаем Данные не появились - сидим ждем дальше.
Этот вариант не рабочий от слова совсем.
Надо делать так, как надо. А как не надо - делать не надо.
TGB написал: Текст данного комментария со Старателем не согласован, но надеюсь, что если, по его мнению, я написал что-то не то, он меня поправит. --------- Предложение1 (от Старателя). Мое краткое описание ситуации, устраняемое при реализации предложения Старателя, а далее цитаты. Бывают ситуации зависания в QLua, когда основной поток обслуживания колбеков всех скриптов пользователя, а также таблиц QUIK (это не таблицы Lua), блокируется выполнением длинного цикла пользовательской программы на «чистом» Lua, в котором нет ни вызова seep ни вызова других C-функций. ---- Далее цитирую Старателя: «Если цикл продолжительный, чтобы не было зависаний, можно вставить внутрь цикла любую с-функцию (не обязательно sleep). Причём, вставлять можно не на каждую итерацию, а через задан-ное количество циклов. Это позволит не подвешивать основной поток и при этом сохранить ско-рость вычислений байткода в циклах.». --- Далее цитирую себя: Комментарий 1. «То, что предлагает Старатель, наверное, имеет смысл реализовать в самом QLua.
Всё же вставлю свои "пятькопеек". В текущей реализации QLua (5.3/5.4) задача легко решаема на уровне пользовательского скрипта методом, предложенным мной выше, что позволяет при необходимости снять блокировку в любом месте цикла. Это позволяет скриптеру писать байткод-циклы (в текущей версии QLua 5.3/5.4), выполняющиеся атомарно (читай потокобезопасно). При реализации вашего пожелания на уровне QLua скриптер лишится такой возможности.
Надо делать так, как надо. А как не надо - делать не надо.
Доступ к Settings.line из кода индикатора, Пропадает доступ к массиву line структуры Settings в индикаторе после добавления индикатора на график и последующего изменения какого-либо параметра.
Сирануш написал: он некорректно получает данные, из соседних таблиц.
Скрипт получает позиции только по тем бумагам, которые запрашиваются в нём самом и других скриптах. Если работает только 1 скрипт, то позиций по другим бумагам он не получает.
Надо делать так, как надо. А как не надо - делать не надо.
local run = true
function OnStop()
run = nil
end
function main()
while run do
getBuySellInfoEx(FIRM_ID, CLIENT_CODE, CLASS_CODE, SEC_CODE, 0)
-- или
--CalcBuySell(CLASS_CODE, SEC_CODE, CLIENT_CODE, ACCOUNT, 0, true, true)
sleep(1)
end
end
local run = true
function OnStop()
run = nil
end
function main()
local pos
while run do
local fut_pos = getFuturesHolding(FIRMID, ACCOUNT, SEC_CODE, TYPE)
if type(fut_pos) == "table" then
local totalnet = fut_pos.totalnet
if pos ~= totalnet then
message(SEC_CODE .. ": pos = " .. tostring(pos) .. "\n" .. fut_pos.sec_code .. ": totalnet = " .. tostring(totalnet), 3)
pos = totalnet
end
else
message("getFuturesHolding error", 3)
end
sleep(1)
end
end
Скрипт 2
Скрытый текст
Код
local run = true
function OnStop()
run = nil
end
function main()
while run do
getFuturesHolding(FIRMID, ACCOUNT, SEC_CODE, TYPE)
sleep(1)
end
end
Запускаем скрипт 1 и несколько скриптов 2 по разным бумагам. Любуемся результатом.
Возможно, другие функции getЧегоТоТам также работают нестабильно. Проверяйте сами.
Надо делать так, как надо. А как не надо - делать не надо.
Сирануш написал: У меня в районе 50 скриптов висят
Т.е., более одного скрипта запрашивают позиции по разным бумагам.
Скрипт 1:
Скрытый текст
Код
local run = true
function OnStop()
run = nil
end
function main()
local mLots
while run do
local tblTotalLot = getDepoEx(FIRM_ID, CLIENT_CODE, SEC_CODE, ACCOUNT, LIMIT_KIND)
if type(tblTotalLot) == "table" then
local TotalLots = tblTotalLot.currentbal
if mLots ~= TotalLots then
message(SEC_CODE .. ": mLots = " .. tostring(mLots) .. "\n" .. tblTotalLot.sec_code .. ": currentbal = " .. tostring(TotalLots), 3)
mLots = TotalLots
end
else
message("getDepoEx error", 3)
end
sleep(1)
end
end
Скрипт 2:
Скрытый текст
Код
local run = true
function OnStop()
run = nil
end
function main()
while run do
getDepoEx(FIRM_ID, CLIENT_CODE, SEC_CODE, ACCOUNT, LIMIT_KIND)
sleep(1)
end
end
Запустил скрипт 1 по "SBER" и несколько скриптов 2 по другим бумагам. В итоге Скрипт 1 стал получать позиции не только по "SBER", но и по другим бумагам из других скриптов.
Скрытый текст
Причём эта ошибка более частая, чем "getDepoEx ничего не возвращает", и возникает в офлайн.
Надо делать так, как надо. А как не надо - делать не надо.
Egor Zaytsev написал: Вы пишите, что getDepoEx ничего не возвращает
Эта проблема легко воспроизводится скриптом, опубликованном мной в сообщении #59
В скрипте Сирануш в том случае, если getDepoEx ничего не возвращает, присваивает значению текущего остатка ноль. Поэтому для него "getDepoEx ничего не возвращает" = "ошибка текущего остатка", если по факту позиция открыта. Если позиция закрыта, то этой ошибки в его скрипте не будет.
Цитата
Egor Zaytsev написал: пользователь Сирануш пишет, что у него ошибка текущего остатка
Что касается левых значений в currentbal, то, вероятно, это может быть связано с открытыми позициями, их количеством, классами, сроков расчётов и пр. факторами. Т.ч. договаривайтесь с ТС о копии рабочего места.
Надо делать так, как надо. А как не надо - делать не надо.