BlaZed пишет:Но не видя кода что-то большее сказать практически не возможно.
kalikazandr пишет:lua сам прекрасно разбирается с типом данных.
Вы абсолютно правы.
Сейчас сброшу код, там три файла, в один не получилось запилить.
Хотя судя по тому что не работает и в три тоже не особо получилось.
Если отключить эту строчку выходит вот что

А так таблица выглядит на реале. И стоп-лосс как-то коряво считает.

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