Странное поведение функции при передаче ей массива

Страницы: 1
RSS
Странное поведение функции при передаче ей массива
 
НаписАл код функции
Код
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")
и получаю странный результат - в передаваемом массиве внутри функции и в нем же при вычислении не совпадает последнее значение массива
 
Получается, что при передаче массива в функцию передается неправильно только одно значение. Специально вывел рядом со значениями массива индексы свечей - они совпадают. Как так может быть, что при передаче массива неправильно передается лишь одно значение?
 
Трудно сказать, не видя всего кода.
Но скорей всего проблема в потокобезопасности.
в документации QLUA.chm, глава "Потокобезопасные функции для работы с таблицами Lua"

а вообще, для передачи чего либо в функцию, придуманы аргументы функции.
 
Цитата
Sergey Gorokhov написал:
а вообще, для передачи чего либо в функцию, придуманы аргументы функции.
Как работать с функциями и для чего нужны аргументы и почему в одних случаях используются локальные переменные, передаваемые через стек (по значению), а в других глобальные переменные(по ссылке), я тоже в курсе. И в данном случае не имеет абсолютно никакого значения как передается в функцию массив, поскольку это ссылочная переменная, и передавая в функцию имя массива (которое одновременно является ссылкой на массив) мы тем самым даем доступ ко всем элементам массива, т.е работать мы будем не с копиями данных, как при обращении по значению, а с самими данными.  Дело в том, что в данном случае я заполняю массив в коде как глобальную таблицу, а потом использую его только для чтения. И в чем тут ошибка я решительно не могу понять. Ведь массив заполняется правильно, а вот при считывании возникает ошибка, причем такая, что равны первый и последний элемент массива.
Каким боком потокобезопасные функции к передаче  данных в функцию я так и не понял. Их всего четыре и ни одна не подходит под рассматриваемую ситуацию. Можно было бы притянуть каким-то макаром функцию insert, но я не вставляю данные в таблицу после ее формирования, а только считываю их. А формируется первоначальная таблица правильно, что и видно при выводе ее значений.
Код могу выложить, не проблема. Немного громоздкий, но зато весь откомментирован.
 
Цитата
VNG_nemo написал:
Код могу выложить, не проблема. Немного громоздкий, но зато весь откомментирован.
да выложите код
 
Код
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
 
Для построения нужно передвинуть метки за экстремумы. На скринах видно, что при построении тренда вверх все строится нормально, а при построении тренда вверх одно значение не верно и поэтому возникает зеленая линия, обведенная овалом.
 
Сорри - при построении тренда ВНИЗ возникает проблема.
 
К сожалению разобраться не получилось, попробуйте воспроизвести на более простом коде.
Страницы: 1
Читают тему
Наверх