Старатель написал: или нет? О каких разных конфигурациях вы пишите, когда эта проблема общего характера. И рассматривать её надо не в частном порядке.
Часто пользователю мерещится, что возникшая у него ошибка - ошибка самого общего характера. проявляющаяся у всех, ведь он жмет на единственную красную кнопку на пульте. Казалось бы, все жму на эту кнопку, а значит проблема имеет общий характер, кнопка не работает, очевидно же! Однако в таких ситуациях не редко оказывается так, что ошибка эта вовсе не носит общего характера, даже при наличии единственной кнопки на пульте, а проявляется лишь в редких экзотических условиях.
Это я вам как коллега коллеге подсказываю.
Я к тому, что, как это модно говорить, "просьба отнестись с пониманием" к запросам о помощи Миру мир и всё такое.
Я подозревал, что это "не новое", видимо везло не сталкивался
Из той ветки:
Цитата
Старатель написал: 3. Если очень хочется, то вместо getScriptPath() можно использовать
Код
getWorkingFolder () .. "\\LuaIndicators"
Уточнение: это не эквивалентно, учитывая, что сканируются все вложенные папки, что позволяет индикаторы (если это удобно) складывать не непосредственно в LuaIndicators, а во вложенные в неё папки (удобно, если индикатор состоит из многих файлов или это некое семейство индикаторов по какой-то теме). Именно поэтому я и начал использовать getScriptPath, а с ним такое вот приключение...
в принципе да, вы мне подсказали вашим сообщением вариант как это объехать. Спасибо. Однако я не понимаю что мешает простую (по функционалу) функцию getScriptPath() сделать корректно работающей в этот момент.
Код тестового индикатора ниже. Кладем в папку LuaIndicators, вызываем диалог добавления графика (индикатора). В окне сообщений выводится: {}
Т.е. наш скрипт вызвался, но getScriptPath() вернула пустое значение. Это явно ошибка.
Добавим этот индикатор. В окне сообщений выводится: {} {D:\Quik-Junior\LuaIndicators} <D:\Quik-Junior\LuaIndicators>
Т.е. индикатор сначала выполняется, но getScriptPath() вернула пустое значение. Потом индикатор еще раз выполняется, но тогда уже getScriptPath() вернула правильное значение.
Проблема в том, что первоначальное выполнение, когда только открывали диалог - getScriptPath() вернула пустое значение, а значит индикатор не смог корректно отработать, если в нем используется getScriptPath(), и не добавился в диалог выбора индикатора.
Надо исправить эту ошибку.
Код
Settings = {}
Settings.line = {}
Settings.Name = "*swerg_test"
Settings.line[1] = {}
Settings.line[1].Name = "swerg_test"
message("{".. getScriptPath() .. "}")
function Init()
message("<".. getScriptPath() .. ">")
return 1
end
function OnCalculate(idx)
return 5
end
Причем тут даже не понятно что требовать от QUIK-то. В самом деле, предположим реализована схема "подписался на данные - передал call-back". Но когда это call-back должен вызваться? а) когда данные по подписке проехали - а толку? это ж не актуальные данные; не говоря уж о том, что данных объективно этих может не быть (неликвид) б) когда данные по подписке все доехали - так этого момента никто и не знает.
И как быть? в самом деле, реализацию какого функционала требовать от QUIK? у меня нет идей, увы
Старатель написал: Но в скриптах почему-то неактуальность цифры становится принципиальной. Но почему?
Разное время реакции. Пока трейдер примет решение, котировка поменяется. А скрипт: получил котировку - выполнил действие.[/QUOTE]
Ну т.е. грубо говоря нужен функционал: 1) подписались на новые данные 2) взвели признак (таймер) "позови функцию2" через 1 сек (условный интервал типичной актуализации данных) 3) вышли из функции 4) через секунду считаем, что данные приехали - на этом основании получаем данные и принимаем решение.
Здесь мне видится принципиальным пункт 3), дабы не подвешивать QUIK на sleep() и точно дать ему обработать полученные данные.
Я про то, что QUIK (да и не только) в принципе ведь не позволяет вам узнать актуальные сейчас вы видите данные в терминале или нет. Просто считается что если человек что-то видит - то он принимает на этом основании решение - и это как бы никого не парит (хотя данные могут быть вовсе не актуальными). А вот при автоматизации почему-то непременно начинает всех волновать актуальность данных.
Так может вопрос лишь в подходе к написанию скрипта? Я прекрасно понимаю, что хочется писать скрипт максимально просто и прозрачно, я и сам так делаю: - подписался на данные - прочитал данные - вычислил формулы - принял решение
А область видимости вы как определяете? Или плюс-минус эмпирически подобрали по используемый вами масштаб? Хотя, если двигать график влево-вправо... То как?!
С первого сообщения пытаюсь объяснить. Если параметр уже заказан (а проверить мы это никак не можем) до запуска скрипта (в ТТТ али другим скриптом), то если брать данные только в OnParam(), придётся ждать следующего обновления параметров. А для неликвидного инструмента это может быть очень не скоро. Глядишь к концу сессий чё-нить дождёмся... А если вызывать getParamEx2 до прихода OnParam(), то нет гарантии, что там не старьё.
Суть проблемы мне понятна, и я с вами согласен, что все это очень не гладко.
Однако, если посмотреть вот с какой стороны. В описанной ситуации откроем в терминале таблицу параметров. Она нам что-то покажет (т.к. когда-то данные были), какую-то цифру мы увидим. Актуальная это цифра или нет? когда она изменилась? когда приедет актуальное значение? Ведь никого это не волнует, правда? Видим цифру - отлично, с ней работаем. Но в скриптах почему-то неактуальность цифры становится принципиальной. Но почему? Это не в плане с пора с вами, это просто понять, порассуждать.
Евгений написал: Если бы каждый график или хотя бы вкладка были в отдельных потоках проблема думаю бы решилась
Так не бывает в Windows. Ну вернее так: можете посмотреть на Google Chrome, он так сделан (там даже отдельные процессы) и на прожорливоть им ресурсов "как не в себя".
1) Если меток несколько сотен - очевидно, что они маленьгого размера. В этом случае gif будет точно меньшего размера, пересохраните картинки в этом формате. Ну просто для пробы помогает ли это. Хотя проблема скорее в большом количестве меток, а не в формате, но попробовать стоит, думаю.
2) Решит ли замена процесора - в момент перемещения графика посмотрите по диспетчеру задач что нагружается: центральный процессор или видеокарточка. Если ЦП - то замена на более мощный поможет, вопрос только в том "на сколько улучшится".
3) Попробуйте в метки не вставлять картинки, а обозначить (метки) только текстом. Найдите подходящий вам символ - и выводите его вместо картинки. Возможно, это будет быстрее работать.
4) Судя по тому, что меток огромное количество - вы наверняка метками пытаетесь нарисовать какой-то график. Переделайте ваш скрипт в индикатор в таком случае, индикаторы работают побыстрее.
Максим написал: под обычный скрипт, чтобы я его мог запустить в терминале, указав в коде нужную мне бумагу.
Не понятно что вы подразумеваете под этой фразой. Какого результата вы хотите достичь? чтобы "обычный скрипт" нарисовал индикатор? чтобы "обычный скрипт" получил данные индикатора и по ним принял какое-то торговое решение? что-то еще?
swerg написал: Было бы очень здорово, если бы вы приводили нормальный полный код, которым получаете указанное вами.
Уточню: нормальный полный, но минимально возможный для воспроизведения проблемы. Бесплатно 5 страниц текста программы мало кто готов разбирать, так что чем короче полный проблемный код - тем выше шансы на успех получения толковой подсказки.
Kolossi написал: Проверил. Нумерация окон меняется конкретно для каждого скрипта-увеличивается с каждым перезапуском начиная с запуска Квика. Запустив два одинаковых скрипта при помощи перезапусков легко получил окна с одинаковыми идентификаторами. Облом.
Один скрипт выводит все таблицы, включая "сводную", другой кидает ему данные через
Дмитрий написал: function OnCalculate (index) plusdi,n,q = getCandlesByIndex ( "SBAdx" , 1 , 0 , getNumCandles ( "SBAdx" )) -- get +DI table minusdi,n,q = getCandlesByIndex ( "SBAdx" , 2 , 0 , getNumCandles ( "SBAdx" )) -- get -DI table return handler() end
function handler(index) if plusdi[index].close ~= nil and minusdi[index].close ~= nil then [/CODE]
1) Правильно ли, что из plusdi[] и minusdi[] значения берутся по индексу index? Ведь в OnCalculate индексы приходят начиная с 1, а в возвращаемых значениях массивов из getCandlesByIndex индексы начитаются с 0...
Наверное правильно будет plusdi[index-1].close и minusdi[index-1].close ?
2) Про оптимизации. Здесь получается, что мы в каждом OnCalculate получаем все свечи с другого графика через getCandlesByIndex(), после чего берём только какое-то одно значение... думаю будет эффективнее написать так:
plusdi = getCandlesByIndex ( "SBAdx" , 1 , index-1 , 1) -- get +DI table minusdi = getCandlesByIndex ( "SBAdx" , 2 , index-1 , 1) -- get -DI table ... и, соответственно, данные брать как plusdi[0].close и minusdi[0].close
Владимир написал: И подобные Вам программисты, гнущие пальцы с вумным видом и немедленно затыкающие хлебальники при первом же щелчке по носу (как это сделали лично Вы в соседней ветке)
Ты, дурач0к, просто достал своей напыщенной тупостью и некомпетентностью. Об тебя мараться не хочется, потому и бегут подальше и не отвечают на твой идиотизм. А ты, глупенький, решил, что сумел кого-то "по носу" достать. Шел бы ты к своим сверстникам по разуму, в старшую группу детского садика.
Формирование звуковых алертов в таблице ”Оповещения” с помощью Lua, Необходимо автоматическое формирование звуковых алертов в таблице ”Оповещения” для роботов-помощников
Юрий написал: Подключение внешних библиотек трудоёмко и не решает проблему для сетки алертов.
Такого быть не может. Казалось бы, как раз из скрипта можно нагородить сколь угодно сложную систему оповещений. Впрочем, есть есть "сетка алертов" - не понятно.
Старатель написал: Я не понял: наблюдаете или нет? Запустите предложенный скрипт на своём демо.
Согласитесь, то, что речь про демо-сервер - вообще не очевидно было по вопросу. А проблема скорее всего именно в сервере, который не заполняет, потому и важно уточнить какой он.
Вставляя проверялку в каждый интерфейсный метод библиотеки, я о чем я и писал сразу. Оно, конечно, затраты на проверялку копеечные - фактически сравнить несколько интов (чем являются указатели) по готовым адресам, особенно если развернуть и убрать вызовы вложенных красивых функций. Но синтаксически все загромождается и загромождается.
ВиталийКак правило, люди крестят Lua и C++, но не QLua. И как я понял исходя даже из этого форума - это немного разные вещи.
Вообще никакой разницы между Lua и QLua нет. Ну с точки зрения программирования, интерфейсов и т.д. QLua - это Lua с добавленными глобальными функциями грубо говоря, и это характерно для любого реального применения Lua где-либо.
Попробую написать подробнее. Напишу как я вижу структуру волшебной библиотеки. Возможно у вас устроено совсем не так, а как-то иначе и указанной проблемы нет, и вы поделитесь вашей структурой. Все "исходные коды" ниже - условны, без соблюдения всех нюансов синтаксиса, чисто для иллюстрации структуры программы.
Код
var
// глобальные переменные, куда будут загружены адреса функций Lua API
lua_pushstring_addr;
lua_pushnumber_addr;
luaL_checkinteger_addr;
luaL_checkstring_addr;
.... и т.д. ....
function LoadLua53()
begin
h := LoadLibrary('Lua53.dll');
lua_pushstring_addr := GetProcAddress(h, 'lua_pushstring');
luaL_checkstring_addr := GetProcAddress(h, 'luaL_checkstring');
....
end;
function LoadLua54()
begin
h := LoadLibrary('Lua54.dll');
lua_pushstring_addr := GetProcAddress(h, 'lua_pushstring');
luaL_checkstring_addr := GetProcAddress(h, 'luaL_checkstring');
....
end;
function luaopen_XXX(L: Plua_State)
begin
if (ХитраяПроверка(L) = Lua54) then
LoadLua54();
else
LoadLua53();
... далее обычный код для luaopen_XXX, ссылки на нужную версию Lua подгружены ...
luaL_newlib(L, ls_lib);
... и т.д. ...
end;
После чего все реализации функций нашей библиотеки пишем обычным образом (без. доп проверок на версию Lua!)
тогда получится так: - скрипт 1 выполняется в Lua53, загрузил нашу библиотеку. Все адреса в глоб. переменных у нас указывают на Lua5.3 и все хорошо.
- скрипт 1 продолжает работать и запустили скрипт 2, для которого указана Lua54. Наша библиотека это определила (необходимость загрузки Lua54), в глоб переменные загрузила адреса из Lua54.dll И второй скрипт работает корректно. Но первый-то скрипт уже будет ходить совсем "не туда"!
Чтобы это исправить - мы должны иметь две полных структуры адресов Lua-API функций для разных версий Lua и вставлять проверку в каждую функцию библиотеку, доступную для Lua-скрипта, переключаясь на адреса нужной версии Lua для каждой интерфейсной функции нашей библиотеки.... Или у вас так и сделано?
Александр В луа 5.4 lua_version просто возращает версию луа 504 не зависимо от того, для какой версии LuaState. Но в целом можно попробовать пошаманить с этим делом.
Ниже вы приводите результаты ваших исследований, за них вам спасибо.
Засада с этим красивым автоматическим определением будет вот где. (предположим что в принципе оно у нас заработало и нам повезло - бинарно интерфейсы совпали) Если пользователь запустит одновременно два скрипта, использующих такую волшебную библиотеку - ему явно не повезёт. Потому что указатели на функции в Lua53.dll / Lua54.dll вы явно храните в глобальных переменных, т.е. в каждый момент времени в них фактически указатели на какую-то одну версию Lua. И даже если разнести указатели в 2 разные структуры по версиям Lua - то придётся в начало каждой интерфейсной функции вставлять хитрую проверку версии переданного стека, а потом еще хитро переключаться на соответствующую версию структуры указателей на функции Lua-API в рамках этой функции, вызванной внутри библиотеки.... Как-то это уже слишком, по-моему.
АлександрНе подходит, т. к. в Lua 5.4 lua_version просто возвращает номер версии, а при передаче в luastate от Lua 5.4 в функцию lua_version от Lua 5.3 происходит ACCESS_VIOLATION.
А, ну и славно, вот и проверили, бинарно не совместимы версии.
Я немного не понял: я вам чем-то обязан, что вы позволяете себе писать именно так? Я писал выше, вариант один: две разные dll для разных версий Lua. Как их загружать в скрипт при условии, что пользователь может выбрать одну из версий Lua - не знаю. Видимо раскладывать dll разных версий Lua по разным папкам и с путями в скрипте играться в зависимости __VERSION, или имена разные давать dll для разных версий Lua и опять же подгружать нужную библу.
Чтобы использовать lua_version надо загрузить нужную dll. Возникает вопрос какую версию dll брать?
Вы не сделаете динамическую загрузку DLL нужной версии. Во-первых потому, что нет интерфейса для понимания того, на какой Lua-стек вам передали указатель, а во вторых потому, что вполне вероятно (но это надо дотошно проверять), что отдельные интерфейсные структуры в 5.3 и 5.4 версиях - разные. И в этом случае вы просто не сможете сделать бинарно совместимые версии dll. Вот и остаётся нам максимум - это проверить, что dll собрана под ту версию Lua, для которой она собрана. Фиговую какашку нам подсунули разработчки QUIK, да. Ведь фактически нельзя теперь просто положить dll в каталог с QUIK и использовать её спокойно, ведь в зависимости от версии Lua, заданной для скрипта, dll либо поедет, либо не поедет.... Да ужж...
Цитата
В луа 5.4 lua_version просто возращает версию луа 504 не зависимо от того, для какой версии LuaState.
Эту фразу не понял. Если вы скомпилировали вашу библиотеку (или динамически подгрузили) lua54.dll - то она вам и вернёт всегда 504 из lua_version. Т.к. эта функция просто возвращает вкомпилированную константу (см. исходники), на LuaState она не смотрит.
TGB, чем вас не устраивает отдельная ветка обсуждения ваших проблем? зачем вы в каждой ветке обсуждаете свою проблему, притом что эта проблема никак не связана с темой ветки? Это так, замечание на будущее.
Цитата
TGB Для обработки всех скриптов пользователя создается один служебный поток (под потоком здесь и далее понимается поток Windows).
В Windows есть понятие "основной поток приложения". В нем и происходит все то, что вы называете "в служебном". Здесь есть картинка https://quik2dde.ru/viewtopic.php?id=16 (замечу что картинку эту ARQA стырила и включила в свою документацию, предварительно формально перерисовав, не спросив ни разрешения, ни даже хотя бы не сказав "спасибо")
Цитата
TGB Известно, что нативные версии Lua однопоточные. Управление автоматической памятью в них тоже однопоточное. Поэтому при внедрении версий Lua в QUIK требуется, наверное, много чего, но, как минимум, необходима переработка автоматического управления памятью с целью обеспечения ее потокобезопасности. И это сложная задача.
..., полностью решённая в исходниках Lua. Там просто можно включить режим сборки "многопоточный". Ну так, если совсем упрощённо. Так что всё "от производителя".
Цитата
TGB Моя программа, на которой «падает» QUIK, тестирует автоматическую память QLua. Похоже, что эта память реализована некорректно, а значит в любых скриптах, в произвольные моменты времени могут возникать ошибки. Так как мой тест специально создает очень большую нагрузку на управление автоматической памятью, то ошибки возникают в течении 2-3 минут. При обычной работе эти ошибки возникают реже и могут проявляться в разных местах.
Я не смотрел вашу программу, однако могу предложить другое объяснение: ваша программа портит память процесса QUIK, после чего он падает. Или подгружаемые вами DLL содержат потоконебезопасный код, из-за которого опять же QUIK падает. Если бы на самом деле управление внутренними хранилищами QUIK было столь потоконебезопасным, то падали бы и обычные скрипты, которые могут нагрузить "автоматческую память" ничуть не хуже. Всё же согласитесь, какого-то тотально-массового падения скриптов QLua явно не наблюдается.
Надеюсь, ответ на вопрос 2) вы теперь сами знаете?
Хотелось бы уточнить у тех. поддержки про новую версию 8.11:
1) Зачем остался в дистрибутиве (в обновлении) файл lua5.1.dll ? как он функционирует?! Вроде его планировали убрать.
2) В списке исправленных недоработок есть несколько пунктов про Lua (пункты 10, 11, 12, 13) Подразумевается, что указанные в них проблемы исправятся только при использовании Lua 5.4 ? или для Lua 5.3 они исправлены тоже?
Делайте сразу расчет портфеля на Lua по вашим формулам. Даже не тешьте себя надеждой, нужная вам формула когда-либо появится в QUIK. Там очень своё видение как рассчитывать параметры.