Помогите с RSI

Страницы: 1
RSS
Помогите с RSI
 
Добрый день!

Если кто-то уже делал подобное, помогите, пожалуйста, модифицировать код индикатора RSI, чтобы поверх самого индикатора считалась еще EMA самого RSI.

RSI:
Код
Settings = {
Name = "*RSI (Relative Strength Index)", 
round = "on",
Period = 14, 
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference
line = {{
        Name = "RSI",
        Type = TYPE_LINE, 
        Color = RGB(255, 0, 0)
        }
        }
}

function Init() 
    func = RSI()
    return #Settings.line
end

function OnCalculate(Index) 
    return func(Index, Settings)
end

function RSI() --Relative Strength I("RSI")
    local Up = {}
    local Down = {}
    local val_Up = {}
    local val_Down = {}
return function (I, Fsettings, ds)
local Out = nil
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
if I == 1 then
    Up[I] = 0
    Down[I] = 0
end
if I>1 then
    local Val = Value(I,VT,ds)
    local ValPrev = Value(I-1,VT,ds)
    if ValPrev < Val then
        Up[I] = Val - ValPrev
    else
        Up[I] = 0
    end
    if ValPrev > Val then
        Down[I] = ValPrev - Val
    else
        Down[I] = 0
    end
    if (I == P) or (I == P+1) then
        local sumU = 0
        local sumD = 0
        for i = I-P+1, I do
            sumU = sumU + Up[i]
            sumD = sumD + Down[i]
        end
        val_Up[I] = sumU/P
        val_Down[I] = sumD/P
    end
    if I > P+1 then
        val_Up[I] = (val_Up[I-1] * (P-1) + Up[I]) / P
        val_Down[I] = (val_Down[I-1] * (P-1) + Down[I]) / P
    end
    if I >= P then
        Out = 100 / (1 + (val_Down[I] / val_Up[I]))
        return rounding(Out, R)
    end
end
end
end

function rounding(num, round) 
if round and string.upper(round)== "ON" then round=0 end
if num and tonumber(round) then
    local mult = 10^round
    if num >= 0 then return math.floor(num * mult + 0.5) / mult
    else return math.ceil(num * mult - 0.5) / mult end
else return num end
end

function Value(I,VType,ds) 
local Out = nil
VType=(VType and string.upper(string.sub(VType,1,1))) or "A"
    if VType == "O" then        --Open
        Out = (O and O(I)) or (ds and ds:O(I))
    elseif VType == "H" then     --High
        Out = (H and H(I)) or (ds and ds:H(I))
    elseif VType == "L" then    --Low
        Out = (L and L(I)) or (ds and ds:L(I))
    elseif VType == "C" then    --Close
        Out = (C and C(I)) or (ds and ds:C(I))
    elseif VType == "V" then    --Volume
        Out = (V and V(I)) or (ds and ds:V(I)) 
    elseif VType == "M" then    --Median
        Out = ((Value(I,"H",ds) + Value(I,"L",ds)) / 2)
    elseif VType == "T" then    --Typical
        Out = ((Value(I,"M",ds) * 2 + Value(I,"C",ds))/3)
    elseif VType == "W" then    --Weighted
        Out = ((Value(I,"T",ds) * 3 + Value(I,"O",ds))/4) 
    elseif VType == "D" then    --Difference
        Out = (Value(I,"H",ds) - Value(I,"L",ds))
    elseif VType == "A" then    --Any
        if ds then Out = ds[I] else Out = nil end
    end
return Out
end

Я пробовал использовать одну версию с другого ресурса, но она не совсем сходится с квиковской, что критично. Квиковский же код сложен.
Вот версия, которую я пробовал использовать, если кому-то нужно:
Код
Settings = 
{
   Name = "xRSI_EMA",
   RSIperiod = 7,
   EMAperiod = 6,
   line=
   {
      {
         Name = "RSI",
         Color = RGB(255, 0, 0),
         Type = TYPE_LINE,
         Width = 1
      },
      {
         Name = "EMA_RSI",
         Color = RGB(0, 0, 192),
         Type = TYPE_LINE,
         Width = 2
      }

   }
}
----------------------------------------------------------
function FF()

   local EMAR={}

   local RSI={}
   local RSI_H={}
   local RSI_L={}

   
   return function(ind, _p, _p2)
      local period = _p
      local index = ind
      local alfa = 0

            
      if index == 1 then
         EMAR={}
         RSI={}
         RSI_H={}
         RSI_L={}

         EMAR[index]=C(index)
         RSI[index]=50
         RSI_H[index]=0.01
         RSI_L[index]=0.01
      
         return nil
      end
      
      ------------------------------
            
         if C(index) > C(index-1) then
            RSI_H[index]=RSI_H[index-1]*(1-2/(_p+1)) + (math.abs(C(index)-C(index-1)))*2/(_p+1)
            RSI_L[index]=RSI_L[index-1]*(1-2/(_p+1))
         else
            RSI_H[index]=RSI_H[index-1]*(1-2/(_p+1))
            RSI_L[index]=RSI_L[index-1]*(1-2/(_p+1)) + (math.abs(C(index)-C(index-1)))*2/(_p+1)
         end
         
         RSI[index]=RSI_H[index]/(RSI_H[index]+RSI_L[index])*100
         
         alfa =2/(_p2+1)
         EMAR[index]=EMAR[index-1]*(1-alfa) + RSI[index]*alfa
         
         return RSI[index], EMAR[index]
         
   end
end
----------------------------------------------------------

function Init()
   myFF = FF()
   
   return 2
end
function OnCalculate(index)
   
   
   return myFF(index, Settings.RSIperiod, Settings.EMAperiod)
end
 
Доделал другой скрипт. Работает, но не выводит среднюю и рси вместе.

Пытаюсь вывести в функции RSI()
Код
return val_RSI, val_EMARSI
Если выводить по одному val_RSI или val_EMARSI, то работает:
Код
return val_EMARSI

Не могу понять что не так, подскажите, почему?

Весь код:
Код
Settings = {
Name = "*RSI xMA",
Period = 14, 
Metod = "MMA", --SMA, MMA, EMA, WMA, SMMA, VMA
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference
line = {{
      Name = "Horizontal line (top)",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      },
      {
      Name = "Horizontal line (bottom)",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      },
      {
      Name = "RSI",
      Type = TYPE_LINE, 
      Color = RGB(221, 44, 44)
      },
      {
      Name = "EMARSI",
      Type = TYPE_LINE, 
      Color = RGB(0, 0, 255)
      }
      },
MA_Period = 26,
MA_Method = "EMA",
Round = "on",
Multiply = 1,
Horizontal_line="20"
}

function Init()
   func = RSI()
   return #Settings.line
end

function OnCalculate(Index)
local Out = ConvertValue(Settings, func(Index, Settings))
local HL = tonumber(Settings.Horizontal_line)
   if HL then
      return 50+HL,50-HL,Out
   else
      return nil,nil,Out
   end
end

function RSI() --Relative Strength I("RSI")
   local RSI_MA_U = MA()
   local RSI_MA_D = MA()
   local EMARSI_MA = MA()
   local sumU = {}
   local sumD = {}
   local cand = {pp=nil, p=nil}
   local it = {pp=0, p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local M = (Fsettings.Metod or MMA)
local VT = (Fsettings.VType or CLOSE)
local P2 = (Fsettings.MA_Period or 26)
local M2 = (Fsettings.MA_Method or "EMA")
if (P>0) then
   if I == 1 then
      it = {pp=0, p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it={pp=it.p, p=I, l=it.l+1}
         cand.pp = cand.p
      end
      cand.p = GetValueEX(it.p,VT,ds)
      local Up = 0
      local Down = 0
      if it.l > 1 then
         if cand.pp < cand.p then
            Up = cand.p - cand.pp
         end
         if cand.pp > cand.p then
            Down = cand.pp - cand.p
         end
      end
      local val_Up = RSI_MA_U(it.l, {Period=P, Metod = M, VType=ANY}, {[it.l] = Up})
      local val_Down = RSI_MA_D(it.l, {Period=P, Metod = M, VType=ANY}, {[it.l] = Down})
      local val_RSI = nil
      local val_EMARSI = nil
      if it.l >= P then
         if val_Down==0 then 
            val_RSI = 100
            val_EMARSI = EMARSI_MA(it.l, {Period=P2, Metod = M2, VType=ANY}, {[it.l] = val_RSI})
            return val_RSI, val_EMARSI
         else
            val_RSI = 100 - (100 / (1 + (val_Up / val_Down)))
            val_EMARSI = EMARSI_MA(it.l, {Period=P2, Metod = M2, VType=ANY}, {[it.l] = val_RSI})
            return val_RSI, val_EMARSI
         end
      end
   end
end
return nil
end
end

function MA() --Moving Average ("MA")
   local T_MA = {[SMA]=F_SMA(),[MMA]=F_MMA(),[EMA]=F_EMA(),[VMA]=F_VMA(),[SMMA]=F_SMMA(),[WMA]=F_WMA()}
return function (I, Fsettings, ds)
   local Fsettings=(Fsettings or {})
   local P = (Fsettings.Period or 14)
   if (P > 0) then
      return T_MA[string.upper(Fsettings.Metod or EMA)](I, P, (Fsettings.VType or CLOSE), ds)
   end
return nil
end
end

------------------------------------------------------------------
----Moving Average SMA, MMA, EMA, WMA, SMMA, VMA
------------------------------------------------------------------
--[[Simple Moving Average (SMA)
SMA = sum(Pi) / n]]
function F_SMA()
   local sum = {}
   local it = {p=0, l=0}
return function (I, P, VT, ds)
   if I == 1 then
      sum = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / P
      end
   end
return nil
end
end

--[[Modified Moving Average (MMA)
MMA = (MMAi-1*(n-1) + Pi) / n]]
function F_MMA() 
   local sum = {}
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      if it.l <= P + 1 then
         sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
         if (it.l == P) or (it.l == P + 1) then
            tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
         end
      else
         tmp.p = (tmp.pp*(P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[Exponential Moving Average (EMA)
EMAi = (EMAi-1*(n-1)+2*Pi) / (n+1)]]
function F_EMA() 
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp*(P-1) + 2*GetValueEX(it.p,VT,ds)) / (P+1)
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[
William Moving Average (WMA)
( Previous WILLMA * ( Period - 1 ) + Data ) / Period]]
function F_WMA()
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it={p=I, l=it.l+1}
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp * (P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[Volume Adjusted Moving Average (VMA)
VMA = sum(Pi*Vi) / sum(Vi)]]
function F_VMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds) * GetValueEX(it.p,VOLUME,ds)
      sum2[Ip] = (sum2[Ipp] or 0) + GetValueEX(it.p,VOLUME,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / (sum2[Ip] - (sum2[Ippp] or 0))
      end
   end
return nil
end
end

--[[Smoothed Moving Average (SMMA)
SMMAi = (sum(Pi) - SMMAi-1 + Pi) / n]]
function F_SMMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         if it.l == P then
            sum2[Ip] = (sum[Ip] - (sum[Ippp] or 0)) / P
         else
            sum2[Ip] = ((sum[Ip] - (sum[Ippp] or 0)) - (sum2[Ipp] or 0)+ GetValueEX(it.p,VT,ds)) / P
         end
         return sum2[Ip]
      end
   end
return nil
end
end


SMA,MMA,EMA,WMA,SMMA,VMA = "SMA","MMA","EMA","WMA","SMMA","VMA"
OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = "O","H","L","C","V","M","T","W","D","A"

function CandleExist(I,ds)
return (type(C)=="function" and C(I)~=nil) or
   (type(ds)=="table" and (ds[I]~=nil or (type(ds.Size)=="function" and (I>0) and (I<=ds:Size()))))
end

function Squeeze(I,P)
   return math.fmod(I-1,P+1)
end

function ConvertValue(T,...)
local function r(V, R) 
   if R and string.upper(R)== "ON" then R=0 end
   if V and tonumber(R) then
      if V >= 0 then return math.floor(V * 10^R + 0.5) / 10^R
      else return math.ceil(V * 10^R - 0.5) / 10^R end
   else return V end
end
   if arg.n > 0 then
      for i = 1, arg.n do
         arg[i]=arg[i] and r(arg[i] * ((T and T.Multiply) or 1), (T and T.Round) or "off")
      end
      return unpack(arg)
   else return nil end
end

function GetValueEX(I,VT,ds) 
VT=(VT and string.upper(string.sub(VT,1,1))) or ANY
   if VT == OPEN then         --Open
      return (O and O(I)) or (ds and ds:O(I))
   elseif VT == HIGH then       --High
      return (H and H(I)) or (ds and ds:H(I))
   elseif VT == LOW then      --Low
      return (L and L(I)) or (ds and ds:L(I))
   elseif VT == CLOSE then      --Close
      return (C and C(I)) or (ds and ds:C(I))
   elseif VT == VOLUME then      --Volume
      return (V and V(I)) or (ds and ds:V(I)) 
   elseif VT == MEDIAN then      --Median
      return ((GetValueEX(I,HIGH,ds) + GetValueEX(I,LOW,ds)) / 2)
   elseif VT == TYPICAL then   --Typical
      return ((GetValueEX(I,MEDIAN,ds) * 2 + GetValueEX(I,CLOSE,ds))/3)
   elseif VT == WEIGHTED then   --Weighted
      return ((GetValueEX(I,TYPICAL,ds) * 3 + GetValueEX(I,OPEN,ds))/4) 
   elseif VT == DIFFERENCE then   --Difference
      return (GetValueEX(I,HIGH,ds) - GetValueEX(I,LOW,ds))
   else                     --Any
      return (ds and ds[I])
   end
return nil
end
 
Цитата
Максим ААА написал:
Доделал другой скрипт. Работает, но не выводит среднюю и рси вместе.

исправьте функцию OnCalculate вот так:
Код
function OnCalculate(Index)
local Out1,Out2 = ConvertValue(Settings, func(Index, Settings))
local HL = tonumber(Settings.Horizontal_line)
   if HL then
      return 50+HL,50-HL,Out1,Out2
   else
      return nil,nil,Out1,Out2
   end
end
 
Цитата
Sergey Gorokhov написал:
исправьте функцию OnCalculate вот так:
Спасибо!
 
Итоговая версия, может кому пригодится.

Relative Strength I(RSI) x Moving Average (MA):
Код
Settings = {
Name = "*RSI xMA",
Period = 14, 
Metod = "MMA", --SMA, MMA, EMA, WMA, SMMA, VMA
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference
line = {{
      Name = "Horizontal line (top)",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      },
      {
      Name = "Horizontal line (bottom)",
      Type = TYPE_LINE, 
      Color = RGB(140, 140, 140)
      },
      {
      Name = "RSI",
      Type = TYPE_LINE, 
      Color = RGB(221, 44, 44)
      },
      {
      Name = "EMA(RSI)",
      Type = TYPE_LINE, 
      Color = RGB(0, 0, 255)
      }
      },
MA_Period = 26,
MA_Method = "EMA",
Round = "on",
Multiply = 1,
Horizontal_line="20"
}

function Init()
   func = RSI()
   return #Settings.line
end

function OnCalculate(Index)
local Out1,Out2 = ConvertValue(Settings, func(Index, Settings))
local HL = tonumber(Settings.Horizontal_line)
   if HL then
      return 50+HL,50-HL,Out1,Out2
   else
      return nil,nil,Out1,Out2
   end
end

function RSI() --Relative Strength I("RSI")
   local RSI_MA_U = MA()
   local RSI_MA_D = MA()
   local EMARSI_MA = MA()
   local sumU = {}
   local sumD = {}
   local cand = {pp=nil, p=nil}
   local it = {pp=0, p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 14)
local M = (Fsettings.Metod or MMA)
local VT = (Fsettings.VType or CLOSE)
local P2 = (Fsettings.MA_Period or 26)
local M2 = (Fsettings.MA_Method or "EMA")
if (P>0) then
   if I == 1 then
      it = {pp=0, p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it={pp=it.p, p=I, l=it.l+1}
         cand.pp = cand.p
      end
      cand.p = GetValueEX(it.p,VT,ds)
      local Up = 0
      local Down = 0
      if it.l > 1 then
         if cand.pp < cand.p then
            Up = cand.p - cand.pp
         end
         if cand.pp > cand.p then
            Down = cand.pp - cand.p
         end
      end
      local val_Up = RSI_MA_U(it.l, {Period=P, Metod = M, VType=ANY}, {[it.l] = Up})
      local val_Down = RSI_MA_D(it.l, {Period=P, Metod = M, VType=ANY}, {[it.l] = Down})
      local val_RSI = nil
      local val_EMARSI = nil
      if it.l >= P then
         if val_Down==0 then 
            val_RSI = 100
            val_EMARSI = EMARSI_MA(it.l, {Period=P2, Metod = M2, VType=ANY}, {[it.l] = val_RSI})
            return val_RSI, val_EMARSI
         else
            val_RSI = 100 - (100 / (1 + (val_Up / val_Down)))
            val_EMARSI = EMARSI_MA(it.l, {Period=P2, Metod = M2, VType=ANY}, {[it.l] = val_RSI})
            return val_RSI, val_EMARSI
         end
      end
   end
end
return nil
end
end

function MA() --Moving Average ("MA")
   local T_MA = {[SMA]=F_SMA(),[MMA]=F_MMA(),[EMA]=F_EMA(),[VMA]=F_VMA(),[SMMA]=F_SMMA(),[WMA]=F_WMA()}
return function (I, Fsettings, ds)
   local Fsettings=(Fsettings or {})
   local P = (Fsettings.Period or 14)
   if (P > 0) then
      return T_MA[string.upper(Fsettings.Metod or EMA)](I, P, (Fsettings.VType or CLOSE), ds)
   end
return nil
end
end

------------------------------------------------------------------
----Moving Average SMA, MMA, EMA, WMA, SMMA, VMA
------------------------------------------------------------------
--[[Simple Moving Average (SMA)
SMA = sum(Pi) / n]]
function F_SMA()
   local sum = {}
   local it = {p=0, l=0}
return function (I, P, VT, ds)
   if I == 1 then
      sum = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / P
      end
   end
return nil
end
end

--[[Modified Moving Average (MMA)
MMA = (MMAi-1*(n-1) + Pi) / n]]
function F_MMA() 
   local sum = {}
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      if it.l <= P + 1 then
         sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
         if (it.l == P) or (it.l == P + 1) then
            tmp.p = (sum[Ip] - (sum[Ippp] or 0)) / P
         end
      else
         tmp.p = (tmp.pp*(P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[Exponential Moving Average (EMA)
EMAi = (EMAi-1*(n-1)+2*Pi) / (n+1)]]
function F_EMA() 
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it = {p=I, l=it.l+1} 
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp*(P-1) + 2*GetValueEX(it.p,VT,ds)) / (P+1)
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[
William Moving Average (WMA)
( Previous WILLMA * ( Period - 1 ) + Data ) / Period]]
function F_WMA()
   local tmp = {pp=nil, p=nil}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      tmp = {pp=nil, p=nil}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then 
         it={p=I, l=it.l+1}
         tmp.pp = tmp.p
      end
      if it.l == 1 then
         tmp.p = GetValueEX(it.p,VT,ds)
      else
         tmp.p = (tmp.pp * (P-1) + GetValueEX(it.p,VT,ds)) / P
      end
      if it.l >= P then
         return tmp.p
      end
   end
return nil
end
end

--[[Volume Adjusted Moving Average (VMA)
VMA = sum(Pi*Vi) / sum(Vi)]]
function F_VMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds) * GetValueEX(it.p,VOLUME,ds)
      sum2[Ip] = (sum2[Ipp] or 0) + GetValueEX(it.p,VOLUME,ds)
      if it.l >= P then
         return (sum[Ip] - (sum[Ippp] or 0)) / (sum2[Ip] - (sum2[Ippp] or 0))
      end
   end
return nil
end
end

--[[Smoothed Moving Average (SMMA)
SMMAi = (sum(Pi) - SMMAi-1 + Pi) / n]]
function F_SMMA()
   local sum = {}
   local sum2 = {}
   local it = {p=0, l=0}
return function(I, P, VT, ds)
   if I == 1 then
      sum = {}
      sum2 = {}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      local Ip,Ipp,Ippp = Squeeze(it.l,P),Squeeze(it.l-1,P),Squeeze(it.l-P,P)
      sum[Ip] = (sum[Ipp] or 0) + GetValueEX(it.p,VT,ds)
      if it.l >= P then
         if it.l == P then
            sum2[Ip] = (sum[Ip] - (sum[Ippp] or 0)) / P
         else
            sum2[Ip] = ((sum[Ip] - (sum[Ippp] or 0)) - (sum2[Ipp] or 0)+ GetValueEX(it.p,VT,ds)) / P
         end
         return sum2[Ip]
      end
   end
return nil
end
end


SMA,MMA,EMA,WMA,SMMA,VMA = "SMA","MMA","EMA","WMA","SMMA","VMA"
OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = "O","H","L","C","V","M","T","W","D","A"

function CandleExist(I,ds)
return (type(C)=="function" and C(I)~=nil) or
   (type(ds)=="table" and (ds[I]~=nil or (type(ds.Size)=="function" and (I>0) and (I<=ds:Size()))))
end

function Squeeze(I,P)
   return math.fmod(I-1,P+1)
end

function ConvertValue(T,...)
local function r(V, R) 
   if R and string.upper(R)== "ON" then R=0 end
   if V and tonumber(R) then
      if V >= 0 then return math.floor(V * 10^R + 0.5) / 10^R
      else return math.ceil(V * 10^R - 0.5) / 10^R end
   else return V end
end
   if arg.n > 0 then
      for i = 1, arg.n do
         arg[i]=arg[i] and r(arg[i] * ((T and T.Multiply) or 1), (T and T.Round) or "off")
      end
      return unpack(arg)
   else return nil end
end

function GetValueEX(I,VT,ds) 
VT=(VT and string.upper(string.sub(VT,1,1))) or ANY
   if VT == OPEN then         --Open
      return (O and O(I)) or (ds and ds:O(I))
   elseif VT == HIGH then       --High
      return (H and H(I)) or (ds and ds:H(I))
   elseif VT == LOW then      --Low
      return (L and L(I)) or (ds and ds:L(I))
   elseif VT == CLOSE then      --Close
      return (C and C(I)) or (ds and ds:C(I))
   elseif VT == VOLUME then      --Volume
      return (V and V(I)) or (ds and ds:V(I)) 
   elseif VT == MEDIAN then      --Median
      return ((GetValueEX(I,HIGH,ds) + GetValueEX(I,LOW,ds)) / 2)
   elseif VT == TYPICAL then   --Typical
      return ((GetValueEX(I,MEDIAN,ds) * 2 + GetValueEX(I,CLOSE,ds))/3)
   elseif VT == WEIGHTED then   --Weighted
      return ((GetValueEX(I,TYPICAL,ds) * 3 + GetValueEX(I,OPEN,ds))/4) 
   elseif VT == DIFFERENCE then   --Difference
      return (GetValueEX(I,HIGH,ds) - GetValueEX(I,LOW,ds))
   else                     --Any
      return (ds and ds[I])
   end
return nil
end
Страницы: 1
Читают тему
Наверх