Дата/время в QLua(Lua)

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

Qlua-основы
Материал статьи взят здесь: http://www.bot4sale.ru/blog-menu/qlua/spisok-statej/368-lua-time.html

Дата/время в QLua(Lua) может быть представлено либо в виде секунд, прошедших с полуночи 1 января 1970 года, либо в виде таблицы, имеющей следующие поля:

   year - год (четыре цифры)
   month - месяц (1 – 12)
   day - день (1 – 31)
   hour - час (0 – 23)
   min - минуты (0 – 59)
   sec - секунды (0 – 59)
   wday - день недели (1 - 7), воскресенью соответствует 1
   yday - день года
   isdst - флаг дневного времени суток, тип boolean

Встроенные функции:

   os.clock() - возвращает время в секундах с точностью до миллисекунд с момента запуска приложения, в нашем случае QUIK. Пример: 1544.801
   os.time() - возвращает время в секундах, прошедших с полуночи 1 января 1970 года, может принимать вышеописанную таблицу, в качестве аргумента, без аргументов возвращает текущее время
   os.date() - возвращает форматированные дату/время, первым аргументом принимает формат, вторым аргументом принимает время в секундах. Аргументы не обязательны. Если не передать 2-й аргумент, функция вернет текущие дату/время компьютера. Если функцию вызвать вообще без аргументов, то она вернет текущие дату/время компьютера в виде 03/22/15 22:28:11

В строке формата можно использовать следующие опции:

%a   - день недели, сокр. (англ.) (пример, Wed)
%A   - день недели, полностью (англ.) (пример, Wednesday)
%b   - месяц, сокр. (англ.) (пример, Sep)
%B   - месяц, полностью (англ.) (пример, September)
%c   - дата и время (по-умолчанию) (пример, 03/22/15 22:28:11)
%d   - день месяца (пример, 22) [диапазон, 01-31]
%H   - час, в 24-х часовом формате (пример, 23) [диапазон, 00-23]
%I   - час, в 12-и часовом формате (пример, 11) [диапазон, 01-12]
%M   - минута (пример, 48) [диапазон, 00-59]
%m   - месяц (пример, 09) [диапазон, 01-12]
%p   - время суток "am", или "pm"
%S   - секунда (пример, 10) [диапазон, 00-59]
%w   - день недели (пример, 3) [диапазон, 0-6, соответствует Sunday-Saturday]
%x   - дата (пример, 09/16/98)
%X   - время (пример, 23:48:10)
%Y   - год, 4 цифры (пример, 2015)
%y   - год, 2 цифры (пример, 15) [00-99]
%%   - символ "%"
*t   - вернет таблицу
!*t  - вернет таблицу (по Гринвичу)

Примеры:

-- Представить произвольное время в секундах
datetime = { year  = 2015,
             month = 03,
             day   = 22,
             hour  = 22,
             min   = 28,
             sec   = 11
           };
seconds = os.time(datetime); -- в seconds будет значение 1427052491
 
-- Представить время в секундах в виде таблицы datetime
datetime = os.date("*t",seconds);
 
-- Преобразование строки даты/времени в таблицу datetime
dt = {};
dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match("22/03/2015 22:28:11","(%d*)/(%d*)/(%d*) (%d*):(%d*):(%d*)");
for key,value in pairs(dt) do dt[key] = tonumber(value) end
 
-- А так можно получить текущие дату/время сервера в виде таблицы datetime
dt = {};
dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match(getInfoParam('TRADEDATE')..' '..getInfoParam('SERVERTIME'),"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)")
for key,value in pairs(dt) do dt[key] = tonumber(value) end

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

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

Дата/время в QLua(Lua): 79 комментариев

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

    1. Здравствуйте, Роман.
      Не знаю что у Вас за алгоритм, возможно действительно очень сложные вычисления выполняются, но может пересмотреть код, оптимизировать его как то.
      Вообще заставить Квик не пробегать по всем свечкам не получится, можно заставить пропускать. Можете при вызове OnCalculate запросить Дату Время бара, произвести сравнение с текущим днем и если бар относится к текущему дню, тогда производить вычисления, иначе вернуть nil
      Так же учтите, что Квик "пробегает" по свечкам не 1 раз, а 2 или даже 3 раза, зачем, трудно сказать, но факт есть факт.
      Приведу пример вычисления над барами за текущий день

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      local curDt;
      function OnCalculate(i)
      	if (i == 1) then curDt = tonumber(os.date("%Y%m%d")) end
      	local dt = T(i);
      	local dtn = (dt.year * 100 + dt.month) * 100 + dt.day;
      	if (curDt == dtn) then
      		-- Тут вычисления над баром
      		return 1;
      	else
      		-- Тут пропуск бара
      		return 0;
      	end
      end
      1. Спасибо, Павел! А то я уж тоже начал задумываться об ограничении времени. Иначе запросишь какой-нибудь текущий параметр на график, и, хорошо, если часовики или дневки, а на минутках всё намертво стоит секунд по 15))!

  2. в qlua в таблице Стоп-заявок stop_orders параметр время выставления стоп-заявки ordertime в чем измеряется? в каком формате? и как его перевести в формат часы: минуты: секунды или в секунды

    1. Здравствуйте, там число, я думаю, ЧЧММСС, типа, 121510, хотя не уверен на 100%, ни разу его не использовал, если число, то можно его перевести в строку и получить из нее составляющие по принципу как сделано в функции StrToTime, которая находится в разделе "Нужные функции"

  3. А в таблице сделок, сделки всегда идут в правильном хронологическом порядке? Допустим я хочу получить определенные "свежие сделки", совершенные после 19:00, могу ли я сделать "пробежку" по таблице с конца, и проверять ,условно если getItem("trades",i).datetime > 19:00 то обрабатываю сделку. Как только getItem("trades",i).datetime <= 19:00 прекратить цикл. Т.е. не окажется ли в таблице сделок "затерявшаяся" , из-за нарушения хронологического порядка? И соответственно может лучше пробегаться по всей таблице, а не прерывать цикл?
    Ну и заодно, такой же вопрос по номерам сделок. Вроде бы они в таблице всегда идут по порядку, чем более свежая сделка, тем номер у нее больше. Но тут я совсем не уверен, что порядок всегда будет соблюден.

    1. Привет!
      Если у вас в квике 1 рынок подключен, например срочный, то хронология будет соблюдена, если подключен еще и фондовый, то хронология не будет соблюдена и последовательности номеров сделок (и таймштампов) не будет, вплоть до 18-50. (после 19-00 нормально).
      Решение: фильтр по интересующему рынку.
      А так все правильно, нашли первую строку с таймштампом < 19:00, запомнили № стр + 1, и больше обратный цикл не нужно вызывать.
      Посчитали что есть от № стр + 1 , до последней сделки и запомнили № строки последней сделки и следующий раз уже от неё плясать.

      1. Спасибо, все понятно объяснили. Хотелось бы еще уточнить, что значит запомнили № строки? Я планировал запоминать DateTime и номер сделки для оценки, что уже было посчитано. Так как только DateTime, наверное, может совпасть у разных сделок до секунды. А вот № строки будет зависеть от того сколько сделок всего в таблице, но оно же не постоянно? Я пока не разобрался, отчего вообще это зависит.
        То только сегодняшние сделки в таблице, то вчерашние за весь день, то с какого-то часа.

        1. Нашел в хелпе. "Если количество строк таблицы превышает пороговое значение, заданное в файле info.ini (без учёта глобальных фильтров), то при вызове пункта меню «Создать окно / Заявки» открывается окно редактирования таблицы. Иначе – открывается сформированная Таблица заявок. По умолчанию пороговое значение равно «100000».
          Получается в базе данных, я так понимаю, в файле trades.dat, по умолчанию хранится до 10000 строк. А сколько отражается в таблице терминала Quik, это уже другой вопрос. Но все равно, количество сделок может быть и больше 10000, это надо учитывать или файл trades.dat удалили, где - то вообще рекомендовали их *.dat периодически удалять, т.к. современный Квик начинает подвисать , когда они разрастаются. Больше это, наверное, к alltrade.dat относится, если в него все сделки пишутся. Сейчас провел эксперимент, удалил trades.dat запустил квик и сделки в таблице появились и файл "восстановился"

        2. local row = 0 -- № строки в таблице всех сделок
          for i=getNumberOf("all_trades") -1, 0, -1 do
          local item = getItem("all_trades", i)
          if item then
          local posix = os.time(item.datetime)
          if posix and tonumber(os.date("%H%M",posix) < 1900 then row = i + 1; break end
          end
          end

          вот когда из цикла, который ищет time < 19-00 , то row будет равно порядковому номеру строки с первым таймштампом == 1900,
          а потом row меняете на getNumberOf("all_trades") -1 (т.е. строка с последней сделкой)

  4. Дмитрий, вразумите - если необходимо сравнить совпадает ли дата, записанная в два разных массива, как проще всего их сравнить?
    Например:

    1
    2
    3
    
    if unpack(trade1.datetime) == unpack(trade2.datetime) then
        -- даты совпали
    end

    В trade1/2 дата записана в виде таблицы день, месяц, год...
    Сравнение через unpack сравнит массивы поэлементно или необходимо явно прописывать условие на каждое поле и делать and?

  5. Дмитрий, здравствуйте! Спасибо за хороший ресурс и отличную обратную связь! Обычно решение нахожу сам, но возник вопрос на который ответ не нашел.
    Вот так мы получаем секунды, из которых потом вытаскиваем дату и время:
    local Size = getNumCandles(tag)
    local t,n,_ = getCandlesByIndex(tag,0,0,Size)
    local seconds = os.time(t[i].datetime)
    Мне нужно наоборот. У вас в примерах есть инфо как из секунд получить таблицу
    local datetime = os.date("*t",seconds).
    А как при наличии секунд получить индекс свечи? Я пока что пришел только к тому чтобы перебирать секунды из свеч и сравнивать со своими, но это долго. Мне кажется есть решение элегантней.

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

  6. %x - дата (пример, 09/16/98)
    если по нормальному по нашему представить то это такой нет функции надо просто разбить как нам надо по %Y - год, 4 цифры (пример, 2015) и т.д.

  7. Здравствуйте.
    Разбираюсь с датой временем. Пример с циклом как раз то что мне нужно

    1
    2
    3
    4
    
    -- Преобразование строки даты/времени в таблицу datetime
    dt = {};
    dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match("22/03/2015 22:28:11","(%d*)/(%d*)/(%d*) (%d*):(%d*):(%d*)");
    for key,value in dt do dt[key] = tonumber(value) end

    Но он у меня не работает, выдает ошибку. "lua:26: attempt to call global 'dt' (a table value)"
    Перешел разбираться с циклом и там в примере указано pairs(Array)
    Исправил код из примера

    1
    2
    3
    4
    
    -- Преобразование строки даты/времени в таблицу datetime
    dt = {};
    dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match("22/03/2015 22:28:11","(%d*)/(%d*)/(%d*) (%d*):(%d*):(%d*)");
    for key,value in pairs(dt) do dt[key] = tonumber(value) end

    И ошибка пропала.
    Я так понял что обязательно писать pairs. или в каких то случаях допускается просто указать таблицу? Если допускается, то в каких? Или это ошибка в примере?

    Код писал в индикаторе.

      1. А к чему это: for key,value in pairs(dt) do dt[key] = tonumber(value) end ?
        С моей точки зрения - это бред. Луа без разницы строковые значения в dt или нет.
        Рекомендую вот тут ознакомится как действительно работать со временем в луа, Дмитрий, без обид))
        http://bot4sale.ru/blog-menu/qlua/spisok-statej/368-lua-time.html

          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
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            
            RUN = true
            Torgtime = 0
            main = function()
             
            while RUN do
                  local Torgtime = TimeTrade()
            	  if Torgtime == 1 then
             
            	  -- выполняем код 
             
            	  end
             
             
            TimeTrade = function()
               epoch_time = os.time()
             
               local tradetime1 = os.date("*t",epoch_time) -- начало основной сессии
                            tradetime1.hour = 09
                            tradetime1.min = 59
                            tradetime1.sec = 55
               local tradetime2 = os.date("*t",epoch_time) -- конец основной сесии (закрытие позиций)
                            tradetime2.hour = 18
                            tradetime2.min = 44
                            tradetime2.sec = 55
               local tradetime3 = os.date("*t",epoch_time) -- начало вечернего клиринга
                            tradetime3.hour = 18
                            tradetime3.min = 45
                            tradetime3.sec = 0				
               local tradetime4 = os.date("*t",epoch_time) -- начало вечерней сесии
                            tradetime4.hour = 18
                            tradetime4.min = 59
                            tradetime4.sec = 55				
               local tradetime5 = os.date("*t",epoch_time) -- конец вечерней сессии (закрытие позиций)
                            tradetime5.hour = 23
                            tradetime5.min = 49
                            tradetime5.sec = 55				
               local tradetime6 = os.date("*t",epoch_time) -- конец торгового дня
                            tradetime6.hour = 23
                            tradetime6.min = 50
                            tradetime6.sec = 0				
             
            if 	epoch_time > os.time(tradetime1) and epoch_time  os.time(tradetime4) and epoch_time  os.time(tradetime2) and epoch_time  os.time(tradetime5) and epoch_time < os.time(tradetime6) then			
            	local Torgtime = 3			
            else 	
                local Torgtime = 2
                return Torgtime
             
            end
            end

            на строке local Torgtime = TimeTrade() выдает ошибку attempt to call global 'TimeTrade' (a nil value)
            Может кто подскажет где косяк?

            1. после if код не вставился

              1
              2
              3
              4
              5
              
              if 	epoch_time > os.time(tradetime1) and epoch_time  os.time(tradetime4) and epoch_time  os.time(tradetime2) and epoch_time  os.time(tradetime5) and epoch_time < os.time(tradetime6) then			
              	local Torgtime = 3			
              else 	
                  local Torgtime = 2
                  return Torgtime
              1. все равно не загрузилась часть кода, запишу без шорткодов
                if epoch_time > os.time(tradetime1) and epoch_time os.time(tradetime4) and epoch_time os.time(tradetime2) and epoch_time os.time(tradetime5) and epoch_time < os.time(tradetime6) then
                local Torgtime = 3
                else
                local Torgtime = 2
                return Torgtime

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