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

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 4, среднее: 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): 103 комментария

    1. А... Я понял... Можно из таблицы при помощи os.time(datetime) получить время в секундах, потом выполнить сложения/вычитание в секундах, полученный результат передать в newDatetime = os.date("*t",seconds);

      1. Но опять же у нас сделки с миллисекундами и даже микросекундами... Сразу возникает вопрос os.time(datetime) возвращает целое или дробное число секунд?

        1. Здравствуйте! К сожалению, целое, чтобы сравнивать, придется небольшую функцию написать, которая будет к секундам добавлять дробную часть, беря ее из переданной таблицы datetime, что-то типа:

          1
          2
          3
          4
          5
          6
          
          os.time_ex = function(datetime)
             local res = os.time(datetime)
             if datetime.ms ~= nil then res = res + datetime.ms * 0.001 end
             if datetime.mcs ~= nil then res = res + datetime.mcs * 0.000001 end
             return res
          end
            1. Lua "легкий" язык, в том плане, что не перегружен разным функционалом, в нем присутствуют только базовые вещи, используя которые, каждый может наполнить его нужным именно ему функционалом, в каком-то смысле это плюс.

  1. Дмитрий, здравствуйте. А как считать время и дату свечи?
    Хочу прогнать через скрипт например 100 свеч. Если выполняется условие скрипта, то выводит сообщение в блокнот.
    Пытался с помощью os.date, но как я понял это время компьютера при котором работает скрипт, а не время конкретной свечи при которой выполнилось условие скрипта.
    Спасибо.

    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
      
      -- Проверка на промежуток с 10:00:00 до 23:50:00
      CheckSessionTime = function()   
         -- Текущие дата/время сервера в виде таблицы datetime
         local c_dt = {}
         local TRADEDATE = getInfoParam('TRADEDATE')
         local SERVERTIME = getInfoParam('SERVERTIME')
         if TRADEDATE == nil or TRADEDATE == '' or SERVERTIME == nil or SERVERTIME == '' then return false end
         c_dt.day,c_dt.month,c_dt.year,c_dt.hour,c_dt.min,c_dt.sec = string.match(TRADEDATE..' '..SERVERTIME,"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)")
         -- Текущие дата/время в секундах
         local c_seconds = os.time(c_dt)
         -- Начало сессии в виде таблицы datetime
         local b_dt = {}
         b_dt.day,b_dt.month,b_dt.year,b_dt.hour,b_dt.min,b_dt.sec = string.match(getInfoParam('TRADEDATE')..' 10:00:00',"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)")
         -- Начало сессии в секундах
         local b_seconds = os.time(b_dt)
         -- Конец сессии в виде таблицы datetime
         local e_dt = {}
         e_dt.day,e_dt.month,e_dt.year,e_dt.hour,e_dt.min,e_dt.sec = string.match(getInfoParam('TRADEDATE')..' 23:50:00',"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)")
         -- Конец сессии в секундах
         local e_seconds = os.time(e_dt)
         -- Если время внутри сессии
         if b_seconds <= c_seconds and c_seconds < e_seconds then
            return true
         else
            return false
         end
      end

      Функция возвращает true или false

  2. Добрый день. Помогите пожалуйста.
    Не получается сравнить дату и время. Переменные даны в строковом виде
    data1="09.06.2016" и time1="15:43:22" сравнить с data2="10.06.2016" и time2="19:00:00"

    1. Здравствуйте! Попробуйте вот так:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      dt1 = {}
      dt1.day,dt1.month,dt1.year,dt1.hour,dt1.min,dt1.sec = string.match(data1..' '..time1,'(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)')
      dt2 = {}
      dt2.day,dt2.month,dt2.year,dt2.hour,dt2.min,dt2.sec = string.match(data2..' '..time2,'(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)')
       
      for key,value in dt1 do
         dt1[key] = tonumber(dt1[key])
         dt2[key] = tonumber(dt2[key])
      end
       
      if os.time(dt1) > os.time(dt2) then message('Первая дата больше второй') end
    2. задача отфильтровать в таблице сделок "trades" все сделки совершенные до 19:00 текущего дня
      В таблице запись datetime -- Дата и время (TABLE)
      может как то проще все это делается без перевода в строковый режим.
      К сожалению плохо знаю QLUA

        1. Дмитрий, помоги пожалуйста.

          if (trade.datetime.hour >= 19 && ( по текущей дате) ) || ( дата сделки была раньше чем сегодня) then
          message('Годная сделка :)')
          end
          если использовать trade.datetime.hour >= 19 то теряются вчерашние сделки после 19:00
          Если делать на С++ или на C# без проблем. А этот .... язык ((

                1. Тогда условие не такое((
                  if (trade.datetime.hour < 19)
                  1. Все сделки которые были сегодня до 19
                  2. и все вчерашние сделки
                  Биржа переносит на следующий день сделки которые были после 19:00

                  1. Если нужны все сделки из таблицы всех сделок, которые были с 10 до 19, то вот так можно:

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    
                    DayTrades = {}
                     
                    -- Запишет в массив DayTrades все сделки из таблицы всех сделок, которые были с 10:00:00 до 19:00:00
                    function GetAllDayTrades()
                       local last_index = getNumberOf('all_trades')
                       for i=0,last_index-1 do
                          local trade = getItem('all_trades', i)
                          if trade.datetime.hour >= 10 and trade.datetime.hour < 19 then
                             table.sinsert(DayTrades, trade)
                          end
                       end
                    end
                    1. Отлично! Спасибо! Так наверно будет наглядно
                      1. 09.06.2016;19:13:15;GZM6;21585835948;Buy;14923;51;761073
                      2. 10.06.2016;18:39:46;GZM6;21602325075;Buy;14739;1;14739
                      3. 10.06.2016;19:39:46;GZM6;21602325075;Buy;14739;3;44217
                      должна попасть 1 и 2 сделка обрати на дату и время

                    2. Добавить условие в
                      if trade.datetime.hour >= 10 and trade.datetime.hour < 19 then
                      И все сделки совершенные не сегодня!!!!

                    1. За вчера сделки все сделки
                      За сегодня с 10:00 до 19:00

                    1. Дим, наверно так будет правильно
                      datetime1 = os.date("*t")
                      if trade.datetime.hour >= 10 and trade.datetime.hour < 19 or
                      trade.datetime.day ~= datetime1.day then
                      table.sinsert(DayTrades, trade)
                      end

                  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
                    
                    DayTrades = {}
                     
                    -- Запишет в массив DayTrades все сделки из таблицы всех сделок, которые прошли до 19:00:00 текущего дня
                    function GetAllDayTrades()
                       local TradeDate = getTradeDate()
                       dt = {}
                       dt.year = TradeDate.year
                       dt.month = TradeDate.month
                       dt.day = TradeDate.day
                       dt.hour = 0
                       dt.min = 0
                       dt.sec = 0
                       local TradeDate_sec = os.time(dt)
                       local last_index = getNumberOf('all_trades')
                       for i=0,last_index-1 do
                          local trade = getItem('all_trades', i)
                          dt = trade.datetime
                          dt.hour = 0
                          dt.min = 0
                          dt.sec = 0
                          if trade.datetime.hour < 19 or os.time(dt) < TradeDate_sec then
                             table.sinsert(DayTrades, trade)
                          end
                       end
                    end
                    1. Красиво)) Спасибо )) сейчас буду экспериментировать.
                      Извини что столько времени отнял.
                      С уважением, Александр

                    1. Да эта ошибка(( я на неё обратил внимание заказчика, на момент обсуждения тз.
                      Но это на его совести

              1. Ну и, напоследок, финальная версия, не проверял, но надеюсь будет работать 🙂

                1
                2
                3
                4
                5
                6
                7
                8
                9
                10
                11
                12
                13
                14
                15
                16
                17
                18
                
                DayTrades = {}
                 
                -- Запишет в массив DayTrades все сделки из таблицы всех сделок, которые прошли до 19:00:00 текущего дня
                function GetAllDayTrades()
                   local dt = getTradeDate()
                   dt.date = nil
                   dt.hour = 19
                   dt.min = 0
                   dt.sec = 0
                   dt = os.time(dt)
                   local last_index = getNumberOf('all_trades') - 1
                   for i=0,last_index do
                      local trade = getItem('all_trades', i)
                      if os.time(trade.datetime) < dt then
                         table.sinsert(DayTrades, trade)
                      end
                   end
                end
  3. Добрый день. Подскажите, пожалуйста, как присвоить переменной Х- время сделки из таблицы обезличенных сделок.?
    X={}
    trade=getNumbetOf("alll_trades")
    X=tonumber(trade ["datetime"])

    Х-возвращает nill

    1. Добрый день, что-то Вы вообще непонятное написали, есть же пример получения данных из таблиц:
      https://quikluacsharp.ru/quik-qlua/poluchenie-dannyh-iz-tablits-quik-v-qlua-lua/
      Поясню Ваш код:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
      -- Объявляете переменную X как таблицу (МАССИВ)
      X={}
      -- Присваиваете переменной trade количество строк в таблице всех сделок (ЧИСЛО)
      trade=getNumbetOf("alll_trades")
      -- Пытаетесь обратиться к несуществующему полю "datetime" переменной trade (поля могут быть только у таблиц (массивов))
      -- такая попытка вернет nil (отсутствие какого-либо значения), потом пытаетесь этот nil привести к числовому типу
      -- и все это присвоить таблице X
      X=tonumber(trade ["datetime"])
      -- Не удивительно, что:
      Х-возвращает nill

      а вот, что должно быть, примерно:

      1
      2
      3
      4
      5
      6
      7
      
      -- Перебираете в цикле все строки таблицы всех сделок, начиная с 0 и до количества строк минус 1, т.к. индексы начинаются с 0
      for i = 0,getNumberOf('all_trades') - 1 do
         -- Создаете переменную X, записываете в нее таблицу datetime из текущей строки таблицы всех сделок (X тоже становится таблицей (массивом))
         local X = getItem('all_trades',i).datetime
         -- Выводите в сообщениях даты каждой сделки в виде 1.1.2016 
         message(X.day..'.'..X.month..'.'..X.year)
      end
  4. я не сравнивал время сделок. просто скрипт делал серию сделок (арбитраж - поэтому сразу много заявок с разным количеством и инструментами) и после этого хотел рассчитывать общую цену входа, отфильтровав сразу не нужные по времени. Однако некоторые сделки (первые) могли пропасть из-за несоответствия времени. Но сейчас пытаюсь решить другим способом: все номера заношу в массив, а потом считаю точку входа (пока есть проблемы).
    За подсказку getInfoParam(«SERVERTIME») спасибо. Не получится через массив, наверное вернусь ко времени через getInfoParam(«SERVERTIME») .

  5. Добавлю, что синхронизация времени компьютера через интернет ресурсу проблему не решает.
    И конечно можно фильтровать по номеру сделки. Просто хочу для собственного развития понять, есть ли решение.

    1. Здравствуйте, Юрий! Спасибо за благодарности, стараюсь!)
      Прошу прощения за генератор случайных ID, исправил в скрипте , разместив math.randomseed(os.date(«*t»,os.time()).sec); один раз в конце функции OnInit(), теперь нет повторов, вроде бы.

      Вообще со временем можно несколько вариантов использовать, вот 2 варианта, возможно и другие придумать, смотря какая задача:
      1. getInfoParam("SERVERTIME") возвращает последнее, известное QUIKу время сервера, т.е. пришли какие-то новые данные в терминал, в них указано время сервера, значение параметра "SERVERTIME" обновилось и именно это время указывается во всех сделках.
      2. В таблице "Таблица сделок" ("trades") в datetime есть поле с миллисекундами и поле с микросекундами, т.е.
      getItem(«trades»,e).datetime.ms и getItem(«trades»,e).datetime.mcs соответственно.

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

      Уточните, пожалуйста, для чего Вы сравниваете время сделок?

  6. Здравствуйте! Благодаря Вашим примерам мои месячные познания в Lua продвигаются 7-ми мильными шагами (я так думаю). В очередной раз слова благодарности в Ваш адрес. Столкнулся с проблемой: получения данных их таблиц Квика (талб Заявок, Сделок) по времени:
    1) t00 = os.time() -- запомнили время начала сделок
    2) for e = 0,getNumberOf("trades") - 1 do --перебираем таблицу с фильтром по инструменту и времени
    if os.time(getItem("trades",e).datetime)>= t00 and getItem("trades",e).sec_code ==Sec_code then
    далее действия
    Проблема в том что os.time() - это локальное время компьютера и не совпадает с таблицами (речь идет даже о секундах, с миллисекундами даже и не пытался). Приходится другими способами фильтровать - по trans_id. Но тоже проблема с получением уникального ID.
    Ваш пример:
    -- Генерирует случайный ID транзакции
    math.randomseed(os.date("*t",os.time()).sec); -- Инициализирует генератор псевдослучайных чисел параметром, каждый параметр порождает соответствующую (но одну и ту же) последовательность псевдослучайных чисел.
    local trans_id=math.random (1,999999)
    также ее не решает, т.к. порой две сделки друг за другом могут быть с одним и тем же ID. Может я и заморачиваюсь, но мне кажется что программирование штука точная и должно быть решение. Может Вы как всегда поможете. Если решение подскажите со временем, то пож-та с миллисекундами (на будущее, что-бы не решать проблему 2 раза). Может запомнить время, получив его из таблицы всех сделок по какой-то последней сделки?