Арифметические операции, операции сравнения и логические операции в QLua (lua)

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

Qlua-основыАрифметические операции:

-- "+"   сложение
A = 2 + 3; -- в переменной A число 5
 
-- "-"   вычитание
A = 5 - 2; -- в переменной A число 3
 
-- "*"   умножение
A = 2 * 3; -- в переменной A число 6
 
-- "/"   деление
A = 6 / 3; -- в переменной A число 2
 
-- "^"   возведение в степень
A = 2 ^ 3; -- в переменной A число 8
 
-- "%"   остаток от деления
A = 5 % 2; -- в переменной A число 1
 
-- ".."  конкатенация (склеивание строк)
s = "lua";
A = "quik"..s.."csharp.ru"; -- в переменной A строка "quikluacsharp.ru"


Операции сравнения:

-- В чистом виде сравнивать имеет смысл строки со строками, числа с числами,
-- потому что выражение "5" == 5 вернет ЛОЖЬ(false),
-- чтобы сравнивать строки с числами, нужно привести сравниваемые элементы к одному типу
 
-- "<"   меньше
2 < 3 -- вернет true
 
-- "<="  меньше, или равно
2 <= 3 -- вернет true
2 <= 2 -- вернет true
 
-- ">"   больше
3 > 2 -- вернет true
 
-- ">="  больше, или равно
3 >= 2 -- вернет true
3 >= 3 -- вернет true
 
-- "=="  равно
2 == 2 -- вернет true
 
-- "~="  не равно
2 ~= 3 -- вернет true

Логические операции:

-- Логические операции возвращают в качестве результата false, или true,
-- ложью считаются только значения false, или nil, все остальные значения считаются истинными (true)
 
-- "and" логическое И вернет true, только если оба сравниваемых аргумента true
5 and 3        -- вернет ИСТИНУ(true), потому что оба аргумента числа, а числа не могут быть false, или nil
5 and (3 == 2) -- вернет ЛОЖЬ(false), потому что второй аргумент false
 
-- "or"  логическое ИЛИ вернет true, если хотя бы один из сравниваемых аргументов true
5 or (3 == 2)  -- вернет ИСТИНУ(true)
 
-- "not" логическое НЕ вернет истину, если один из аргументов false, а другой true (порядок не важен)
5 not (3 == 2)  -- вернет ИСТИНУ(true) "ИСТИННО высказывание: ИСТИНА не ЛОЖЬ"

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

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

Арифметические операции, операции сравнения и логические операции в QLua (lua): 66 комментариев

  1. Здравствуйте! Подскажите, как на языке луа записать следующее выражение: "Сумма лотов по инструменту за 10 минут по одной цене"? Что-то не нашел таких операторов. Спасибо.

      1. Здравствуйте.
        Вам нужно использовать либо Таблицу обезличенных сделок, там есть и направления сделок, а не только цены.
        Либо тиковый график или CreateDateSource и ее калбэк, но направления сделки вы не узнаете.
        для обезличенных сделок:
        map = {}
        --это первая 10-минутка ваша
        map[1] = { time_stamp = time_stamp1 время начала 10 минутки, [price1] = {buy, sell}, [price2] = {buy, sell}, ... [priceN] = {buy, sell}, }
        map[time_stamp1] = 1
        --это вторая 10-минутка
        map[2] = { time_stamp = time_stamp2, .... }
        map[time_stamp2] = 2
        и т.д.
        Вместо buy/sell пишете лоты обезличенной сделки, или деньги, которые прошли по цене price.

        1. Спасибо большое, что-то не совсем понял логику. Получается, мне нужно высчитать сколько десятиминуток внутри дня и для каждой писать условие типа : "Если........, то сообщение(к примеру)........?

          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
            29
            30
            31
            32
            33
            34
            35
            
            local int = 10 * 60
            for i = 0, getNumberOf("all_trades")-1 do
               local item = getItem("all_trades",i)
            --округлил секунды до 10 минут
               local posix_10 = math.floor(os.time(item.datetime)/int) * int
            --это лишнее, posix_10 уже уникален, но визуально наблюдать лучше YYYYMMDDHHMM
               local time_stamp = os.date("%Y%m%d%H%M", posix_10) 
              local c = #map
              if not map[time_stamp] then
               -- делаем что-то с предыдущим "баром"
                 c = c+1
                 map[c] = { time_stamp = time_stamp }
                 map[time_stamp] = c -- по этой ссылке можно найти нужный "бар"
               end
               local bar = map[c]
               local price = item.price
               if not bar [price] then
                 bar [price] = {0,0}
               end
                if покупка then
                    bar [price] [1] = bar [price] [1]  + item.qty
               else
                  bar [price] [2] = bar [price] [2]  + item.qty
               end
            end
             
            --получаем бар в 12-10
            local time_stamp = "202003051210"
            local index = map[time_stamp] 
            local bar = map[index]
            for p, t in pairs(bar) do
              if p ~= time_stamp then
               message("price= "..p.."\n".."qty_buy= "..t[1].."\n".."qty_sell= "..t[2])
              end
            end
  2. Господа, Всех с прошедшими Праздниками, нынешним Праздником и будущими Праздниками! Подскажите, кто ещё не начал праздновать, что я здесь напутал?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    function OnCalculate(indx)
    	if indx==1 then   return func_value(indx)
     
    	elseif
    	(indx==Size()) then return func_value(indx)
     
    	else return func_value(indx)
     
    	end
     
    	func_value=function(indx)
    		if C(indx)>O(indx) then return Н(indx)
     
    			elseif C(indx)<O(indx) then return L(indx)
     
    			else return O(indx)
    		end
    	end
    end

    Ошибка такого плана: attempt to call global 'func_value' (a nil value) - получается, что функция ничего не сравнивает и ничего не возвращает?
    Это моя первая попытка вынести расчёт в отдельную функцию(

      1. Добрый вечер, Дмитрий! Вот читаю Ваш ответ и восхищаюсь своей тупостью))) Спасибо Вам! А я ведь знал, что надо вынести, а не сделал. Да уж!... Спасибо ещё раз.

  3. Ребятки и Девчатки, всех с НГ! Про Счастье и главное Здоровье, всем всЁ понятно - Здравствуйте и будьте Счастливы! Благополучия всем!

    Давайте разберемся, раз уж никто не объясняет - НИГДЕ

    Что есть Знание - это боль, гиподинамия всех настигнет.
    Что же делать?
    Увлеченно искать Грааль, попутно разбираясь в основах QLUA?
    Я вас умоляю ))))))))))))))))))))))))))))))))))))))))))))))
    Вам не Дано! найти Граааль, т.к. он уже есть и впрямую используется по назначению - Вы, желающий приобщиться к системе Грааля - есть - ЛОХ! ( и наверное Лох-иня? - для женщин? )

    Не помню свой пост, но вот Дмитрий, Граааль не нашел.
    А почему?
    Потому-что Дмитрий занимался его поиском пару месяцев, от силы - год. (Дима, не в обиду, ну давай смотреть правде в глаза).
    Имеем:
    Дмитрия, меня, еще чел. 5- 10, которые понимают и отвечают "страждущим", что и как может произойти на Рынке.
    Мы знаем ТО, чего ВЫ, даже не понимаете отдаленно - Вам рановато это понимать, все придет со временем.
    ВНИМАНИЕ ВОПРОС:
    А сколько времени у вас есть?
    Забудьте этот вопрос, иначе Грааль перестанет работать, т.к. не будет "Мяса и крови",
    А Грааль, чтоб вы знали, это не Божественное создание, отнюдь))
    Господь, при создании человека - НИЧЕГО ему не дал,.
    Тогда кто? Кто дал идею Грааля и вообще всей Херни, которой занимается Человечество?

    Вы все поймете, на моем примере с "зарплатой дворника"( а оно вам надо? )

    Есть много вещей, точнее, - событий и состояний, которые Гораздо круче денег - это:
    Дружба, Любовь - и ни как иначе!
    Доброта, Всепрощение и много еще чего с БОЛЬШОЙ БУКВЫ, что всегда было у русскоязычного населения в Крови - относится КО ВСЕМ, ЧЕЙ ЯЗЫК, С РОЖДЕНИЯ И ДО 7 ЛЕТ БЫЛ - РУССКИЙ.

    И было Счастье - Уют семейного очага, Веселый хохот ребятни, да много чего - ЕСТЬ осознание Счастья и оно же и есть Цель!
    цЕЛЬ, которую себе тут вы ставите, но не понимаете как ее достичь - дЕНЬГИ - это говно на палочке - они не решают - Ни- Че - Го!
    Решаешь Ты сам, - кто ТЫ, и как к ТЕБЕ будут относится другие,
    Заведешь ли ТЫ кучу Друзей или кучу Врагов - тебе решать.

    Я катался на яхте, на которой катается блядина-пУТИН в Кижах.
    В чем прикол?
    Надувная лодка / плот и Друзья - гораздо КРУЧЕ!!!!!!!!!!!!!!!!!!!
    Крутизна, которую вам СПАМИТ реклама - отстой полный - никто - так - не - живет!
    Не нужно вестись на пропаганду херни.

    Задумайтесь:
    а вы готовы отдать, неизвестно чему, свою Жизнь?
    Если не готовы - отдайте мне свои деньги (и Души), я пропью, так и быть, чтоб не держать зла, ну, или помогу вам заработать, эти, как их - деньги - хз, чем чрт не шутит)

    1. Привет, kalikazandr! И Тебя с праздниками! Ты всё правильно сказал! Деньги - это мусор! И другое! Но есть ещё кое-что, что лично меня заставляет получать новые знания. Лично я стараюсь жить по принципу: "НЕ БУДЬ ОВЦОЙ - И ВОЛКИ ЗА ТОБОЙ НЕ ПРИДУТ"! Я всю жизнь стараюсь ставить перед собой цели, пусть даже порой временно недосягаемые. Это позволяет почувствовать вкус жизни. Самое приятное - это в конце концов самому понять суть какого-нибудь процесса. Поэтому я очень благодарен всем тем, кто не остался равнодушен к моим наивным вопросам, потому как Ваши ответы и советы оказались намного ценнее платных обучающих программ. Спасибо Вам за понимание и поддержку! И спасибо Дмитрию за этот прекрасный и единственный в своём роде ресурс! Ещё раз всех с праздниками!

      1. Спасибо.
        Ну да, можно убить пол жизни на поиск Грааля, в итоге, найти не так уж и сложно, просто пропалить чужой.
        Тогда, лет через уже 5 - за бабло можно купить новое тело, и тогда пофик потраченные годы ;).
        Даже в инвалидном кресле кнопку "пуск" нажмет красивая мед сестричка молоденькая ;).
        Начальства - нет.
        Сплошные плюсы.
        Ну или накрайняк, в красивом гробу похоронят, с табличкой: "Он был трейдером до мозга костей... Спасибо за Грааль..."
        и подпись: "Благодарные родственники".
        Или, как вариант - с Останкинской башни и тут есть плюс - красиво ушел 😉

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

          1. ИИ сможет начётно выбрать кучу патернов, на основе кучи параметров, при которых цена куда-то прет дуром и силу сигнала в %.
            А вот сработает патерн или нет, хз. И хз этих нет и 50%. Граалем даже не пахнет.
            А жизнь нужна для того, что бы отработать программу "время жизни" и получить мальца опыта.
            Каждому смотреть свой телик 6Д (тело) + программа.

            1. Тогда будем смотреть по телику свечки, уровни и как они отрабатываются. И, может быть, эта жизненная лотерея выдаст джекпот . А может быть всё тихо и мирно закончится!
              Вот давно хочу спросить умного человека: если, например, нужно возвращать неизвестное кол-во уровней - то есть кол-во выводимых и продолжаемых уровней-значений по Y (ставим, например, точки в линию, пока уровень сохраняется), а в Settings у нас одна Line с параметрами, то нужно будет значения выводимых уровней загнать в отдельную таблицу? а потом через цикл возвращать эти уровни на каждой свечке через цикл?

              1
              2
              3
              4
              5
              6
              7
              
              level = {}
              if C(indx)>O(indx) then 
              level[#level+1]=H(indx)
              end
              for i=1, #level do 
              return level[i]
              end

              так будет работать? или нет?

              и вот ещё какой вопрос! если нужно возвращать уровень до пересечения его ценой, то можно ли использовать:

              1
              2
              3
              4
              
              repeat
              return value
              until value~=C(indx)
              end

              можно ли так?

              1. Привет. Конструкция repeat ... until не требует end и поскольку в ней return value, то цикл всегда будет выполнятся 1 раз.
                Индикаторы не позволяют "вернуть не известное кол-во уровней" т.к. линии строго ограничены в Init и программно не добавляются.
                Но можно задать их максимальное кол-во:

                function Init()
                  --в Settings тоже объявляем 20 линий
                  return 20
                end
                function OnCalculate(index)
                  local res = {}
                  for i=1, 20 do -- это линии
                    res[#res+1] = H(index) + Settings.line[i].depth
                  end
                   -- если индекса в res нет, линия рисоваться не будет
                  return res[1],res[2],res[3]....res[20]
                end
                1. Привет! Огромное спасибо! Всё отлично! А вот что такое depth ? Что это за сегмент таблицы? Он как-то встроен в Settings.line или его надо отдельно как-то представить в настройках?
                  И вот ещё вопрос:
                  установили 20 линий для индикатора,
                  взяли значения для них, распределили Settings.line,
                  вывели, но рано или поздно ячейки в ограниченном массиве линий закончатся,
                  а новые значения для линий появятся? Как тут быть?
                  Или лучше другое:
                  есть значение,
                  возвращаем линию до того, как цена не коснётся её,
                  после этого удаляем это значение из таблицы res.
                  а при появлении нового значения H(indx) помещаем его в освободившееся место
                  таким образом количество линий остаётся неизменным, а значения меняются,
                  иначе при переполнении талицы res придётся удалять её и создавать её заново

                  Или как-то использовать вот это?

                  1
                  2
                  3
                  
                  if #res>20 then 
                  table.remove(res, i) 
                  end
                  1. table.remove(res, i) -- смотря какой тут i-тый элемент хотите удалить
                    depth -- это настраиваемый доп-параметр в line, отступ от пред идущей линии.
                    Для чего вам все это? Если делаете алгоритм "сетка", то проще написать ее в обычном скрипте, в настройках которого сразу пишете количество линий -100, например (если депо хватит), а в индикатор транслировать нужные уровни, если капец как нужна визуализация.
                    Только сетка вам даст минус, если будете продавать ниже средне-взвешенной цены покупки, а покупать выше средне-взвешенной цены продажи.
                    "купил - продал 50 руб. в копилку" - не работает, будет минус.

                    1. Хочу найти локальные экстремумы,
                      провести от них линии до пересечения их ценой в определённой последовательности по свечам
                      и таким образом, указывая последовательность характеристик свечей,
                      определить необходимые устойчивые закономерности.
                      Это будет удобно в плане того,
                      что не надо ничего рисовать на графике
                      и при переключении инструмента можно сразу увидеть возможные точки входа.
                      И в заключении установить метки на потенциальных точках входа.
                      При этом кол-во экстремумов будет изменяться в процессе движения цены.
                      Вот и нужно мне, чтобы: пересекли уровень - смотрим что это (например,пробой, ретест, или ничего), а после этого отключаем этот уровень, меняя его по необходимости на какой-нибудь новый, когда таковой появится.

                    2. "Хочу найти локальные экстремумы"
                      "Мартышкин труд" по моему 😉

  4. Добрый вечер! Подскажите, почему в выражении:

    if C(indx)>O(indx) then
    value = H(indx)
    SetValue(indx, 1, value) -- метка не ставится
    SetValue(indx-1, 1, value)-- метка ставится, но на одну свечу назад
    end
    Как должны выглядеть параметры SetValue, чтобы метка была над той свечкой, которая отвечает условию?

    1. Роман. Метка ставится, но Вы ее не видите, потому что она стирается.
      Вы не привели полный код, а дело именно в нем.

      1
      2
      3
      4
      5
      6
      7
      8
      
      function OnCalculate(indx)
      	if C(indx)>O(indx) then
      		value = H(indx)
      		SetValue(indx, 1, value) -- метка ставится
      		SetValue(indx-1, 1, value)-- метка ставится, но на одну свечу назад
      	end
      -- Функция ничего не возвращает.
      end

      Если у Вас такой код, то смотрите что происходит. Предположим происходит вызов функции OnCalculate с параметром 254. Спрашиваете "C(indx) > O(indx)" - Если да, тогда установили значение линии 1 для бара 254. Тем самым установили значение, как и хотели. Далее, установили значение на линии 1 для бара 253, тоже так и хотели.
      После этого функция OnCalculate завершается, но терминал ждет, что из функции вернутся значения, которые нужно установить на все линии для бара 254. Как там у Вас в коде я не знаю, но у меня нет return, а значит функция возвращает nil, тем самым терминал стирает значения со всех линий бара 254, прописывая в них nil. Значения с бара исчезают, вот Вы их и не видите, а бар 253 терминал не трогает, по этому они остаются на графике.
      Так что используйте return. Ну а как именно, зависит от того что у Вас внутри OnCalculate имеется.

      1
      2
      3
      4
      5
      6
      7
      8
      
      function OnCalculate(indx)
      	if C(indx)>O(indx) then
      		value = H(indx)
      		-- SetValue(indx, 1, value) -- метка не ставится
      		SetValue(indx-1, 1, value)-- метка ставится, но на одну свечу назад
      		return value; -- Выход из функции и возврат value, терминал запишет значение на бар indx
      	end
      end

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

      1. Добрый день, Павел! Огромное спасибо Вам за столь развёрнутое объяснение. У меня идея была в том, что, что индикатор вычисляет локальные экстремумы, а затем проверяет вид свечки и если она отвечает условиям, то на такой свечке ставится метка на уровне H(indx) или L(indx). У меня при условии использования return перед закрытием function OnCalculate(indx) метка выводилась каждый раз на новой свече на уровне value, пока не изменится значение value. А мне надо было только один раз. Может моя ошибка в том, что не использовал return внутри условия для параметров свечи? Как-то я об этом не подумал. Мне казалось, что возврат значений должен быть в конце после всех условий, а SetValue в данном случае поставит единичную метку на графике. Другими словами, получается, что если условий для свечей несколько, то можно использовать return значения внутри каждого отдельного условия после SetValue, а перед закрытием OnCalculate обойтись без return вообще? Я ещё в этом вопросе попробовал другой способ: создал четыре массива для параметров HLOC свечей, потом при нахождении локального high проверяю остальные условия через точку значений в массивах и если условия выполняются, то присваиваю значение переменной, после этого ставлю метку.
        Например:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        
        P = math.floor(Settings.period/2)*2+1				
        R = math.floor(Settings.period/2)
        		t_H,t_L={},{}
        		t_O,t_C={},{}
        				local l=indx-P
        					for l=l,indx-1 do
        						t_H[l]=H(l)
        						t_L[l]=L(l)
        						t_O[l]=O(l)
        						t_C[l]=C(l)
        					end
        					if t_H[#t_H-(P-1)/2]==math.max(unpack(t_H,#t_H-P+1,#t_H)) then
        						if t_C[#t_C-(P-1)/2]>t_O[#t_O-(P-1)/2]
        							and t_O[#t_O-(P-1)/2]==t_L[#t_L-(P-1)/2]
        							and ((t_H[#t_H-(P-1)/2])-(t_C[#t_C-(P-1)/2]))>=(((t_C[#t_C-(P-1)/2])-(t_O[#t_O-(P-1)/2]))*2)
        							then
        							H_ind_value=t_H[#t_H-(P-1)/2]
        							con_up = H_ind_value
        							SetValue(l+R, 3, con_up)
        						end

        а перед закрытием OnCalculate(indx) return nil

        1. Роман, у меня нет желания вникать в алгоритм, в переменные, в многомерные массивы и выяснять что происходит, как там выполняется вычисление, что лежит и в какой момент времени. А если всего этого не знать, то лучше я брошу программирование, чем буду методом тыка что то писать. Отладка дает ответы на 99% вопросов.
          Я пишу что происходит, некая теория, а практически Вы уже сами реализуете.
          Терминал вызывал функцию OnCalculate, ждет значения, которые она вернет, эти вернувшиеся значения, терминал нанесет на график. Исходя из этой информации пишите свой алгоритм.
          Поставьте себя на место терминала. Дали Вам задание, у всех, кто входит в комнату, проверить документы и внести информацию из документов в журнал. Заходит человек, Вы ему, - "документы", а он Вам в ответ - "А я уже сам взял ручку и все записал в Ваш журнал". Ну и что Вы будете делать? Скажете - "А, ну тогда идите..." Это нарушение работы. Компьютеры не нарушают записанные в них алгоритмы, а следуют строго. Так вот, предоставил Вам человек документ, Вы записали данные из документа. Не предоставил, Вы все равно записали данные в журнал "Нет Данных" или nil. И не имет значения, писал он сам что то в журнал или нет.
          Что бы Вы там не делали внутри OnCalculate, если из функции ничего не вернется, терминал запишет NIL. Хоть 1000 раз вызывайте SetValue и вносите значение, все равно терминал туда nil запишет, если данных не будет на выходе из функции.
          Вот и думайте, как Вы будете вносить значение, через return или SetValue. Терминал трогает только бар indx, другие не трогает, так что Вы можете внести значения на indx-1 и их не тронут, можете на indx+1, но если нужно внести именно на indx, тогда только через return
          Поймите теорию работы терминала с графиком. Терминал вызывает OnCalculate с параметрами от 1 до N, где N - это количество баров на графике. И делает он это только в момент отрисовки всего графика. Далее терминал вызывает OnCalculate с параметром N, где N номер последнего бара на графике и вызывает как только этот бар N изменился. Если бар изменится 100 раз за 1 секунду, значит терминал вызовет OnCalculate 100 раз за секунду и 100 раз запишет значения на линию бара N. Так что даже если Вы как то внесете через SetValue значение на последний бар, то терминал все равно его сотрет, как только придет новая сделка. В итоге получатся, что если Вам нужно в реальной торговле изменять значение на последнем баре, то нужен return Для всех остальных return не обязателен.

          Теперь немного о Вашей идее.
          - " индикатор вычисляет локальные экстремумы"
          - Как он должен это делать? Сначала пробежать по всем барам или сразу в процессе движения. Да. компьютеры многозадачные, много поточные, но алгоритмы все равно линейные. Вот взяли Вы бар номер 1. Можете ли Вы на основании только 1 бара выяснить, является ли он экстремумом или нет. Думаю что нет. взяли второй бар, теперь можете определить какой из них экстремум? Вот и подумайте, как Вы это будете делать, В какой момент времени.
          Вот пример из Вашего кода for l=l,indx-1 do Допустим график имеет 65535 баров. Вы понимаете, сколько всего итераций будет на таком графике? Давайте немного посчитаем:
          Вызов первый OnCalculate, indx = 1
          Запускаем цикл от 1 до 0 - Ни одной итерации не будет.
          Вызов второй OnCalculate, indx = 2
          Запускаем цикл от 1 до 1 - Одна итерация
          Вызов третий OnCalculate, indx = 3
          Запускаем цикл от 1 до 2 - Две итерации
          Вызов четвертый OnCalculate, indx = 4
          Запускаем цикл от 1 до 3 -Три итерации
          Вызов пятый OnCalculate, indx = 5
          Запускаем цикл от 1 до 4 -Четыре итерации
          ....
          Всего 5 баров из 65535 обработали, а уже 10 итераций.
          Давайте прыгнем ближе к концу графика
          Вызов OnCalculate, indx = 65530
          Запускаем цикл от 1 до 65529
          Вызов OnCalculate, indx = 65531
          Запускаем цикл от 1 до 65530
          Вызов OnCalculate, indx = 65532
          Запускаем цикл от 1 до 65531
          Вызов OnCalculate, indx = 65533
          Запускаем цикл от 1 до 65532
          Вызов OnCalculate, indx = 65534
          Запускаем цикл от 1 до 65533
          Вызов OnCalculate, indx = 65535
          Запускаем цикл от 1 до 65534
          ...
          Обработка последних 5 баров, а итераций 458724. Пол миллиона итераций на последних 5 барах Миллион итераций, что бы обработать последние 10 баров. Вы представляете сколько миллиардов итераций будет, пока все 65535 баров обработано будет?
          Еще страшнее картина. Последний бар на графике 65531. За 1 секунду приходит 100 сделок.
          Терминал вызывает OnCalculate 100 раз и внутри выполняет цикл из 65530. За 1 секунду 6553000 - Шесть с половиной миллионов итераций за секунду на одном индикаторе.
          Вот и подумайте, оно Вам надо? Что делает Ваш алгоритм, проверяет одни и те же бары:
          1 бар
          1 и 2 бар
          1 2 3 бары
          1 2 3 4
          1 2 3 4 5
          ...
          1 2 3 ... 65533
          1 2 3 ... 65534
          1 2 3 ... 65535
          На истории может измениться только последний бар, так зачем постоянно проверять все бары?
          Не проще переформировать так, что бы алгоритм 1 раз запустил цикл от 1 до 65535, все что ему нужно вычислил, а потом расставил значения на всех барах. Дальше только на последнем баре меняет значения при необходимости.
          Это может быть примерно так:

          1
          2
          3
          4
          5
          6
          7
          
          if (indx == 1) then
          	-- Тут полная работа. Цикл для всех баров и запись значения через return на бар 1
          elseif (indx = Size()) then
          	-- Только запись на последний бар через return
          else
          	-- Запись на промежуточные бары через return
          end

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

          1. Огромное спасибо, Павел! Вы мне открыли глаза на многие вещи!
            У меня в коде так начинается:

            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            
            function OnCalculate(indx)
            	if indx==1 then
            		P = math.floor(Settings.period/2)*2+1
            		t_H,t_L={},{}
            		t_O,t_C={},{}
            	end
            	if indx~=nil and indx>P then
            						local l=indx-P
            					for l=l,indx-1 do
            						t_H[l]=H(l)
            						t_L[l]=L(l)
            						t_O[l]=O(l)
            						t_C[l]=C(l)
            					end

            а потом уже остальные условия: нашли экстремум - проверили свечу.
            Только вот у меня вопрос, код после elseif будет повторяться (будет повторение блока внутри if (indx == 1) then), и как тогда будет происходить запись в третьем блоке на промежуточные бары? А у меня код при indx==1 вычисляет переменную периода и создаёт таблички.

            1. Выполнение в моем примере следующее:
              Первый блок выполняется 1 раз на первом баре
              Второй блок выполняется много раз, при каждом изменении последнего бара
              Третий блок выполняется 1 раз для каждого бара, кроме первого и последнего
              Почему код после elseif будет повторяться? - Условие не выполнится. Size() возвращает количество баров на графике и если indx это последний бар, то условие выполнится, иначе уйдет в третий блок.
              Пример. На графике 1024 бара.
              Бар 1 - истинное условие if (indx == 1) then - выполняется код первого блока. Второй и третий блоки не выполняются.
              Бары 2...1023 - условие if (indx == 1) then - не выполняется. Условие elseif (indx == Size()) then - не выполняется, остается else, код оправляется в 3 блок. первый и второй блоки не выполняются.
              Бар 1024 - условие if (indx == 1) then - не выполняется. Условие elseif (indx == Size()) then - выполняется, код оправляется во второй блок. первый и третий блоки не выполняются.
              Дальше будет вызов функции с indx = 1024 с каждой новой сделкой, до тех пор, пока не появится бар 1025. То есть с каждой новой сделкой выполняется второй блок.

              1. Павел, это всё мне понятно! А как же разделить сам код индикатора в том случае? Или для такого деления процессов код нужно представить в виде набора функций, которые будут вызываться отдельно при выполнении одного из условий?

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                
                if indx==1 then
                	if C(indx)>O(indx) then 
                	value=H(indx)
                	SetValue(indx,1,value)
                	return value
                elseif (indx=Size()) then
                	if C(indx)>O(indx) then 
                	value=H(indx)
                	SetValue(indx,1,value)
                	return value
                else 
                	if C(indx)>O(indx) then 
                	value=H(indx)
                	SetValue(indx,1,value)
                	return value
                end

                вот что я имел ввиду. Нужно для каждого условия повторять код. Или же вынести код в отдельную функцию, а в OnCalculate только ссылаться на функцию в момент присвоения и вывода конечного значения метки? А саму функцию проверки свечей вынести за пределы OnCalculate. Так код будет в три раза меньше по количеству строк. Правильно я понял Вас?

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

                  1. Добрый день! Вот теперь всё стало понятно. Значит через SetValue предыдущие свечи, а последняя только через return и будет возвращать графические метки в порядке Settings.line Если, например, три разных графических метки, а нужно вывести вторую, то:
                    return nil, value, nil

                    а расчёт value в отдельной

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    
                    if (indx==Size()) then return func_value(indx)
                    elseif
                    indx==1 then   return func_value(indx)
                    else return func_value(indx)
                    end
                    func_value=function(indx)
                    if C(indx)>O(indx) then
                     return H(indx)
                    end

                    так, например? или я опять что-то напутал?

                    1. вам никогда не нужно проверять, равен indx Size() или нет. ваша функция ВСЕГДА должна возвращать значения линий через return для переданного indx. КРОМЕ этого, вы можете поменять что-то в прошлом через SetValue().

                    1. return nil я добавил для вас, чтобы было понятнее. когда функция ничего не возвращает, для получателя (у нас это quik) это все равно что nil.
                      этот код:

                      1
                      
                      if C(indx) > O(indx) then return H(indx) else return nil end

                      и этот код:

                      1
                      
                      if C(indx) > O(indx) then return H(indx) end

                      эквивалентны.

                    2. но, ясное дело, только в том случае, если кроме него ничего больше в OnCalculate() нет.

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

                    1. ну так смотрите, в чем проблема?

                      вам в функцию никакая свеча не передается. вам передается просто номер, который определяет момент "настоящее".

                      НАПРИМЕР: "настоящее" == 100. тогда "прошлое" это множество [1..99], а "будущее" - это множество [101..]. вы можете получать "исторические" значения свечей при помощи функций O(), H(), L(), C() если передаете в них значения от 1 до 99, вы можете получать текущую свечку, которая меняется в данный момент, передавая значение 100. для "будущего" (значения 101 и выше) значения O(), H(), L(), C() не определены, хотя, многие бы за это отдали пол-жизни.

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

  5. Добрый день.. скажите будет работать этот код ? Нужно чтобы при выполнении любого из условий сравнения выполнялось одно действие

    1
    2
    3
    
     if v1 > v2 or t1 > t2 or u1 > u2 then
            return 1, false, true 
     end
  6. Здравствуйте, помогите пожалуйста разобраться в чем проблема, не срабатывает сравнение в луа
    Вот такой код:
    local yes = 0
    local gbo = 0
    if buy_orders[key].price == myBid then yes = 1 end
    if good_buy_order ~= nil then gbo = 1 end
    message('bop='..buy_orders[key].price..type(buy_orders[key].price)..' mBid='..myBid..type(myBid)..' yes='..yes..' gbo='..gbo)
    В месседжах вот такое:
    bop=742.3number mBid=742.1number yes=0 gbo=0
    и типы одинаковы и занчения , почему yes=0 ?

      1. Здравствуйте! Попробуйте применить вот эту функцию, она округляет переданное число до указанного количества знаков после запятой:

        1
        2
        3
        4
        
        math_round = function(num, idp)
          local mult = 10^(idp or 0)
          return math.floor(num * mult + 0.5) / mult
        end

        вот так:

        1
        
        if math_round(buy_orders[key].price, 2) == math_round(myBid, 2) then yes = 1 end

        В Луа есть такая проблема, что она может добавить к числу единичку, например, десятым знаком после запятой, т.е. куча нулей и в конце единичка.

          1. Здравствуйте! 10 в степени idp, или в степени 0, если функция вызывается без второго параметра, т.е. получается 10 ^ 0 = 1. В результате, переданное число округляется до целого. Т.е. выражение (idp or 0) вернет 0, если idp == nil, или вернет idp, если в idp есть какое-то значение.

            1. Спасибо Дмитрий, что отвечаете.
              Правильно ли я понимаю, что
              А = nil or 3 or 2
              будет равно 3?
              а в
              A =func1() or func2()
              во вторую функцию даже не заглянет, если func1() не равно ЛОЖЬ или nil ?

              1. Всегда пожалуйста! В первом случае да, A будет равно 3, во втором случае А будет присвоен результат, который возвращает функция func1, если она не возвращает никакого результата, то А будет равна nil, func2 вообще никогда не вызовется.

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

    Заранее благодарю за ответ.

  8. Интересно, каким образом выглядит аналогичная операции -- ".." конкатенация (склеивание ячеек столбца)?Если,конечно, такая операция есть в QLUA.Спасибо.

  9. Добрый день.Возник вопрос, можно ли складывать(вычитать) не переменные, а значения ячеек? Если можно,то можете привести какой-нибудь простой пример? Спасибо.

      1. Добрый день!

        Вам поможет GetCell
        Функция возвращает таблицу, содержащую данные из ячейки в строке с ключом «key», кодом колонки «code» в таблице «t_id».
        Формат вызова:
        TABLE GetCell(NUMBER t_id, NUMBER key, NUMBER code)
        Параметры таблицы:
        image – строковое представление значения в ячейке,
        value – числовое значение ячейки.
        Если входные параметры были заданы ошибочно, то возвращается «nil».

        Из файла qlua.chm "Функции для работы с таблицами Рабочего места QUIK"