1

Тема: Ошибка в параметрах даты

Доброго времени всем.
Народ, очень нужна помощь в коде, вожусь  тут с одной таблицей и
никак не могу в толк взять почему при загрузке скрипта выдаёт вот эту ошибку.
( :time result cannot be represented in this installation)

https://c.radikal.ru/c21/2105/e2/f6ea86cc1c4d.png

Я конечно не спец в программировании, но если я не ошибаюсь, то всё написано верно.

function utils.formatDate (dt) 
 return os.date("%d.%m.%Y", os.time{year = dt.year, month = dt.month, day = dt.day})   
end
function utils.formatDateTime (dateTime) 
  return os.date("%d.%m.%Y %H:%M:%S", dateTime and os.time{year = dateTime.year, month = dateTime.month, day = dateTime.day, hour = dateTime.hour, min = dateTime.min, sec = dateTime.sec} or os.time())
end

Ругается именно на  возврат функции formatDate (dt), хотя ниже прописана formatDateTime (dateTime) почти аналогично и всё в порядке.
Подскажите в чём причина.
https://c.radikal.ru/c14/2105/b6/de5b1c17f8a4.png

2

Re: Ошибка в параметрах даты

Такая ошибка возникает если результат os.time < 0, причем с учетом локальной временной зоны.
А такая ситуация может возникнуть если запросить у функции дату меньше чем 1 января 1970 года 0:00:00 по Гринвичу

Примеры у меня
  message("time="..os.time{year=1970, month=1, day=1, hour=0}) -- Ошибка "time result cannot be represented in this installation"
  message("time="..os.time{year=1970, month=1, day=1, hour=3}) -- Результат 0 (т.к. моя зона GMT3)
  message("time="..os.time{year=1970, month=1, day=1, hour=4}) -- Результат 3600 (т.к. моя зона GMT3)

3

Re: Ошибка в параметрах даты

BlaZed пишет:

Такая ошибка возникает если результат os.time < 0

Нет-нет. Я знаю про Unix Time, или так называемое начало отсчёта. В таблицу для анализа берётся дата и время для сегодняшних данных и пять торговых дней назад.

4

Re: Ошибка в параметрах даты

RRR пишет:
BlaZed пишет:

Такая ошибка возникает если результат os.time < 0

Нет-нет. Я знаю про Unix Time, или так называемое начало отсчёта. В таблицу для анализа берётся дата и время для сегодняшних данных и пять торговых дней назад.

С представленным кодом у вас проблем не видно, по-любому проблема в передаваемых параметрах.

Воткните временно перед проблемной строчкой

 message("dt.year="..dt.year.." dt.month="..dt.month.." dt.day="..dt.day)

И посмотрите какие параметры придут непосредственно перед ошибкой.
Думаю вылезет что-нибудь такое чего вы не ожидали.

5

Re: Ошибка в параметрах даты

BlaZed пишет:

И посмотрите какие параметры придут непосредственно перед ошибкой.
Думаю вылезет что-нибудь такое чего вы не ожидали.

Хорошо, попробую. Вдруг что-нить вылезет.

6 (2021-05-23 20:11:44 отредактировано RRR)

Re: Ошибка в параметрах даты

BlaZed пишет:

Думаю вылезет что-нибудь такое чего вы не ожидали.

Реально странная вещь вылезла, особенно год. И как такое возможно.....?
https://a.radikal.ru/a27/2105/a2/7ed819e592c0.png

7

Re: Ошибка в параметрах даты

RRR пишет:
BlaZed пишет:

Думаю вылезет что-нибудь такое чего вы не ожидали.

Реально странная вещь вылезла, особенно год. И как такое возможно.....?

Дата 1 января 1601 года как раз нисколько не странная, это начало отчета структуры FILETIME, но вот откуда она у вас появилась достаточно интересно.
Короче копать надо как и чем у вас таблица dt заполняется.
Но не видя кода что-то большее сказать практически не возможно.

8

Re: Ошибка в параметрах даты

Ребята, привет!
Вы обсуждаете написанный кем-то бред.
Если datetime таблица, в которой есть как минимум год, месяц и день, то достаточно os.time(datetime).
Если в полях datetime какой-то бред (а судя по фрагменту кода это так и есть), то будет ошибка.
Если нужно получать корректную дату до начала 1970г, то нужно писать корректную функцию.
И еще, в функции getPercentDiff нет проверки на x0 == 0 (ошибки не будет, вернет отрицательную неопределенность), зато есть 100.0 в котором ".0" лишнее - lua сам прекрасно разбирается с типом данных.

9 (2021-05-24 14:43:54 отредактировано RRR)

Re: Ошибка в параметрах даты

BlaZed пишет:

Но не видя кода что-то большее сказать практически не возможно.

kalikazandr пишет:

lua сам прекрасно разбирается с типом данных.

Вы абсолютно правы.
Сейчас сброшу код, там три файла, в один не получилось запилить.
Хотя судя по тому что не работает и в три тоже не особо получилось.
Если отключить эту строчку выходит вот что
https://a.radikal.ru/a14/2105/9f/b156600315d8.jpg
А так таблица выглядит на реале. И стоп-лосс как-то коряво считает.

https://c.radikal.ru/c01/2105/54/ae2ab5a45c71.jpg
main.lua

package.path = getScriptPath() .. '/?.lua;' .. package.path
local RankedWatchList = require('ranked_watch_list')
local settings = {
  color = {
    new = RGB(0, 255, 0),
    old = RGB(255, 255, 0),
    out = RGB(255, 0, 0)  },
    daysBack = 0,
    top = 8,               --Количество лучших которое будем искать
    period = 5,            -- Период за который будем считать
}
local getWatchList = function ()  -- Список акций для отбора добавляем в ручную
  return {
    QJSIM = {                    
      "RASP","HYDR","GMKN", "LKOH","MVID","CHMF","MFON","NVTK","ALRS","NLMK","RTKM","SNGSP","ROSN","IRAO","FEES","PHOR","RSTI","MAGN","SIBN","TRNFP","SBERP","VTBR","SNGS","GAZP","MGNT","MTSS","TATN","MSNG","SBER","MOEX","AFLT","MTLR"
    }---------------------------------------- или TQBR для реала
  }
end
function main ()
  local tId = AllocTable()
  AddColumn(tId, 0, "Ticker", true, QTABLE_STRING_TYPE, 8) -- акции 
  AddColumn(tId, 1, "Close", true, QTABLE_DOUBLE_TYPE, 10) -- цена закрытия
  AddColumn(tId, 2, "StopLoss", true, QTABLE_DOUBLE_TYPE, 10) -- рекомендуемая цена стоп-лоса
  AddColumn(tId, 3, "Prev. close", true, QTABLE_DOUBLE_TYPE, 10) -- звкрытие на прошлой неделе
  AddColumn(tId, 4, "% diff", true, QTABLE_DOUBLE_TYPE, 10) -- % изменения
  AddColumn(tId, 5, "Rank", true, QTABLE_INT_TYPE, 10) -- классифицирование
  AddColumn(tId, 6, "Prev. Rank", true, QTABLE_INT_TYPE, 10) -- предыдущее значение, классификация
  AddColumn(tId, 7, "Avg. daily vol", true, QTABLE_DOUBLE_TYPE, 15) -- средн.суточный объем за 2 недели
    CreateWindow(tId)
        local rankedWatchList = RankedWatchList:new(getWatchList(), settings)
        rankedWatchList:renderToTable(tId)
end

utils.lua

local utils = {}
function utils.getPercentDiff (x0, x1)-- получение %-й разницы
  return 100 * (x1 - x0) / x0
end
function utils.formatDate (dt) -- дата
 message("dt.year="..dt.year.." dt.month="..dt.month.." dt.day="..dt.day)
 return os.date("%d.%m.%Y", os.time{year = dt.year, month = dt.month, day = dt.day})    --ошибка в параметрах даты
end
function utils.formatDateTime (dateTime) --дата и время
  return os.date("%d.%m.%Y %H:%M:%S", dateTime and os.time{year = dateTime.year, month = dateTime.month, day = dateTime.day, hour = dateTime.hour, min = dateTime.min, sec = dateTime.sec} or os.time())
end
function utils.calculateStopLossPrice (args) --расчёт стоплосса
  return args.close - (2 * args.avgDailyVol * args.close / 100.0)
end
function utils.getSecurityParams (classCode, secCode) --получение параметров
    local dbName = "SEC_SCALE"
    local result = {}
  if ParamRequest(classCode, secCode, dbName) then
  result.scale = tonumber(getParamEx2(classCode, secCode, dbName).param_value)
  else
    error(string.format("Не удалось выполнить запрос на получение параметров: ParamRequest(class_code=%s, sec_code=%s, db_name=%s)", classCode, secCode, dbName))
      message("Не удалось выполнить запрос на получение параметров: ParamRequest(class_code=%s, sec_code=%s, db_name=%s)", classCode, secCode, dbName)
  end
  if not CancelParamRequest(classCode, secCode, dbName) then
    error(string.format("Не удалось выполнить запрос на отмену получения параметров: CancelParamRequest(class_code=%s, sec_code=%s, db_name=%s)", classCode, secCode, dbName))
      message("Не удалось выполнить запрос на отмену получения параметров: CancelParamRequest(class_code=%s, sec_code=%s, db_name=%s)", classCode, secCode, dbName)
  end
    return result
end
    return utils

ranked_watch_list.lua

package.path = getScriptPath() .. '/?.lua;' .. package.path
local utils = require('utils')
local RankedWatchList = {
  list = nil,
  info = nil
}
function RankedWatchList:new (securitiesList, settings)
  local daysBack = settings.daysBack or 0
  local period = settings.period
  local public = {}
    function public:refresh ()
  
    self.list = {}
    self.info = {}
  --------------------------------------------- открытые источники данных для ценных бумаг в списке
    for classCode, secCodes in pairs(securitiesList) do
      for _, secCode in ipairs(secCodes) do
        local datasource = CreateDataSource(classCode, secCode, INTERVAL_D1)
        datasource:SetEmptyCallback()
        table.sinsert(self.list, {
          classCode = classCode,
          secCode = secCode,
          datasource = datasource,
          params = utils.getSecurityParams(classCode, secCode)
        })
      end
    end
    sleep(1000)
-------------------------------------------------------------------------создаём таблицу
    for _, security in ipairs(self.list) do
        local datasource = security.datasource
        local lastCandleIndex = datasource:Size() - daysBack
      if not self.info.reportDateTime then 
        self.info.reportDateTime = datasource:T(lastCandleIndex)
      end
        local periodAgoCandleIndex = lastCandleIndex - period
      if not self.info.periodAgoDateTime then 
        self.info.periodAgoDateTime = datasource:T(periodAgoCandleIndex)
      end
        local closePeriodAgo = datasource:C(periodAgoCandleIndex)
      local closeTwoPeriodsAgo = datasource:C(periodAgoCandleIndex - period)
        local twoPeriods = 2 * period
      local avgDailyVolSum = 0.0
      for i = lastCandleIndex, lastCandleIndex - twoPeriods + 1, -1 do
        avgDailyVolSum = avgDailyVolSum + math.abs(utils.getPercentDiff(datasource:C(i - 1), datasource:C(i)))
      end
      local avgDailyVol = avgDailyVolSum / twoPeriods
        local close = datasource:C(lastCandleIndex)
        datasource:Close()
      security.datasource = nil
      security.close = close
      security.closePeriodAgo = closePeriodAgo
      security.difference = utils.getPercentDiff(closePeriodAgo, close)
      security.differencePeriodAgo = utils.getPercentDiff(closeTwoPeriodsAgo, closePeriodAgo)
      security.avgDailyVol = avgDailyVol
      security.stopLoss = utils.calculateStopLossPrice({close = close, avgDailyVol = avgDailyVol})
    end
     table.ssort(self.list, function (a, b) return a.differencePeriodAgo > b.differencePeriodAgo end)
    for i, entry in ipairs(self.list) do
      entry.prevRank = i
    end
     table.ssort(self.list, function (a, b) return a.difference > b.difference end)
      return self
  end
  function public:renderToTable(tId)
      Clear(tId)
      local nowDateTimeAsString = utils.formatDateTime()
      local reportDateAsString
    if daysBack == 0 then
      reportDateAsString = nowDateTimeAsString
    else
      reportDateAsString = utils.formatDate(self.info.reportDateTime)
    end
    SetWindowCaption(tId, string.format("[%s] Лучшие акции от %s до %s", nowDateTimeAsString, utils.formatDate(self.info.periodAgoDateTime), reportDateAsString)) -- Выдаёт ошибку в названии от и до не вводится от которой даты считает
     for rank, security in ipairs(self.list) do
      local rowId = InsertRow(tId, -1)                      --Заполним столбцы данными
      SetCell(tId, rowId, 0, security.secCode)
      SetCell(tId, rowId, 1, tostring(security.close), security.close)
      SetCell(tId, rowId, 2, string.format("%"..tostring(security.params.scale).."f", security.stopLoss), security.stopLoss)   --ОШИБКА   _invalid option '%.' to 'format')
      SetCell(tId, rowId, 3, tostring(security.closePeriodAgo), security.closePeriodAgo)
      SetCell(tId, rowId, 4, string.format("%.2f", security.difference), security.difference)
      SetCell(tId, rowId, 5, tostring(rank), rank)
      SetCell(tId, rowId, 6, tostring(security.prevRank), security.prevRank)
      SetCell(tId, rowId, 7, string.format("%.2f", security.avgDailyVol), security.avgDailyVol)
      local color = nil
      if rank > settings.top then                          --Окраска в соответствии изменений
        if security.prevRank <= settings.top then 
          color = settings.color.out
        end
      else
        if security.prevRank > settings.top then 
          color = settings.color.new
        else
          color = settings.color.old
        end    
      end
  if color then SetColor(tId, rowId, QTABLE_NO_INDEX, color, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR, QTABLE_DEFAULT_COLOR) end
    end
  end
    setmetatable(public, self)
    self.__index = self
    public:refresh()
    return public
end
    return RankedWatchList

10 (2021-05-24 23:01:50 отредактировано BlaZed)

Re: Ошибка в параметрах даты

Тут все предельно просто.
Скрипт начинает работать со свечами не дождавшись пока инструменты подпишутся на график. Как следствие попытка получить дату 0 свечи, которой даже не существует, ну и т.д.

Достаточно добавить в ranked_watch_list.lua после datasource:SetEmptyCallback() ожидание подписки на график, типа такого

local n=0
while(datasource:Size()==0)and(n<100)do sleep(100) n=n+1 end

PS: Ну и в utils.lua замени

--  result.scale = tonumber(getParamEx2(classCode, secCode, dbName).param_value)
  result.scale = string.format("%.0f",getParamEx2(classCode, secCode, dbName).param_value)

чтобы на заполнение стоплосса не ругалось
а в ranked_watch_list.lua точку поставить забыл

--  SetCell(tId, rowId, 2, string.format("%"..tostring(security.params.scale).."f", security.stopLoss), security.stopLoss)
SetCell(tId, rowId, 2, string.format("%."..tostring(security.params.scale).."f", security.stopLoss), security.stopLoss)

11

Re: Ошибка в параметрах даты

BlaZed пишет:

Тут все предельно просто.
Скрипт начинает работать со свечами не дождавшись пока инструменты подпишутся на график. Как следствие попытка получить дату 0 свечи, которой даже не существует, ну и т.д.

Достаточно добавить в ranked_watch_list.lua после datasource:SetEmptyCallback() ожидание подписки на график, типа такого

local n=0
while(datasource:Size()==0)and(n<100)do sleep(100) n=n+1 end

Я бы не был так уверен. С датасорсем не все просто. А если дисконект? Нужно отписаться после соединения, а потом заново подписаться.
Ваш while точно - нет!
Кста код, приведенный автором - не весь и работать не будет совсем.

12

Re: Ошибка в параметрах даты

kalikazandr пишет:

Я бы не был так уверен. С датасорсем не все просто. А если дисконект? Нужно отписаться после соединения, а потом заново подписаться.

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

kalikazandr пишет:

Ваш while точно - нет!

Аргументы будут?

kalikazandr пишет:

Кста код, приведенный автором - не весь и работать не будет совсем.

Кста код, приведенный автором - может быть и не весь (мне это не известно), но работать будет.

13

Re: Ошибка в параметрах даты

BlaZed пишет:

Предлагаете все возможные проверки в код вкорячивать?

Точно, если нет желания слить депо в моменте.

BlaZed пишет:

Аргументы будут?

А какие нужны? то что ваш цикл выполнит 100 итераций и что? должно что то поменяться? может данные поступят за это время? ну может быть, с утра, до торговой сессии, а ну как вечером?
Достаточно аргументов?

BlaZed пишет:

Кста код, приведенный автором - может быть и не весь (мне это не известно), но работать будет.

Не будет, не определен рабочий цикл типа while is run do
Смотрите внимательнее. Хотя смотреть там особо нечего, создатель кода не знает луа, судя по бессмысленным вызовам встроенных функций, тем более не знает qlua.

14

Re: Ошибка в параметрах даты

kalikazandr пишет:
BlaZed пишет:

Предлагаете все возможные проверки в код вкорячивать?

Точно, если нет желания слить депо в моменте.

А так понимаю, вы или код не смотрели, или смотрели но ничего не поняли.
Подсказка, это не торговый робот, это анализ данных.

kalikazandr пишет:
BlaZed пишет:

Аргументы будут?

А какие нужны? то что ваш цикл выполнит 100 итераций и что? должно что то поменяться? может данные поступят за это время? ну может быть, с утра, до торговой сессии, а ну как вечером?
Достаточно аргументов?

Еще раз взгляните на мой while, только повнимательнее, может быть поймете что чушь сморозили.

kalikazandr пишет:
BlaZed пишет:

Кста код, приведенный автором - может быть и не весь (мне это не известно), но работать будет.

Не будет, не определен рабочий цикл типа while is run do

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

kalikazandr пишет:

Смотрите внимательнее. Хотя смотреть там особо нечего, создатель кода не знает луа, судя по бессмысленным вызовам встроенных функций, тем более не знает qlua.

Тут согласен, код так себе, но как бы автор кода в первом посте упомянул что он не спец, какие вопросы то?

15 (2021-05-25 00:04:11 отредактировано RRR)

Re: Ошибка в параметрах даты

BlaZed пишет:

................................

kalikazandr пишет:

..........................

Парни спасибо за советы. Завтра попробую пофиксить,посмотрю что получится.
И да, это пока просто анализатор. Что бы он начал торговать нужно ещё руки приложить.
Вот только не пойму, почему получается корявый стоп лосс...

16

Re: Ошибка в параметрах даты

BlaZed пишет:

Еще раз взгляните на мой while, только повнимательнее, может быть поймете что чушь сморозили.

Чушь не морозят, ее обычно порют свинопасы.
Ваш цикл сделает 99 итераций (~= 10 секунд) и закончит свое выполнение, т.к. n = 100, если в источнике не появились данные, а они там не успеют появиться. По этому ваше решение - не работает.

BlaZed пишет:

Тут согласен, код так себе, но как бы автор кода в первом посте упомянул что он не спец, какие вопросы то?

В первом посте не автор кода, если вы не заметили, то код писал С# -вец, а RRR лишь автор поста и разбирается в чужом говнокоде, в котором, еще раз отмечу, разбираться нечего - выкинуть в помойку и написать свое, рабочее решение.

RRR пишет:

Вот только не пойму, почему получается корявый стоп лосс...

Потому что на "0" делить нельзя.

17

Re: Ошибка в параметрах даты

kalikazandr пишет:

Ваш цикл сделает 99 итераций (~= 10 секунд) и закончит свое выполнение, т.к. n = 100, если в источнике не появились данные, а они там не успеют появиться. По этому ваше решение - не работает.

Мой цикл ожидает загрузку данных в источник по каждому инструменту не более ~10 секунд, чего более чем достаточно даже для плохого соединения.
И это решение отлично работает.

Да и с чего вы решили что "они там не успеют появиться"?
Вы по диалапу с антарктиды что ли в интернет ходите?
Ну поставьте тогда не 100 итераций, а 1000, суть то остается такой же надо просто дождаться загрузки данных в источник.

18

Re: Ошибка в параметрах даты

RRR пишет:

Вот только не пойму, почему получается корявый стоп лосс...

Если имеется ввиду отсутствие десятичных разрядов на реальном счете, то вторая часть коммента [url]https://quik2dde.ru/viewtopic.php?pid=3118#p3118[/url] должна помочь с этим.

19

Re: Ошибка в параметрах даты

BlaZed пишет:

Мой цикл ожидает загрузку данных в источник по каждому инструменту не более ~10 секунд, чего более чем
Ну поставьте тогда не 100 итераций, а 1000, суть то остается такой же надо просто дождаться загрузки данных в источник.

Допустим у меня 300 акций, 3 фьюча и 4500 опционов, по каждому я хочу получить дни, часы, минуты из соответствующих источников. Про то, что столько источников одновременно не протянет квик пропустим. Считаем время, после которого ваш бот "включится".

Запустите свой код после вечернего клиринга, а лучше, после дисконекта, ждать вы будете минут 20, а цикл рассчитан на 10 сек., т.е. порядка 120 инструментов включатся и получат БОЛТ, вместо данных.

Если у вас работает, это не значит, что код рабочий. Факторов задержки данных может быть много.
Я живу в 14 км от ЦОД, у меня оптика в ПК и инет 1Гб/с, и я не пользуюсь такими циклами, потому что это не рабочее решение.
ЗЫ: я самоучка и могу ошибаться, т.к. я не знаю тонкостей луа, которые мне не нужны в торговле, но то что я знаю, это наверняка, спорить со мной бесполезно wink

20

Re: Ошибка в параметрах даты

kalikazandr пишет:

Допустим у меня 300 акций, 3 фьюча и 4500 опционов, по каждому я хочу получить дни, часы, минуты из соответствующих источников. Про то, что столько источников одновременно не протянет квик пропустим.

Естественно, пропустим. Если вы берете 100500 источников, которые не потянет квик, то причем тут вообще код lua.

kalikazandr пишет:

Считаем время, после которого ваш бот "включится".
Запустите свой код после вечернего клиринга, а лучше, после дисконекта, ждать вы будете минут 20, а цикл рассчитан на 10 сек., т.е. порядка 120 инструментов включатся и получат БОЛТ, вместо данных.

Вы хоть пробовали делать то, что предлагаете? Уверен что нет.
Еще раз и медленно.
Это не торговый робот, а аналитика. Ему не надо постоянно работать, запустил, данные увидел, сделал вывод.
Если это не первый запуск скрипта, то данные будут в локальном архиве, откуда без проблем их можно получить.
Да и откуда цифры про 20 минут?

kalikazandr пишет:

Если у вас работает, это не значит, что код рабочий. Факторов задержки данных может быть много.
Я живу в 14 км от ЦОД, у меня оптика в ПК и инет 1Гб/с, и я не пользуюсь такими циклами, потому что это не рабочее решение.

Вот есть люди, которые что-то делают, а есть такие, которые только критикуют.
Если считаешь это "не рабочим" решением, то предоставь свое "рабочее" в котором не будет надуманных вами проблем.

kalikazandr пишет:

ЗЫ: я самоучка и могу ошибаться, т.к. я не знаю тонкостей луа, которые мне не нужны в торговле, но то что я знаю, это наверняка, спорить со мной бесполезно wink

Да я уже вижу, что спорить тут бесполезно.
Придумываете несуществующие проблемы, а сами даже проверить свои же слова действием не в состоянии. Зато уверенности на 146%

21

Re: Ошибка в параметрах даты

Уважаемый BlaZed, мне не интересно ваше мнение, совсем.
Автор топика уже понял, что не так в коде. Диалог окончен.

22

Re: Ошибка в параметрах даты

Взаимно, kalikazandr, выводы сделал, и дискутировать с вами более не намерен.
Удачи вам!

23

Re: Ошибка в параметрах даты

kalikazandr пишет:

.....

BlaZed пишет:

.....

Парни, благодарю вас за помощь!
Каждый из вас в чём-то прав по своему.
Главное что на данный момент всё заработало, пусть и не идеально на 100%.
https://b.radikal.ru/b20/2105/6b/f7f870c6c8c2.jpg
Буду рад с вами пообщаться в новых темах.