VNG_nemo (Все сообщения пользователя)

Выбрать дату в календареВыбрать дату в календаре

Страницы: 1 2 След.
Прошу пояснить формат вывода хотя бы в общих чертах, При выводе в Эксель не могу найти DDE-ссылку на листе.
 
Спасибо за ответ. Вторая часть вопроса была немного неверно мной изложена. Дело обстоит так - мне надо принимать таблицу обезличенных сделок весь торговый день. Если при этом не предпринимать никаких мер, то файл принимает огромные размеры и начинает тормозить не только Эксель, но и комп. Поэтому я решил выйти из положения так - установить лимит выведенных по DDE строк и при его превышении сбрасывать таблицу на диск, очищать ее и затем продолжать вывод с первой строки. И так до окончания торгов. И если все обстоит так как Вы написали (т.е. Quik - клиент), то мне неясна реализация самого процесса вывода. Хотя, наверное, стоит почитать о том, как устанавливается связь и осуществляется вывод через по DDE с учетом того, что запросы шлет Квик, а обрабатывает и выполняет Эксель. Еще раз спасибо.  
Прошу пояснить формат вывода хотя бы в общих чертах, При выводе в Эксель не могу найти DDE-ссылку на листе.
 
Прошу прояснить следующие вопросы:

при выводе таблиц по DDE в Эксель Quik - это сервер или клиент? Если сервер, то где в Эксель находятся ячейки с DDE запросом и почему вывод таблицы обезличенных сделок идет построчно с записью в каждую новую строку?

Я так понимаю, что вывод организован через библиотеку DLL. Для ускорения работы по DDE в Эксель рекомендуют использовать метод SetLinkOnData, но в нем в качестве параметра нужно указать DDE-ссылку с запросом к серверу. В выводимой таблице я таких ссылок не обнаружил. Посему вопрос - где можно эту ссылку увидеть, в какую ячейку выводятся данные и как организовано копирование из одной ячейки в строки. Хотя бы в общих чертах, чтобы понять куда рыть.
Заранее благодарен за ответ.
Как заполнить дыры в графике, Нужны свечи при отсутствии торгов
 
Спасибо.
Как заполнить дыры в графике, Нужны свечи при отсутствии торгов
 
Для правильного расчета индикаторов мне необходимо посчитать количество свечек на графике. В моменты отсутствия торгов свечи на графике просто пропускаются. Возможно ли вывести на месте отсутствующих свечек цену закрытия сессии на каждой свече вплоть до начала следующей сессии. Если такой вопрос уже поднимался, прошу поделиться ссылкой.
Странное поведение функции при передаче ей массива
 
Сорри - при построении тренда ВНИЗ возникает проблема.
Странное поведение функции при передаче ей массива
 
Для построения нужно передвинуть метки за экстремумы. На скринах видно, что при построении тренда вверх все строится нормально, а при построении тренда вверх одно значение не верно и поэтому возникает зеленая линия, обведенная овалом.
Странное поведение функции при передаче ей массива
 
Код
package.path = package.path .. ";" .. getWorkingFolder() .."\\LuaIndicators\\modules\\" .. "?.lua";

require ("Format");
require ("Round");
--require ("Lines");

Settings={
   Name = "0_11.03.2019",--имя индикатора
   AssetID = "sber",--идентификатор иструмента
   LabelName = "D:\метка.bmp",--имя файла метки "down-254095_1280_1",
   stopper = false,--обработка на каждом тике 
   complect = 0,
-- начальное местоположение меток
   fplace = 110,
   splace = 8,
   thplase = 30,
   Yvalue = 0,
      line=
         {
            {
               Name = "ChTrnd",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(255,255, 0)
            },
            {
               Name = "UpTrend",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(0,255,0)
            },
            {
               Name = "DnTrend",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(0,255, 0)
            },
            {
               Name = "APointLvl",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "BPointLvl",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "IntLine1",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(105,105,105)--DimGray
            },
            {
               Name = "IntLine2",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(0,0,255)--Blue
            },
            {
               Name = "IntLine3",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(218,165,32)--Goldenrod
            },
            {
               Name = "IntLine4",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(255,0,0)--Red
            },
            {
               Name = "IntLine5",
               Type =TYPE_LINE,
               Width = 2,
               Color = RGB(0,128,0)--Green
            },
            {
               Name = "IntLine6",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(255,0,0)--Red
            },
            {
               Name = "fLine1",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "fLine2",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "ChannelFormingZone",
               Type =TYPE_HISTOGRAM,
               Width = 1,
               Color = RGB(255,255, 0)
            },
            {
               Name = "pLine1",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "pLine2",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "ChannelActionZone",
               Type =TYPE_HISTOGRAM,
               Width = 1,
               Color = RGB(255,255, 0)
            },
            {
               Name = "ChannelActionZone",
               Type =TYPE_HISTOGRAM,
               Width = 1,
               Color = RGB(255,255, 0)
            },
            {
               Name = "ExtLine1",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ExtLine2",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ExtLine3",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ExtLine4",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ExtLine5",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ExtLine6",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(0,255,255)--Aqua
            },
            {
               Name = "ChTrndExt",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(120,90,140)--Aqua
            },
            {
               Name = "ChUpExt",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(120,90,140)--Aqua
            },
            {
               Name = "ChDnExt",
               Type =TYPE_POINT,
               Width = 1,
               Color = RGB(120,90,140)--Aqua
            }                                 
         }
}

--глобальные переменные
-- Внимание, название всех параметров меток должны писаться большими буквами
   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={}
g_PriceStep = 0--шаг цены
g_PriceScale = 0--точность цены
g_tChLines={}

g_APointIdx=0;
g_BPointIdx=0;   
g_APointLvl=0;
g_BPointLvl=0;
   
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;   --путь к файлу метки
      --message("Init_ScriptPath  "..ScriptPath);      
   --label["IMAGE_PATH"]=ScriptPath;
--номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
    NmbrOfCandles = getNumCandles(Settings.AssetID)-2;
--получим таблицу с данными всех свечек, проиндексированную по номеру свечки
--t - таблица значений свечек
--n - количество полученных свечек(строк таблицы)
--l - подпись к инструменту
--текущую свечу не получаем
   t,n,l = getCandlesByIndex(Settings.AssetID,0,0,NmbrOfCandles);
   --[[
      for i=0, NmbrOfCandles-1 do
         message("Init_t   "..tostring(t[i].high))
      end
   --]]   
--получить индекс двух свечек, номера которых заданы во входных параметрах
--и установить метки
   CandleIndex = NmbrOfCandles-Settings.splace;
   tposixOldLabelTime["splace"], Label_Id["splace"] = PUTLABEL(CandleIndex);
   CandleIndex = NmbrOfCandles-Settings.fplace;
   tposixOldLabelTime["fplace"], Label_Id["fplace"] = PUTLABEL(CandleIndex);
   CandleIndex = NmbrOfCandles-Settings.thplase;   
   tposixOldLabelTime["thplase"], Label_Id["thplase"] = PUTLABEL(CandleIndex);
   
--берем из таблицы только время-дату свечи
   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);
      tposixByTime[tDT[k]] = k;
   end

--message("Init_tposixByTime_"..tostring(tDT[Size()-5]))--1539075600
--message("Init_tposixByTime_"..tostring(tDT[1550826000]))
   return 27

end

function OnCalculate(index)

   local info={}
   local CandleIndex
   local LblIdF = 0
   local LblIdS = 0   
   local indput
   local IndLines={}
   local VChTrend
   local VAPointLvl
   local VBPointLvl
   local flagIndChange=false--true-перестроить индикатор, false - не перестраивать
         
   if index==1 then
      info = getDataSourceInfo();
      --шаг цены
      g_PriceStep = getParamEx(info.class_code, info.sec_code, 'SEC_PRICE_STEP').param_value
      --точность цены
      g_PriceScale = getParamEx(info.class_code, info.sec_code, 'SEC_SCALE').param_value
   end
---[[
--если флаг перемещения метки не установлен
   if flagLblModify==false then
--message("OnCalculate_flagLblModify_"..tostring(flagLblModify))   
--проверяем перемещалась ли первая метка   
      LblIdF=IsLabelChange("fplace");
--проверяем вторую метку      
      LblIdS=IsLabelChange("splace");
      --если индикатор существует, то выходим без расчетов, возвращаем массив линий
         if  flagIndExist==true then
               flagIndChange=false;
         --иначе строим индикатор, возвращаем массив линий      
            else 
            flagIndChange=true;
         end
   --если метка перемещалась flagLblModify==true         
      else
      --строим индикатор, выставляем флаг изменения индикатора, 
      --сбрасываем флаг метки, возвращаем индикатор
         flagIndChange=true;
         LblIdF=Label_Id.fplace
         LblIdS=Label_Id.splace
   end
--message("OnCalculate_flagLblModify_"..tostring(flagLblModify))
--message("OnCalculate_LblIdF_"..tostring(LblIdF).." "..tostring(LblIdS))      
   --рассчитываем индикатор или выводим линии без расчета
   
   VChTrend,VChUp,VChDn,VAPointLvl,VBPointLvl,VIntLine1=PUTINDICATOR(LblIdF,LblIdS,flagIndChange,index)
   --]]
   if index==0 then VChTrend=nil end
   if index >= Size() then VChTrend=nil end   
   return VChTrend,VChUp,VChDn,VAPointLvl,VBPointLvl,VIntLine1,VIntLine2,VIntLine3,VIntLine4,VIntLine5,VIntLine6,VfLine1,VfLine2,VFormingTime,VpLine1,VpLine2,VActionTme,VActionTime,VExtLine1,VExtLine2,VExtLine3,VExtLine4,VExtLine5,VExtLine6,VChTrndExt,VChUpExt,VChDnExt
end

function IsLabelChange(place)
--функция принимает индекс массива Label_Id("строка")
--устанавливает глобальные флаги и 
--записывает posix-время в глобальную таблицу tposixOldLabelTime
--возврашает Id метки
   local LblId = 0
   local posixNewLblTime = 0   
   local posixOldLblTime = 0


--проверяем перемещалась ли метка   
--считываем Id метки из массива   
      LblId = Label_Id[place];
--message("IsLabelChange_LabelId_"..tostring(place))      
--считываем posix-время для этой метки
      posixOldLblTime = tposixOldLabelTime[place];
--преобразуем время метки с чарта в posix-формат
--если функция вернула nil, время не меняем
      if GETLABLEPOSIXTIME (LblId)== 0 then
         posixNewLblTime = posixOldLblTime
         else 
            posixNewLblTime = GETLABLEPOSIXTIME (LblId)
      end
   --если время не совпадает, выставляем флаги отсутствия индикатора и модификации метки
      if   posixOldLblTime ~= posixNewLblTime  then
      --выставляем флаги
         --метка перемещена   
         flagLblModify=true;
         --индикатор не построен
         flagIndExist=false;
      --изменяем время метки в массиве
         tposixOldLabelTime[place] = posixNewLblTime;                  
      end

   return LblId
end 
   
PUTLABEL = function (index)
--[[функция для установки метки на чарт по индексу
   принимает индекс свечи 
   возвращает время метки в posix-формате и Id метки
   
   входные параметры:
            -индекс свечи
            -строка с названием точки для индексации массива установленных меток
   вызывается в Init()
--]]
   local Date=""--дата свечки
   local Time=""--время свечки   
   local Yvalue=0
   LabelId=0

   --message ("PUTLABEL_index.."..tostring(index));
--дата и время свечи
   Date=t[index].datetime.year..Format.FTEXT(t[index].datetime.month)..Format.FTEXT(t[index].datetime.day); --дата

   Time=Format.FTEXT(t[index].datetime.hour)..Format.FTEXT(t[index].datetime.min)..Format.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 ("PUTLABEL  LabelId  "..tostring(LabelId).." "..tostring(os.time (t[index].datetime)))
   return os.time (t[index].datetime), LabelId
end

function GETLABLEPOSIXTIME (LabelId)

--функция принимает Id метки и возвращает ее время в posix-формате
--при перемещении метки временно Id может стать нулем, поэтому функция выдает ошибку ноль
   local id--Id метки
   local NewLbLParam = {}--структура параметров метки
   local LabelTime = ""--строка с данными даты-времени метки
   local dt={}--структура в формате datetime
   local err=0
   local retval
---[[   
   id = LabelId;
--message("GETLABLEPOSIXTIME_LabelId_"..tostring(LabelId))   
   
--получаем таблицу с параметрами метки (в нижнем регистре в формате строки)
   if LabelId==0 then retval=err
      else
         NewLbLParam = GetLabelParams(Settings.AssetID, id);
      --преобразуем в формат 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
         if tostring(NewLbLParam.time)=="0" then
            LabelTime="000000"
         end
         dt.hour,dt.min,dt.sec = string.match(LabelTime,"(%d%d)(%d%d)(%d%d)");         
      --преобразуем в формат POSIX
         retval = os.time (dt)
   end;
   return retval;
end

function PUTINDICATOR(LblId1,LblId2,boolIndChange,idx)

   local a=0
   local i
   local j
   local k
   local TrndH=0
   local TrndL=0   
   local h
   local l 
   local CndlIdx1=0
   local CndlIdx2=0
   local tABIdx={}
   local IntervalCndlNmbr=0
   local koef
   local p1koef
   local p2koef
   local tChTrend={}
   local tChUp={}
   local tChDn={}
   local ChUpMax=0
   local ChDnMin=0
   local posixLblTime1
   local posixLblTime2   
   local APointIdx
   local BPointIdx   
   local APointLvl
   local BPointLvl
   local idxUpMax
   local idxDnMin
   local AidxUp
   local AidxDn
   local BidxUp
   local BidxDn
   local ChTrnd
   local ChUp
   local ChDn
   local APntLvl
   local BPntLvl
   local StepsUp
   local TrUp=false
   local TrDn=false
   local Lu
   local tfLine1={}
   local tfLine2={}
   local tpLine1={}
   local tpLine2={}
   local Aidx
   local Bidx
   

   g_tChLines["ChTrend"]=tChTrend;
   g_tChLines["ChUp"]=tChUp;
   g_tChLines["ChDn"]=tChDn;
   g_tChLines["fLine1"]=tfLine1;
   g_tChLines["fLine2"]=tfLine2;
   g_tChLines["pLine1"]=tpLine1;   
   g_tChLines["pLine2"]=tpLine2;
   
--если метка перемещалась или индикатор строится впервые рассчитываем линии и выводим их
   if boolIndChange then

   --для каждой свечи в интервале между метками получить максимальное и минимальное 
   --значение цены
   --сравниваем время меток для задания переменной цикла
   --если GETLABLEPOSIXTIME вернула ошибку

      if GETLABLEPOSIXTIME (LblId1)==0 or LblId1==0 then
      --считываем старое время из массива
            posixLblTime1 = tposixOldLabelTime.fplace
         --иначе считываем новое время метки
         else posixLblTime1 = GETLABLEPOSIXTIME (LblId1)
      end
   --так же и для второй метки
      if GETLABLEPOSIXTIME (LblId2)==0 or LblId2==0 then
            posixLblTime2 = tposixOldLabelTime.splace
         else posixLblTime2 = GETLABLEPOSIXTIME (LblId2)
      end
   --получаем значения индекса свечи по его posix-времени
      CndlIdx1=tposixByTime[posixLblTime1];
      CndlIdx2=tposixByTime[posixLblTime2];
   --если метка перемещена вправо за последнюю свечу, то индекс = максимальному
      if CndlIdx1 == nil then CndlIdx1 = Size()-5 end
      if CndlIdx2 == nil then CndlIdx2 = Size()-4 end
   --находим более раннюю свечу   
      if CndlIdx1 < CndlIdx2 then
            j=CndlIdx1;
            k=CndlIdx2
         else 
            j=CndlIdx2;
            k=CndlIdx1   
      end
   --для всех свечей внутри диапазона меток
      for i = j, k, 1 do
      --находим максимальное и минимальное значение и индекс свечки
      
         h = t[i].high;
         l = t[i].low;
         if h~=0 then
            if h >= TrndH then 
               TrndH = h;            
               tABIdx["hi"] = i--индекс свечки
            end;
         end
         if l~=0 then
            if TrndL==0 then TrndL = l end;
            if l <= TrndL then 
               TrndL = l;
               tABIdx["lo"] = i--индекс свечки      
            end;
         end
      end   
   --находим количество свечек на интервале тренда (от точек А и В)
      IntervalCndlNmbr = tABIdx["hi"] - tABIdx["lo"];
      
   --если получили отрицательное число(слева индекс максимума, тренд вниз), то инвертируем
      if IntervalCndlNmbr < 0 then
         TrUp=false;
         TrDn=true;
         APointIdx=tABIdx["hi"];
         BPointIdx=tABIdx["lo"];
         APointLvl=TrndH;   
         BPointLvl=TrndL;

         else
            TrUp=true;
            TrDn=false;         
            APointIdx=tABIdx["lo"];
            BPointIdx=tABIdx["hi"];
            APointLvl=TrndL;   
            BPointLvl=TrndH;
            IntervalCndlNmbr=-IntervalCndlNmbr            
      end;
   --вычисляем коэффициент наклона прямой
   --отрицательный (тренд вниз),положительный (тренд вверх)
      koef = (APointLvl - BPointLvl)/IntervalCndlNmbr   
   --цикл для вычисления значений всеx линий
      j=0;
      for i=APointIdx, BPointIdx, 1 do
      --вычисляем значения точек основного тренда
      --i-индекс свечи, j - номер шага
         tChTrend[i] = Round.math_round(APointLvl+koef*j,g_PriceScale);
      --заносим значения тренда в глобальную таблицу
         g_tChLines.tChTrend = tChTrend[i]
      --вычисляем значения точек верхней и нижней границы канала
         h = t[i].high;
         l = t[i].low;
         if h - tChTrend[i] > 0 and h~=0 then         
            if 
                  ChUpMax < h - tChTrend[i] 
               then
               --максимальное отклонение от тренда вверх
                  ChUpMax = h - tChTrend[i];
               --индекс свечи с максимальным отклонением от тренда
                  idxUpMax = i;
            end
         end
         if tChTrend[i] -l > 0 and l~=0 then
            if 
                  ChDnMin < tChTrend[i] -l
               then 
                  ChDnMin = tChTrend[i] - l;            
                  idxDnMin = i;
            end
         end            
         j=j+1;         
      end      
      --количество шагов от точки А
         StepsUp=Round.math_round(ChUpMax/koef,0)
      --сдвиг назад для тренда вверх, сдвиг вперед для тренда вниз
         AidxUp = APointIdx - StepsUp;
         BidxUp = BPointIdx - StepsUp;
      --количество шагов от точки А
         StepsDn=Round.math_round(ChDnMin/koef,0)
         --сдвиг назад для тренда вверх, сдвиг вперед для тренда вниз
         AidxDn = APointIdx + StepsDn;
         BidxDn = BPointIdx + StepsDn;               
   
   --цикл по сдвинутому назад диапазону
      j=0;
      for i=AidxUp, BidxUp, 1 do
      --линия тренда верхней границы канала
         tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
         g_tChLines.tChUp = tChUp[i]
if idx==Size() then
message("PUTINDICATOR_Up  "..tostring(g_tChLines.tChUp).."  "..tostring(i))
end            
         j=j+1;      
      end
   --цикл по сдвинутому вперед диапазону   
      j=0;
      for i=AidxDn, BidxDn, 1 do
      --линия тренда нижней границы канала   
         tChDn[i] = math_round(APointLvl+koef*j,g_PriceScale);
         g_tChLines.tChDn = tChDn[i]
--if idx==Size() then
--message("PUTINDICATOR_Dn  "..tostring(g_tChLines.tChDn).."  "..tostring(i))
--end         
         j=j+1;         
      end      
--вычисляем ExtLine
   --koef положительный    
      if TrUp==true then         
      --линия тренда верхней границы канала 
         --ниже уровня точки А
         j=0;
         for i=AidxUp, 2*AidxUp-BidxDn, -1 do
            tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChUp = tChUp[i]
         j=j-1;   
         end         
         --выше уровня точки А         
         j=0;
         for i=AidxUp, BidxDn, 1 do
            tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChUp = tChUp[i]
            if i==BPointIdx then
               ExtLine1Level=tChUp[i]
               local ExtLine1idx=i
            end
            if i==BidxDn then
               ExtLine2Level=tChUp[i]
               local ExtLine2idx=i               
            end
         j=j+1;   
         end         
      --линия медианы         
         j=0;
         --ниже уровня точки А
         for i=APointIdx, AidxUp, -1 do 
            tChTrend[i] = Round.math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChTrend = tChTrend[i]
            if i==AidxUp then
               ExtLine6Level=tChTrend[i]            
               local ExtLine6idx=i
            end
         j=j-1;   
         end
         j=0;
         --выше уровня точки B
         for i=BPointIdx, BidxDn, 1 do
            tChTrend[i] = Round.math_round(BPointLvl+koef*j,g_PriceScale);
            g_tChLines.tChTrend = tChTrend[i]
            if i==BidxDn then
               ExtLine3Level=tChTrend[i]
               local ExtLine3idx=i
            end
         j=j+1;   
         end         
      --линия тренда нижней границы канала         
         j=0;
         --ниже уровня точки А
         for i=AidxDn, AidxUp, -1 do   
            tChDn[i] = math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChDn = tChDn[i]
            if i==APointIdx then
               ExtLine4Level=tChDn[i]
               local ExtLine4idx=i
            end
            if i==AidxUp then
               ExtLine5Level=tChDn[i]               
               local ExtLine5idx=i
            end
         j=j-1;   
         end         
      end
      
   --koef отрицательный   
      if TrDn==true then
      --линия тренда нижней границы канала
         --от уровня точки B и ниже
         j=0;
         for i=BidxDn, BidxUp, 1 do         
            tChDn[i] = math_round(BPointLvl+koef*j,g_PriceScale);
            g_tChLines.tChDn = tChDn[i]
            if i==BPointIdx then
               ExtLine1Level=tChDn[i]
               local ExtLine1idx=i
            end
            if i==BidxUp then
               ExtLine2Level=tChDn[i]
               local ExtLine2idx=i
            end
         j=j+1;   
         end

      --линия медианы
         --от уровня выше точки А до точки А 
         j=0;
         for i=APointIdx, AidxDn, -1 do       
            tChTrend[i] = Round.math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChTrend = tChTrend[i]
            if i==AidxDn then
               ExtLine6Level=tChTrend[i]
               local ExtLine6idx=i
            end
         j=j-1;   
         end
         --ниже точки В         
         j=0;
         for i=BPointIdx, BidxUp, 1 do
            tChTrend[i] = Round.math_round(BPointLvl+koef*j,g_PriceScale);
            g_tChLines.tChTrend = tChTrend[i]
            if i==BidxUp then
               ExtLine3Level=tChTrend[i]
               local ExtLine3idx=i
            end
         j=j+1;   
         end
         
      --линия тренда верхней границы канала
         --от уровня выше точки А до точки А      
         j=0;
         for i=AidxUp, AidxDn, -1 do         
            tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChUp = tChUp[i]
            if i==APointIdx then
               ExtLine4Level=tChUp[i]
               local ExtLine4idx=i
            end
            if i==AidxDn then
               ExtLine5Level=tChUp[i]
               local ExtLine5idx=i
            end
         j=j-1;   
         end   
         --от уровня ниже точки В   
         j=0;
         for i=BidxUp, 2*BidxUp-AidxDn, 1 do         
            tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
            g_tChLines.tChUp = tChUp[i]
         j=j+1;   
         end            
      end   

      if TrUp==true then
      --уровни IntLine
         IntLine1=tChUp[APointIdx]
         IntLine2=tChTrend[AidxDn]
         IntLine3=tChUp[AidxDn]
         IntLine4=tChTrend[BidxUp]
         IntLine5=tChDn[BidxUp]
         IntLine6=tChDn[BPointIdx]         
      end   
      if TrDn==true then      
         IntLine1=tChDn[APointIdx]
         IntLine2=tChTrend[AidxUp]
         IntLine3=tChDn[AidxUp]
         IntLine4=tChTrend[BidxDn]
         IntLine5=tChUp[BidxDn]
         IntLine6=tChUp[BPointIdx]         
      end      
--вычисление значений fLne1 и fLne2
      j=0
      for i=BPointIdx,Size()-1 do         
         tfLine1[i] = Round.math_round(BPointLvl-koef*j,g_PriceScale);
         tfLine2[i] = Round.math_round(BPointLvl-koef*j/2,g_PriceScale);
         g_tChLines.tfLine1 = tfLine1[i]
         g_tChLines.tfLine2 = tfLine2[i]
         --message("PUTINDICATOR  tfLine2_i  "..tostring(g_tChLines.tfLine2).." "..tostring(i));
         j=j+1
      end      
--вычисление значений pLine

      if    TrUp then
      --1-ая точка - значение цены - APointLvl, значение времени - APointIdx
      --2-ая точка - значение цены - IntLine6, значение времени - BidxDn
      --3-я точка - значение цены - IntLine6, значение времени - 2*BidxDn-BPointIdx
         p1koef=Round.math_round((IntLine6-APointLvl)/(BidxDn-APointIdx),g_PriceScale)
         p2koef=Round.math_round((IntLine6-APointLvl)/(2*BidxDn-BPointIdx-APointIdx),g_PriceScale)
      end
      if TrDn then
      --1-ая точка - значение цены - APointLvl, значение времени - APointIdx
      --2-ая точка - значение цены - IntLine6, значение времени - BidxUp
      --3-я точка - значение цены - IntLine6, значение времени - 2*BidxUp-BPointIdx
         p1koef=Round.math_round((IntLine6-APointLvl)/(BidxUp-APointIdx),g_PriceScale)
         p2koef=Round.math_round((IntLine6-APointLvl)/(2*BidxUp-BPointIdx-APointIdx),g_PriceScale)
      end
      
      j=0
      for i=APointIdx,Size()-1 do
         tpLine1[i] = Round.math_round(APointLvl+p1koef*j,g_PriceScale);
         g_tChLines.tpLine1 = tpLine1[i]
         tpLine2[i] = Round.math_round(APointLvl+p2koef*j,g_PriceScale);            
         g_tChLines.tpLine2 = tpLine2[i]
         j=j+1
      end

      g_APointIdx=APointIdx;
      g_BPointIdx=BPointIdx;   
      g_APointLvl=APointLvl;
      g_BPointLvl=BPointLvl;

      ChTrnd=GETTRENDLINE(1,g_APointIdx,g_BPointIdx,"ChTrend")
      if    TrUp then
         Aidx=AidxUp
         Bidx=BidxDn
      end
      if    TrDn then
         Aidx=AidxDn
         Bidx=BidxUp
      end         
      ChTrndExt=GETTRENDLINE(25,Aidx,Bidx,"ChTrend")
      
      ChUp=GETTRENDLINE(2,AidxUp,BidxUp,"ChUp")
      ChUpExt=GETTRENDLINE(26,Aidx,Bidx,"ChUp")      
      
      ChDn=GETTRENDLINE(3,AidxDn,BidxDn,"ChDn")
      ChDnExt=GETTRENDLINE(27,Aidx,Bidx,"ChDn")      
      
      if    TrUp then
         Aidx=AidxUp
         Bidx=BidxUp
      end
      if    TrDn then
         Aidx=AidxDn
         Bidx=BidxDn
      end      
      APntLvl=GETHORLINE(g_APointLvl,4,Aidx)
      BPntLvl=GETHORLINE(g_BPointLvl,5,Bidx)
      IntLin1=GETHORLINE(IntLine1,6,g_APointIdx)
      if TrUp then Lu=AidxDn end
      if TrDn then Lu=AidxUp end      
      IntLin2=GETHORLINE(IntLine2,7,Lu)
      IntLin3=GETHORLINE(IntLine3,8,Lu)      
      if TrUp then Lu=BidxUp end
      if TrDn then Lu=BidxDn end
      IntLin4=GETHORLINE(IntLine4,9,Lu)
      IntLin5=GETHORLINE(IntLine5,10,Lu)
      IntLin6=GETHORLINE(IntLine6,11,g_BPointIdx)
      fLne1=GETFLINE(12,g_BPointIdx,"fLine1")
      fLne2=GETFLINE(13,g_BPointIdx,"fLine2")
      if    TrUp then
         Aidx=AidxUp
         Bidx=BidxDn
         ActionIdx=2*Bidx-Aidx
      end
      if    TrDn then
         Aidx=AidxDn
         Bidx=BidxUp
         ActionIdx=2*Bidx-Aidx         
      end      
      APntTme=GETVERTLINE(Aidx,14,g_APointLvl)
      pLne1=GETTRENDLINE(15,APointIdx,Size()-1,"pLine1")
      pLne2=GETTRENDLINE(16,APointIdx,Size()-1,"pLine2")
      BPntTme=GETVERTLINE(Bidx,17,g_BPointLvl)
      ActionZone=GETVERTLINE(ActionIdx,18,g_BPointLvl)
      Lu=BPointIdx
      ExtLine1=GETHORLINE(ExtLine1Level,19,Lu)
      if TrUp then 
         Lu=BidxDn
      end
      if TrDn then 
         Lu=BidxUp
      end      
      ExtLine2=GETHORLINE(ExtLine2Level,20,Lu)      
      ExtLine3=GETHORLINE(ExtLine3Level,21,Lu)
      Lu=APointIdx
      ExtLine4=GETHORLINE(ExtLine4Level,22,Lu)
      if TrUp then 
         Lu=AidxUp
      end
      if TrDn then 
         Lu=AidxDn
      end      
      ExtLine5=GETHORLINE(ExtLine5Level,23,Lu)
      
      ExtLne6=GETHORLINE(ExtLine6Level,24,Lu)
            
   --перестроили индикатор-устанавливаем флаг
      flagIndExist=true;
      flagLblModify=false
   end         
   return ChTrnd,ChUp,ChDn,APntLvl,BPntLvl,IntLin1,IntLin2,IntLin3,IntLin4,IntLin5,IntLin6,fLne1,fLne2,APntTme,pLne1,pLne2,BPntTme,ExtLine1,ExtLine2,ExtLine3,ExtLine4,ExtLine5,ExtLne6,ChTrndExt,ChUpExt,ChDnExt

end

function math_round (num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

function GETHORLINE(Level,LineNumber,Luch)
--Luch - индекс свечи от которой начнется прямая
   local indx
   local Line
   local z
   
   indx=Size()
   for i=0,indx do
      if Luch==nil then
         Line=Level
         else
         if i<=Luch then 
            Line=nil
            else
               Line=Level
         end
      end
      
      z=SetValue(i, LineNumber, Line)
--if    Level==ExtLine5Level then      
--message("GETHORLINE_z "..tostring(z))
--end      
   end
   return Line
end

function GETTRENDLINE(LineNumber,APntIdx,BPntIdx,Trend)
---[[
   local Line
   local indx
   local TrLine={}
   indx=Size()-1;
   for i=0,indx do
      if i < APntIdx then
         TrLine[i]=nil
         SetValue(i+1, LineNumber, TrLine[i])
      end
      if i > BPntIdx then
         TrLine[i]=nil      
         SetValue(i+1, LineNumber, TrLine[i])
      end         
      if i>=APntIdx and i<=BPntIdx then
            TrLine[i]=g_tChLines[Trend][i]
if LineNumber==2 then
message("GETTRENDLINE  "..tostring( g_tChLines[Trend][i]).."  "..tostring(i))
end               
      SetValue(i+1, LineNumber, TrLine[i])
      end
   
   end
   return TrLine
--]]
end

function GETFLINE(LineNumber,BPntIdx,Trend)
---[[
   local Line
   local indx
   local TrLine={}
--message("GETTRENDLINE  LineNumber Trend  "..tostring(LineNumber).."  "..tostring(Trend));

   SetValue(1, LineNumber, nil)   
   indx=Size();
--message("GETFLINE BPntIdx  "..tostring(BPntIdx));   
   for i=1,indx do
      if i < BPntIdx then
         TrLine[i]=nil
         SetValue(i+1, LineNumber, TrLine[i])
      end
      if i >= BPntIdx then
         TrLine[i]=g_tChLines[Trend][i]         
         SetValue(i+1, LineNumber, TrLine[i])
--message("GETFLINE BPntIdx  "..tostring(TrLine[i]));
      end         
   end
   return TrLine
--]]
end

function GETVERTLINE(PointIndex,LineNumber,PointValue)
   local value

   for i=0,Size()-1 do

      if i<=PointIndex then 
         value=nil   
         SetValue(i, LineNumber, value)
      end
      if i==PointIndex+1 then   
         value=PointValue 
         SetValue(i, LineNumber, value)   
      end
      if i>PointIndex+1 then 
         value=nil   
         SetValue(i, LineNumber, value)
      end
         
   end
   return value
end

function OnDestroy ()
   local tmp
   tmp=DelAllLabels(Settings.AssetID)
end




Format={}
function Format.FTEXT (V)
--функция подставляет нули при их отсутствии на первой позиции даты-времени
   V=tostring (V)
   if string.len (V) == 1 then V = "0".. V end
   return V 
end   
return Format


Round={}
function Round.math_round (num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end
return Round
Странное поведение функции при передаче ей массива
 
Цитата
Sergey Gorokhov написал:
а вообще, для передачи чего либо в функцию, придуманы аргументы функции.
Как работать с функциями и для чего нужны аргументы и почему в одних случаях используются локальные переменные, передаваемые через стек (по значению), а в других глобальные переменные(по ссылке), я тоже в курсе. И в данном случае не имеет абсолютно никакого значения как передается в функцию массив, поскольку это ссылочная переменная, и передавая в функцию имя массива (которое одновременно является ссылкой на массив) мы тем самым даем доступ ко всем элементам массива, т.е работать мы будем не с копиями данных, как при обращении по значению, а с самими данными.  Дело в том, что в данном случае я заполняю массив в коде как глобальную таблицу, а потом использую его только для чтения. И в чем тут ошибка я решительно не могу понять. Ведь массив заполняется правильно, а вот при считывании возникает ошибка, причем такая, что равны первый и последний элемент массива.
Каким боком потокобезопасные функции к передаче  данных в функцию я так и не понял. Их всего четыре и ни одна не подходит под рассматриваемую ситуацию. Можно было бы притянуть каким-то макаром функцию insert, но я не вставляю данные в таблицу после ее формирования, а только считываю их. А формируется первоначальная таблица правильно, что и видно при выводе ее значений.
Код могу выложить, не проблема. Немного громоздкий, но зато весь откомментирован.
Странное поведение функции при передаче ей массива
 
Получается, что при передаче массива в функцию передается неправильно только одно значение. Специально вывел рядом со значениями массива индексы свечей - они совпадают. Как так может быть, что при передаче массива неправильно передается лишь одно значение?
Странное поведение функции при передаче ей массива
 
НаписАл код функции
Код
function GETTRENDLINE(LineNumber,APntIdx,BPntIdx,Trend)
---[[
   local Line
   local indx
   local TrLine={}
   indx=Size()-1;
   for i=0,indx do
      if i < APntIdx then
         TrLine[i]=nil
         SetValue(i+1, LineNumber, TrLine[i])
      end
      if i > BPntIdx then
         TrLine[i]=nil      
         SetValue(i+1, LineNumber, TrLine[i])
      end         
      if i>=APntIdx and i<=BPntIdx then
            TrLine[i]=g_tChLines[Trend][i]
if LineNumber==2 then
message("GETTRENDLINE  "..tostring( g_tChLines[Trend][i]).."  "..tostring(i))
end               
      SetValue(i+1, LineNumber, TrLine[i])
      end
   
   end
   return TrLine
--]]
end
В коде индикатора вычисляю значения и записываю их в массив
Код
      j=0;
      for i=AidxUp, BidxUp, 1 do
      --линия тренда верхней границы канала
         tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
         g_tChLines.tChUp = tChUp[i]
if idx==Size() then
message("PUTINDICATOR_Up  "..tostring(g_tChLines.tChUp).."  "..tostring(i))
end            
         j=j+1;      
      end

вызываю функцию
Код
      ChUp=GETTRENDLINE(2,AidxUp,BidxUp,"ChUp")
и получаю странный результат - в передаваемом массиве внутри функции и в нем же при вычислении не совпадает последнее значение массива
Прошу помочь разобраться с получением данных, Как получить данные с графика не создавая источник данных и не прописывая идентификатор.
 
В таком виде заработала, спасибо.
Прошу помочь разобраться с получением данных, Как получить данные с графика не создавая источник данных и не прописывая идентификатор.
 
Мне нужен именно первый вариант для построения таблицы по всем свечкам. Но в таком виде как Вы написали скрипт выдает синтаксическую ошибку в строке 20. Если же заменить у dt скобки на квадратные, то все выводимые значения нулевые. Что не так?
Прошу помочь разобраться с получением данных, Как получить данные с графика не создавая источник данных и не прописывая идентификатор.
 
Недавно я пытался получить разъяснения по поводу получения данных с графика. Получил такой ответ:"вместо getCandlesByIndex() в индикаторе надо использовать функции O, H, L, C, V, T которые вернут данные о свечке по ее индексу на которую наложен индикатор."

НаписАл код:
Код
Settings =    {
         Name = "0_Candle",
         line =
         {
            {
            Name = "__Trend",
            Color = RGB(255, 255, 128),
            Width = 2,
            Type = TYPE_LINE
            }
         }
         }
dt={}
function Init()

   local Num=Size()

   
   for i=1, Num do
      dt=T(i)
      message(tostring(dt(i).hour))
   end

   return 1
end

function OnCalculate(index)

         
return Line1      

end
И получил ошибку обращения к таблице dt. Что в коде не так?
И все-таки это не ошибка в коде, Странное поведение таблицы всех свечек
 
Вчера я выкладывал код индикатора, который работает на всех ТФ Н4 и ниже и отказывается работать на дневках и выше. И вот какие раскопал неожиданности. В функции Init() я создаю таблицу всех свечек, затем вот таким кодом вывожу ее:
Код
t,n,l = getCandlesByIndex(Settings.AssetID,0,0,NmbrOfCandles);      
for i=0, NmbrOfCandles do
message("Init_t   "..tostring(t[i]))
end
При запуске индикатора получаю шестнадцатиричные значения - вроде как таблица заполнена. Затем  в функции PUTINDICATOR, которая вызывается из OnCalculate в строке:
Код
h = t[i].high;
на каждой свече получаю ошибку с описанием "попытка индексации неизвестного (?) поля (nil value). Никаких преобразований с таблицей в коде после ее создания я не произвожу, только считываю значения. Еще раз обращаю внимание, что код нормально работает на ТФ Н4 и ниже. Как такое может быть?
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Цитата
Sergey Gorokhov написал:
Это не шутка
Да, растянул график по горизонтали и увидел штрихи. Это ж надо так гениально воплотить идею, чтобы длина штриха была равна ширине свечки, а расстояние между штрихами можно было разглядеть только под микроскопом!!!
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Вот скрин - на нем все отлично видно. Линия на скрине сплошная красная, в диалоговом окне штрих-точка.
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Цитата
Sergey Gorokhov написал:
Цитата
VNG_nemo написал:
 
Цитата
Sergey Gorokhov  написал:
Проблема в толщине линии, укажите  Width = 1,
Не помогло.
Приблизьте график.
Это была шутка? Сергей, все осталось без изменения. В диалоговом окне редактирования линия указана дашдот, а на чарте сплошная.
Кроме того, прошу Вас ответить на вопрос выше - как такое может быть, что на Н4 и ниже все норм, а при переходе на дневки и выше массив перестает переиндексироваться.
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Цитата
Sergey Gorokhov написал:
Проблема в толщине линии, укажите  Width = 1,
Не помогло.
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Локализовал проблему о которой писАл выше. Если в код Init()  в цикл добавить отладочные выражения, то видно, что в строке tposixByTime[tDT[k]] = k не происходит присваивания и длина массива равна нулю, хотя с массивом tDT[k] все ОК, и его длина при проверке после выхода из цикла равна количеству свечей. В чем засада?
З.Ы. На ТФ Н4 все работает, на дневном - нет.
Код
   for k=0,NmbrOfCandles-1  do
      count = count + 1; if count > 100000 then break end;
--преобразуем в POSIX-формат поле datetime
--транспонируем таблицу - индексируем по времени      
      tDT[k] = os.time (t[k].datetime);
      tposixByTime[tDT[k]] = k;
      if k==1 then 
         message("Init_tDT_ "..tostring(tDT[k]))
      end
      if k==NmbrOfCandles-1 then
         message("Init_tDT_tposixByTime_ "..tostring(#tDT).." "..tostring(#tposixByTime))
      end      
   end
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Линия, которая отражается неправильно - IntLine6
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Код
package.path = package.path .. ";" .. getWorkingFolder() .."\\LuaIndicators\\modules\\" .. "?.lua";

require ("Format");
require ("Round");
require ("Lines");

Settings={
   Name = "0_28.02.2019_0",--имя индикатора
   AssetID = "sber",--идентификатор инструмента
   LabelName = "D:\метка.bmp",--имя файла метки "down-254095_1280_1",
   stopper = false,--обработка на каждом тике 
   complect = 0,
-- начальное местоположение меток
   fplace = 100,
   splace = 5,
   Yvalue = 0,
      line=
         {
            {
               Name = "ChTrnd",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(255,255, 0)
            },
            {
               Name = "UpTrend",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(0,255,0)
            },
            {
               Name = "DnTrend",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(0,255, 0)
            },
            {
               Name = "APointLvl",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "BPointLvl",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(120,90,140)
            },
            {
               Name = "IntLine1",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(105,105,105)--DimGray
            },
            {
               Name = "IntLine2",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(0,0,255)--Blue
            },
            {
               Name = "IntLine3",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(218,165,32)--Goldenrod
            },
            {
               Name = "IntLine4",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(255,0,0)--Red
            },
            {
               Name = "IntLine5",
               Type =TYPE_LINE,
               Width = 1,
               Color = RGB(0,128,0)--Green
            },
            {
               Name = "IntLine6",
               Type =TYPE_DASHDOT,
               Width = 2,
               Color = RGB(255,0,0)--Red
            }                              
         }
}

--глобальные переменные
-- Внимание, название всех параметров меток должны писаться большими буквами
   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={}
g_PriceStep = 0--шаг цены
g_PriceScale = 0--точность цены
g_tChLines={}

g_APointIdx=0;
g_BPointIdx=0;   
g_APointLvl=0;
g_BPointLvl=0;
   
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;   --путь к файлу метки
      --message("Init_ScriptPath  "..ScriptPath);      
   --label["IMAGE_PATH"]=ScriptPath;
--номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
    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["splace"] = PUTLABEL(CandleIndex);
   CandleIndex = NmbrOfCandles-Settings.fplace;
   tposixOldLabelTime["fplace"], Label_Id["fplace"] = PUTLABEL(CandleIndex);
--берем из таблицы только время-дату свечи
   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 11

end

function OnCalculate(index)

   local info={}
   local CandleIndex
   local LblIdF = 0
   local LblIdS = 0   
   local indput
   local IndLines={}
   local VChTrend
   local VAPointLvl
   local VBPointLvl
   local flagIndChange=false--true-перестроить индикатор, false - не перестраивать

   if index==1 then
      info = getDataSourceInfo();
      --шаг цены
      g_PriceStep = getParamEx(info.class_code, info.sec_code, 'SEC_PRICE_STEP').param_value
      --точность цены
      g_PriceScale = getParamEx(info.class_code, info.sec_code, 'SEC_SCALE').param_value
   end

   
   if t==nil then
   --номер предпоследней справа свечи на графике. Нумерация начинается с нуля.
      NmbrOfCandles = getNumCandles(Settings.AssetID)-2;
   --получим таблицу с данными всех свечек, проиндексированную по номеру свечки
   --t - таблица значений свечек
   --текущую свечу не получаем
      t,n,l = getCandlesByIndex(Settings.AssetID,0,0,NmbrOfCandles);
   --берем из таблицы только время-дату свечи
      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
   end
   
---[[
--если флаг перемещения метки не установлен
   if flagLblModify==false then
--проверяем перемещалась ли первая метка   
      LblIdF=IsLabelChange("fplace");
--проверяем вторую метку      
      LblIdS=IsLabelChange("splace");
      --если индикатор существует, то выходим без расчетов, возвращаем массив линий
         if  flagIndExist==true then
               flagIndChange=false;
         --иначе строим индикатор, возвращаем массив линий      
            else 
            flagIndChange=true;
         end
   --если метка перемещалась flagLblModify==true         
      else
      --строим индикатор, выставляем флаг изменения индикатора, 
      --сбрасываем флаг метки, возвращаем индикатор
         flagIndChange=true;   
   end
   --рассчитываем индикатор или выводим линии без расчета
   VChTrend,VChUp,VChDn,VAPointLvl,VBPointLvl,VIntLine1=PUTINDICATOR(LblIdF,LblIdS,flagIndChange,index)
   --]]
   if index==0 then VChTrend=nil end
   if index >= Size() then VChTrend=nil end   
   return VChTrend,VChUp,VChDn,VAPointLvl,VBPointLvl,VIntLine1,VIntLine2,VIntLine3,VIntLine4,VIntLine5,VIntLine6
end

function IsLabelChange(place)
--функция принимает индекс массива Label_Id("строка")
--устанавливает глобальные флаги и 
--записывает posix-время в глобальную таблицу tposixOldLabelTime
--возврашает Id метки
   local LblId = 0
   local posixNewLblTime = 0   
   local posixOldLblTime = 0


--проверяем перемещалась ли метка   
--считываем Id метки из массива   
      LblId = Label_Id[place];
--считываем posix-время для этой метки
      posixOldLblTime = tposixOldLabelTime[place];
--преобразуем время метки с чарта в posix-формат
--если функция вернула nil, время не меняем
      if GETLABLEPOSIXTIME (LblId)== 0 then
         posixNewLblTime = posixOldLblTime
         else 
            posixNewLblTime = GETLABLEPOSIXTIME (LblId)
      end
   --если время не совпадает, выставляем флаги отсутствия индикатора и модификации метки
      if   posixOldLblTime ~= posixNewLblTime  then
      --выставляем флаги
         --метка перемещена   
         flagLblModify=true;
         --индикатор не построен
         flagIndExist=false;
      --изменяем время метки в массиве
         tposixOldLabelTime[place] = posixNewLblTime;                  
      end

   return LblId
end 
   
PUTLABEL = function (index)
--[[функция для установки метки на чарт по индексу
   принимает индекс свечи 
   возвращает время метки в posix-формате и Id метки
   
   входные параметры:
            -индекс свечи
            -строка с названием точки для индексации массива установленных меток
   вызывается в Init()
--]]
   local Date=""--дата свечки
   local Time=""--время свечки   
   local Yvalue=0
   LabelId=0
   --message ("PUTLABELindex.."..tostring(index));
--дата и время свечи
   Date=t[index].datetime.year..Format.FTEXT(t[index].datetime.month)..Format.FTEXT(t[index].datetime.day); --дата

   Time=Format.FTEXT(t[index].datetime.hour)..Format.FTEXT(t[index].datetime.min)..Format.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  LabelId  "..tostring(LabelId))
   return os.time (t[index].datetime), LabelId
end

function GETLABLEPOSIXTIME (LabelId)

--функция принимает Id метки и возвращает ее время в posix-формате
--при перемещении метки временно Id может стать нулем, поэтому функция выдает ошибку ноль
   local id--Id метки
   local NewLbLParam = {}--структура параметров метки
   local LabelTime = ""--строка с данными даты-времени метки
   local dt={}--структура в формате datetime
   local err=0
   local retval
---[[   
   id = LabelId;
--получаем таблицу с параметрами метки (в нижнем регистре в формате строки)
   if LabelId==0 then retval=err
      else
         NewLbLParam = GetLabelParams(Settings.AssetID, id);
      --преобразуем в формат 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)");
      --преобразуем в формат POSIX
         retval = os.time (dt)
   end;
   return retval;
end

function PUTINDICATOR(LblId1,LblId2,boolIndChange,idx)

   local a=0
   local i
   local j
   local k
   local TrndH=0
   local TrndL=0   
   local h
   local l 
   local CndlIdx1=0
   local CndlIdx2=0
   local tABIdx={}
   local IntervalCndlNmbr=0
   local koef

   local tChTrend={}
   local tChUp={}
   local tChDn={}
   local ChUpMax=0
   local ChDnMin=0
   local posixLblTime1
   local posixLblTime2   
   local APointIdx
   local BPointIdx   
   local APointLvl
   local BPointLvl
   local idxUpMax
   local idxDnMin
   local AidxUp
   local AidxDn
   local BidxUp
   local BidxDn
   local ChTrnd--=200
   local ChUp--=210
   local ChDn--=190
   local APntLvl--=220
   local BPntLvl--=180   
   local StepsUp
   local TrUp=false
   local TrDn=false
   local Lu

   
   g_tChLines["ChTrend"]=tChTrend;
   g_tChLines["ChUp"]=tChUp;
   g_tChLines["ChDn"]=tChDn;
--если метка перемещалась или индикатор строится впервые рассчитываем линии и выводим их
   if boolIndChange then
   
   --для каждой свечи в интервале между метками получить максимальное и минимальное 
   --значение цены
   --сравниваем время меток для задания переменной цикла
   --если GETLABLEPOSIXTIME вернула ошибку
      if GETLABLEPOSIXTIME (LblId1)==0 or LblId1==0 then
      --считываем старое время из массива
            posixLblTime1 = tposixOldLabelTime.fplace
         --иначе считываем новое время метки
         else posixLblTime1 = GETLABLEPOSIXTIME (LblId1)
      end
   --так же и для второй метки
      if GETLABLEPOSIXTIME (LblId2)==0 or LblId2==0 then
            posixLblTime2 = tposixOldLabelTime.splace   
         else posixLblTime2 = GETLABLEPOSIXTIME (LblId2)
      end
   --получаем значения индекса свечи по его posix-времени
      CndlIdx1=tposixByTime[posixLblTime1];
      CndlIdx2=tposixByTime[posixLblTime2];
   --если метка перемещена вправо за последнюю свечу, то индекс = максимальному
      if CndlIdx1 == nil then CndlIdx1 = Size() end
      if CndlIdx2 == nil then CndlIdx2 = Size() end
   --находим более раннюю свечу   
      if CndlIdx1 < CndlIdx2 then
            j=CndlIdx1;
            k=CndlIdx2
         else 
            j=CndlIdx2;
            k=CndlIdx1   
      end
--message("PUTINDICATOR_CndlIdx1_CndlIdx2_j_k_"..tostring(CndlIdx1).."_"..tostring(CndlIdx2).."_"..tostring(j).."_"..tostring(k));      

   --для всех свечей внутри диапазона меток
      for i = j, k, 1 do
      --находим максимальное и минимальное значение и индекс свечки
         h = t[i].high;
         l = t[i].low;
         if h~=0 then
            if h >= TrndH then 
               TrndH = h;            
               tABIdx["hi"] = i--индекс свечки
            end;
         end
         if l~=0 then
            if TrndL==0 then TrndL = l end;
            if l <= TrndL then 
               TrndL = l;
               tABIdx["lo"] = i--индекс свечки      
            end;
         end
--message("PUTINDICATOR_h_l_"..tostring(h).."_"..tostring(l));      
         
--message("PUTINDICATOR_TrndH_TrndL_tABIdx.hi_tABIdx.lo_"..tostring(TrndH).."_"..tostring(TrndL).."_"..tostring(tABIdx["hi"]).."_"..tostring(tABIdx["lo"]));      
         
      end   
   --находим количество свечек на интервале тренда (от точек А и В)
      IntervalCndlNmbr = tABIdx["hi"] - tABIdx["lo"];
      
   --если получили отрицательное число(слева индекс максимума, тренд вниз), то инвертируем
      if IntervalCndlNmbr < 0 then
         TrUp=false;
         TrDn=true;
         APointIdx=tABIdx["hi"];
         BPointIdx=tABIdx["lo"];
         APointLvl=TrndH;   
         BPointLvl=TrndL;

         else
            TrUp=true;
            TrDn=false;         
            APointIdx=tABIdx["lo"];
            BPointIdx=tABIdx["hi"];
            APointLvl=TrndL;   
            BPointLvl=TrndH;
            IntervalCndlNmbr=-IntervalCndlNmbr            
      end;

--message("PUTINDICATOR_APointIdx_BPointIdx_APointLvl_BPointLvl_"..tostring(APointIdx).."_"..tostring(BPointIdx).."_"..tostring(APointLvl).."_"..tostring(BPointLvl));      
   --вычисляем коэффициент наклона прямой
   --отрицательный (тренд вниз),положительный (тренд вверх)
      koef = (APointLvl - BPointLvl)/IntervalCndlNmbr   
--message("PUTINDICATOR  koef  "..tostring(koef));   
   
   --цикл для вычисления значений всеx линий
   --заносим значения в таблицу
      --tChTrend[APointIdx] = Round.math_round(APointLvl,g_PriceScale);
      --g_tChLines.tChTrend = tChTrend[APointIdx]
      --tChTrend[BPointIdx] = Round.math_round(BPointLvl,g_PriceScale);
      --g_tChLines.tChTrend = tChTrend[BPointIdx]      
      j=0;
      for i=APointIdx, BPointIdx, 1 do
      --вычисляем значения точек основного тренда
      --i-индекс свечи, j - номер шага
         tChTrend[i] = Round.math_round(APointLvl+koef*j,g_PriceScale);
      --заносим значения тренда в глобальную таблицу
         g_tChLines.tChTrend = tChTrend[i]
      --вычисляем значения точек верхней и нижней границы канала
         h = t[i].high;
         l = t[i].low;
         if h - tChTrend[i] > 0 and h~=0 then         
            if 
                  ChUpMax < h - tChTrend[i] 
               then
               --максимальное отклонение от тренда вверх
                  ChUpMax = h - tChTrend[i];
               --индекс свечи с максимальным отклонением от тренда
                  idxUpMax = i;
            end
         end
         if tChTrend[i] -l > 0 and l~=0 then
            if 
                  ChDnMin < tChTrend[i] -l
               then 
                  ChDnMin = tChTrend[i] - l;            
                  idxDnMin = i;
            end
         end            
         j=j+1;         
      end      
      --количество шагов от точки А
         StepsUp=Round.math_round(ChUpMax/koef,0)
      --сдвиг назад
         AidxUp = APointIdx - StepsUp;
         BidxUp = BPointIdx - StepsUp;
      --количество шагов от точки А
         StepsDn=Round.math_round(ChDnMin/koef,0)
         --сдвиг вперед
         AidxDn = APointIdx + StepsDn;
         BidxDn = BPointIdx + StepsDn;               
---[[   
   --цикл по сдвинутому назад диапазону
      j=0;
      for i=AidxUp, BidxUp, 1 do
      --линия тренда верхней границы канала
         tChUp[i] = math_round(APointLvl+koef*j,g_PriceScale);
         g_tChLines.tChUp = tChUp[i]
--message("PUTINDICATOR  tChUp_i "..tostring( tChUp[i]).."  "..tostring(i));
         j=j+1;         
      end

   --цикл по сдвинутому вперед диапазону   
      j=0;
      for i=AidxDn, BidxDn, 1 do
      --линия тренда нижней границы канала   
         tChDn[i] = math_round(APointLvl+koef*j,g_PriceScale);
         g_tChLines.tChDn = tChDn[i]
--message("PUTINDICATOR  tChDn_i "..tostring( tChDn[i]).."  "..tostring(i));         
         j=j+1;         
      end
      if TrUp==true then
      --уровени IntLine
         IntLine1=tChUp[APointIdx]
         IntLine2=tChTrend[AidxDn]
         IntLine3=tChUp[AidxDn]
         IntLine4=tChTrend[BidxUp]
         IntLine5=tChDn[BidxUp]
         IntLine6=tChDn[BPointIdx]         
      end   
      if TrDn==true then
      --уровень IntLine1
         IntLine1=tChDn[APointIdx]
         IntLine2=tChTrend[AidxUp]
         IntLine3=tChDn[AidxUp]
         IntLine4=tChTrend[BidxDn]
         IntLine5=tChUp[BidxDn]
         IntLine6=tChUp[BPointIdx]         
      end      
      
      g_APointIdx=APointIdx;
      g_BPointIdx=BPointIdx;   
      g_APointLvl=APointLvl;
      g_BPointLvl=BPointLvl;
--]]
      ChTrnd=GETTRENDLINE(1,g_APointIdx,g_BPointIdx,"ChTrend")
      ChUp=GETTRENDLINE(2,AidxUp,BidxUp,"ChUp")
      ChDn=GETTRENDLINE(3,AidxDn,BidxDn,"ChDn")
      APntLvl=GETHORLINE(g_APointLvl,4,g_APointIdx)
      BPntLvl=GETHORLINE(g_BPointLvl,5,g_BPointIdx)
      IntLin1=GETHORLINE(IntLine1,6,g_APointIdx)
      if TrUp then Lu=AidxDn end
      if TrDn then Lu=AidxUp end      
      IntLin2=GETHORLINE(IntLine2,7,Lu)
      IntLin3=GETHORLINE(IntLine3,8,Lu)      
      if TrUp then Lu=BidxUp end
      if TrDn then Lu=BidxDn end
      IntLin4=GETHORLINE(IntLine4,9,Lu)
      IntLin5=GETHORLINE(IntLine5,10,Lu)
      IntLin6=GETHORLINE(IntLine6,11,g_BPointIdx)      
   --перестроили индикатор-устанавливаем флаг
      flagIndExist=true;
      flagLblModify=false
   end         
   return ChTrnd,ChUp,ChDn,APntLvl,BPntLvl,IntLin1,IntLin2,IntLin3,IntLin4,IntLin5,IntLin6
--]]
end

function math_round (num, idp)
  local mult = 10^(idp or 0)
  return math.floor(num * mult + 0.5) / mult
end

function GETHORLINE(Level,LineNumber,Luch)
--Luch - индекс свечи от которой начнется прямая
   local indx
   local Line
   local z
   
   indx=Size()
   for i=0,indx do
      if Luch==nil then
         Line=Level
         else
         if i<=Luch then 
            Line=nil
            else
               Line=Level
         end
      end
      z=SetValue(i, LineNumber, Line)      
   end

--message("GETHORLINE  Line "..tostring(Line));
   return Line
end

function GETTRENDLINE(LineNumber,APntIdx,BPntIdx,Trend)
---[[
   local Line
   local indx
   local TrLine={}
--message("GETTRENDLINE  LineNumber Trend  "..tostring(LineNumber).."  "..tostring(Trend));
--message("GETTRENDLINE  APntIdx BPntIdx  "..tostring(APntIdx).."  "..tostring(BPntIdx));
   SetValue(1, LineNumber, nil)   
   indx=Size();
   for i=1,indx do
      if i < APntIdx then
         TrLine[i]=nil
         SetValue(i+1, LineNumber, TrLine[i])
      end
      if i > BPntIdx then
         TrLine[i]=nil      
         SetValue(i+1, LineNumber, TrLine[i])
      end         
      if i>=APntIdx and i<=BPntIdx then
            TrLine[i]=g_tChLines[Trend][i]
--message("GETTRENDLINE  TrLine_i "..tostring(i).."  "..tostring(TrLine[i]));            
            SetValue(i+1, LineNumber, TrLine[i])
      end
   
   end
   return TrLine
--]]
end

function OnDestroy ()
   local tmp
   tmp=DelAllLabels(Settings.AssetID)
end
Код
Format={}
function Format.FTEXT (V)
--функция подставляет нули при их отсутствии на первой позиции даты-времени
   V=tostring (V)
   if string.len (V) == 1 then V = "0".. V end
   return V 
end   
return Format
Работает пока только на Н4, на других ТФ вылетает с ошибкой, отлавливаю.
Не изменяется отображение линии независимо от указанного в Settings, Нужно поменять тип линии, но этого не происходит.
 
Прошу помочь в таком вопросе - меняю тип линии в Settings - реакции ноль, выводится только сплошная. Пытаюсь изменить тип в диалоге редактирования - такая же байда. Что делаю не так?
Как такое может быть?, В Settings задаю пять линий, в окне редактирования вижу только три
 
Сергей, огромное спасибо, действительно опять сам тупанул. Значение в Init() не поменял. Заработало.
Как такое может быть?, В Settings задаю пять линий, в окне редактирования вижу только три
 
Собственно сам вопрос задан в теме. Количество заданных линий пять, но странности возникают при выводе. Сам алгоритм индикатора таков, что сначала рассчитываются трендовые линии, а затем принудительно при помощи SetValue они выводятся на график. Таких линий три.Затем пытаюсь добавить две горизонтальные линии, проходящие через концы трендовых, но горизонтальные мало того, что не отображаются, так еще и не выводятся в окне редактирования. Причем последнее обстоятельство обнаружил случайно на третий день мучений и вскипания мозга. Кто-нибудь с таким сталкивался?
Странности интерпретатора, Индикатор исчезает из списка.
 
Цитата
Sergey Gorokhov написал:
Цитата
VNG_nemo написал:
Я так понимаю, что такое поведение интерпретатора наблюдается при ошибках в синтаксисе
не только при ошибках в синтаксисе, а вообще при любых ошибках.
попробуйте запустить Lua индикатор как обычный Lua скрипт, тогда Вы увидите ошибку.
Спасибо Сергей, помогло.
Странности интерпретатора, Индикатор исчезает из списка.
 
Прошу ответить всех кто сталкивался с подобным поведением.
Добавляю в код всего одну строку require ("Lbels"); и индикатор исчезает из списка в окне доступных индикаторов. Я так понимаю, что такое поведение интерпретатора наблюдается при ошибках в синтаксисе. Но где здесь ошибка? Может что-то не так с системными файлами или виртуальной машиной LUA? Кто сталкивался с такой проблемой и как такое можно решить?
Прошу помочь найти ошибку в коде простой функции, Подозреваю выход за пределы видимости, но не могу обнаружить
 
Цитата
SDL написал:
Судя по замыслу, TrLine - таблица:
Абсолютно так
Цитата
SDL написал:
Вот в этом подозрительном месте TrLine (возможно) становится каким-то скаляром:КодTrLine=g_tChLines["ChTrends"]
Спасибо, въехал. Сам виноват, надо быть внимательней. Пропустил выражение для индексирования. Надо было так :КодTrLine[i]=g_tChLines["ChTrends"].
Еще раз благодарю.
Прошу помочь найти ошибку в коде простой функции, Подозреваю выход за пределы видимости, но не могу обнаружить
 
Функция ниже пишет - ошибка в строке.... попытка индексации локальной переменной TrLine в блоке
if i > BPntIdx then
TrLine[i]=nil
SetValue(i, LineNumber, TrLine[i])
end

хотя точно в таком же блоке выше ошибки не возникает. В чем может быть проблема?
Код
function GETTRENDLINE(LineNumber,APntIdx,BPntIdx)
   local Line
   local indx
   local TrLine={}

   indx=Size();
   for i=1,indx do
      if i < APntIdx then
         TrLine[i]=nil
         SetValue(i, LineNumber, TrLine[i])
      end
      if i>=APntIdx and i<=BPntIdx then
            TrLine=g_tChLines["ChTrends"][i]
            SetValue(i, LineNumber, TrLine)
      end
      if i > BPntIdx then
         TrLine[i]=nil      
         SetValue(i, LineNumber, TrLine[i])
      end      
   end
   return TrLine
end
Как работает OnCalculate(), Интерактивно указываю интервал расчета при помощи меток. Пересчитывается только текущая свеча
 
Спасибо Егор.
Еще один вопрос - будет ли корректно отрабатывать  SetValue() если ее вызовы будут находится в другой функции ( в ней в цикле рассчитываются сразу все значения, которые необходимо вывести ), вызываемой из OnCalculate(), или ее необходимо разместить в теле OnCalculate().
Пример:
Код
function GETTRENDLINE(APntIdx,APntLvl,BPntIdx,BPntLvl,koe)
   local Line
        local indx
   local TrLine
   --g_PriceStep
   --g_PriceScale 
   indx=Size();
   --message(tostring(indx));
   for i=0,indx do
      if indx < APntIdx then
         SetValue(i, 1, nil)
         else
            if indx > BPntIdx then
               SetValue(i, 1, nil)
               else
                  if indx==APntIdx then
                     SetValue(i, 1, APntLvl)
                  end
                  if indx==BPntIdx then
                     SetValue(i, 1, BPntLvl)
                  end
                  if indx>APntIdx then
                     if indx<BPntIdx then
                        TrLine=math_round(APntLvl*koe,g_PriceScale)
                        SetValue(i, 1, TrLine)
                     end
                  end
            end
      end
   end
   return 
end
Как работает OnCalculate(), Интерактивно указываю интервал расчета при помощи меток. Пересчитывается только текущая свеча
 
Здравствуйте форумчане и разработчики.
Прошу пояснить такой вопрос - как работает функция OnCalculate(). Я кодом Lua выбрасываю на график две метки, затем перемещаю их руками и затем провожу расчет индикатора на интервале между метками. Ожидал, что все линии индикатора изменятся после расчета. Но...алгоритм работы функции OnCalculate() не соответствует моим ожиданиям. На скрине ниже все видно - сначала выводятся рассчитанные значения до перемещения меток и только на последней свечке (по приходу тиков) выводятся рассчитанные значения. Это так задумано изначально?
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Цитата
Sergey Gorokhov написал:
какая разница что в этом цикле будет t из getCandlesByIndex или T(k)?
Разница существенная, поскольку для получения первоначальной t из getCandlesByIndex используется сишная откомпилированная функция, а для получения всех значений первоначальной Т(к) мне придется использовать цикл интепретатора, что в разы медленнее, а учитывая, что при запуске пересчет ведется аж два раза, картина еще печальнее. Да, переиндексировать мне придется обе таблицы и это займет примерно одинаковое время. Но это второе действие.  
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Уточните что из себя представляет файл bmp.bmp (прикрепите к сообщению)
Сергей, посыпаю голову пеплом, прошу простить. Пытался вывести в качестве метки файл png, сейчас еще раз перечитал документацию и прорубило. Ваш код отработал, спасибо.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Виноват, не тот файл прикрутил
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Если нет, повторите эксперимент, указав в TIME существующее время свечки.
Повторил, время и дату свечи выставил другие:DATE="20190211",
     TIME="080000", результат не изменился.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Вот код
Код
Settings = {
Name = "*metka", 
line = {{
      Name = "Horizontal line",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      }},
AssetID = "qwe",
LabelName = "bmp.bmp"
}


function Init()
   ScriptPath = getScriptPath().."\\"..Settings.LabelName;   --путь к файлу метки
   message(ScriptPath)
   label={
      IMAGE_PATH=ScriptPath,
      YVALUE="0.038",
      DATE="20190213",
      TIME="095500"
   };
   LabelId = AddLabel(Settings.AssetID,label);
    message(LabelId.."") 
   return 1
end

function OnCalculate(Index)
   return 0.038
end
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Цитата
Sergey Gorokhov написал:
Зачем? Если Вы в любой момент по индексу и так можете достать нужные данные без лишних функций.
Как пример - интерактивная работа с метками. Где в таблице данных метки индекс свечи? Я переместил метку, она привязана ко времени и цене свечи. Я считал эти данные. Мне не нужны раздельные данные по времени, мне нужен только индекс свечи, к которой привязана метка. Укажите мне легкий способ получения такого индекса.
Цитата
Sergey Gorokhov написал:
Есть доказательства или это просто мысли? Если просто мысли тогда прошу воздержаться во избежания дезинформации других пользователей.
Хорошо, воздержусь. Ибо доказывать, что скорость работы откомпилированной сишной функции выше скорости работы интерпретатора занятие неблагодарное.
Цитата
Sergey Gorokhov написал:
Что такого Вы делаете с каждой свечкой отдельно? Зачем Вам захламлять лишний кусок памяти?
Уже указал раньше - не нужны данные свечек, нужны индексы свечек к которым привязаны метки. И это не какая-то отдельная задача, а кусок кода комплексной задачи. Работать же с метками, привязанными ко времени неудобно в силу разрастания программного кода если нужно получить данные свечи. Гораздо эффективнее заранее проиндексировать все свечки по времени, получая доступ к индексу свечи по этому времени для получения конкретной свечи и работой с ее данными. Одно обращение по индексу
-получить индекс свечи по смещению в таблице
вместо следующей последовательности действий:
-сравнить время и дату каждой свечи со временем и датой , полученными из данных метки В ЦИКЛЕ
-получить индекс свечи если совпало
Уверен, что вопрос эффективности данных действий очевиден.
А учитывая, что:
- индикатор работает в потоке терминала
- разработчики всеми правдами и неправдами открещиваются от того, чтобы дать программный доступ к таким элементарным объектам как прямая, луч, канал, полигон и т.д. и предлагают все это заменить тормозной работой с метками,
становится очевидно, что чаяния простых пользователей для разработчиков и компании не на первом месте, хотя в других системах торговли уже давно такие сервисы предоставляются. И потому пользователи часто срываются, как я ранее, хотя, конечно, и не стоило этого делать. Но, полазив по форуму и найдя обещания о внесении изменений "вот-вот, скоро в ближайшей версии", начинаешь нервно про себя материться и плеваться.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
На скрине путь к файлу и Id метки в окне сообщений. Изменил только название файла метки (ну и сам файл)
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Цитата
VNG_nemo написал:
попробую сделать скрины.
для скриншотов, отдельная программа не нужна, достаточно нажать кнопку PrintScreen на клавиатуре, потом открыть mspaint и вставить картинку туда.
OK, делаю.
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Цитата
Sergey Gorokhov написал:
Вместо getNumCandles() есть функция Size() вызвав которую в индикаторе, Вы получите количество свечек.
Принимается.
Цитата
Sergey Gorokhov написал:
вместо getCandlesByIndex() в индикаторе надо использовать функции O, H, L, C, V, T которые вернут данные о свечке по ее индексу на которую наложен индикатор.
Нужны не отдельные данные по каждой свечке, а упорядоченная (проиндексированная по номеру свечки) таблица всех значений всех свечей для дальнейшего обращения к ней. Функция для работы с источником данных - это усложнение кода и, соответственно, увеличение времени обработки данных. Мой код делает все манипуляции в три строки. Вы же предлагаете обработать каждую свечу отдельно в интерпретаторе, затем свести все данные в одну таблицу и уже работать с ней вместо того, чтобы обратиться единожды к оптимизированной и откомпилированной сишной функции. Мне это напоминает удаление гланд через задницу.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Скопировал Ваш код, изменил имя своего файла на прописанное Вами в коде, поменял инструмент (акции ВТБ), изменил цену, добавил строку сообщения с Id метки. Присоединил к графику. Получил Id метки в окне сообщения, путь к файлу там же, прямую линию на графике. Метки нет. Сейчас попробую установит программу для работы с экраном (не уверен, что получится, комп на работе, админских прав нет), и попробую сделать скрины.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
VNG_nemo,
Вы же сказали что вопрос снимается, или это было к другой теме?
Я снял третий вопрос. Вопрос об отсутствии меток так и  не решен.
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Цитата
Sergey Gorokhov написал:
К сожалению вынуждены отказать т.к. для таких целей существует демо контур.
Прошу пояснить что есть "демоконтур" или пнуть, куда обратиться за разъяснениями.
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Цитата
Sergey Gorokhov написал:
Поле Идентификатор уникально для каждого графика, а не окна с графиком. То что Вы в одном окне используете один график не значит что остальные тоже так делают. В связи с чем в таком виде мы не можем зарегистрировать пожелание.
Я не случайно указал, что идентификатор нужно добавить ТОЛЬКО для инструмента верхнего уровня. Будь в одном окне хоть миллион графиков, идентификатор будет прописан ТОЛЬКО у одного инструмента или индикатора по желанию пользователя. Остальные останутся пустыми. Так что, это никак не скажется на уникальности.
Цитата
Sergey Gorokhov написал:
Тем более не понятно зачем из индикатора может потребоваться Идентификатор графика на который этот индикатор накладывается, ведь в индикаторе Вы и так можете получить все данные без Идентификатора.Просьба пояснить этот момент.
Я выше не зря указал две функции без передачи идентификатора в которые НЕВОЗМОЖНО получить доступ к данным свечей. Если Вы мне укажете такой механизм без прописывания руками идентификатора графика в коде индикатора при смене инструмента (графика свечей), буду очень благодарен.
Может как-то сумбурно объяснил, попробую "на пальцах". Есть индикатор. В его коде есть указанные выше функции, расположенные в Init(), что исключает возможность прописывания идентификатора после присоединения его к графику (сразу в момент присоединения вылетит ошибка). Простой пользователь (не разработчик) хочет просто кинуть индикатор на любой график без танцев с бубном. Но при такой ситуации, которая есть на данный момент, у него это не получится. Мало того, что надо прописать идентификатор на вкладке "дополнительно" - с этим можно как-то смириться, но нужно еще открыть код индикатора и прописать  идентификатор в секции Settings, что для рядового пользователя крайне проблематично. В случае же если в данном окошке для графика первого слоя будет прописан идентификатор по умолчанию, в программном коде достаточно будет просто считать эту строчку и проблема будет закрыта. Как это может отразиться на уникальности я даже представить себе не могу. Кроме того, можно запретить редактирование этой строки из программного кода, оставить только возможность редактирования руками в терминале.
Цитата
Sergey Gorokhov написал:
что же тут непонятного? Чтобы метки ставить на самого себя без бубна с назначениями идентификатора и передачей идентификатора в параметры.замечу в скобках, что это уже давно "зарегистрировано", а тут вот здрасьте, "просьба пояснить"
Честно говоря, я не понял о каких метках идет речь. Большая просьба кинуть ссылку на "давно "зарегистрировано"".
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Похожая проблема уже чинилась, проверьте версию терминала, рекомендуем использовать 7.19 или выше.Если с версией всё в порядке, проверьте внимательней все параметры метки.Проблема не воспроизводится, значит явно где-то просто ошиблись.
Сергей, здравствуйте.
Удалось ли воспроизвести проблему? Проверил все еще раз - проблема осталась. Каково будет Ваше положительное решение?
Добавление функциональности клиентского терминала, Ввод параметра инструмента по умолчанию
 
Прошу разработчиков рассмотреть вопрос по добавлению следующих изменений в клиентский терминал:
1. На вкладке "дополнительно" окна редактирования инструмента в окно идентификатора автоматически прописывать название окна графика для инструмента верхнего слоя, естественно с возможностью редактирования и считывания прописанного по умолчанию значения строки из этого окна в программном коде индикатора. Это существенно облегчит написание кода индикаторов. В этом случае при обращении к функциям getNumCandles() и getCandlesByIndex() не придется лезть в программный код индикатора для внесения вручную изменений ID инструмента в секции Settings при смене графика инструмента, достаточно будет считать значение по умолчанию. Я, например, не использую более одного графика цены в каждом окне и меня сильно напрягает, что при смене окна и инструмента нужно лезть в программный код индикатора и вносить правки вручную. Сделать же это после присоединения индикатора к графику невозможно, поскольку указанные выше функции я использую в секции Init() и к моменту запуска индикатора эта секция уже должна получить все параметры. Для тех же, кому нужно использовать более одного графика инструмента в окне, останется возможность редактирования значения по умолчанию ручками.

2. Создать в интерфейсе кнопку  с программным кодом, эмулирующим выдачу тика цены для любого инструмента. Это нужно для отладки программного кода индикаторов без подключения к серверу. Особенно это актуально в часы отсутствия торгов.
Функция возвращает nil, При выходе из функции она возвращает nil, хотя внутри функции все ОК
 
Цитата
Sergey Gorokhov написал:
Цитата
VNG_nemo написал:
переменная posixNewLblTime получает значение nil.
А как Вы это поняли?
Если по строке
Цитата
VNG_nemo написал:
message(tostring(posixNewLblTimeF).."  IsLabelChange_posixNewLblTime")

То в ней явно другая переменная, а не искомая posixNewLblTime
Сергей, огромное спасибо, все работает. Искал один косяк, а накосячил в другом месте.
Еще раз спасибо
Функция возвращает nil, При выходе из функции она возвращает nil, хотя внутри функции все ОК
 
Здравствуйте форумчане. В коде ниже функция GETLABLEPOSIXTIME внутри себя
рассчитывается корректно (должна возвращать время метки в формате posix, в
сообщении его и выводит), но при обращении к ней в функции IsLabelChange
переменная posixNewLblTime получает значение nil. Второй день бьюсь, не пойму
в чем косяк. Что не так делаю?
Скрытый текст
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Третий вопрос снимается. Где-то был мой косяк., где, так и не нашел, проблема исчезла.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Довольно странное имя для файла с картинкой. Тем более что раньше файл назывался "метка.bmp"
Без разницы как он называется. Файл скачан из инета, формат bmp, обрезан до малого размера в paint.
Цитата
Sergey Gorokhov написал:
Что значит через рабочий стол пользователя?У Вас терминал на рабочем столе установлен?
Все так и есть, папка терминала находится на рабочем столе

Цитата
Sergey Gorokhov написал:
Похожая проблема уже чинилась, проверьте версию терминала, рекомендуем использовать 7.19 или выше.Если с версией всё в порядке, проверьте внимательней все параметры метки.Проблема не воспроизводится, значит явно где-то просто ошиблись.
Версия терминала 7.19.0.51. Если проблема раньше всплывала и была устранена, ткните меня носом, буду благодарен. Проверять мне уже давно нЕчего, я на проверки убил две недели. Если желаете, я скину полный код и сам файл, который пытаюсь вывести в качестве метки. На данный момент для меня это не критично, пока пишу для себя. Но как только отладку завершу, выложу в открытый доступ и если посыпятся такие же вопросы, буду перенаправлять их Вам. Я, конечно, еще слегка плаваю в синтаксисе, но в написании кода я не новичок и прежде, чем обратиться на форум техподдержки, сто раз все проверил.
Что же касается параметров метки, то из кода видно, что метка задана глобальной переменной и путь к файлу прописывается сразу после его получения из кода. При этом в коде функции вывода метки я ничего не менял, только две строки в Init():
ScriptPath = getScriptPath().."\\"..Settings.LabelName; --путь к файлу метки
label["IMAGE_PATH"]=ScriptPath;
первая из которых получает полный путь к файлу, а вторая прописывает его в глобальной переменной. Ткните носом, где я ошибся в синтаксисе этих двух строк.
Таким образом, ошибка возникает только в результате смены полного имени пути к файлу метки, остальные параметры остаются неизменными (имею ввиду дату и время). При этом, если файл находится на другом диске или не на рабочем столе на диске С, проблем нет.
Как получить значения глобальной таблицы в Init(), При выходе из Init() глобальная таблица возвращает nil.
 
Цитата
Sergey Gorokhov написал:
Цитата
VNG_nemo написал:
 
Цитата
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, слитый с именем файла (через рабочий стол пользователя)

Id метки возвращается, самой метки на чарте нет.
Страницы: 1 2 След.
Наверх