Дата/время в 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): 74 комментария

  1. А в таблице сделок, сделки всегда идут в правильном хронологическом порядке? Допустим я хочу получить определенные "свежие сделки", совершенные после 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 (т.е. строка с последней сделкой)

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

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

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

  3. Дмитрий, здравствуйте! Спасибо за хороший ресурс и отличную обратную связь! Обычно решение нахожу сам, но возник вопрос на который ответ не нашел.
    Вот так мы получаем секунды, из которых потом вытаскиваем дату и время:
    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. Всегда пожалуйста! 🙂 Никак не получить индекс, только перебор, т.к. ночью, в выходные и праздничные дни свечей нет и не получиться зная время первой свечи просто разделить секунды на таймфрейм.

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

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

    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 &gt; os.time(tradetime1) and epoch_time  os.time(tradetime4) and epoch_time  os.time(tradetime2) and epoch_time  os.time(tradetime5) and epoch_time &lt; 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 и искал бы всю ночь.
                    Спасибо за помощь!