Мастер LUA

Страницы: 1
RSS
Мастер LUA, Помощь в переписи индикатора из thinkorswim в LUA
 
Уважаемые мастера, кто может расшифровать код написанный в thinkorswim, индикатор: "stochastic momentum index"
Код
declare lower;

input over_bought = 40.0;
input over_sold = -40.0;
input percentDLength = 3;
input percentKLength = 5;

def min_low = lowest(low, percentKLength);
def max_high = highest(high, percentKLength);
def rel_diff = close - (max_high + min_low)/2;
def diff = max_high - min_low;

def avgrel = expaverage(expaverage(rel_diff, percentDLength), percentDLength);
def avgdiff = expaverage(expaverage(diff, percentDLength), percentDLength);

plot SMI = if avgdiff != 0 then avgrel / (avgdiff / 2) * 100 else 0;
smi.setDefaultColor(getColor(1));

plot AvgSMI = expaverage(smi, percentDLength);
avgsmi.setDefaultColor(getcolor(5));

plot overbought = over_bought;
overbought.setDefaultColor(getcolor(5));

plot oversold = over_sold;
oversold.setDefaultColor(getcolor(5));
Нужно преобразовать его в кодировке LUA
 
Цитата
Денис Лихачев написал:
Уважаемые мастера, кто может расшифровать код написанный в thinkorswim, индикатор: "stochastic momentum index"
Код
  declare lower;

input over_bought  =   40.0 ;
input over_sold  =   -  40.0 ;
input percentDLength  =   3 ;
input percentKLength  =   5 ;

def min_low  =  lowest(low, percentKLength);
def max_high  =  highest(high, percentKLength);
def rel_diff  =  close  -  (max_high  +  min_low)/ 2 ;
def diff  =  max_high  -  min_low;

def avgrel  =  expaverage(expaverage(rel_diff, percentDLength), percentDLength);
def avgdiff  =  expaverage(expaverage(diff, percentDLength), percentDLength);

plot SMI  =   if  avgdiff  !  =   0   then  avgrel / (avgdiff /  2 )  *   100   else   0 ;
 smi.setDefaultColor (getColor( 1 ));

plot AvgSMI  =  expaverage(smi, percentDLength);
 avgsmi.setDefaultColor (getcolor( 5 ));

plot overbought  =  over_bought;
 overbought.setDefaultColor (getcolor( 5 ));

plot oversold  =  over_sold;
 oversold.setDefaultColor (getcolor( 5 ));
  
Нужно преобразовать его в кодировке LUA
это всего лишь набор вызовов к встроенным функциям tos и настройка параметров индикатора.

для написания версии индикатора для Квик этот тест бесполезен.
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Текст
www.bot4sale.ru

Пасхалочка для Алексея Иванникова: https://forum.quik.ru/messages/forum10/message63088/topic7052/#message63088
 
Вот формула для Amibroker
Код
percentDLength = param("",3,1,10,1);
percentKLength = param("",5,1,10,1);

min_low = llv(low,percentKLength);
max_high = hhv(high, percentDLength);

rel_diff = close - (max_high + min_low)/2;
diff = max_high - min_low;

avgrel = ema(ema(rel_diff, 3), 3);
avgdiff = ema(ema(diff, 3), 3);

smi = iif(avgdif !=0, (avgrel/(avgdiff/2))*100,0);
avgsmi = ema(smi,3);

plot(smi,""32);
plot(avgsmi,"",27);
 
В оригинале, этот индикатор носит имя: Stochastic Momentum Index, написанный William Blau в 1993 году.
Вот код Stochastic Oscillator для Quik написанный на языке Lua:
Код
Settings = {
Name = "*SO (Stochastic Oscillator)", 
Period = 5, 
Metod = "SMA", --(SMA)
Shift = 3, 
Period_D = 3, 
Metod_D = "SMA", --(SMA)
line = {{
      Name = "SO", 
      Type = TYPE_LINE, 
      Color = RGB(221, 44, 44)
      },
      {
      Name = "SO - %D", 
      Type = TYPE_LINE, 
      Color = RGB(0, 206, 0)
      }
      },
Round = "off",
Multiply = 1,
Horizontal_line="30"
}
         
function Init()
   func = SO()
   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 SO() --Stochastic Oscillator ("SO")
   local K_MA1=MA()
   local K_MA2=MA()
   local D_MA=MA()
   local H_tmp={}
   local L_tmp={}
   local it = {p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 5)
local S = (Fsettings.Shift or 3)
local M = (Fsettings.Metod or SMA)
local PD = (Fsettings.Period_D or 3)
local MD = (Fsettings.Metod_D or SMA)
if (P>0) and (PD>0) then
if I == 1 then 
      H_tmp={}
      L_tmp={}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      H_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,HIGH,ds)
      L_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,LOW,ds)
      if it.l>=P then
         local val_h=math.max(unpack(H_tmp))
         local val_l=math.min(unpack(L_tmp))
         local v_K_MA1 = K_MA1(it.l-P+1, {Period=S, Metod = M, VType=ANY},{[it.l-P+1] = GetValueEX(it.p,CLOSE,ds) - val_l})
         local v_K_MA2 = K_MA2(it.l-P+1, {Period=S, Metod = M, VType=ANY},{[it.l-P+1] = val_h - val_l})
         if it.l>=P+S-1 and v_K_MA2~=0 then
            local t_K = 100 * v_K_MA1 / v_K_MA2
            return t_K, D_MA(it.l-(P+S-2), {Period=PD, Metod = MD, VType=ANY}, {[it.l-(P+S-2)] = t_K})
         end
      end
   end
end
return nil,nil
end
end

function MA() --Moving Average ("MA")
   local T_MA = {[SMA]=F_SMA()}
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,
------------------------------------------------------------------
--[[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

SMA = "SMA"
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




 
Уважаемые бойцы, кто силён в Lua, подскажите какие строки нужно переписать?
 
за пол часа решите это самостоятельно
 
Ренат, не думайте что я лентяй. Из тоса в Амик - сам перевел. С Lua пол ночи просидел:
Код
Settings=
{
             Name = "*SMI",
             periodK = 5,
          metodK = "EMA", --(EMA)
          periodD = 3,
          metodK = "EMA", --(EMA)
             line = 
             {
                    {
                      Name = "K",
                      Color = RGB(222, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
               },
               {
                 Name = "D",
                      Color = RGB(333, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
           }
}
function Init()
 return 1
end

function OnCalculate(index)


  
 return 100
end

 
За мануал Спасибо!
 
Код
Settings=
{
             Name = "*SMI",
             periodK = 5,
          metodK = "EMA", --(EMA)
          periodD = 3,
          metodK = "EMA", --(EMA)
             line = 
             {
                    {
                      Name = "K",
                      Color = RGB(222, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
               },
               {
                 Name = "D",
                      Color = RGB(333, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
           }
}
function Init()
 func = smi()
 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 SMI() --Stochastic Momentum Index ("SMI")
   local K_MA=EMA()
   local D_MA=EMA()
   local H_tmp={}
   local L_tmp={}
   local it = {p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local K = (Fsettings.Period or 5)
local MK = (Fsettings.Metod or EMA)
local D = (Fsettings.Period_D or 3)
local MD = (Fsettings.Metod_D or EMA)
if (K>0) and (D>0) then
if I == 1 then 
      H_tmp={}
      L_tmp={}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      H_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,HIGH,ds)
      L_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,LOW,ds)
      if it.l>=K then
  
 return 100
end
 
Можете проверить?
 
Код
Settings=
{
             Name = "*SMI",
             periodK = 5,
          metodK = "EMA", --(EMA)
          periodD = 3,
          metodK = "EMA", --(EMA)
             line = 
             {
                    {
                      Name = "K",
                      Color = RGB(222, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
               },
               {
                 Name = "D",
                      Color = RGB(333, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
           }
}
function Init()
 func = smi()
 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 SMI() --Stochastic Momentum Index ("SMI")
   local K_MA=EMA()
   local D_MA=EMA()
   local H_tmp={}
   local L_tmp={}
   local it = {p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local K = (Fsettings.Period or 5)
local MK = (Fsettings.Metod or EMA)
local D = (Fsettings.Period_D or 3)
local MD = (Fsettings.Metod_D or EMA)
if (K>0) and (D>0) then
if I == 1 then 
      H_tmp={}
      L_tmp={}
      it = {p=0, l=0}
   end
   if CandleExist(I,ds) then
      if I~=it.p then it={p=I, l=it.l+1} end
      H_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,HIGH,ds)
      L_tmp[Squeeze(it.l,P-1)+1] = GetValueEX(it.p,LOW,ds)
      if it.l>=K then
                local val_h=math.max(unpack(H_tmp))
             local val_l=math.min(unpack(L_tmp))
             local v_K_MA1 = K_MA1(it.l-P+1, {Period=S, Metod = M, VType=ANY},{[it.l-P+1] = GetValueEX(it.p,CLOSE,ds) - val_l})
             local v_K_MA2 = K_MA2(it.l-P+1, {Period=S, Metod = M, VType=ANY},{[it.l-P+1] = val_h - val_l})
             if it.l>=P+S-1 and v_K_MA2~=0 then
            local t_K = 100 * v_K_MA1 / v_K_MA2
            return t_K, D_MA(it.l-(P+S-2), {Period=PD, Metod = MD, VType=ANY}, {[it.l-(P+S-2)] = t_K})
         end
      end
   end
end
return nil,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

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

--[[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

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
 
Вот это начала правильно?
Код
Settings=
{
             Name = "*SMI",
             periodK = 5,
          metodK = "EMA", --(EMA)
          periodD = 3,
          metodK = "EMA", --(EMA)
             line = 
             {
                    {
                      Name = "K",
                      Color = RGB(222, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
               },
               {
                 Name = "D",
                      Color = RGB(333, 0, 0),
                      Type = TYPE_LINE,
                 Width = 2
           }
}
function Init()
 func = smi()
 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 SMI() --Stochastic Momentum Index ("SMI")
   local K_MA=EMA()
   local D_MA=EMA()
   local H_tmp={}
   local L_tmp={}
   local it = {p=0, l=0}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local K = (Fsettings.Period or 5)
local MK = (Fsettings.Metod or EMA)
local D = (Fsettings.Period_D or 3)
local MD = (Fsettings.Metod_D or EMA)
        
Страницы: 1
Читают тему
Наверх