Как уже много раз было сказано и подтверждено разработчиками - виртуальные машины, используемые для QLua-скриптов и QLua-индикаторов - разные. В том числе, у них разный состав глобальных переменных, функций и т. п.
Ниже, с помощью простенького скрипта запущенного в режиме фейк-индикатора мне удалось получить более полный (по сравнению со штатной документацией) список всего того, что поддерживается в окружении QLua-Indicators VM:
Скрытый текст
Код
table os
table io
table _G
table coroutine
table debug
table string
table package
table bit
table Settings
table table
table math
const BAR_TYPICAL =7
const TYPE_CANDLE =3
const TYPE_DASHDOT =6
const TYPE_TRIANGLE_DOWN =11
const BAR_OPEN =1
const TYPE_LINE =1
const TYPE_DASH =7
const TYPE_HISTOGRAM =2
const TYPET_BAR =4
const BAR_LOW =3
const TYPE_TRIANGLE_UP =10
const TYPE_POINT =5
const BAR_VOLUME =5
const BAR_HIGH =2
const BAR_WEIGHTED =8
const BAR_MEDIAN =6
const BAR_CLOSE =4
string const _VERSION =Lua 5.1
function getFuturesHolding
function tostring
function gcinfo
function DelLabel
function SetRangeValue
function IsSubscribed_Level_II_Quotes
function pairs
function getSecurityInfo
function OnCalculate
function assert
function Init
function tonumber
function message
function getTradeDate
function getClassInfo
function load
function Subscribe_Level_II_Quotes
function module
function getDepoEx
function getClientCorrelationCoefs
function getBuySellInfoEx
function getFuturesLimit
function PrintDbgStr
function getQuoteLevel2Ex
function DelAllLabels
function SetLabelParams
function AddLabel
function VMA
function Size
function CalcBuySell
function getMoneyEx
function RGB
function getClientSecurityCoefs
function dofile
function loadstring
function getBuySellInfo
function getPortfolioInfo
function getCandlesByIndex
function getNumCandles
function getInfoParam
function getNumberOf
function sendTransaction
function xpcall
function getDepo
function getMoney
function GetLabelParams
function GetInfoParam
function GetTradeDate
function Unsubscribe_Level_II_Quotes
function require
function getQuoteLevel2
function SearchItems
function setmetatable
function next
function getLinesCount
function getClassesList
function ipairs
function isConnected
function getParamEx
function getDataSourceInfo
function getItem
function collectgarbage
function newproxy
function getOrderByNumber
function getScriptPath
function print
function C
function rawset
function SMA
function unpack
function H
function getfenv
function L
function pcall
function O
function type
function rawequal
function GetValue
function select
function T
function getmetatable
function rawget
function SetValue
function getWorkingFolder
function V
function setfenv
function getPortfolioInfoEx
function getClassSecurities
function error
function loadfile
Среди этого списка - есть некоторые вещи, которые я хотел бы прояснить у разработчиков:
Что такое function getQuoteLevel2Ex . У нас, как бы ведь уже есть не "Ex"
как известно - всё познаётся в сравнении. Поэтому, расширил своё мини-"исследование". Ниже приведена таблица различий на уровне двух виртуальных машин (скриптов и скриптов-индикаторов). Разумеется, эта таблица - не полная и не может быть полной по определению. Внимание! Те функции, переменные, константы и т. п., которые работают в обоих виртуальных машинах (и в скриптах и в скриптах-индикаторах) - НЕПОКАЗАНЫ!
Скрытый текст
Скрытый текст
Видно, что основное отличие выразилось в отсутствии доступа к классу QTable из скриптов-индикаторов, а также отсутствии функции "sleep". А также в отсутствии "знаменитого" CreateDataSource. При том, что все остальные функции - вполне доступны: можно создавать/управлять метками, работать с такими функциями, как getLinesCount, getCandleByIndex, как из индикаторов - так и из скриптов.
И, кстати, попутно выяснилось о существовании функции SettableCallback (не путать с SettableNotificationCallback) в скриптах QLua VM. Что-то я её тоже не встречал в документации...
sam063rus пишет: Кроме того, в таблицах не высветились штатные коллбеки скриптов QLua-script VM : OnInit,OnAllTrade и т.п. Но, это уже тема для отдельного топика...
забегая вперёд- можно сказать, что насчёт этого нет на самом деле никаких противоречий - бо как запись об этих функциях в глобальной таблице ещё не существует, потому как они ещё не были созданы пользователем. На то они и коллбеки)) Но всё можешь измениться - если их прописать в скрипте.
1. Сделал тестовый скриптик и попытался наложить на график. Саму библиотеку qte - положил вместе с индикатором.
Скрытый текст
Код
package.cpath=getScriptPath().."\\?.dll"
package.path=getScriptPath().."\\?.lua"
require "qte" -- моя библиотека
Settings=
{
Name = "testThread",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
check()
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
function check()
h = qte.getCurrentThreadId() -- в комментариях не нуждается
message(tostring(h))
end
Result -> Не прокатило, - он даже не появился в списке индикаторов.
2. Немного "допилил" скриптик - разместил "пути" и require - в функции Init()
Скрытый текст
Код
Settings=
{
Name = "testThread",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
package.cpath=getScriptPath().."\\?.dll"
package.path=getScriptPath().."\\?.lua"
require "qte"
check()
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
function check()
h = qte.getCurrentThreadId()
message(tostring(h))
end
Result -> скрипт запустился, попутно выяснилось следующие вещи:
Все эти Ваши м-м э-э... так называемые графики и индикаторы-порисульки - работают в основном потоке квика
Чем больше Вы на "открываете" графиков и таблиц, чем больше наложите индикаторов - тем медленее будет Ваш квик.
Получается, имеет значение место расположения "путей" и функции require.
3. Вернул опять - всё, как было. Поместил "пути" и require в самое начало скрипта см. пример из "1"-ой версии
Result -> старина квик - не вынес всего этого (нувыпоняли... :) ) ) Он просто завис и даже экран побелел :) ))
Скорей всего: проблема в том, что по великой "умности" разработчиков - своей функцией getScriptPath - они нае... (перемудрили) самих себя. Всякий раз - она выдаёт совершенно разные пути. Причём, весьма "неисповедимые".
--------------------
Далее, исследование продолжать не стал - т.к. то, что нужно уже выяснил: индикаторы работают в одном потоке с квиком, есть ли разница где находится require или нет - уже нестоль важно (для меня) - да и с getScriptPath - похоже - никто не спешит разбираться.
Начинаем разбираться с getScriptPath() Итак, "поехали"
Такой код - вешает намертво квик - он даже не может толком загрузиться. Бо как начинает выполнение скриптов индикаторов сразу же при своей загрузке:
Скрытый текст
Код
message(getScriptPath())
Settings=
{
Name = "testGetScriptPath",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
ок! "Спрячем" getScriptPath() в коллбек Init():
Скрытый текст
Код
Settings=
{
Name = "testGetScriptPath",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
message(getScriptPath())
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
Скрипт благополучно и правильно отобразил путь
Ладно, удалим индикатор и по новой наложим на график. Что ж, и так всё работает.
Вернём getScriptPath обратно наверх. (см. первый вариант кода) не выключая квик, удалим и по новой наложим индикатор
Причина такого непредсказуемого "поведения" - для меня известна... Однако, понадеемся услышать мнение на этот счёт от разработчиков (с обязательным отражением в документации). Итак, разработчики - You are Welcome! :))
Дмитрий пишет: Здравствуйте! Также обнаружил, что любой вызов функции getScriptPath() в скрипте индикатора (и вообще любого скрипта, находящегося в папке LuaIndicators) приводит к зависанию терминала при попытке открыть окно добавления индикатора на график, но только в том случае, если вызов getScriptPath() производится не внутри какой-либо другой функции (типа Init(), OnCalculate() и т.п.). Версия терминала 6.16.0.42
Здравствуйте, Мы в курсе описанной проблемы. Она будет исправлена в одной из следующих версий программы.
Лично меня - не устраивает извечная констатация факта и очередные "приносим свои извинения". Мне нужна - причина. + толковая, соответствующая реальной жизни - документация.
да вот, что-то мне это теперь уже особо не очевидно бо как и там и там: 1. функция загружена 2. инициализирована 3. находится не в коллбеке Понятное дело, что машины разные и пути папок, которые транслирует функция разные - но, в одном случае, она "мусорит", а в другом нет.
1. Не стоит размещать в папке LuaIndicators никаких файлов, кроме самих индикаторов, поскольку при добавлении любого индикатора каждый файл в этой папке сканируется минимум два раза:
Цитата
При добавлении нового индикатора на график плагин qlua сканирует папку LuaIndicators, проверяет файлы с расширением lua и luac (скомпилированные скрипты lua) [брехня! проверяются все файлы. Примеч. автора, т.е. меня] на соответствие следующим требованиям
2. Не стоит делать в теле индикатора (вне функций) что-либо, кроме объявления таблицы Settings, поскольку эти действия также будут выполняться минимум два раза при добавлении любого индикатора. Лучше сделать инициализацию в Init()
3. Если очень хочется, то вместо getScriptPath() можно использовать
Код
getWorkingFolder().."\\LuaIndicators"
Надо делать так, как надо. А как не надо - делать не надо.
Старатель, или в кратце - такая "песочница" - пока ничего кроме очередных глюков не принесла. -> скрипты весьма нестабильны, полного доступа к qchart - они не представляют, а только "дразнят". Запускаются "автоматом", при старте квика (чем не основа для вирусописательства?). Ну и спрашивается, "на хрена козе баян?"
Выше, глагол "добавлении" используется в настоящем времени несовершенного вида, т.е. указанные действия выполняются в момент добавления индикатора на график.
Надо делать так, как надо. А как не надо - делать не надо.
sam063rus пишет: чем не основа для вирусописательства?
А вообще, конечно, да. Пользователям нужно внимательно следить за тем, какие скрипты они помещают в папку LuaIndicators, т.к. с их помощью можно выполнять различные действия (в т.ч., отправку транзакций) без ведома пользователя. Только не при старте QUIK, а при добавлении индикаторов. Надеюсь это пофиксят. После прочтения - удалить.
Надо делать так, как надо. А как не надо - делать не надо.
sam063rus пишет: Запускаются "автоматом", при старте квика (чем не основа для вирусописательства?)
Вы можете привести конкретный пример скрипта, который не будучи добавленным на график автоматически запускается при старте QUIK?
специально для Вас, потратил время:
Скрытый текст
Код
message(getScriptPath())
Settings=
{
Name = "testBug",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
Индикатор - не добавлен, но присутствует в списке индикаторов. Квик, просил передать, что он висит до сих пор:)))
ну, или, если без getScriptPath, а просто голый мессэдж:
Скрытый текст
Код
message("testBug#00002")
Settings=
{
Name = "testBug",
line =
{
{
Name = "test",
Color = RGB(0,0,255),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
return nil
end -- выход из функции OnCalculate
как видите, в "индикаторе", ни на графике - нигде - нет привязки ни кодному источнику данных/либо графику - но он всё-равно запускается. И причём, несколько раз:
sam063rus пишет: т.е. - я вообще ничего не делал: я просто кинул его в папку LuaIndicators и включил квик - в итоге, не будучи ни на одном графике - он сам запустился.
Да, действительно. Если на графике добавлен хоть один Lua-индикатор, то при старте QUIK будут запускаться все скрипты из папки LuaIndicators. Причём столько раз, сколько открыто Lua-индикаторов. Это ещё один повод, чтобы вне колбеков ничего лишнего не размещать.
Цитата
sam063rus пишет: но он всё-равно запускается. И причём, несколько раз
Очевидно, у вас добавлено несколько Lua-индикаторов на графиках.
Надо делать так, как надо. А как не надо - делать не надо.
Старатель пишет: Причём столько раз, сколько открыто Lua-индикаторов.
поверьте - у меня индикаторов - много больше чем 11 на всех вкладках. конкретно на той вкладке - которая последняя (перед предыдущем отключением квика) - там вообще нет индикаторов - только окно системных сообщений.
Тогда можно предположить следующий алгоритм. Из документации:
Цитата
При выборе пункта меню Настройки/Сохранить настройки в файл, сохраняются все значения из таблицы Settings в wnd-файл. При загрузке настроек из файла, модуль qchart получает от модуля qlua список индикаторов и автоматически создает индикатор по его имени.
При этом имя самого файла Lua-индикатора не сохраняется. Поэтому при создании индикатора последовательно перебираются файлы из папки LuaIndicators, пока не будет найден индикатор с именем Settings.Name. Поиск, очевидно, происходит путём их запуска.
Надо делать так, как надо. А как не надо - делать не надо.