Переменные, массивы и функции в QLua (lua)

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 8, среднее: 5,00 из 5)
Загрузка...

Qlua-основыВ Qlua есть следующие типы переменных:

   nil (неопределенный),
   boolean (логический),
   number (числовой),
   string (строковый),
   function (функция в Lua является типом данных),

а также, есть массивы (таблицы Lua), в т.ч. многомерные, которые могут содержать в себе все вышеперечисленные типы данных.

Для того, чтобы объявить переменную в Qlua, достаточно присвоить ей значение. Язык Qlua сам определит к какому типу отнести переменную.

Примеры:

A = true; -- Теперь переменная A имеет логический тип boolean
   -- в QLua(Lua) все значения являются TRUE, кроме nil и FALSE
 
B = 1;
C = 1.5;
-- Переменные B и C имеют числовой тип number, который может содержать как целые числа, так и числа с дробной частью
 
D = "Текст"; -- Переменная D имеет строковый тип string
 
E = {}; -- Переменная E теперь является массивом нулевой длинны
-- Массив в QLua может хранить внутри себя значения РАЗНЫХ! типов одновременно
-- Так присваиваются значения элементам:
E[1] = 10; -- ВАЖНО !!! Элементы массива в QLua, по умолчанию, индексируются, начиная с 1, а не с 0,
   -- хотя ключами(индексами) могут быть и отрицательные числа и слова и строки
   -- пример инициализации:
   F = {green = "Зеленый", [-10] = 30};
   -- НЮАНС!!!
   G = {good year = 2015}; -- такая инициализация вызовет ошибку
   G["good year"] = 2015;  -- а так ошибки не будет
   -- примеры добавления:
   F["apple"] = "Яблоко";
   F[-20] = 12345;
   E[2] = "Текст";
 
-- МНОГОМЕРНЫЕ массивы создаются так же, как и одномерные, мерность зависит от количества вложенных фигурных скобок:
A = {{{}}}; -- объявлен трехмерный массив
A[1][1][1] = "Значение"; -- пример обращения к массиву
 
-- Массивы в QLua являются таблицами, по-этому к ним можно применять функции из таблицы table языка lua:
table.concat(Array, str, i, j) -- Выполняет конкатенацию элементов массива в одну строку и возвращает ее
   -- Array - это исходный массив,
   -- str (необязательный параметр) - строка, вставляемая между элементами
   -- i (необязательный параметр) - начальный индекс (по умолчанию, 1)
   -- j (необязательный параметр) - конечный индекс (по умолчанию, индекс последнего элемента массива)
table.insert(Array, i, new_element) -- Вставляет элемент new_element в массив Array по индексу i, сдвигая существующие элементы
   -- i (необязательный параметр) - по умолчанию, новый элемент добавляется в конец массива, увеличивая его на 1 элемент
table.maxn(Array); -- Возвращает максимальный положительный числовой индекс, если таковых нет, возвращает 0
table.remove(Array, i); -- Удаляет элемент таблицы по индексу i
   -- i (необязательный параметр) - по умолчанию, удаляется последний элемент массива
table.sort(Array, func); -- Сортирует элементы массива, размещая их по определенному правилу
   -- func (необязательный параметр) - по умолчанию, функция сортирует элементы по возрастанию, применяя сравнение "<",
     -- но можно применить свой порядок, для этого, вторым параметром нужно передать функцию, принимающую 2 параметра, 
     -- которая будет возвращать true, если параметр 1 меньше параметра 2.      
     -- Пример:      
     Arr = {2,4,3,1,5};      
     function MySort(a,b)         
        if a > b then 
           return true; 
        else 
           return false; 
        end;
     end;
     table.sort(Arr);         -- В результате в массиве Arr будет такой порядок {1,2,3,4,5}
     table.sort(Arr, MySort); -- В результате в массиве Arr будет такой порядок {5,4,3,2,1}
 
-- Чтобы узнать количество элементов в массиве, применяется оператор "#"
-- в предыдущем примере #Arr вернет 5, но есть один ВАЖНЫЙ МОМЕНТ!!!:
Arr[2] = nil; -- теперь в массиве содержатся значения {5,3,2,1}, а индексы (1,3,4,5), т.е. индекс 2 отсутствует,
-- сейчас #Arr вернет 1, т.к. элемент по индексу 2 не существует

Все переменные, объявленные выше, являются ГЛОБАЛЬНЫМИ по типу видимости, т.е., объявив так переменную в одной функции, можно будет использовать ее значение в любой другой функции, находящейся в том же скрипте. Можно объявить переменную ЛОКАЛЬНОГО типа, использовать которую можно будет только внутри той функции, в которой Вы ее создали. Для этого перед именем переменной нужно поставить идентификатор local.

Примеры:

A = 1; -- ГЛОБАЛЬНАЯ, видна везде в скрипте
local B = 2; -- ЛОКАЛЬНАЯ, но, так как объявлена в основном теле скрипта, а не внутри функции, видна везде в скрипте
 
function F1()
   -- Здесь видны переменные A и B, можно как брать из них значения, так и изменять их
 
   C = 3; -- Объявлена ГЛОБАЛЬНАЯ переменная
   local D = 4; -- Объявлена ЛОКАЛЬНАЯ переменная
   local A = 5; -- Объявлена НОВАЯ ЛОКАЛЬНАЯ переменная, которая не изменила значение ранее объявленной переменной A
end;
 
function F2()
   -- Здесь видны переменные A(первая), B и C, можно как брать из них значения, так и изменять их
   -- Если обратиться здесь к переменной A, то увидим, что она, по-прежнему, равна 1
   -- Переменная D здесь не видна 
end;

Функции

-- Объявление:
function Name(параметр1, параметр2,...)
end;
-- следующая запись эквивалентна:
Name = function(параметр1, параметр2,...)
end;
   -- Функция в QLua(Lua) может иметь входные параметры, а может и не иметь
   -- Параметры, это локальные для данной функции переменные, значения которых передаются при вызове функции
-- Функция в QLua(Lua) может иметь переменное число параметров
-- пример 1:
function F1(a,b,...)
end;
   -- Пример вызова:
   F1(1,2,3,4);
   -- Значение 1 присвоится переменной a
   -- Значение 2 присвоится переменной b
   -- Для оставшихся значений (3 и 4), существует встроенная переменная arg, у которой есть поле n,
      -- в которую заносится количество переданных дополнительных значений, в данном случае arg.n равно 2
   -- Значение 3 присвоится переменной arg[1] 
   -- Значение 4 присвоится переменной arg[2]
 
-- пример 2:
function F2(...)
end;
   -- Пример вызова:
   F2(1,2,3);
   -- Значение 1 присвоится переменной arg[1]
   -- Значение 2 присвоится переменной arg[2]
   -- Значение 3 присвоится переменной arg[3]
   -- arg.n равно 3
 
-- Функции в QLua(Lua) могут не возвращать, или возвращать одно и более значений,
   -- для этого служит оператор return
-- Пример:
function F()
   return 1,2,3;
end;
-- Вызов 1:
A = F();
-- A[1] получит значение 1
-- A[2] получит значение 2
-- A[3] получит значение 3
-- Вызов 2:
A,B,C = F();
-- A получит значение 1
-- B получит значение 2
-- C получит значение 3
-- Вызов 3:
_,_,A = F();
-- A получит значение 3
-- Символ "_" служит в QLua(Lua) для замены ненужных переменных

QLua поддерживает параллельное присваивание:

   -- Запись
   a,b,c = 1,2,3;
   -- эквивалентна записи
   a = 1;
   b = 2;
   c = 3;

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!

Добавить комментарий

Переменные, массивы и функции в QLua (lua): 307 комментариев

  1. Всем Добрый Вечер! Помогите, пожалуйста найти ошибку. При загрузке индикатора работает нормально, но в процессе изменение значений время от времени сравнивает себя с собой (одно и то же значение). Всю голову сломал, какие варианты только не пробовал. Прилагаю пример в виде функции значений свечей. Цель: найти и вернуть последнее совпадающее значение (кроме самого себя).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    Equality=function(indx)
    	local old_ind=0
    	if indx>old_ind then
    		val_table={}
     
    		val_table[1]= H(indx)
    		val_table[2]= L(indx)
    		val_table[3]= O(indx)
    		val_table[4]= C(indx)
     
    		for i=1, #val_table do
    			for j=1+i, #val_table do
    				if val_table[i]==val_table[j]
    					then
    					level = val_table[i]
    				end
    			end
    		end
    	else return nil
    	end
     
    	old_ind=indx
    	return level
    end
    1. Добрый,
      Equality и есть большая ошибка.
      Создается впечатление, что вы не понимаете, что делаете, а вроде понимаете, но усердно лепите горбатого...
      Подучить вам нужно мат. часть: таблицы, переменные, функции и циклы, по сути - всё подучить.
      Сделать тестового робота (не индикатор) с кучей message , задать необходимые параметры и усердно тыркать кнопку "Запустить", до тех пор, пока не наступит просветление.

          1. Вроде да! Но там несколько функций, которые берут значения некоторые при закрытии свечей, другие на тиках. Может в этом разнообразии дело? Смысл в том, что если нет нового значения, то возвращается последнее! Но в определённые моменты (всегда разные ситуации) возвращается неправильное значение (оно меняется, хотя не должно было)! Может в моменте, когда значение на тиках меняется, то и итоговое значение становится некорректным? Неправильный вывод линии происходит, когда в процессе работы индикатора меняются значения! Может приравнять к самому себе(видимо, при окончании совпадения). Хотя и не всегда. При загрузке всё нормально!

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

              1. Вы проблему решаете, или книгу пишите, уже детектив какой то.
                - "Но в определённые моменты (всегда разные ситуации) возвращается неправильное значение (оно меняется, хотя не должно было)!"
                - "когда одни функции взаимодействуют с другими функциями, то результат который получается он в некоторых случаях может быть как правильным, так и иногда наорборот"
                Как эти рассуждения помогают Вам решить задачу, я не понимаю. Да займитесь делом, внедритесь в процесс работы, расставьте те же message, черт с ним, пусть повесится терминал, перезапустите. Почитайте сообщения и увидите какие функции выполняются, что и с чем они сравнивают. Ну не работают программисты тыкая пальцем в небо.
                Если очень сильно будет вешаться терминал, перейдите на PrintDbgStr, он чуть пошустрее. Если и Debug View будет вешаться, печатайте в файл.
                Вам хоть и в пустую отвечают, но как говорится, какой вопрос, такой ответ. Вы какой ответ ожидаете услышать на вопрос:
                - "Может в этом разнообразии дело?"
                Отвечаю, может. Вам от этого легче стало?
                Я тоже в пустую пишу, нет конкретных вопросов, нет и ответов.

                    1. вам, конечно! вы же мне отвечаете, что нет конкретных вопросов. вот я и задал! даже не знаю, можно ли сформулировать вопрос еще конкретнее?

                    2. Нет, я Вам не отвечал, Вы вообще вопросов не задавали.
                      Я лишь процитировал часть Вашего комментария.
                      Конкретных вопросов не задает Роман, и Вы так же как и я, отвечаем ему в пустую.
                      Если говорить в целом о Вашем комментарии, то я не могу сказать ни да ни нет, потому что я вообще не понял что Вы хотели сказать.
                      Для меня алгоритм возвращает ВСЕГДА то что я от него жду, пусть там хоть сотни функций взаимодействуют между собой. Если алгоритм хоть раз мне вернет то, что я от него не ждал, значит алгоритм работает не правильно, буду выяснять причину и устранять.

                    3. вы нажали на ссылку "ответить" в моем комментарии, и мне на почту пришло уведомление, что "ПавелИ ответил(а) на Ваш комментарий к записи Переменные, массивы и функции в QLua (lua)" (это цитата из письма) и так далее, текст вашего ответа. почему же я не должен ему верить? 🙂
                      если говорить в целом о моем комментарии, то я попытался ответить, понятным автору вопроса, языком. то, что он не понятен вам - это вполне логично, так как вопросы оригинального автора точно так же непонятны нам.
                      как я уже заметил ниже в обсуждении, алгоритм не может работать неправильно, он работает точно так, как его запрограммировал его автор. если вы имели в виду не то, что написали, то алгоритм в этом не виноват.

                    4. Ну извините. Я вообще не знаю на какую "ОТВЕТИТЬ" тут жать, жму на ту, которая ближе.
                      Да, для меня комментарий не несет никакой информации написано тоже самое что написал автор, только другими словами. Может автору чем то и поможет.
                      - "алгоритм не может работать неправильно" - Вот с этим согласен на все 100%, но Вы же пишите "всё правильно работает!" - без правки этот алгоритм будет возвращать не то что от него ожидается. А если бы я задал вопрос вместо автора и получил ответ "всё правильно работает!" - это для меня дало бы команду, "код верный, не трогай, ничего не меняй".
                      Да, можно написать готовую функцию, автор ее скопирует себе и все, завтра вернется с другим кодом, причем очень похожим, но это для нас он очень похож, а для него вообще все другое. Так как автору развиваться. Я лично не даю готовый вариант. Если 1-2 ошибки в коде, можно сказать, исправь вот это и пояснить почему, автор поймет свою ошибку, исправит и впредь ее не совершит. Но тут лучший совет уничтожить Equality чем что то в ней исправить.

                    5. Павел, вы пишите: "без правки этот алгоритм будет возвращать не то что от него ожидается". А ЧТО ОТ НЕГО ОЖИДАЕТСЯ? автор вопроса приводит некий код и не может объяснить, что его не устраивает. он пишет: "Цель: найти и вернуть последнее совпадающее значение (кроме самого себя).". Вы что-нибудь из этой постановки поняли? Я - нет.

        1. Роман, если честно, совершенно нет желания больше отвечать на Ваши сообщения.
          С одной стороны пишите такие алгоритмы, что уже не плохо разбираетесь в программировании, с другой стороны, код в таком виде, как будто Вы первые шаги делаете. Как у Вас так получается, не знаю. Могу предположить что Вы берете готовый код, исправляете в нем пару символов и пытаетесь его заставить работать, а как пишите код собственно ручно, в итоге вообще кошмар выходит. Вам верно пишут "Подучить вам нужно мат. часть: таблицы, переменные, функции и циклы, по сути - всё подучить". Бросьте, остановитесь, сделайте хотя бы недельный перерыв, лучше месяц, вообще не думайте и не открывайте редактор, а потом начните с самого начала. Если у Вас цель научиться писать алгоритмы, послушайте других. Если у Вас цель просто заставить что то, что Вы пишите, хоть как то работать, добивайте, может добъете, заработает, будет как то работать, жрать ресурсы компа, иногда или часто зависать, вываливаться с ошибками, но все же как то работать.
          Что касается кода, даже не знаю, стоит ли его разбирать, врдя ли это Вам что то даст. Такое ощущение что Вы не знаете и не понимаете что пишите, мыслите как то так, вот там то я видел что было так написано, напишу и у себя так же.
          Ладно, разберу код, надеюсь Вы сделаете перерыв и вернетесь с чистой головой и усвоенной теорией.
          Строка 2 и 3, сразу вопрос, на кой тут условие стоит? Вы на будущее его прописали? В old_ind записываете 0, а потом проверяете что бы indx обязательно был больше 0. Вы что боитесь что indx может быть не больше 0? Ладно, черт с ним с условием, на кой вообще тут нужна переменная old_ind ? Вы ее не используете в коде, она встречается лишь в строке 22, где в нее записываете значение indx, а в строке 23 выходите из функции, тем самым уничтожая все локальные переменные. Ну и зачем это условие и переменная old_ind? Мне непонятно.
          Цикл, это вообще что то ст. Я уже много раз писал, Вы руками считаете что алгоритм делает? Или Вы думаете что ПК обладает какими то волшебными свойствами и мы, люди, не можем посчитать, так нет, может удивлю, но комп просто сичтает 1+1, ничего волшебного в недрах процессора не происходит. Как только Вы возьмете ручку и лист бумаги, произведете вычисление своего же алгоритма хотя бы 1 раз, для одного графика, поймете, сколько работы делает процессор, с такими алгоритмами, неверное тетради в 96 листов не хватит. Ладно для всего графика, просто пропишите все итерации этих двух циклов, узнаете, что с чем сравнивается. Не буду расписывать, это Вам домашнее задание.
          Так же у Вас сказано "Цель: найти и вернуть последнее совпадающее значение". Так получается есть какой то приоритет по совпадениям?
          И еще, с чего Вы взяли что в процессе выполнения происходит сравнение самого с собой? Какой то журнал отчетов делали, где увидели что CLOSE сравнилось с CLOSE? Или message выдало сообщения типа "Эй, ты меня со мной же сравнил ))) " Или это Ваши догадки? Так как исходя из кода переменная i никогда не будет равна переменной j, а значит сравнения самого с собой нет. Ну конечно же Вы скажете, но ведь сравнивается, я же вижу. Так вот для этого Вас и отправляют изучать основы, чтобы Вы научились читать код и отбросили свои догадки и пошли искать причину в другом месте. Еще важный именно для Вас совет "Сделать тестового робота (не индикатор) с кучей message" Выделю важное "с кучей message" с огромной кучей, что бы он Вас завалил сообщениями, пусть терминал повесится на несколько минут, печатая сообщения, может тогда поймете что творится в недрах процесора. message для Вас это отчеты, отладка, называйте как хотите, важно не то что бы алгоритм отчитался, естественно в рабочей версии все message удалите, но в процессе разработки Вы должны знать что происходит. Ну ни кто не даст Вам ответ, что происходит в Вашем алгоритме, НИ КТО. Потому что ни кто не знает что там происходит. Открою тайну, знаете что сделает человек, который решит дать Вам ответ, он возьмет Ваш код, расставит в нем message, запустит, прочитает эти message, получит некий отчет о работе и поймет, что происходит. Может не message, может PrintDbgStr или печать в файл, не важно, суть одна, составить отчет о работе алгоритма. Понимаете к чему все это пишу? - К тому что Вам нужно научиться делать отчеты и соответственно научиться читать отчеты. Это и есть отладка алгоритма, без отладки далеко не уедите.
          Я не запускал Вашего кода, но раз Вы пишите что идет сравнение самого с собой, а в коде я вижу что это не так, нет тут никакого сравнения самого с собой, значит копайте в другом направлении. Вот и включайте голову, что происходит или может происходить в процессе? Представьте. время 11:00:00 идет сделка. по цене 125.43, эта сделка первая в баре 11:00. Так какие цены имеет бар 11:00 в это мгновение? O = 125.43 H = 125.43 L = 125.43 C = 125.43. Так может именно это Вы воспринимаете как сравнение самого с собой?

          1. Спасибо , Павел, за помощь и поддержку! Вы правы! Я, как Вы правильно заметили, не обладаю достаточными знаниями, чтобы разобраться самому. Вот поэтому я и задаю вопросы. Извините, что потратил Ваше время. Понимаю Вас. К сожалению, у меня нет возможности в реальности задать кому-то вопрос. Но, обещаю, что больше не буду тратить Ваше время на помощь мне. Ещё раз извините за доставленные неудобства!

            1. Да дело не в потраченном времени, а в том что у Вас нет движения вперед. Если бы это было Ваше первое сообщение, совершено бы иначе смотрели и отвечали. Но уже много раз расписывали, Вы вроде как читаете, понимаете, а результат тот же. Выходит что наши объяснения пустые.
              Все мы когда то начинали, все понимают и хотят помочь, потому и пишут тут, но нельзя слово в голову засунуть, человек сам должен усвоить. А Вы не усваиваете, а не усваиваете потому что не понимаете, а не понимаете, потому что нет основы, а основы нет, потому что Вы либо не читали книги, может не нашли, либо просто проигнорировали, решив что на чужих примерах научитесь. Вот Вас и отправляют основы изучать, не потому что мы не хотим Вам помочь, а потому что без них Вы не сможете развиваться.
              Или ожидаете что тут в комментариях будут основы писать, что такое переменная, как объявляется, где ее видно, где не видно.... Не будут.
              Если книгу не нашли, то вот отличная книга:
              Roberto Ierusalimschy "Programming in Lua"
              Не знаю кому как, а мне очень помогла разобраться в LUA.
              По моему есть и на русском языке, называется "Программирование на языке Lua" автор естественно тот же, но с названием могу ошибаться, но вроде так называется.
              Ну а если не хотите книгу читать, тут уж извините, ни чем помочь не могу.

              1. Тут дело в другом!
                Зачастую книжные примеры и работа с источником данных - это не одно и то же! Вот и получаются ошибки, а они зачастую, типовые, без объяснения причины. Но обязательно учту Ваши пожелания. Указанную Вами книгу знаю! Сейчас нет возможности приобрести. Вот и советуюсь. Собираю чужие коды, пытаюсь разобраться. Но мой вопрос написан целиком мной. Просто использование функций - это для меня новое. Функцию написал сам. Просто упростил для наглядности(H(indx) и т.д)!

                1. Ваше дело как развиваться. Я без основ не могу двигаться вперед, топчусь на месте, в итоге бросаю и забываю как страшный сон. Потом возвращаюсь и начинаю с самых азов.
                  - "Зачастую книжные примеры и работа с источником данных - это не одно и то же!"
                  Какие примеры, какой источник данных, вообще о чем речь? В книге описана теория, как оно устроено. Если написано a = 10 это значит что переменная a содержит число 10. Считайте что это закон, какой источник данных может на это повлиять? В программировании нет коррупции, ни кто не даст взятку что бы он подменил 10 на 11. Если в переменной лежит 11, значит это Ваш алгоритм туда 11 положил, это Ваша проблема, ищите в коде, кто положил 11 в переменную а. А как искать, отладка, те же message помогут. Нашли кто положил 11, принимайте решение, этот кто то правильно сделал? Нет, скажите что бы не ложил. Но что бы понять откуда могло попасть число 11, снова нужны основы. Если a локальная, значит надо искать в области ее видимости, если глобальная, вообще кто угодно мог положить, придется message по всему коду расставлять. Еще есть таблица debug с функциями для отладки, тоже может помочь понять , в какой строке был код, когда в переменную 11 попало. Но с этой библиотекой тоже нужно научиться работать, снова нужна книга, ну или статья в Интернете хотя бы. debug только для отладки, в готовых кодах обычно ее не встретить, по крайней мере я в рабочих версиях уничтожаю все debug, может кто оставляет, так встретите.
                  - "Просто использование функций - это для меня новое"
                  И опять отправил бы Вас к основам. Почитайте, что функции бывают локальные, а бывают глобальные, в зависимости от задачи, будете использовать или локальные или глобальные. А еще функции можно в таблицы записывать, или мета таблицы... Да вообще теории много, в книге страниц 400, кто же тут в комментариях столько будет писать. Или все это, как любят говорить, "вода", давайте нам практику лучше. ну берите практику, мучайтесь без этой "воды".

        2. "Может это из-за old_ind ?"
          Вот это прям подход настоящего программиста ). Только не обижайтесь.
          С таким подходом Вы скоро начнете подозревать, что дело наверное в том что редактор, в котором пишите, переменные красным цветом выделяет, а числа розовым.

        3. Уважаемый, тут не клуб оракулов.
          Если ошибается, значит не работает, с чего вы взяли, что именно Equality не работает?
          То что она не работает, это понятно, но судя по примеру, основной код - это просто одна большая ошибка, которую надо удалить в корзину.

          Вы хоть раз пробовали написать комментарий к своему коду?
          Я уверен на 100%, что если попробуете описать, что делает текущая строка кода, то у вас не возникнет вопросов.

          Раз вам лень писать комментарии и не жалко своего и Чужого времени.
          Что ж, я потрачу свое время специально для вас, но в последний раз.

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          
          --глобальная функция Equality считает какую-то хер..ю и принимает один параметр: индекс какого-то бара/свечи
          Equality=function(indx)
          	local old_ind=0 -- объявил локальную переменную old_ind и присвоил ей значение 0
          	if indx>old_ind then  --если текущий indx > 0 , то будет выполнен этот блок кода, т.е. всегда только этот блок кода, т.к. indx > old_ind априори (мат пере-мат)
          		val_table={} --объявил глобальную переменную val_table и присвоил ей значение - пустая таблица, 
                                                    -- если val_table уже объявлена выше, то прошлая таблица будет уничтожена и создана новая пустая таблица
                         --заполнил таблицу значениями, для наглядности напишу циферьки
          		val_table[1]= H(indx) --  =102
          		val_table[2]= L(indx) --   =99
          		val_table[3]= O(indx) --   =101
          		val_table[4]= C(indx) --   =100
           
          		for i=1, #val_table do --для каждого i-того элемента массива выполняю цикл for j=1+i, #val_table do
                                  local val = val_table[i]   -- если  i=1, то  val = H(indx) = 102 ... ... если  i=4, то  val = C(indx) = 100
           
                                   for j=1+i, #val_table do --для каждого j-того элемента выполняю:
          				--если i=1, то начинаю обход val_table с 2-го элемента 
                                          --если i=4, начинаю обход с 5-го элемента, т.е. тупо не зайдет в этот цикл, т.к. 5-го  элемента нет!
                                          if val == val_table[j] then
          					--в этот блок не зайдет, т.к. в текущем вызове H~=L~=O~=C
                                                  --но зайти по идее может, например если O==C, то при i=3 один раз сюда попадет
           
                                                  level = val_table[i] --объявил глобальную переменную level и присвоил ей val
          				end
          			end
          		end
          	else   --этот блок кода не будет выполнен никогда, почему? написано выше, смысла в этом блоке нет.
                         return nil
          	end
                  --присвоил переменной old_ind
          	old_ind=indx
                  --если переменная level все-таки где-то объявлена, а не внутри этой функции, то вернет значение этой переменной НЕ nil, а какую - то хер..ю!
                  --а вот если попадет в  if val == val_table[j] then, то вернет то, что там присвоилось
           
          	return level --так как level это глобальная переменная, то смысла в этой строке нет, как впрочем и в самой Equality
          end

          Из примера понятно, что вы игнорируете знания, которые уже получили от местного сообщества и которых вполне достаточно для написания индикатора более сложного, чем тот, который вы пытаетесь слепить из каких то обрывков чужих индикаторов.
          Вы не понимаете что такое функция, для чего она нужна и как ее использовать, вы не различаете слова "локально" и "глобально".

          Переменных вообще не существует.
          "переменная" это абстрактное понятие введенное для простоты? простоты чего? понимания? я не в курсе, не я их вводил.

          Всех нас окружают только таблицы.
          И вы, и я, и Вася и тупо ВСЁ - тоже таблица: ключ = значение, куда положил, оттуда взял.

          Учите мат. часть и если что-то у вас не получается, то весь код в студию, полный код, упрощенный, но что бы его можно было запустить в терминале, а не гадать на кофейной гуще.
          Только сами сначала "упрощенку" у себя запустите.
          Хотя... можете продолжать спамить, мне пофик.

          1. Роман, Вам отлично прокомментировали код.
            Кстати, учитесь писать так же, комментируйте свои строки.
            Кстати я не обратил внимание что level глобальная, там реально может лежать что угодно. Сделайте level локальной. Хотя нет, лучше уничтожьте Equality, напишите заново и хорошо эту функцию.

          2. Вы меня извините, но судя по недолгому общению с некоторыми талантливыми разработчиками, у меня сложилось впечатление, что у большинства из них самооценка явно завышена! Причины могут быть разные! Но не в этом дело! Я считал, что это обучающий ресурс. Поэтому задавал вопросы! Возможно, Ваш ответ - это проявление гордыни и, как производное, тщеславия! Вы же сами начали отвечать на мои вопросы! Значит Вам захотелось показать себя! Иначе, зачем отвечать?! В чате кто-то вопрос, человек значит что-то хочет узнать, к чему-то стремится. Иначе бы не задавал вопросы. Просто сам-бы справился. Исходя из Вашего, если можно так выразиться, тщеславия - Вы ответили! Второй, третий, четвёртый вопрос - и Вы возгордились! Может и не так! Поэтому, если можете и хотите - то помогите, если можете, но не хотите - то и незачем, простите, отвечать, если хотите, но не можете - то сидите, как я! А понты колотить и про бухло базарить все могут!))) Я уже и так максимально упрощал код для того, чтобы не засорять комментариями.

            1. вы можете обижаться сколько угодно. но вот в программировании есть такое понятие - "эквивалентный код". вот эквивалентный код вашей функции Equality():

              1
              2
              3
              4
              5
              6
              7
              8
              9
              10
              11
              12
              13
              14
              15
              16
              17
              18
              19
              
              level = nil
               
              function Equality(indx)
                  if indx > 0 then
                      if H(indx) == L(indx) then level = H(indx) end
                      if H(indx) == O(indx) then level = H(indx) end
                      if H(indx) == C(indx) then level = H(indx) end
                      if H(indx) == nil     then level = H(indx) end
                      if L(indx) == O(indx) then level = L(indx) end
                      if L(indx) == C(indx) then level = L(indx) end
                      if L(indx) == nil     then level = L(indx) end
                      if O(indx) == C(indx) then level = O(indx) end
                      if O(indx) == nil     then level = O(indx) end        
                      if C(indx) == nil     then level = C(indx) end
                      return level
                  else
                      return nil
                  end
              end

              теперь, внимание, вопрос: ВЫ УВЕРЕНЫ, ЧТО ВЫ ИМЕННО ЭТО ХОТЕЛИ ЗАПРОГРАММИРОВАТЬ?

              1. извиняюсь, невнимателен. даже вот так:

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                
                level = nil
                 
                function Equality(indx)
                    if indx > 0 then
                        if H(indx) == L(indx) then level = H(indx) end
                        if H(indx) == O(indx) then level = H(indx) end
                        if H(indx) == C(indx) then level = H(indx) end
                        if L(indx) == O(indx) then level = L(indx) end
                        if L(indx) == C(indx) then level = L(indx) end
                        if O(indx) == C(indx) then level = O(indx) end
                        return level
                    else
                        return nil
                    end
                end
                1. По сути да, так как второй цикл смещается! Но другого я понять и придумать не смог. Поэтому и задал вопрос. Есть несколько значений, которые надо сравнить между собой, кроме самого себя. В итоге при загрузке всё нормально. Но вот в процессе работы индикатора (появляются новые свечи) иногда линия соскакивает на собственное значение (зачастую любое из существующих). При этом после перезагрузки всё становится нормально. Может из-за того, что одна из функций меняется на тиках? Поэтому возникают ситуации, когда равенство то есть, то нет? Или же лучше переместить создание массива в if indx==1 ? Я просто запутался в логике индикатора. Но мне казалось, что сознавая массив внутри функции - он будет обновляться каждый раз при обращении к функции?! В любом случае, спасибо!

                  1. - "...что у большинства из них самооценка явно завышена"
                    Да считайте как хотите...
                    - "Вы же сами начали отвечать на мои вопросы!"
                    То есть мы еще и виноваты остались. В следующий раз кто то напишет чушь, вообще не отвечать не помогать, ни как не реагировать, вот это общение.
                    Люди разные, и мы не знаем кто там с другой стороны. Один может молча выслушать критику и продолжать упорно работать, а другой жаловаться начнет, что его обидел.
                    Вам черным по белому написали "Идите читайте основы" - И если Вы это воспринимаете как "ууу тщеславные, возгордились..." так это Ваша проблема, не наша.
                    Если Вы к примеру пришли к мастеру, который всю свою жизнь занимается своим делом, просите его научить, а он Вам говорит, вот возьми книжечку, почитай, а через год приходи. А Вы ему в ответ "ой какой гордый,самооценка завышена..." А чего Вы ожидали, что он Вас за станок поставит и Вы за 5 минут шедевр сделаете? Так вот один возьмет книгу и пойдет читать, а другой всем рассказывать, как его обидели.
                    Вот дали Вам готовый код, и что полезного Вы для себя вынесли? То что зря циклы написали? Так завтра Вы еще пятое значение захотите сравнивать, еще 4 условия поставите, а после завтра шестое добавите для сравнения, так функция в 1000 строк станет. Я не говорю что такой код писать категорически запрещено, да пишите, Вам с ним работать.
                    Вот только опять level глобальная, опять получите тоже самое что и у себя в коде. Ну поймите Вы (я сейчас Роману) научитесь читать происходящее, как до Вас донести. Не хотите брать ручку и лист бумаги, считайте в уме.
                    Пишу наипростейшим языком, без всяких понтов:
                    Запустили код. пошло выполнение сверху вниз.
                    Строка 1. В глобальную переменную level записали nil (черт знает зачем, ну ладно)
                    Строка 2. Объявляем глобальную функцию. НЕ ВЫПОЛНЯЕМ, только объявляем.
                    Все, код закончился. Так как это индикатор, скажем так, инициализация выполнена (естественно эта часть кода не запустится просто так в индикаторе, это следующим читателям, кто любит копировать, вставлять и запускать, а потом ругаться что в Интернете коды не верные пишут )
                    Кто то вызвал функцию Equality, начинаем выполнять.
                    Строка 4. Ну скажем так 99% что условие ИСТИНА (кто знает что автор передаст)
                    Строка 5. Если High == Low - допустим Да.
                    в level поместили High
                    Если High == Low то и Open и Close тоже равны High - или Вы другие бары видели.
                    Все условия выполнятся. Значит в 10 строке последний раз перепишется level, допустим в level записали 105
                    Строка 11 вышли из функции, вернули level (105)
                    Кто то опять вызвал Equality
                    Допустим что ничего не совпадает, ни одно условие не выполнилось, только if indx > 0 then выполнилось.
                    Строка 11. Что вернет функция? - nil ??? - Нет
                    А кто в level nil положил? Оно само должно там пропасть? Или рассчитываете на строку 1? - Так там только в момент инициализации в level nil записалось. Все, ни кто не стирал level, а значит там как лежало 105 с прошло раза, так и лежит, так что функция вернет? - 105 она вернет, хотя ни одно значение не совпадает.
                    И хоть 1000 раз вызывайте Equality. все равно получите 105, если не будет совпадений. А вот когда совпадение найдется, то level перепишется. Это Вам нужно?
                    Готовый код тем и плох, что мы понятия не имеем что Вам надо, а Вы понятия не имеете как оно работает.
                    Хорошо, запустили, заметили что не так работает. Что дальше, как искать ошибку. Если Вы хотите проверить верно ли работает функция, воткните message(indx .. " = " .. level) перед return level и запустите. В ответ Терминал повесится на несколько секунд, может минут, пока напечатает несколько тысяч сообщений, но он отвиснет. Посмотрите сообщения, что написано.
                    1 = 105
                    2 = 105
                    3 = 105
                    4 = 105
                    Открываете график и видите что первый бар действительно имеет совпадения, а вот 2 3 4 не имеет совпадающих цен, значит функция возвращает не то что Вы ожидали от нее. Первый шаг Вы сделали, нашли виновника. Ищите причину. Вот как в level попадает 105, если ни одно значение не совпадает? Да и при том что вообще ни O H L C ни кто не равен 105, откуда тогда в level 105 лежит? И вот что бы это понять нужна теория, книга, статья, да что угодно, где будет написано что глобальная переменная видна везде и всегда и зная это Вы сделаете вывод что никто не писал 105 в level на 2 3 4 барах а просто level никто не очистил.
                    Или чего Вы в книге ждете, что будет написано "если Вы объявили глобальную переменную, внутри функции в нее занесли значение, потом вызвали второй раз функцию, не стерли значение глобальной переменной и не присвоили внутри функции ей новое значение, то функция вернет старое значение". Да нет, так писать ни кто не будет книги, логически думайте.
                    Для toxa. Я не критикую Ваш код, я расписал его работы для Романа.

                    1. не знаю, как вы форум читаете, но я вот через ленту: quikluacsharp.ru/wp-admin/edit-comments.php это единственный адекватный способ, потому что структура каментов wordpress антигуманна и авторы движка должны гореть за нее в аду! в ленте по крайней мере написано: "В ответ автору toxa" со ссылкой на исходный камент. это тоже антигуманно, но в меньшей степени.

                    2. Спасибо, Павел! Очень Вам признателен! Эта мистика с работой индикатора, видимо, действительно происходит из-за глобальные переменных. Я попробовал закомментировать одну функцию, и после этого индикатор перестал выдавать половину меток из оставшихся функций. Хотя и ошибок не возникало. Просто не вернул значения. Видимо, нужно внутри функций использовать локальные переменные. Тогда работа индикатора будет стабильной! А глобальные только при создании таблиц в случае indx==1 при закрузке индикатора.

                    1. Да ничего я у Вас не спрашиваю, я код прокомментировал.
                      Ну если хотите вопрос, тогда такой: Почему не очищаете level ?

                    2. Павел, вы опять отвечаете на мой комент, адресованный не вам. Я знаю, что вы у меня ничего не спрашивали. Я не очищаю leval потому, что в оригинальном коде значение level тоже сохраняется между вызовами Equality(). Вы понимаете, что значит "эквивалентный код"? Это код, который приводит к точно такому же результату, что и исходный.

                    3. Ааа, так это Вы не мне написали, понятно, ну вот такие тут сообщения.
                      На счет кода, давайте закрывать тему, пусть автор сам решает, что ему нужно.

                2. тоха, в луа нет необходимости возвращать из функции nil, тем более определять для этого блок
                  вот так понятнее и быстрее, примерно в 14 раз:

                  1
                  2
                  3
                  4
                  5
                  6
                  7
                  8
                  9
                  10
                  11
                  12
                  13
                  14
                  15
                  16
                  17
                  18
                  19
                  20
                  21
                  22
                  23
                  24
                  25
                  26
                  
                  --нужно постараться забыть про глобальные переменные в луа вообще
                  --глобальные переменные нужны лишь для того, что бы подключаемый внешний модуль мог ее использовать
                  --во всех остальных случаях нужно использовать только локальные переменные
                  --доступ к локальным переменным быстрее в разы
                  local level = nil -- функция Equality прекрасно видит эту переменную
                   
                  local function Equality(indx)
                      level = nil --чистим значение с прошлой линии
                   
                  --сначала фильтры
                      if indx == 0 then return end --какой-то косяк, дальнейший расчет не имеет смысла
                   
                  --что бы не делать всеми любимую проверку на nil
                      local Open, High, Low, Close = O(indx) or 0,  H(indx) or 0,  L(indx) or 0,  C(indx) or 0
                   
                      if Open == 0 or High== 0 or Low == 0 or Close == 0 then return end -- тоже косяк, считать не будем
                   
                  --всё, фильтры прошли
                      if High == Low or High  == Open or High  == Close then
                          level = High; return
                      end
                      if Low == Open or Low == Close then
                          level = Low; return
                      end
                      level = Open
                  end
                  1. вы меня программированию собрались учить? дело не в том, есть смысл возвращать nili или нет. я явно все возвращаю в этом примере, чтобы у читателя кода не было неоднозначности в понимании. это раз. второе, с чего вы взяли, что это именно функция Equality - сам индикатор? может эта функция вызывается из другой с отрицательными indx? третье - ваш код не является эквивалентным. в оригинальной функции когда ничего ничему не равно значение level остается нетронутым, а у вас ему безусловно присваивается Open.

                    1. зачем мне вас учить программированию? не в этом цель.
                      вы написали пример, я написал пример, еще кто-то написал пример, а читатель сам выберет, что ему подходит лучше.
                      что бы у читателя не было неоднозначности, существуют комментарии.
                      я не оракул и не знаю - отрицательным может быть индекс? не указано явно, значит не может.
                      в вашем примере будет возвращать 0 периодически и этого никто не заметил, значит неоднозначность присутствует не явно.
                      мной ошибка допущена намерено, на внимательность, и ее тут же заметили и это радует.

                  2. я понимаю, что вы хотите помочь, но на самом деле, вы еще больше запутываете. у вашего кода есть несколько существенных недостатков:
                    1. он не эквивалентен, как я уже говорил выше
                    2. он не отвечает требованиям структурного программирования, в частности, из него много выходов.
                    3. он неприменим в качестве индикатора, что является нарушением требований автора. функция-индикатор обязана возвращать значение, если мы хотим, чтобы что-то изобразилось на графике.
                    4. синтаксический сахар типа вот этого: "local Open, High, Low, Close = O(indx) or 0, H(indx) or 0, L(indx) or 0, C(indx) or 0" хорошо выглядит, но не вносит ясности для человека, который с трудом улавливает смысл даже таких понятий как "локальная переменная".

                  3. и самое главное: вы пытаетесь исправишь ошибку в коде, не понимая, в чем она состоит. и я не понимаю, в чем она состоит. пока автор внятно русским по белому не объяснит нам, что должен делать его индикатор предлагать разные варианты решения его проблемы просто бессмысленно. тем более, НАМЕРЕННО допуская в своем решении ошибки.

                    1. а вы не пытаетесь исправить ошибку? 😉
                      по пункту 1, какая нафик эквивалентность? с чем? с примером, который не работает?
                      по пункту 2, ваш код тоже не должен присваивать level-у значение внутри функции - зачем, если это значение и так будет возвращено?
                      мало того, пока дело дойдет до строки return level, придется проверить все блоки if ...end, а это не правильно - о каком структурном программировании речь?
                      правильно вот так:
                      if H(indx) == L(indx) then return H(indx) end, получается противоречие пункту 2 - "в частности, из него много выходов."

                      по пункту 3, это не функция-индикатор, это обычная функция в вашем и процедура в моем случае, которая не обязана возвращать ничего
                      в итоге имеем:
                      вызов вашей функции так:

                      1
                      2
                      3
                      4
                      5
                      
                      level = nil
                      function OnCalculate(indx)
                          level = Equality(indx)
                          return level
                      end

                      и так:

                      1
                      2
                      3
                      4
                      5
                      
                      local level
                      function OnCalculate(indx)
                         Equality(indx)
                          return level
                      end

                      по пункту 4, ключевая фраза "хорошо выглядит", читабельно, даже без комментариев и ясности гораздо больше.
                      на счет "намеренной ошибки", а с чего все вдруг решили, что ошибка?
                      может автору нужно именно такое решение, что бы возвращалось дефолтное значение и оно совпадает с условием Open == Close?
                      никто не знает, кроме вопрошающего и даже он не знает.

                    2. конечно, я не пытаюсь исправить ошибку, я пытаюсь выяснить, что человек хочет!

                      эквивалентность с исходным кодом! у меня есть подозрения, что автор не понимает, что он написал. переписав его код, я показал, что именно у него написано. и задал наводящий вопрос: "а это ли вы имели в виду?". на что я получил ответ вроде "да, но нет", в котором опять ничего не понял, но это уже детали.

                      прочтите в википедии, что такое структурное программирование.

                      насчет того, как и откуда эта функция вызывается мы не знаем ровным счетом ничего. по-этому моя ЭКВИВАЛЕНТНАЯ функция ведет себя ТОЧНО ТАК ЖЕ. КАК ОРИГИНАЛЬНАЯ. в этом смысл рефакторинга.

                      мы не знаем, что хочет автор. он не может объяснить. по-этому предлагать решения и улучшать его код - бессмысленно. может ему нужно дефолтное значение, когда open == close. а может не нужно. это наука не установила.

            2. Роман76, а вы хамло.
              Развивая вашу идею про тщеславие, выходит, что создатель данного ресурса вообще очень опасный и самый тут тщеславный гордивец, который и днем и ночью только и думает, как бы навязать Роману76 какую то помощь, а потом расплыться тщеславной улыбкой и сильно сильно загордиться?
              Ошибаешься, ему, как и всем тут - насрать на тебя лично, с высокой колокольни.

              Вот я хлебнул литр водки и тебя не спрашивал - можно ли мне выпить литр водки, зато спрошу, а ты кто Роман76?
              С какой канавы ты вылез, что позволяешь себе такие высказывания?
              Где уважение к старшим? Ты с родителями так же разговариваешь?

              Если тебя мучает зависть, то подсыплю тебе угля:
              -я горжусь, что у меня три сына и две дочки и жена красавица
              -я гожусь своими текущими достижениями и будущими, как и многие здесь
              -я горжусь, что я не работаю, за меня работают мои роботы
              -я горжусь, что у меня самый быстрый робот в рунете
              Достаточно?
              Могу еще строк 500 на вскидку написать, чем я горжусь, завидуй, завидуй молча, хотя мне вообще пофик на тебя и на таких как ты.

              1. kalikazandr, не понял про строку 25. Почему просто Open в level пишем?
                Если O = 10; H = 15; L = 8; C = 13 - Никаких совпадений нет, но в level все равно окажется 10.
                Описаны 5 сравнений, а нужно 6. Не хватает сравнения Open == Close

              2. Задел! точно задел Ваше самолюбие! Рад за Вас! Только на личности не стоило переходить.. , и, кстати, хамите тут Вы мне, совершенно меня не зная. А это уже..! И кто старший ?))).. или это проявление гордыни опять?..)) Судя по вашим комментариям, до старшего лично Вы ещё не доросли!)) А завидовать мне нечему, особенно таким, как Вы! Таким, как Вы, грех завидовать и, как говориться, над такими грех смеяться! Остальное оставлю без комментариев. В своём поведении Вы достойны жалости и снисходительного отношения. Это лишний раз доказывает мою правоту относительно Вас. Удачи!
                P.S. сие для "kalikazandr"

                  1. Вот Вам бесплатный совет для долгой, здоровой и счастливой жизни: если Вам нечего сказать - тогда лучше промолчите! Так хотя бы будете умнее выглядеть. А то Вы уже своими словами поставили себе диагноз поставили и подписали приговор)))! И меньше пейте, чтобы не нести всякий бред! Всегда Будьте осторожны! В жизни не всегда можно спрятаться в сети под вымышленным псевдонимом! (для" kalikazandr" !)

  2. Всем доброго утра!

    Подскажите, а то я всю голову сломал, почему при последовательном выводе двух функций в индикаторе путаются линии Settings (значения выводятся не те и не там)? При выводе функций по отдельности всё нормально. Через SetValue всё нормально, на той линии, что и должно быть. А вот через return пробовал пропускать линии с помощью nil и просто последовательно выводить - и ничего.
    Вот абстрактный пример:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    Settings= {
    Name = "*Test",
    line =
    {
    	{Name = "high", Color = RGB(0,0,255), Type = TYPE_POINT, Width = 5,},
    	{Name = "low",Color = RGB(255,0,0), Type = TYPE_POINT, Width = 5,},
    	{Name = "open",Color = RGB(0,0,255), Type = TYPE_POINT, Width = 6,},
    	{Name = "close",Color = RGB(255,0,0), Type = TYPE_POINT, Width = 12,},
    	{Name = "middle",Color = RGB(255,255,128), Type = TYPE_POINT, Width = 3,},
     
    }}
     
    function Init()
    	return #Settings.line
    end
     
    function OnCalculate(indx)
    	if indx==1 then
    		return candles(indx), open_close(indx)
    	elseif
    		(indx==Size()) then return candles(indx), open_close(indx)
     
    	else
    		return candles(indx), open_close(indx)
    	end
    end
     
     
    candles=function(indx)
     
    	if C(indx)>O(indx)
    		then return H(indx)
    	elseif C(indx)<O(indx)
    		then return L(indx)
    	else return nil, nil
    	end
    end
     
    open_close=function(indx)
    	open=O(indx)
    	close=C(indx)
    	middle=(L(indx)+H(indx))/2
    	SetValue(indx-1,5,middle)
    return  open, close
    end

    Целую ночь думаю!)) Уснуть из-за этого не могу!))
    Дело в том, что в моём индикаторе два совершенно разных по принципу расчёта в двух блоках для линий. Поэтому нельзя их объединить в одной функции.

    1. Здравствуйте, Роман.
      Ну раз всю ночь не спали, то лучше все же для начала выспаться, на чистую голову думается намного лучше.
      Вообще линии не путаются, а вот значения в эти линии Вы записываете по разному.
      Что бы разобраться что происходит, уже не раз писал, производите вычисления руками.
      Итак, вычисляем код на 1 баре.
      В функции OnCalculate(indx) попадаем в строку 19.
      Сначала вызов функции candles(indx). Эта функция умеет возвращать High | Low | nil, nil. То есть, данная функция вернет ОДНО число или ДВА nil
      Позже разберем все варианты.
      Далее в строке 19 вызов функции open_close(indx). Эта функция устанавливает значение на предыдущем баре в 5 линию, а так же возвращает ДВА числа.
      Теперь подробно разбираем:

      1 Вариант: Open = 124.18 High = 125.78 Low = 123.56 Close = 125.08
      Функция candles(indx) возвращает High (125.78);
      Функция open_close(indx) возвращает Open (124.18), Close (125.08). Так же данная функция устанавливает значение middle (124.67), на предыдущем баре (бар 0), на 5 линию, а так как такого бара нет, то соответственно ничего не устанавливает.
      В строке 19 Записано return 125.78, 124.18, 125.08.
      Происходит установка значений:
      Линия 1 - 125,78 (High)
      Линия 2 - 124,18 (Open)
      Линия 3 - 125.08 (Close)

      2 Вариант: Open = 125.15 High = 125.93 Low = 124.05 Close = 124.25
      Функция candles(indx) возвращает Low (124.05);
      Функция open_close(indx) возвращает Open (125.15), Close (124.25). Так же данная функция устанавливает значение middle (124.99), на предыдущем баре (бар 0), на 5 линию, а так как такого бара нет, то соответственно ничего не устанавливает.
      В строке 19 Записано return 124.05, 125.15, 124.25.
      Происходит установка значений:
      Линия 1 - 124,05 (Low)
      Линия 2 - 125,15 (Open)
      Линия 3 - 124.25 (Close)

      3 Вариант: Open = 123.65 High = 124.07 Low = 122.11 Close = 123.65
      Функция candles(indx) возвращает nil, nil;
      Функция open_close(indx) возвращает Open (123.65), Close (123.65). Так же данная функция устанавливает значение middle (123.09), на предыдущем баре (бар 0), на 5 линию, а так как такого бара нет, то соответственно ничего не устанавливает.
      В строке 19 Записано return nil, nil, 123.65, 123.65.
      Происходит установка значений:
      Линия 1 - nil
      Линия 2 - nil
      Линия 3 - 123.65 (Open)
      Линия 4 - 123.65 (Close)

      Это описано для 1 бара. На 2 и далее барах происходит тоже самое, но еще и на линию 5 будет записываться middle. Значение middle попадет на все бары, кроме последнего. Так как при выполнении условия indx==Size(), функция open_close(indx) запишет значение на предпоследний бар.

      Из алгоритма видно, что в первую линию записывается либо high либо low. А Open и Close записываются либо в линии 2 и 3, либо в 3 и 4, соответственно. А так ли это задумано, Вам виднее.

      1. Сбасибо, Павел, за такое отличное подробное объяснение причины! Я так тоже интуитивно думал, что всё зависит от ситуации с выводимыми значениями. Но вот вопрос: как принудительно указать с помощью return только строго определённую линию для значения, если функции две и более? Через SetValue всё понятно: указываем номер линии и всё: если значение есть - то выводится, если нет - то не выводится. Оно никогда не попадёт на другую линию. А вот через return в одной функции можно логически указать все возможные варианты вывода с помощью nil и значений. А вот в двух функциях? - во второй-то как быть? ведь она не видит значений первой?

      1. Здравствуйте, Дмитрий! Вот-вот! Как раз в этом и дело. Функции выводятся последовательно, а значения не всегда имеются. Может действительно принудительно объявить выводимые переменные в определённой последовательности (по списку линий Settings))? Тогда значения всегда будут на своих местах!

    2. Привет!
      Явно объявить возвращаемые значения линий пробовали? Это важно.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      
      local old_indx = 0
      function OnCalculate(indx)
        local a, b, c, d, e
        a = candles(indx)
        b, c, e = open_close(indx)
        return a, b, c, d, e -- это хорошо, тут d всегда nil
      --return candles(indx), open_close(indx) - не правильно, т.к. эти функции возвращают больше 1-го значения
      end
      open_close=function(indx)
      	local open=O(indx)
      	local close=C(indx)
          if indx > old_indx then -- не нужно каждый тик заниматься херн...й
      	local middle=(L(old_indx)+H(old_indx))/2
             SetValue(old_indx, 5, middle)
             old_indx = indx
         end
        return  open, close
      end
      candles=function(indx)
      	if C(indx)>O(indx)
      		then return H(indx)
      	elseif C(indx)<O(indx)
      		then return L(indx)
      	end
      --return nil, nil  - нет нужды в такой записи.
      --если C(indx) == O(indx), вернет nil
      end
      1. Привет! Вот это идея! Принудительно объявить и закрепить последовательность. Тогда точно не перепутаются. И через return вывести последовательность переменных. Попробую. Очень интересно. А если какого-то значения внутри последовательности функции нет, то ставить на его место nil ?
        И спасибо за способ:

        1
        2
        3
        4
        5
        6
        
        local old_indx = 0
        if indx > old_indx then 
        	local middle=(L(old_indx)+H(old_indx))/2
               SetValue(old_indx, 5, middle)
               old_indx = indx
        end

        я такое встречал в кодах, но не понимал смысла сравнения с old_indx. Значит это нужно для расчётов только при появлении следующей свечи?!
        Огромное спасибо! А то я со своим индикатором совсем запутался. Хочу несколько индикаторов объединить в один и рассчитать новые относительные значения . Мне кажется, что один будет работать быстрее, чем несколько. Ведь для трейдера глаза - самый важный орган! Их надо беречь! Даже важнее. чем мозг))))!

          1. Точно!
            Между ног даже не орган, а function main(), так сказать!)))

            Вот ещё мучает меня такой вопрос:

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            
            function OnCalculate(indx)
            if indx == 1 then 
            a=15
            return val(indx) 
            end
            end
            val=function(indx)
            c = 20 - a
            return c
            end

            При этом в функции возникает ошибка. Переменная "а" не видна, хотя по сути, она глобальная.
            А вот, если объявить пустую таблицу (a={}),а потом поместить в неё значения внутри функции, то всё нормально работает.
            В чём же разница?
            Или я путаюсь в видимости переменных?

            1. Не знаю, ваш "абстрактный" пример вполне себе работает, т.к. это не полный код индикатора, то и сказать нечего.

              1
              2
              3
              4
              5
              6
              7
              8
              9
              10
              11
              12
              13
              14
              
              Settings ={}
              Settings.Name = "*T"
              function Init()
              	return 1
              end
              function OnCalculate(indx)
              	if indx == 1 then 
              		a=15
              		message("val= "..tostring(val(indx)))
              	end
              end
              val=function(indx)
              	return 20 - a
              end

              У меня ошибки не возникает

              1. Привет! У меня вот какая же штука:

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                
                function OnCalculate(indx)
                	if indx==1 then
                                         А = 10
                                       return Value
                         elseif
                                    (indx ==Size()) then 
                                      return Value
                          else
                                      return Value
                        end
                end
                function Value(indx)
                 b = H(indx) - a
                return  b

                а если объявить таблицу:

                1
                2
                3
                4
                5
                
                a = {} -- создать при условии (indx==1)
                --потом внутри функции Value:
                for i=1, 20 do 
                a[i] = i 
                end

                то в этом случае всё нормально: таблица создана, видна внутри функции, значения заносятся!
                И вот ещё с чем столкнулся. Вы говорили, что else return nil не обязательно в конце, так как если нет значения - то вернётся nil?
                Но я вот столкнулся с таким вопросом: имеем ряд значений, которые записываем в переменные в отдельных функциях.
                А потом в специальной функции находим равенство каких-либо двух значений из числа переменных.
                Ищем то, что равно чему-либо другому (кроме самого себя).
                И при этом, если в конце функции не поставить else return nil, то в случае, когда существующее значение перестаёт существовать (равенство пропадает на какой-либо свече), то линия начинает возвращаться на неправильном значении:
                Вот как у меня это выглядит:

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                
                Equality=function(indx)
                	val_table={}
                	if A ~=nil then
                		val_table[#val_table+1]=A
                	end
                	if B ~=nil then
                		val_table[#val_table+1]=B
                	end
                	if C ~=nil	then
                		val_table[#val_table+1]=C
                	end
                	if D ~=nil then
                		val_table[#val_table+1]=D
                	end
                	if E ~=nil then
                		val_table[#val_table+1]= E
                	end
                	for i=1, #val_table do
                		for j=1+i, #val_table do
                			if val_table[i]==val_table[j]
                				then
                				level = val_table[i]
                			end
                		end
                	end
                	if level ~= nil then -- если этого нет, то возникают неправильные результаты линии
                		return level
                	else
                		return nil
                	end
                end

                От чего такое может происходить?
                P.S. Остальная часть кода по принципу if indx==1 elseif indx==Size() else (между первой и последней свечкой).

                1. у вас не такая же "штука"
                  а ~= A, это разные переменные.
                  Вы пишете: "От чего такое может происходить?"
                  От того, что вы таким образом:
                  val_table[#val_table+1]= E
                  хезаете идею множественных линий, т.к. в разные линии будет попадать хз-какие результаты.
                  а вот таким - нет, каждой линии свое значение
                  val_table[1]= А
                  ...
                  val_table[5]= E

                  1. P.S.
                    Если ваш индикатор настолько важен и дает четкие сигналы, то резонно его купить и начать на нём зарабатывать, а уже потом сидеть и разбираться, в чём различие между вашей поделкой и рабочим алгоритмом.
                    Если это так себе индикатор, в чём я нисколько не сомневаюсь, то и смысла в нём нет.
                    Если вы не понимаете азов программирования (а судя по примерам так и есть), то индикатор это не самый легкий путь для изучения.

                    1. Так вот я и хочу научиться! Дело в том, что порой очень сложно бывает словами описать закономерность с первого раза. Надо экспериментировать и главное - смотреть, как графически реализуется идея. А подобного моему готового решения я не встречал. Обычно в готовых индикаторах много бессмысленных, порой сложных и главное, что совершенно ненужных математических формул, которые в большинстве случаев базируются на усреднении каких-либо параметров. А усреднение, как показывает практика, - это прямой путь к убыткам. Иной раз приходится раз 100 менять условия и подходы к оценке входных данных и фильтрам, годами тестировать стратегию на реальном рынке и в реальном времени, а также на истории. Это даже не месяцы, а годы! Я считаю, что та стратегия, которую нельзя описать с помощью алгоритма - не будет работать. Только строгие правила дают предсказуемые результаты. Вот моя стратегия год от года обрастает новыми закономерностями. Ей уже пять лет. И она ещё до конца не закончена. В итоге, когда закончу с индикатором, то буду пробовать создать робота, который при получении сигналов с индикатора будет входить в сделки с учётом рисков. Но это следующий этап. А насчёт смысла - то смысл в том, чтобы сократить время на поиск глазами повторяющихся закономерностей. При масштабировании графика, переключении ТФ, количестве графиков на экране - теряется внимание трейдера. А индикатор не подвержен эмоциям и его сосредоточенности всегда одинакова. Вот в этом и состоит моя цель. И я очень благодарен Вам за помощь и поддержку.

                  2. А насчёт val_table[5]= E - это отличное решение. Действительно, нужно сравнивать то, что существует на текущий момент, хотя даже в моём варианте последние совпадения в здоровенном массиве val_table (своеобразный приоритет при выводе одной линии индикатора) будут выводиться индикатором. И, вроде бы, всё правильно, но вот массив огромный. А в Вашем, гениальном для меня, подходе данный вопрос решён определённым образом. Массив маленький, обход быстрый и последнее реальное равенство - результат на линии индикатора. Всё, как всегда, просто здорово. И ещё. Мне нравятся Ваши подходы своей неординарностью по отношению к общепринятым стандартам! Ещё раз спасибо!

                    1. Не за что, на счет гениальности, это преувеличение сильное.
                      На счет поиска закономерностей, может и есть смысл, но график это всего лишь график, закономерностей в нем нет и не может быть или могут быть, но больше не повторяться никогда! и это нормально.
                      Я в свое время перепробовал все индикаторы какие есть в квике, своих написал множество и чужих
                      Ни в совокупности, ни в частности индикаторы не дают ни каких гарантий движения цены.
                      Если есть деньги, то обычная стратегия на 2-х ема даст денег достаточно для жизни, а если денег нет, то нет.
                      В торговле важно "здесь и сейчас", что было, то было, а что будет, того никто не знает, уже на понимании этого можно строить стратегию, без всякой визуализации и зарабатывать 50-60% в год, но опять же - с каких денег такая прибыль интересна?

      2. Не очень хорошо использовать old_indx в таком варианте.
        Один раз индикатор выполнит все что необходимо, но после того как пользователь сменит ТФ, произойдет перерисовка графика, все линии индикатора будут уничтожены, а функция OnCalculate(indx) будет вызвана с параметром от 1 до последнего бара. Попадая в строку if indx > old_indx then условие выполнено не будет, так как indx = 1, а old_indx, к примеру, 1254. Переменную old_indx нужно обнулять. Это можно сделать например, когда indx = 1.

        1
        
        if indx==1 then old_indx = 0 end

        На счет изменения строки "local middle=(L(old_indx)+H(old_indx))/2", не знаю, автору виднее с какого бара нужны цены.

  3. Всем привет!
    Вы уж простите за глупый вопрос?!
    Я что-то запутался!))
    Объясните, пожалуйста такую конструкцию:

    table[i] = {(indx), tab[value]}
    i = i+1

    Почему у indx скобки круглые? Это ключ? или?
    И как из такого массива достать (indx)? По индексу массива [i]? Тогда как будет выглядеть ячейка массива без квадратных скобок?

    1. Ну раз Вы привели просто переменные, без пояснения что в них лежит, тогда конструкция звучит так:
      В таблицу table, в элемент с ключем i записываем таблицу, в которой создаем элемент с ключем indx и значением из элемента таблицы tab с ключем value.
      Почему у indx круглые скобки, это лучше у автора кода спросить. Возможно это не изначальный код, а его уже сотни раз резали, а круглые скобки остались. Из того что сейчас есть, можно сказать что отсутствие круглых скобок не повлияет на работу.
      indx - это ключ, как вообще из таблицы достать какой то ключ? Мы по ключу получаем некое значение, на то он и ключ. Или необходимо получить значение элемента с ключем indx?
      Если значение, то так:
      local tmp = table[i][indx];
      А список ключей можно получить перебором таблицы. но может Вы хотите получить ключ у которого известное значение, тогда перебор всех ключей и сравнение значений с образцом. А вот если не известно ни названия ключа, ни значения, то вообще что Вы ищите, в таком случае, непонятно.
      А вот как будет выглядеть ячейка без квадратных скобок, это уже вопрос олимпиадный. В "ячейках" лежат значения, числа, текст, функции .... о каких квадратных скобках идет речь, непонятно.
      Либо Вы хотите получить значение элемента из таблицы не используя квадратные скобки, тогда так:
      local tmp = table.i.indx;
      Но в такой записи i и indx это НЕ переменные, это и есть названия ключей. То есть в table должен быть элемент с ключем "i", а в значении лежать таблица в которой есть элемент с ключем "indx". Запись с квадратными скобками была бы записана так;
      local tmp = table["i"]["indx"];

      А теперь немного отступление. Если Вы изучаете LUA, что мешает выполнять проверки самостоятельно? Просто всегда было интересно, каким способом человек, который только только начинает изучать язык программирования, двигается вперед и развивается. Мне всегда интересен такой вариант "а что будет, если..." Так я изучал LUA. Читаю книгу, там описан пример я его копирую, запускаю и смотрю на результат. А потом начинаю этот пример менять "а что будет, если..." Изменил, запустил, результат не изменился, значит и так можно писать, изменил, запустил, не запустился вообще, значит так нельзя писать, изменил, запустил, а результат другой получился, "а почему так произошло, почему другой результат?" - отправляюсь читать книгу...

      1. Доброго..! Спасибо за Вашу помощь мне! Тут вот на самом деле:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        
         function OnCalculate(idx)
        	if idx==1 then
        		P = math.floor(Settings.period/2)*2+1 -- точка фрактала, Settings - период индикатора Fractals
        		t_H,t_L={},{} -- таблицы значений ХАЙ и ЛОУ
        		t_Fr_H={} -- таблица фракталов ХАЙ
        		t_Fr_L={} -- таблица фракталов ЛОУ
        		th=1 -- нумератор для t_Fr_H[th]
        		tl=1 -- нумератор для t_Fr_L[tl]
        	end
         
        		if idx~=nil and idx>P then
        			if idx_prosl~=idx then
         
        				---- занесение в таблицы ХАЙ и ЛОУ
        				for l=idx-P,idx-1 do
        					t_H[l]=H(l)
        					t_L[l]=L(l)
        				end
         
        				-- нахождение фракталов
        				if t_H[#t_H-(P-1)/2]==math.max(unpack(t_H,#t_H-P+1,#t_H)) then
        					t_Fr_H[th]={(idx-1-(P-1)/2),t_H[#t_H-(P-1)/2]} -- и вот эта штука
        					th=th+1 -- увеличения индекса таблицы
        				end
        				if t_L[#t_L-(P-1)/2]==math.min(unpack(t_L,#t_L-P+1,#t_L)) then
        					t_Fr_L[tl]={(idx-1-(P-1)/2),t_L[#t_L-(P-1)/2]}
        					tl=tl+1
        				end

        и вот после этого мне необходимо добавить фильтр параметров (H,L,O,C,V) для свечки фрактала, чтобы затем либо использовать данный фрактал, либо нет. И тут вопрос в том, как получить из t_Fr_H[th], например, свечку, к которой впоследствии применить дополнительный фильтр, так как, когда фрактал индикатора будет сформирован, то индексы свечей уйдут на половину периода вперёд. Или же проще при формирование фрактала сразу посмотреть, например, H(-math.floor(Settings.period/2)*2+1) - ту свечку, на которой он образовался. Но тогда сложнее после образования уже нескольких фракталов для последующего анализа? Придётся сознавать новый массив, куда заносить H,L,O,C,V фракталов. Поэтому, на мой взгляд, лучше получить и проанализировать свечку тогда, когда это понадобится. Так вот и вопрос, как вызвать (idx-1-(P-1)/2) из t_Fr_H[th] ?

        1. Да уж...
          Вопрос как я понял один "как вызвать из t_Fr_H[th]"
          Так и вызывайте t_Fr_H[1], t_Fr_H[2] ...
          В результате получите таблицу, в которой будут еще ключи и значения.
          Теперь. Вам известен ключ? - получайте значение по ключу. Не известен ключ, но известно значение - перебирайте все ключи и выполняйте сравнение с известным значением, пока не найдете нужное значение, после того как нашли, смотрите ключ. Не известен ни ключ ни значение - невозможно получить данные не имея вообще ничего.

          1. Спасибо Вам, Павел огромное! Если я правильно понял, то в t_Fr_H[1] будут параметры (H,L,O,C) свечи из источника данных OnCalculate по графику инструмента? Или это не так? Или, может нужно получить номер(индекс) этой свечки свечки от начала истории открытого графика? А потом по этому номеру её идентифицировать? Либо вообще по-другому :сначала каждую свечку анализировать, потом, если какая-то свечка соответствует необходимому условию - то смотреть, является ли она фракталом(есть ли она в t_Fr_H или t_Fr_L)?

            1. Что то я не нашел где Вы в t_Fr_H записываете H L O C
              t_Fr_H[th]={(idx-1-(P-1)/2),t_H[#t_H-(P-1)/2]}
              Распишу
              t_Fr_H[th]={"ключ",значение}
              ключ - (idx-1-(P-1)/2)
              значение - t_H[#t_H-(P-1)/2]
              Как видим, значение получаем из таблицы t_H, в которой есть ключ: #t_H-(P-1)/2.
              Отправляемся в таблицу t_H
              t_H[l]=H(l)
              В таблице лежат H
              Может я не заметил, где Вы в таблицу поместили O L C

                1. Добрый вечер! Вот я сначала так и думал! Только меня круглые скобки смущают. Я думаю, как без дополнительных таблиц HLOC достать эти значения из встроенного в основную функцию индикатора источника. Как H(indx-((P-1)/2), например, только для фрактала в любой момент и с любой текущей свечки. Тогда вот и надо точно знать индекс свечи фрактала..!

                  1. скобки в математическом выражении, коем является (idx-1-(P-1)/2) определяют приоритет операций. внешние скобки тоже, хотя в них и нет смысла. фигурные скобки - конструктор таблицы. в эту таблицу помещаются два элемента с ключами по-умолчанию. первый элемент с ключом 1, второй - с ключом 2.

                    если я вас правильно понимаю, то мы мучаем некий индикатор, исходник которого лежит здесь: smart-lab.ru/blog/325360.php

                    судя по исходнику, то, что вы называете "фракталом" - это есть некое значение H, которое является локальным максимумом на каком-то интервале idx. аналогично со значением L. теперь возвращаемся к вашему вопросу: "как без дополнительных таблиц HLOC достать эти значения из встроенного в основную функцию индикатора источника". очень просто. вам нужно знать интервалы idx, которые им соответствуют. и вызывать функции H(), L(), O(), C(), передавая в них значения из этих интервалов.

                    1. Да, верно! Это есть тот код! Его начальную часть я и хотел использовать, так как по сути это и есть индикатор фракталов, который их соединяет. С фракталами-то всё понятно. Для меня важно их отфильтровать, а потом уже доделать вторую часть индикатора (рисовать от последней свечи до фрактала линию, при этом, чтобы она не пересекалась с графиком цены). Для этого мне и нужно было понять, как получить HLOC прошлых свечей, опираясь как раз на таблицу значений фракталов t_Fr_H[th] или t_Fr_L[tl], не загоняя предварительно в указанные таблицы или в другие массивы лишние значения.

                  2. несмотря на то, что вы пишите "С фракталами-то всё понятно.", очевидно, что ничего вам "с фракталами" не понятно. 🙂 судя по всему, вы не понимаете, как данный индикатор хранит данные в своих массивах. во-первых, нет такого понятия "фрактал", или вы не можете внятно объяснить, что вы под ним подразумеваете. поясню. данный индикатор считает локальные максимумы (хранит их в таблице t_H) и локальные минимумы (хранит их в таблице t_L). нет никакого "фрактала", который бы объединял эти значения, интервалы локальных максимумов и локальных минимумов не связаны между собой. это видно по скриншоту. что такое "точно знать индекс свечи фрактала" нам остается только догадываться.

                    1. даже не так. t_H это просто таблица H, t_L это просто таблица L. значение индикатора меняет значение, когда H середины интервала становится равно максимуму за интервал. с минимумами то же самое, только L и min. вот и весь грааль.
                      после того, как мы разобрались, что же именно происходит, вам нужно понять что, куда и откуда вы хотите изобразить. если вы хотите рисовать что-то от края горизонтальных линий, которые порождает данный алгоритм, то нужно запоминать индекс свечей, на которых значения изменяются. если что-то другое - то другое, но вы должны для себя четко прояснить алгоритм и, если вы хотите, чтобы вам помогли, постараться внятно объяснить его собеседникам. 🙂
                      удачи.

                  3. кроме того, и автор данного индикатора тоже не был особо в курсе, что такое "фрактал", иначе не назвал бы так свое поделие. возможно, ему просто понравилось слово: звучит красиво и загадочно.

                    1. Наверно Вы в термин фрактал вкладываете его более широкое понимание. Вместе с тем в понимание фракталов, как индикатора - это, по сути то, что в первой половине этого кода. В терминале родной индикатор Fractals по сути повторяет те же действия, только написан через применение некого ряда универсальных функций с параметрами на все случаи жизни. Впрочем все родные индикаторы в Квике на LUA написаны как под копирку. Да, нужен локальный хай за большой период, чтобы вычислить экстремум, далее посмотреть HLOC свечки фрактала и согласно необходимым соотношениям данных параметров или использовать в дальнейшем этот фрактал или нет. А сам по себе фрактал - вещь бессмысленная и бесполезная (по крайней мере на сегодняшнем рынке). Наличие фрактала, или как угодно его ещё называть, подразумевает наличие свечи, вот я и думаю, как имея таблицу фракталов выйти на свечки этих фракталов по индексам значений этих таблиц?!

                    2. ок, не важно, как называется.

                      вы все время говорите о "фрактале" в единственном числе. но совершенно не ясно, что вы под этим подразумеваете. дело в том, как я уже говорил, оригинальный индикатор рожает две, не связанных между собой, линии: одну по локальным максимумам, другую - по локальным минимумам. считаете ли вы "фракталом" горизонтальный отрезок, построенный по максимумам? или по минимумам? или набор свечей между этими линиями, но что тогда делать с тем, что отрезки заканчиваются на разных свечах?

                    3. +100500 не в курсе.
                      то что индикатор smart-lab.ru/blog/325360.php работает, не означает, что этот метод можно использовать для своих целей. Задача, которую с таким трудом "вытянули" из автора топика решается просто:
                      1. на график добавить индикатор Fractals от арки
                      2. добавить на график свой индикатор, который выполняет следующее:
                      - при каждом изменении индекса в OnCalculate(idx) рисовать виртуально отрезок от фрактала 1 до фрактала 2.
                      - сравнивать, что на промежутке от фр1 до фр2 цена не пересекала "виртуальный" отрезок.
                      Если не пересекала - отобразить линию, пересекала - нет.
                      Роман76, еще раз повторюсь, не нужно одну задачу делить на фрагменты и задавать вопросы в разных топиках.
                      Не нужно сразу решать сложные задачи, разделите их на простые, поймите как работает, а уже потом задавайте вопросы.
                      Мне не жалко вам дать готовое решение, но у меня его нет, а у кого оно есть может не дать. А специально делать я не буду, потому что оно никому не нужно, да и вы про этот "чудо" индикатор забудете через неделю, после того как сделаете и получите убыток от сделок по "сигналам" этого индикатора.

              1. Другими словами, надо дополнить остальными значениями L O C V таблицу t_H ? А потом эти значения оттуда достать? Получится огромный массив по все свечам!

                  1. Вот я и хотел сделать индикатор полегче, чтобы работал и загружался быстрее. А то, если штук 10-15 инструментов - то Квик точно задумается до следующего клиринга!))

                    1. У Вас в коде столько циклов, что он во время торговли может помереть.
                      В реальном времени сделки поступают с интервалом менее секунды, каждая новая сделка приводит к вызову OnCalculate. Весь этот алгоритм будет выполняться несколько раз за секунду.

                  1. Здравствуйте! А что такое I в таблице? Это индекс свечки?
                    Но ведь это индекс свечки
                    из таблицы t_H[l] только за период
                    (P = math.floor(Settings.period/2)*2+1)?
                    А если эта свечка дальше, чем пол периода? Если это, например, прошлый или позапрошлый фрактал?

                    1. а какая разница? в цикле заполняется таблица фракталов от 1 до inx и I это индекс, который соответствует фракталу

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

                    1. лучше держать фракталы в одной таблице подряд и по L и по H экстремумам, и работать с одной таблицей.

              2. Тут дальше совсем для меня чертовщина какая-то!))) Соединяются любые фракталы из таблицы. А мне надо только строго определённые фракталы по фильтру HLOC для начала построения линии тренда плюс идентификация разворотных свечей на фракталах.

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                19
                20
                21
                22
                23
                24
                25
                26
                27
                28
                29
                30
                31
                32
                33
                34
                35
                
                 				if #t_Fr_H>=3 and #t_Fr_L>=3 then 
                					i_bar=idx 
                					dd=#t_Fr_H 
                					for s=#t_Fr_H-1,1,-1 do 
                						if t_Fr_H[s][2]>=t_Fr_H[dd][2] then
                							d=s
                						break
                						end
                					d=s
                					end
                					if d==1 then
                						H_ind_value=t_Fr_H[dd][2] 
                					else
                						H_ind_value=((i_bar-t_Fr_H[d][1])*
                						(t_Fr_H[dd][2]-t_Fr_H[d][2])/
                						(t_Fr_H[dd][1]-t_Fr_H[d][1]))
                						+t_Fr_H[d][2]
                					end
                						dd=#t_Fr_L 
                					for s=#t_Fr_L-1,1,-1 do 
                						if t_Fr_L[s][2]<=t_Fr_L[dd][2] then
                							d=s
                						break
                						end
                							d=s
                					end
                					if d==1 then
                						L_ind_value=t_Fr_L[dd][2] 
                					else
                						L_ind_value=((i_bar-t_Fr_L[d][1])*
                						(t_Fr_L[dd][2]-t_Fr_L[d][2])/
                						(t_Fr_L[dd][1]-t_Fr_L[d][1]))
                						+t_Fr_L[d][2]
                					end
                				end
                1. По моему Вы единственный, кто понимает, что происходит в коде.
                  d, dd, t_Fr_H, t_Fr_L ... по таким именам не реально ориентироваться. Вы то их понимаете, сами же создавали, а нам то как в них ориентироваться. Бегать по комментариям и искать что где лежит. Тем более не понимая что нужно получить. "строго определённые фракталы по фильтру HLOC" какому фильтру, "плюс идентификация разворотных свечей", и как их идентифицируете... В общем это Вам разбираться.

                  1. 1
                    2
                    3
                    4
                    
                    L_ind_value=((i_bar-t_Fr_L[d][1])*
                    				(t_Fr_L[dd][2]-t_Fr_L[d][2])/
                    				(t_Fr_L[dd][1]-t_Fr_L[d][1]))
                    				+t_Fr_L[d][2]

                    Вот кусок Вашего кода. Вы можете руками посчитать значение переменной L_ind_value ?
                    Вы поймите, что бы код успешно работал, нужно в любой момент времени знать что должно лежать в любой переменной, а потом проверить, а действительно ли там лежит то что должно, или там лежит что то другое, если так, то откуда оно, это другое, там взялось.

        1. ахах) красава, тогда вопрос понятен, уравнение прямой вам очень подойдет, точнее уравнение единичного отрезка.

          график можно представить в виде осей ординат, где каждый бар может быть нулевой точкой, тогда расстояние по оси OX(в барах):
          x = index1 - index0, где индексы это ваши фракталы
          цены этих фракталов y0 и y1 соответственно, это ось OY, где y0 будет нашим b, т.е. смещением относительно оси OX.
          вычисляем коэффициент, который будет определять по сути угол наклона прямой и хорош,
          для вычисления любой точки удаленной от x0 достаточно функции Point

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          
          local function Koeff ( x, y0, y1 )
          	return ( y1 - y0 ) / x
          end
          local function Point(k, x, b)
          --b = y0
          --x = index - x0
          	return k * x + b
          end
          --это расстояние от двух заданных фракталов,  index0  содержит точку x0 = high or low (нулевой фрактал)
          local x = index1 - index0
          local k = Koeff(x, y0, y1)
          local point = Point(k, x, y0)

          это решение для рисования линий тренда/беломор-канала, пользуйтесь.
          в вашем случае вы хотите рисовать зиг-заги по сути, и ваши index0 будут смещаться в index1.
          а пересекает цена эту прямую или нет, эта задача мне не по силам, хз как узнать.
          да, чуть не забыл, учителю математики расскажите потом, пусть пол-литра мне зашлет.

              1. Да фик с ней, x0 это нулевая точка, просто кого-то могут смутить комментарии, в одном случае это цена в другом индекс, а в коде вообще ее нет)

  4. Господа! Всем Доброго..! Подскажите, как добавить в индикатор звуковое оповещение (алерт) в случае, например, пересечения ценой уровня, созданного индикатором или при смене возвращаемого индикатором значения?

      1. Спасибо огромное! Смотрел, читал, изучаю! Пробовал добавить звуки в индикатор. Получилось. Теперь вот размышляю об остальных возможностях w32.

      1. Добрый день, Дмитрий! Подскажите, есть ли у Вас какая-нибудь статься об использовании библиотеки w32.dll в скриптах и индикаторах? Или примеры и варианты использования?

          1. Никак не пойму, как установить алерт в индикатор, попробовал на значения возвращаемых параметров:

            1
            2
            3
            4
            5
            
            w32 = require("w32")
            	if C(idx) == H_ind_value or C(idx) == L_ind_value then
            		sound = w32.MessageBeep(w32.MB_OK)
            	return sound
            	end

            и ничего не получилось! или надо выводить ещё переменную звука?

            1. сам факт вызова w32.MessageBeep(w32.MB_OK) воспроизводит звук. нет нужды что-то куда-то возвращать. если звук не воспроизводится, значит ваше условие не выполняется. вы проверяете на равенство, а надо бы на "меньше минимума" или "больше максимума". сравнение чисел с плавающей точкой на равенство вообще не очень хорошая идея.

                1. вам нужно определить для себя, что вы подразумеваете под словом "касание". предположим, цена инструмента 1.34, а значение индикатора 1.34000001. это касание? с "пересечением" еще сложнее. дело в том, что индикатор считается не непрерывно, а в некоторых точках, которые соединяются отрезками. вам нужно знать старое значение индикатора и новое, и далее решить геометрическую задачу из курса средней школы.

                  1. Геометрические задачи - не мой конёк!)) Но у меня получилось. Тут всё проще. Нужен был алерт для индикатора фракталов с возвращаемым значением. На графиках ликвидных фьючерсов при касании возвращаемого значения индикатора.

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    
                    H_ind_value=t_H[#t_H-(P-1)/2]
                    L_ind_value=t_L[#t_L-(P-1)/2]
                     
                    	w32 = require("w32")
                    	if C(idx) == H_ind_value or C(idx) == L_ind_value then
                    		w32.MessageBeep(w32.MB_OK)
                    	end

                    сигнал есть при совпадении цены.
                    Осталось только понять, какие есть варианты звуков в этой библиотеке. Где бы список найти?

                    1. я же дал вам ссылку. вот прям под этим сообщением.

                    2. главное, чтобы вы сами понимали что и зачем вы делаете. 🙂 мне ваши действия понимать не обязательно.

        1. вот тут: quik2dde.ru/viewtopic.php?id=78 есть список функций, которые есть в этой библиотеке. там же в обсуждении есть про использование. если нужно ознакомиться подробнее с каждой функцией и что она делает, то, вот, msdn вам в помощь: docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebeep

          1. А, да, спасибо огромное, сейчас смотрю! Только вот интересно, при загрузке индикатора w32.MessageBeep(w32.MB_OK) выдаёт только текущие алерты, а при использовании примера:

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            
             		--poluton = 2 ^ (1/12)
            -- определим константами частоты гармонического звукоряда
            		--A1 = 440
            		--B1 = A1 * (poluton ^ 2)
            		--C1 = A1 * (poluton ^ 3)
            		--D1 = A1 * (poluton ^ 5)
            		--E1 = A1 * (poluton ^ 7)
            		--F1 = A1 * (poluton ^ 8)
            		--G1 = A1 * (poluton ^ 10)
            		--A2 = A1 * (poluton ^ 12)
            		--B2 = A1 * (poluton ^ 14)
            		--C2 = A1 * (poluton ^ 15)
            -- играем звуки вверх
            		--music1 = {C1, E1, G1, C2}
            		--for i, tone in ipairs(music1) do
            			--w32.Beep(tone, 100)
            		--end
            --sleep(300)
            -- играем звуки вниз
            		--music2 = {C2, G1, E1, C1}
            		--for i, tone in ipairs(music2) do
            			--w32.Beep(tone, 100)
            		--end

            внутри того же условия при загрузке индикатора проигрывает звук по всем свечам из истории. Почему? В чём разница?

            1. ну во-первых в вышем примере все строки закомментарены. во вторых, я вообще ваш код не понимаю. что вы хотели этим сказать:

              1
              
              H_ind_value=t_H[#t_H-(P-1)/2]

              ?!

              1. Закомментированы - это я потом сделал, чтобы эта часть кода не работала. А H_ind_value=t_H[#t_H-(P-1)/2] - это просто выводимое значение индикатора. Это просто другая функция - w32.Beep. И работает она по-другому (по всем свечам при загрузке) в отличие от MessageBeep. вот в чём вопрос.

                    1. я имел в виду, ваш скрипт, который вы запускаете.

                  1. я фрагмент этого скрипта поместил в свой индикатор. внутри условия, так же как MessageBeep, но вот результат оказался совсем другой - при загрузке бежит по всей истории и пиликает!)) и КВИК висит!

                    1. повторяю вам: ошибка в 17 строке вашего скрипта.

                    2. а если серьезно, то пока вы не поймете смысл того, что вы написали тут:

                      1
                      
                      H_ind_value=t_H[#t_H-(P-1)/2]

                      вы не продвинитесь в поиске проблемы.

  5. Доброго времени, Господа! Подскажите, можно ли с помощью table.insert вставлять элементы в многомерный массив, если их парное количество совпадает?

    1. не совсем понятно, что вы имели в виду. ответ: да, можно, но, скорее всего, вам это не нужно.

      ps: в lua нет массивов, таблицы - это key-value хранилища. получая значение "по индексу" выражением вроде a = tbl[5] - на самом деле вы достаете из dict некое значение с ключом типа number, которое имеет значение 5. все эти insert, remove - они просто перенумеровывают ключи, из-за этого они довольно медленные, особого смысла в их использовании нет.

      1. Просто размышляю, с чем проще и удобнее работать: может со строковыми функциями? Например, создаём многомерный массив с параметрами опционов, которые отбираем при помощи фильтров перебираемых таблиц инструментов, когда получаем необходимый опцион - добавляем в таблицу, например, страйк, открытый интерес с помощью table.insert , указывая часть (ключ) таблице (например "Strike"), или же перебираем с помощью string.gmatch, а потом помещаем в таблицу. Или же проще и быстрее работать с массивами традиционным способом без строковых функций?

      2. Или же вот, например, создать таблицу параметров опционов наподобие getQuoteLevel2 только для доски опционов, поскольку специальной функции для получения данных из доски опционов нет. После этого можно спокойно обрабатывать все цены, греки и другие параметры для построения индикаторов на графике базового актива.

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

          1. я вообще заметил странную вещь в Квике! такое впечатление, что индикатор с глобальными переменными работает быстрее. хотя это как-то странно! но, поскольку, я больше трейдер, чем программист, поэтому многие вещи мне в диковинку. поначалу покупал что-то- и в итоге получал не то, что надо или то, что не может нормально работать в виде скомпилированного кода. вот и приходится хоть насколько-нибудь немного самому пытаться понять суть некоторых вещей. так что заранее извиняюсь за порой глупые вопросы. я так понимаю, Вы ребята очень подкованы в вопросах разработок. и вообще - данный ресурс, по моему убеждению, лучший в своём роде. поэтому очень Вам благодарен за помощь и поддержку!

            1. очевидно, "индикатор с глобальными переменными" работает не так, как другой индикатор потому, что различаются алгоритмы. от того, что вы пишите i = 1 вместо local i = 1 в функции OnCalculate() - на скорости это сказывается примерно никак.

        2. пользуйтесь.

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          
          function opcode_totab(ticker)
          	-- возвращает таблицу с кодом опциона, смотри у моекс
          	-- t[1] = C, t[2] = P, t[3] = K, t[4] = M, t[5] = Y, t[6] = W
          	local t = {}
          	t[1], t[2], t[3], t[4], t[5] = ticker:match("(%a%a)([%d%.]+)(%a)(%a)(%d)(%a-)")
          	local x = ticker:sub(-1) --м.б недельки?
          	t[6] = (tonumber(x) and "") or x
          	return t
          end
          locat t = opcode_totab("Si62500BX9")
          t[2] = 63000
          t[4] = "L"
          message(table.concat(t), 2) --> Si63000BL9
           
          table.remove(t, 2)
          --получаем уникальный ключ для выбранной серии call-опционов:
          message(table.concat(t), 2) --> SiBL9
  6. добрый вечер!
    нуждаюсь в помощи...
    пишу индикатор...
    Settings=
    {
    Name = "xerman",
    period=4,
    line=
    {
    {
    Name = "High",
    Type =TYPE_LINE,
    Width = 1,
    Color = RGB(120,90, 140)
    },
    {
    Name = "Low",
    Type =TYPE_LINE,
    Width = 1,
    Color = RGB(120,90,140)
    }
    }
    }

    function Init()
    return 2
    end
    function OnCalculate(index)
    local induc=0
    local vxod=60
    local diap=math.abs(C(index)-C(index-1))
    t={}
    t[#t+1]= diap
    Period = Settings.period
    if #t<Period then
    return nil
    else
    local sum=0
    for i=#t-Period+1, #t do
    sum=sum+diap
    end
    induc=sum/Period
    end
    return induc, vxod
    end

    мне нужно посчитать среднее значение нескольких последних разниц цен закрытия.... не понимаю синтаксис языка... в общей сложности 10 часов провел переписывая код, вставляя в график и получая шлямбуром по подбородку....
    я так понимаю у меня есть переменная diap и когда я просто пишу return diap, то индикатор строится и показывает мне значения разниц, а вот как среднюю то от них взять???????????????????????????????????????
    я догадываюсь что надо создать массив в который эта переменная diap будет наполняться новыми значениями, но как это реализовать хоть убейте не пойму....
    помогите пожалуйста, умоляю....

    1. Здравствуйте, надеюсь поможет

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      
      main = function()
         -- Создали массив
         Arr = {}
         -- Заполнили его значениями
         for i=1, 100 do
            Arr[i] = i
         end
         -- Вычисляем и выводим средние за каждые 5 последних значений (период 5)
         for i=5, 100, 5 do
            local Sum = 0
            for j=4,0,-1 do
               Sum  = Sum  + Arr[i-j]
            end
            message(tostring(Sum/5))
         end
      end
      1. спасибо огромное, правда решил задачу без массива уже, но то что вы написали очень мне поможет в моих следующих муках. еще раз спасибо огромное)

          1. вобщем.... тупица я непрошибаемый... ничего не выходит у меня с массивами...
            доброго времени суток=)
            T={} - создал массив
            function onalltrade(alltrade) - написал функцию
            if alltrade.sec_code == "RIZ9" then
            local a=alltrade.qty - написал что переменная должна получать из функции
            end
            return a - вернул значение переменной
            end
            T[i]=i - а вот тут пытаюсь ежика родить.............. что делать не понимаю.....
            for i=a, (а вот до чего здесь писать??????????????????? p.s. for i=1, 100 do - это ясно. а в моем то случае как мне получить этот злосчастный массив состоящий из {a1,a2,a3,......................an}?????????????????????????????????????????????????????????)

            1. "return a" у вас возвращает nil, т.к. она объявлена локально внутри блока if .... end, и на выходе из блока ее уже нет.
              function onalltrade(alltrade)
              if alltrade.sec_code == "RIZ9" then
              return alltrade.qty
              end
              return 0
              end