1 (2013-10-25 23:10:30 отредактировано swerg)

Тема: Исследование разных нюансов работы индикатора

Захотелось проверить разные нюансы в работе с индикаторами, которые явно не прописаны в документации (либо я проглядел). Возможно, результаты будут кому-то интересны.

Исследования проводились на QUIK версии 6.9.1.2, возможно в других будут какие-то отличия.


1. Сканируются ли вложенные директории внутри папки LuaIndicators?
Создал в ней несколько папок на пару уровней вложенности, в папки разложил скрипты с разными наименованиями индикаторов. И все они отобразились в диалоге выбора!

Вывод 1: Скрипты с индикаторами ищутся терминалом как в папке LuaIndicators, так и во всех вложенных в нее папках на любых уровнях.


2. Из каких файлов считываются индикаторы?
Добавил в каталог LuaIndicators файл с именем "aaa", записал в него корректный код индикатора с уникальным опознаваемым именем. И этот индикатор появился в диалоге добавления!

Вывод 2: QUIK при сканировании папки LuaIndicators берет из нее буквально все файлы и все их пытается выполнить на Lua-машине в надежде не получить ошибку выполнения, после чего вычитывает результаты выполнения, если выполнение было успешным.


3. Когда перезачитывается текст скрипта индикатора?
Добавил индикатор на график, изменил правила построения индикатора. С приходом новой свечи индикатор нарисовался по старым правилам (т.е. по тексту скрипта до обновленя)

Вывод 3: Индикатор один раз при его добавлении на график загружается в QUIK, после чего этот загруженный скрипт и выполняется вне зависимости от модификации файла с исходным кодом. Обновится индикатор только при повторном добавлении его на график (при этом ранее добавленный индикатор будет продолжать рисоваться на основании старой версии исходников).


4. Какая часть кода выполняется при считывании названия индикатора?
Для этого теста добавил в папку LuaIndicators скрипт с таких текстом:

Settings={}
Settings.Name = "test-log"
 
file = io.open("d:\\test-lua-indicator.log", "a+t")
 
function Log(s, ...)
    if file ~=nil then
        file:write(tostring(os.date()) .. " " .. string.format(s, unpack(arg)) .. "\n")
        file:flush()
    end
end
function Init()
    Log("Init")
    return 1
end
function OnCalculate(idx)
    Log("OnCalculate idx=" .. tostring(idx))
end
function OnDestroy()
    Log("OnDestroy")
    if file~=nil then
        file:close()
    end
end

Log("Body") 

Выполняя по шагам действия по добавлению индикатора, получил следующие соответствующие этим действиям записи в логе:

Открывается диалог выбора графика/индикатора -> Body

Выбираю индикатор "test-log" из списка, жму "Да".
Открывается диалог параметров графика -> 2 раза Body(??!) и Init

Нажимаю в этом диалоге "Сохранить" -> последовательные вызовы OnCalculate с индексом, начиная с 1. Вызовы сразу для всех имеющихся свечей источника данных (графика).

После этого при перемещении графика между окнами никаких вызовов уже не логируется, т.е. индикатор для имеющихся свечей рассчитывается однократно.

Удаляю индикатор ->ожидаемо появляется OnDestroy.

Снова добавляю индикатор с логированием, как сказано выше, логируются последовательно Body, Init и OnCalculate для всех имеющихся свечей.

Теперь устанавливаю соединение с сервером -> заново последовательные вызовы OnCalculate с индексом, начиная с 1.

Для свечи с последним индексом вызов OnCalculate теперь происходит многократно (для одного и того же значения индекса) по мере поступления новых данных с сервера (и соответственно, изменения параметров самой этой последней свечи).

Вызываю параметры добавленного индикатора, меняю цвет (или другой параметр),  нажимаю "Сохранить" -> в логе снова последовательные вызовы OnCalculate с индексом, начиная от 1.

Меняю тайм-фрейм графика -> в логе снова последовательные вызовы OnCalculate с индексом, начиная от 1.

Выводы 4: Возникающая последовательность выполнения отдельных частей скрипта индикатора подробно расписана выше, а здесь хотелось бы обратить внимание на следующий момент. Если в индикаторе используется какая-то итерационная формула, где каждый последующий вызов OnCalculate использует вычисленные ранее данные (в предыдущих вызовах OnCalculate), то внутри этого самого OnCalculate следует сохранять последний индекс рассчитанной свечи. При этом надо отслеживать два момента:

  • индекс не изменился с предыдущего вызова – значит повторно рассчитывается последняя свечка, дал которой уже был расчет, но с новыми параметрами;

  • индекс стал меньше ранее рассчитанного (или равным 1, хотя нигде не гарантируется, что индекс первой свечи именно 1, поэтому такое условие может оказаться ненадежным). Этот сигнал говорит о том, необходимо заново проинициализировать глобальные переменные, т.к. это означает, что изменились условия графика и полностью заново пересчитывается.

2 (2013-10-25 23:26:22 отредактировано swerg)

Re: Исследование разных нюансов работы индикатора

Разные особенности и баги.

Версия 6.9.1.2

  • отсутствует константа TYPE_DOT, задающая тип графика "точки"; чтобы задать графику тип "точки" надо полю Type присвоить 5. Например:
    Settings.line[1].Type = 5

3

Re: Исследование разных нюансов работы индикатора

< reserved >

4

Re: Исследование разных нюансов работы индикатора

swerg пишет:

Разные особенности и баги.

Версия 6.9.1.2

  • отсутствует константа TYPE_DOT, задающая тип графика "точки"; чтобы задать графику тип "точки" надо полю Type присвоить 5. Например:
    Settings.line[1].Type = 5


TYPE_POINT