Здравствуйте. Задача вкратце: Нужно выбросить две метки на чарт для их интерактивного использования - задания диапазона вычисления индикатора. На данном этапе метки выводятся, я считываю их параметры. Для упрощения нахождения положения метки на чарте я решил исходную таблицу всех свечек чарта переиндексировать по времени в формате POSIX, тогда, получив новое местоположение метки можно напрямую из этой таблицы получить индекс свечи, к которой привязана метка. Переиндексировать таблицу решил в Init(), тк.к это нужно делать всего один раз при присоединении индикатора к графику. Засада вот в чем - переиндексация производится в цикле, внутри цикла все работает как надо. Но при выходе из цикла значения таблицы nil. В чем косяк?
Нужная таблица в коде называется tposixByTime.
Код
Settings={
Name = "2_ind",--имя индикатора
AssetID = "sber",--идентификатор иструмента
LabelName = "D:\метка.bmp",--имя файла метки
stopper = false,--обработка на каждом тике
complect = 0,
-- начальное местоположение меток
fplace = 40,
splace = 5,
Yvalue = 0,
line=
{
{
Name = "High",
Type =TYPE_LINE,
Width = 1,
Color = RGB(120,90, 140)
}--,
--{
--Name = "Low",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--},
--{
--Name = "Close",
--Type =TYPE_LINE,
-- Width = 1,
--Color = RGB(120,90, 140)
--},
--{
--Name = "Open",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--}
--}
}
}
--глобальные переменные
-- Внимание, название всех параметров меток должны писаться большими буквами
label={
--TEXT="метка";
IMAGE_PATH=Settings.LabelName;
--TRANSPARENCY=50,
--TRANSPARENT_BACKGROUND=1,
--YVALUE=Settings.Yvalue,
DATE=0,
TIME=0;
--R=255;
--G=255;
--B=255;
}
t={}--исходная таблица данных свечек
tposixByTime={}--индексы свечек проиндексированные по времени
tposixOldLabelTime={}--таблица старых значений даты-времени выведенных на чарт меток в POSIX-формате
count=0--ограничитель количества циклов
Label_Id = {}--массив с идентификаторами меток
ScriptPath=""--полный путь к иконке (для метки)
flagIndExist=false--флаг существования индикатора на чарте
flagLblModify=false--флаг, сигнализирующий о перемещении метки
a=0
b=0
c=0
k=0
v=0
tDT={}
function Init()
--объявление переменных. Присваиваем начальные значения чтобы сразу типизировать.
local n = 0--количество строк в таблице (количество свечек)
local l = ""--подпись инструмента
local NmbrOfCandles = 0--номер последней справа свечи на графике
local CandleIndex = 0
--local tDT={}
---[[
if Settings.AssetID == "" then
message("Необходимо установить идентификатор инструмента")
end
--ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки
--номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
NmbrOfCandles = getNumCandles(Settings.AssetID)-2;
--получим таблицу с данными всех свечек, проиндексированную по номеру свечки
--t - таблица значений свечек
--n - количество полученных свечек(строк таблицы)
--l - подпись к инструменту
--текущую свечу не получаем
t,n,l = getCandlesByIndex(Settings.AssetID,0,0,NmbrOfCandles);
--получить индекс двух свечек, номера которых заданы во входных параметрах
--и установить метки
CandleIndex = NmbrOfCandles-Settings.splace;
tposixOldLabelTime["splace"], Label_Id["spl"] = PUTLABEL(CandleIndex);
--message("Initsplace "..tostring(tposixOldLabelTime["splace"]));
--message("Initsplace "..tostring(Label_Id["spl"]));
CandleIndex = NmbrOfCandles-Settings.fplace;
tposixOldLabelTime["fplace"], Label_Id["fpl"] = PUTLABEL(CandleIndex);
--message("Initfplace "..tostring(tposixOldLabelTime["fplace"]));
--message("Initfplace "..tostring(Label_Id["fpl"]));
--берем из таблицы только время-дату свечи
count = 0;
for k=0,NmbrOfCandles-1 do
count = count + 1; if count > 100000 then break end;
--преобразуем в POSIX-формат поле datetime
--транспонируем таблицу - индексируем по времени
tDT[k] = os.time (t[k].datetime);
b=k;
tposixByTime[tDT[b]] = b;
---[[
if NmbrOfCandles-Settings.splace==b then
message("Initsplace "..tostring(tDT[b]).." "..tostring(tposixByTime[b]))
end;
if NmbrOfCandles-Settings.fplace==b then
message("Initfplace "..tostring(tDT[b]).." "..tostring(tposixByTime[b]))
end
--]]
end
return 1
end
VNG_nemo написал: Здравствуйте. Задача вкратце: Нужно выбросить две метки на чарт для их интерактивного использования - задания диапазона вычисления индикатора. На данном этапе метки выводятся, я считываю их параметры. Для упрощения нахождения положения метки на чарте я решил исходную таблицу всех свечек чарта переиндексировать по времени в формате POSIX, тогда, получив новое местоположение метки можно напрямую из этой таблицы получить индекс свечи, к которой привязана метка. Переиндексировать таблицу решил в Init(), тк.к это нужно делать всего один раз при присоединении индикатора к графику. Засада вот в чем - переиндексация производится в цикле, внутри цикла все работает как надо. Но при выходе из цикла значения таблицы nil. В чем косяк?
Нужная таблица в коде называется tposixByTime.
Код
Settings = {
Name = "2_ind" , --имя индикатора
AssetID = "sber" , --идентификатор иструмента
LabelName = "D:\метка.bmp" , --имя файла метки
stopper = false , --обработка на каждом тике
complect = 0 ,
-- начальное местоположение меток
fplace = 40 ,
splace = 5 ,
Yvalue = 0 ,
line =
{
{
Name = "High" ,
Type = TYPE_LINE,
Width = 1 ,
Color = RGB ( 120 , 90 , 140 )
} --,
--{
--Name = "Low",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--},
--{
--Name = "Close",
--Type =TYPE_LINE,
-- Width = 1,
--Color = RGB(120,90, 140)
--},
--{
--Name = "Open",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--}
--}
}
}
--глобальные переменные
-- Внимание, название всех параметров меток должны писаться большими буквами
label = {
--TEXT="метка";
IMAGE_PATH = Settings.LabelName;
--TRANSPARENCY=50,
--TRANSPARENT_BACKGROUND=1,
--YVALUE=Settings.Yvalue,
DATE = 0 ,
TIME = 0 ;
--R=255;
--G=255;
--B=255;
}
t = {} --исходная таблица данных свечек
tposixByTime = {} --индексы свечек проиндексированные по времени
tposixOldLabelTime = {} --таблица старых значений даты-времени выведенных на чарт меток в POSIX-формате
count = 0 --ограничитель количества циклов
Label_Id = {} --массив с идентификаторами меток
ScriptPath = "" --полный путь к иконке (для метки)
flagIndExist = false --флаг существования индикатора на чарте
flagLblModify = false --флаг, сигнализирующий о перемещении метки
a = 0
b = 0
c = 0
k = 0
v = 0
tDT = {}
function Init ()
--объявление переменных. Присваиваем начальные значения чтобы сразу типизировать.
local n = 0 --количество строк в таблице (количество свечек)
local l = "" --подпись инструмента
local NmbrOfCandles = 0 --номер последней справа свечи на графике
local CandleIndex = 0
--local tDT={}
---[[
if Settings.AssetID = = "" then
message ( "Необходимо установить идентификатор инструмента" )
end
--ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки
--номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
NmbrOfCandles = getNumCandles (Settings.AssetID) - 2 ;
--получим таблицу с данными всех свечек, проиндексированную по номеру свечки
--t - таблица значений свечек
--n - количество полученных свечек(строк таблицы)
--l - подпись к инструменту
--текущую свечу не получаем
t,n,l = getCandlesByIndex (Settings.AssetID, 0 , 0 ,NmbrOfCandles);
--получить индекс двух свечек, номера которых заданы во входных параметрах
--и установить метки
CandleIndex = NmbrOfCandles - Settings.splace;
tposixOldLabelTime[ "splace" ], Label_Id[ "spl" ] = PUTLABEL(CandleIndex);
--message("Initsplace "..tostring(tposixOldLabelTime["splace"]));
--message("Initsplace "..tostring(Label_Id["spl"]));
CandleIndex = NmbrOfCandles - Settings.fplace;
tposixOldLabelTime[ "fplace" ], Label_Id[ "fpl" ] = PUTLABEL(CandleIndex);
--message("Initfplace "..tostring(tposixOldLabelTime["fplace"]));
--message("Initfplace "..tostring(Label_Id["fpl"]));
--берем из таблицы только время-дату свечи
count = 0 ;
for k = 0 ,NmbrOfCandles - 1 do
count = count + 1 ; if count > 100000 then break end ;
--преобразуем в POSIX-формат поле datetime
--транспонируем таблицу - индексируем по времени
tDT[k] = os.time (t[k].datetime);
b = k;
tposixByTime[tDT[b]] = b;
---[[
if NmbrOfCandles - Settings.splace = = b then
message ( "Initsplace " .. tostring(tDT[b]) .. " " .. tostring(tposixByTime[b]))
end ;
if NmbrOfCandles - Settings.fplace = = b then
message ( "Initfplace " .. tostring(tDT[b]) .. " " .. tostring(tposixByTime[b]))
end
--]]
end
return 1
end
VNG_nemo написал: Здравствуйте. Задача вкратце: Нужно выбросить две метки на чарт для их интерактивного использования - задания диапазона вычисления индикатора. На данном этапе метки выводятся, я считываю их параметры. Для упрощения нахождения положения метки на чарте я решил исходную таблицу всех свечек чарта переиндексировать по времени в формате POSIX, тогда, получив новое местоположение метки можно напрямую из этой таблицы получить индекс свечи, к которой привязана метка. Переиндексировать таблицу решил в Init(), тк.к это нужно делать всего один раз при присоединении индикатора к графику. Засада вот в чем - переиндексация производится в цикле, внутри цикла все работает как надо. Но при выходе из цикла значения таблицы nil. В чем косяк?
Нужная таблица в коде называется tposixByTime.
Код
Settings = {
Name = "2_ind" , --имя индикатора
AssetID = "sber" , --идентификатор иструмента
LabelName = "D:\метка.bmp" , --имя файла метки
stopper = false , --обработка на каждом тике
complect = 0 ,
-- начальное местоположение меток
fplace = 40 ,
splace = 5 ,
Yvalue = 0 ,
line =
{
{
Name = "High" ,
Type = TYPE_LINE,
Width = 1 ,
Color = RGB ( 120 , 90 , 140 )
} --,
--{
--Name = "Low",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--},
--{
--Name = "Close",
--Type =TYPE_LINE,
-- Width = 1,
--Color = RGB(120,90, 140)
--},
--{
--Name = "Open",
--Type =TYPE_LINE,
--Width = 1,
--Color = RGB(120,90,140)
--}
--}
}
}
--глобальные переменные
-- Внимание, название всех параметров меток должны писаться большими буквами
label = {
--TEXT="метка";
IMAGE_PATH = Settings.LabelName;
--TRANSPARENCY=50,
--TRANSPARENT_BACKGROUND=1,
--YVALUE=Settings.Yvalue,
DATE = 0 ,
TIME = 0 ;
--R=255;
--G=255;
--B=255;
}
t = {} --исходная таблица данных свечек
tposixByTime = {} --индексы свечек проиндексированные по времени
tposixOldLabelTime = {} --таблица старых значений даты-времени выведенных на чарт меток в POSIX-формате
count = 0 --ограничитель количества циклов
Label_Id = {} --массив с идентификаторами меток
ScriptPath = "" --полный путь к иконке (для метки)
flagIndExist = false --флаг существования индикатора на чарте
flagLblModify = false --флаг, сигнализирующий о перемещении метки
a = 0
b = 0
c = 0
k = 0
v = 0
tDT = {}
function Init ()
--объявление переменных. Присваиваем начальные значения чтобы сразу типизировать.
local n = 0 --количество строк в таблице (количество свечек)
local l = "" --подпись инструмента
local NmbrOfCandles = 0 --номер последней справа свечи на графике
local CandleIndex = 0
--local tDT={}
---[[
if Settings.AssetID = = "" then
message ( "Необходимо установить идентификатор инструмента" )
end
--ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки
--номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
NmbrOfCandles = getNumCandles (Settings.AssetID) - 2 ;
--получим таблицу с данными всех свечек, проиндексированную по номеру свечки
--t - таблица значений свечек
--n - количество полученных свечек(строк таблицы)
--l - подпись к инструменту
--текущую свечу не получаем
t,n,l = getCandlesByIndex (Settings.AssetID, 0 , 0 ,NmbrOfCandles);
--получить индекс двух свечек, номера которых заданы во входных параметрах
--и установить метки
CandleIndex = NmbrOfCandles - Settings.splace;
tposixOldLabelTime[ "splace" ], Label_Id[ "spl" ] = PUTLABEL(CandleIndex);
--message("Initsplace "..tostring(tposixOldLabelTime["splace"]));
--message("Initsplace "..tostring(Label_Id["spl"]));
CandleIndex = NmbrOfCandles - Settings.fplace;
tposixOldLabelTime[ "fplace" ], Label_Id[ "fpl" ] = PUTLABEL(CandleIndex);
--message("Initfplace "..tostring(tposixOldLabelTime["fplace"]));
--message("Initfplace "..tostring(Label_Id["fpl"]));
--берем из таблицы только время-дату свечи
count = 0 ;
for k = 0 ,NmbrOfCandles - 1 do
count = count + 1 ; if count > 100000 then break end ;
--преобразуем в POSIX-формат поле datetime
--транспонируем таблицу - индексируем по времени
tDT[k] = os.time (t[k].datetime);
b = k;
tposixByTime[tDT[b]] = b;
---[[
if NmbrOfCandles - Settings.splace = = b then
message ( "Initsplace " .. tostring(tDT[b]) .. " " .. tostring(tposixByTime[b]))
end ;
if NmbrOfCandles - Settings.fplace = = b then
message ( "Initfplace " .. tostring(tDT[b]) .. " " .. tostring(tposixByTime[b]))
end
--]]
end
return 1
end
Код
PUTLABEL = function (index)
--[[функция для установки метки на чарт по индексу
принимает индекс свечи
возвращает время метки в posix-формате и Id метки
входные параметры:
-индекс свечи
-строка с названием точки для индексации массива установленных меток
--]]
local Date=""--дата свечки
local Time=""--время свечки
local Yvalue=0
LabelId=0
--message ("PUTLABELindex.."..tostring(index));
--дата и время свечи
Date=t[index].datetime.year..FTEXT(t[index].datetime.month)..FTEXT(t[index].datetime.day); --дата
Time=FTEXT(t[index].datetime.hour)..FTEXT(t[index].datetime.min)..FTEXT(t[index].datetime.sec);
--привязка к оси У
Yvalue = t[index].high;
--заполнить структуру данных метки
label={
IMAGE_PATH=Settings.LabelName;
YVALUE=Settings.Yvalue+Yvalue;
DATE=Date,
TIME=Time
};
--добавляем метку на чарт и запоминаем Id метки в массиве, проиндексированном принятой строкой
LabelId = AddLabel(Settings.AssetID,label);
--message ("PUTLABELindex "..tostring(os.time (t[index].datetime)))
return os.time (t[index].datetime), LabelId
end
Sergey Gorokhov написал: VNG_nemo, Приведите часть кода где при считывании значений tposixByTime выдает nil.
Код ниже. Вынесен в отдельную функцию, которая вызывается из OnInit(). CndlIdx1 и CndlIdx2 - индексы свечей. При обращении получаю nil.
З.Ы. Как свернуть код в спойлер?
Код
--для каждой свечи в интервале между метками получить максимальное и минимальное
--значение цены
--сравниваем время меток для задания переменной цикла
posixLblTime1 = GETLABLEPOSIXTIME (LblId1);
--message(tostring(posixLblTime1));
posixLblTime2 = GETLABLEPOSIXTIME (LblId2);
--message(tostring(posixLblTime2));
--получаем значения индекса свечи по его posix-времени
CndlIdx1=tposixByTime.posixLblTime1;
message(tostring(CndlIdx1));
CndlIdx2=tposixByTime.posixLblTime2;
message(tostring(CndlIdx2));
function GETLABLEPOSIXTIME (LabelId)
--функция принимает Id метки и возвращает ее время в posix-формате
local id--Id метки
local NewLbLParam = {}--структура параметров метки
local LabelTime = ""--строка с данными даты-времени метки
local dt={}--структура в формате datetime
---[[
id = LabelId;
--message("GETLABLEPOSIXTIME_LabelId "..tostring(id));
--получаем таблицу с параметрами метки (в нижнем регистре в формате строки)
NewLbLParam = GetLabelParams(Settings.AssetID, id);
--message("GETLABLEPOSIXTIME_NewLbLParam "..tostring(NewLbLParam));
--message("GETLABLEPOSIXTIME_LbLParam.date "..tostring(NewLbLParam.date));
--message("GETLABLEPOSIXTIME_LbLParam.time "..tostring(NewLbLParam.time));
--преобразуем в формат datetime
dt.year,dt.month,dt.day = string.match(NewLbLParam.date,"(%d%d%d%d)(%d%d)(%d%d)")
if #NewLbLParam.time == 5 then
LabelTime="0".. NewLbLParam.time
else LabelTime="".. NewLbLParam.time
end
dt.hour,dt.min,dt.sec = string.match(LabelTime,"(%d%d)(%d%d)(%d%d)")
--[[
message("GETLABLEPOSIXTIME_dt.year "..tostring(dt.year));
message("GETLABLEPOSIXTIME_dt.month "..tostring(dt.month));
message("GETLABLEPOSIXTIME_dt.day "..tostring(dt.day));
message("GETLABLEPOSIXTIME_dt.hour "..tostring(dt.hour));
message("GETLABLEPOSIXTIME_dt.min "..tostring(dt.min));
message("GETLABLEPOSIXTIME_dt.sec "..tostring(dt.sec));
message("GETLABLEPOSIXTIME_os.time "..tostring(os.time (dt)));
--]]
--преобразуем в формат POSIX
return os.time (dt);
end
Попутно еще один вопрос. В коде ниже если пытаюсь глобальный массив Label_Id["spl"] проиндексировать индексами "splace" и "fplace", то он тоже возвращает nil. В чем косяк здесь?
И еще один вопрос. При создании графических меток долго мучился - путь к файлу метки задан, Id метки возвращается, а самой метки на чарте нет. Путем долгих мытарств выяснил, что когда работаешь не под админскими правами и файл метки расположен в каталоге индикатора (т.е обращение идет через пользовательский рабочий стол), то функция AddLabel() возвращает пустой путь. Это мой косяк или косяк разработчика?
VNG_nemo написал: Путем долгих мытарств выяснил, что когда работаешь не под админскими правами и файл метки расположен в каталоге индикатора (т.е обращение идет через пользовательский рабочий стол), то функция AddLabel() возвращает пустой путь.
В Lua пути к папкам надо использовать через \\ вместо \
VNG_nemo написал: В коде ниже если пытаюсь глобальный массив Label_Id["spl"] проиндексировать индексами "splace" и "fplace", то он тоже возвращает nil. В чем косяк здесь?
Проведите дополнительную диагностику, проверьте что возвращает AddLabel
Sergey Gorokhov написал: В Lua пути к папкам надо использовать через \\ вместо \
У меня в коде, приведенном в первом посте есть закомментированная строка
--ScriptPath = getScriptPath().."\"..Settings.LabelName; --путь к файлу метки.
Именно в таком виде она и не работает. .LabelName - название файла метки.
Проверьте какой точно путь получается при повторении проблемы. message(ScriptPath)
В settings поменял путь к файлу на LabelName = "down-254095_1280_1". В Init() ввел код: ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки message("Init_ScriptPath "..ScriptPath); label["IMAGE_PATH"]=ScriptPath;
massage вернула путь до папки LuaIndicators, слитый с именем файла (через рабочий стол пользователя)
Что значит через рабочий стол пользователя? У Вас терминал на рабочем столе установлен?
Цитата
VNG_nemo написал: Id метки возвращается, самой метки на чарте нет.
Похожая проблема уже чинилась, проверьте версию терминала, рекомендуем использовать 7.19 или выше. Если с версией всё в порядке, проверьте внимательней все параметры метки. Проблема не воспроизводится, значит явно где-то просто ошиблись.
Sergey Gorokhov написал: Довольно странное имя для файла с картинкой. Тем более что раньше файл назывался "метка.bmp"
Без разницы как он называется. Файл скачан из инета, формат bmp, обрезан до малого размера в paint.
Цитата
Sergey Gorokhov написал: Что значит через рабочий стол пользователя?У Вас терминал на рабочем столе установлен?
Все так и есть, папка терминала находится на рабочем столе
Цитата
Sergey Gorokhov написал: Похожая проблема уже чинилась, проверьте версию терминала, рекомендуем использовать 7.19 или выше.Если с версией всё в порядке, проверьте внимательней все параметры метки.Проблема не воспроизводится, значит явно где-то просто ошиблись.
Версия терминала 7.19.0.51. Если проблема раньше всплывала и была устранена, ткните меня носом, буду благодарен. Проверять мне уже давно нЕчего, я на проверки убил две недели. Если желаете, я скину полный код и сам файл, который пытаюсь вывести в качестве метки. На данный момент для меня это не критично, пока пишу для себя. Но как только отладку завершу, выложу в открытый доступ и если посыпятся такие же вопросы, буду перенаправлять их Вам. Я, конечно, еще слегка плаваю в синтаксисе, но в написании кода я не новичок и прежде, чем обратиться на форум техподдержки, сто раз все проверил. Что же касается параметров метки, то из кода видно, что метка задана глобальной переменной и путь к файлу прописывается сразу после его получения из кода. При этом в коде функции вывода метки я ничего не менял, только две строки в Init(): ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки label["IMAGE_PATH"]=ScriptPath; первая из которых получает полный путь к файлу, а вторая прописывает его в глобальной переменной. Ткните носом, где я ошибся в синтаксисе этих двух строк. Таким образом, ошибка возникает только в результате смены полного имени пути к файлу метки, остальные параметры остаются неизменными (имею ввиду дату и время). При этом, если файл находится на другом диске или не на рабочем столе на диске С, проблем нет.
Sergey Gorokhov написал: Похожая проблема уже чинилась, проверьте версию терминала, рекомендуем использовать 7.19 или выше.Если с версией всё в порядке, проверьте внимательней все параметры метки.Проблема не воспроизводится, значит явно где-то просто ошиблись.
Сергей, здравствуйте. Удалось ли воспроизвести проблему? Проверил все еще раз - проблема осталась. Каково будет Ваше положительное решение?
Скопировал Ваш код, изменил имя своего файла на прописанное Вами в коде, поменял инструмент (акции ВТБ), изменил цену, добавил строку сообщения с Id метки. Присоединил к графику. Получил Id метки в окне сообщения, путь к файлу там же, прямую линию на графике. Метки нет. Сейчас попробую установит программу для работы с экраном (не уверен, что получится, комп на работе, админских прав нет), и попробую сделать скрины.
VNG_nemo, Проверьте, на графике действительно есть свечка 9:55? Если нет, повторите эксперимент, указав в TIME существующее время свечки. Уточните что из себя представляет файл bmp.bmp (прикрепите к сообщению)
Sergey Gorokhov написал: Уточните что из себя представляет файл bmp.bmp (прикрепите к сообщению)
Сергей, посыпаю голову пеплом, прошу простить. Пытался вывести в качестве метки файл png, сейчас еще раз перечитал документацию и прорубило. Ваш код отработал, спасибо.