BULLS & BEARS

Страницы: 1
RSS
BULLS & BEARS, как получить линию разности быков и медведей с помощью индикаторов на Луа
 
Здравствуйте.

Пытаюсь слегка изменить выложенные разработчиком индикаторы: получить Линию разности Быков и Медведей..
Соединил их вместе:

Думал, BULLS() возвращает значение (но если tostring, то печатает "function: F028E025" - примерно, tonumber - nil).

Предположил, что значение сидит в Out (func = Out1- Out2), но выходит nil, а дальше ошибка, что ожидается число..Вроде логично, ведь период 13 и первые 12 значений скорее всего пустые.
Убрал под if Out1~=nil and Out2~=nil .. и вот тут началось самое интересное - индикатор просто пропал из списка доступных индикаторов!
Возможно, это встроенная защита от ошибок ..
Джуниор 7.0.0.289

Подскажите, пожалуйста, начинающему в чём ошибка.

Код
Settings = {
Name = "*line_1", 
round = "off",
Period = 13, 
Metod = "EMA", --SMA, EMA, VMA, SMMA, VMA 
VType = "Close", --Open, High, Low, Close, Volume, Median, Typical, Weighted, Difference 
line = {
      Name = "LINE", 
      Type = TYPE_LINE, 
      Color = RGB(255, 0, 0)
      }
}
   
function Init() 
   func1 = BULLS()
   func2 = BEARS()
   message (tostring(Out1), 1)
   if Out1~=nil and Out2~=nil
      func = Out1- Out2
   end
   return #Settings.line
end

function OnCalculate(Index) 
   return func1(Index, Settings) and func2(Index, Settings)
end

function BULLS() --Bulls Power ("BULLS")
   local Bulls_MA=MA()
return function (I, Fsettings, ds)
local Out1 = nil
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 13)
local M = (Fsettings.Metod or "EMA")
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
local b_ma = Bulls_MA(I, {Period=P, Metod = M, VType=VT, round=R}, ds)
if I>=P and b_ma then
   Out1 = Value(I, "High", ds)-b_ma
else Out1 = b_ma end
   return rounding(Out1, R),0
end
end

function BEARS() --Bears Power ("BEARS")
   local Bears_MA=MA()
return function (I, Fsettings, ds)
local Out2 = nil
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 13)
local M = (Fsettings.Metod or "EMA")
local VT = (Fsettings.VType or "Close")
local R = (Fsettings.round or "off")
local b_ma = 0

b_ma=Bears_MA(I, {Period=P, Metod = M, VType=VT, round=R}, ds)
if I>=P and b_ma then
   Out2 = Value(I, "Low", ds)-b_ma
else Out2 = b_ma end
   return rounding(Out2, R),0
end
end

function MA() --Moving Average ("MA")
local t_SMA = F_SMA()
local t_EMA = F_EMA()
local t_VMA = F_VMA()
local t_SMMA = F_SMMA()
local t_WMA = F_WMA()
return function(I, Fsettings, ds)
   local Out = nil
   local Fsettings=(Fsettings or {})
   local P = (Fsettings.Period or 9)
   local M = (Fsettings.Metod or "EMA")
   local VT = (Fsettings.VType or "Close")
   local R = (Fsettings.round or "off")
   if M == "SMA" then
      Out = t_SMA(I, P, VT, ds, R)
   elseif M == "EMA" then
      Out = t_EMA(I, P, VT, ds, R)
   elseif M == "VMA" then
      Out = t_VMA(I, P, VT, ds, R)
   elseif M == "SMMA" then
      Out = t_SMMA(I, P, VT, ds, R)
   elseif M == "WMA" then
      Out = t_WMA(I, P, VT, ds, R)
   else
      Out = nil
   end
   return rounding(Out, R)
end
end
------------------------------------------------------------------
--Moving Average SMA, EMA, VMA, SMMA, VMA
------------------------------------------------------------------
--[[Simple Moving Average (SMA)
SMA = sum(Pi) / n
]]
function F_SMA()
return function (I, Period, VType, ds, round) 
local Out = nil
   if I >= Period then
      local sum = 0
      for i = I-Period+1, I do
         sum = sum +Value(i, VType, ds)
      end
      Out = sum/Period
   end 
   return rounding(Out,round)
end
end

--[[Exponential Moving Average (EMA)
EMAi = (EMAi-1*(n-1)+2*Pi) / (n+1)
]]
function F_EMA() 
local EMA_TMP={}
return function(I, Period, VType, ds, round)
local Out = nil
   if I == 1 then
      EMA_TMP[I]=rounding(Value(I, VType, ds),round)
   else
      EMA_TMP[I]=rounding((EMA_TMP[I-1]*(Period-1)+2*Value(I, VType, ds)) / (Period+1),round)
      EMA_TMP[I-2]=nil
   end
   
   if I >= Period then
      Out = EMA_TMP[I]
   end
   return rounding(Out,round)
end
end

--[[
William Moving Average (WMA)
( Previous WILLMA * ( Period - 1 ) + Data ) / Period
]]
function F_WMA()
   local WMA_TMP={}
return function(I, Period, VType, ds, round)
local Out = nil
   if I == 1 then
      WMA_TMP[I]=rounding(Value(I, VType, ds),round)
   else
      WMA_TMP[I]=rounding((WMA_TMP[I-1]*(Period-1)+Value(I, VType, ds)) / Period,round)
     WMA_TMP[I-2]=nil
   end
   if I >= Period then
      Out = WMA_TMP[I]
   end
   return rounding(Out,round)
end
end

--[[Volume Adjusted Moving Average (VMA)
VMA = sum(Pi*Vi) / sum(Vi)
]]
function F_VMA()
return function (I, Period, VType, ds, round)
local Out = nil
   if I >= Period then
      local sum = 0
      local sumV = 0
      for i = I-Period+1, I do
         sum = sum +Value(i, VType, ds)*Value(i, "Volume", ds)
         sumV = sumV +Value(i, "Volume", ds)
      end
      Out = sum/sumV
   end
   return rounding(Out,round)
end
end

--[[Smoothed Moving Average (SMMA)
SMMAi = (sum(Pi) - SMMAi-1 + Pi) / n
]]
function F_SMMA()
local SMMA_TMP={}
return function(I, Period, VType, ds, round)
local Out = nil
   if I >= Period then
      local sum = 0
      for i = I-Period+1, I do
         sum = sum +Value(i, VType, ds)
      end
      
      if I == Period then
         SMMA_TMP[I]=rounding((sum-Value(I, VType, ds)+Value(I, VType, ds)) / Period, round)
      else
         SMMA_TMP[I]=rounding((sum-SMMA_TMP[I-1]+Value(I, VType, ds)) / Period, round)
      end
      SMMA_TMP[I-2]=nil
      Out = SMMA_TMP[I]
   end
   return rounding(Out,round)
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
 
Как начинающему, советую начать с изучения языка луа на простых примерах.
потом написать эти индикаторы самостоятельно по формулам инета.
В результате размер кода будет раз в 10 меньше (получится примерно 5 строчек кода)
и исполняться будет быстрее и у Вас будет понимание того, что делаете.
--------------------------------------
Примечание:
Если не обращать внимание на громкие и пустые фразы вокруг этих индикаторов,
то реально  индикаторы по сути  самые примитивные фильтры первого порядка.
Реально показывают лишь слабые знания математики и богатое воображение у их автора.
 
Причина в том что в коде много ошибок, причем не синтаксических а логических
вот Вы выводите сообщение
Код
message (tostring(Out1), 1)

однако сама переменная Out1 у Вас нигде не задана.
далее
Код
   if Out1~=nil and Out2~=nil
      func = Out1- Out2
   end

Этот текст вообще не понятен. Что такое func? Где задаются значения для Out1 и Out2?

далее
Код
return func1(Index, Settings) and func2(Index, Settings)

Здесь вообще не понятно чего Вы пытались добиться выводя boolean тип данных, когда надо выводить число.
Зачем вообще надо было трогать переменные внутри функции?

Функция выводит результат, вот и работайте с результатом, а не с тем что внутри функции.
То что внутри вообще трогать не надо.

Скрытый текст
 
Sergey Gorokhov, спасибо , всё работает!
 
Sergey Gorokhov,
а не подскажете как убрать вот эту ошибку: C:\FinamJunior\LuaIndicators\_Line.lua:27: attempt to perform arithmetic on a nil value. Выскакивает по количеству периодов расчета

такой вариант не помог
Код
if func1 ~= nil and func2 ~= nil then
   return (func1(Index, Settings)+func2(Index, Settings))/2
end
 
Здравствуйте,
Проверять нужно не сами функции а результат этих функций.

Код
if func1(Index, Settings) ~= nil and func2(Index, Settings) ~= nil then


а еще лучше задать переменные и дальше работать с ними
Код
x = func1(Index, Settings) 
y = func2(Index, Settings)

if x ~= nil and y ~= nil then
   return (x+y)/2
end
 
Sergey Gorokhov, a можно к созданному индикатору присвоить идентификатор через Lua (сразу при добавлении), чтобы потом обращаться к его значениям через getNumCandles и getCandlesByIndex?

или вот такое обращение будет корректным: ma_out[i], ma_out[i-1]... ?
Код
for i=1+x,ds:Size() do
   ma_out=func(i, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds)
   tmp=InsertRow(t_id,-1)
   SetCell(t_id,tmp,1,tostring(ds:C(i)),ds:C(i))
   SetCell(t_id,tmp,2,tostring(ma_out),ma_out)
            
   if i > 4+x and ma_out[i-1] > ma_out[i-2] and ma_out[i] < ma_out[i-1]
end 
 
Цитата
Сергей Качурин написал:
Sergey Gorokhov, a можно к созданному индикатору присвоить идентификатор через Lua (сразу при добавлении), чтобы потом обращаться к его значениям через getNumCandles и getCandlesByIndex?

К сожалению в текущей реализации в Lua индикаторы нельзя добавить идентификатор средствами Lua.

Цитата
Сергей Качурин написал:
или вот такое обращение будет корректным: ma_out[i], ma_out[i-1]... ?

нет, так как функция возвращает значение рассчитанное для конкретной свечи, а не таблицу.
 
Sergey Gorokhov, а как тогда обратиться к значениям каждой конкретной свечи из диапазона i=1+x,ds:Size() ?

чтобы получить вот эти значения:
Код
if i > 4+x and ma_out[i-1] > ma_out[i-2] and ma_out[i] < ma_out[i-1]

Создать таблицу (где?) в которую сохранять № свечи и значение, а потом обращаться к этой таблице?

Вы, наверное, уже видите, что задача перебрать несколько периодов индикатора и на каждом периоде проверить выполнение условий на всем диапазоне i=1+x,ds:Size() ..
 
Цитата
Сергей Качурин написал:
как тогда обратиться к значениям каждой конкретной свечи

первый параметр функции вернет значение для конкретной свечки
  ma_out=func(1, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds) --первая свечка
  ma_out=func(2, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds) --вторая
и т.д.
 
Sergey Gorokhov,  не подскажете в чем может быть засада?


C:\FinamJunior\LuaIndicators\SROC.lua:110: attempt to perform arithmetic on field '?' (a nil value)  

Если вместо SROC звать МА, то ошибка на 83 строке.
Код
for x = 2,4 do --periods
      func = SROC()
      t_id = AllocTable()
      AddColumn(t_id,1,"Price",true,QTABLE_INT_TYPE,10)
   AddColumn(t_id,2,"SROC",true,QTABLE_INT_TYPE,10)
   CreateWindow(t_id)
   SetWindowCaption(t_id,"SROC")
   ds = CreateDataSource("SPBFUT", "RIU6", INTERVAL_M1) 

   for i=1+x,ds:Size() do --candels
         
   ma_out=func(i, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds) --ОШИБКА
   tmp=InsertRow(t_id,-1)
   SetCell(t_id,tmp,1,tostring(ds:C(i)),ds:C(i))
   SetCell(t_id,tmp,2,tostring(ma_out),ma_out)
            

 
Приведите полную версию кода.
 
Скорее всего ошибка в этой строке
Цитата
Сергей Качурин написал:
for i=1+x,ds:Size() do --candels

EMA рассчитывается на основе своих предыдущих значений.
То есть для того чтобы он считался на определенной свече нужно прогнать все предыдущие свечи.

попробуйте указать так:
for i=1,ds:Size() do
 
И потом, в моем примере после CreateDataSource был sleep(100), а у Вас его нет.
Его нужно добавить, иначе цикл может начать работать до того как прокачаются свечки
 
Sergey Gorokhov,
вот так расчет пошел - for i=1,ds:Size() do

результат в таблице:
Код
   Price            SROC
1   91360   
2   91330   
3   91310   
4   91310   
5   91280   
6   91270   
7   91310          99,955126281672
и снова  C:\FinamJunior\LuaIndicators\SROC.lua:110: attempt to perform arithmetic on field '?' (a nil value)

код:
Код
for x = 2,4 do --periods
         func = SROC()
         t_id = AllocTable()
         AddColumn(t_id,1,"Price",true,QTABLE_INT_TYPE,10)
         AddColumn(t_id,2,"SROC",true,QTABLE_INT_TYPE,10)
         CreateWindow(t_id)
         SetWindowCaption(t_id,"SROC")
         message("2", 1)
         ds = CreateDataSource("SPBFUT", "RIU6", INTERVAL_M1) 
         sleep(100)

for i=1,ds:Size() do --candels
         message("4", 1)
         ma_out=func(i, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds)
         tmp=InsertRow(t_id,-1)
         SetCell(t_id,tmp,1,tostring(ds:C(i)),ds:C(i))
         SetCell(t_id,tmp,2,tostring(ma_out),ma_out)
         message("5", 1)
            
         if i > 4+x then
            y = func(i-2, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds) 
            y1 = func(i-1, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds) 
            y2 = func(i, {Period = x, Metod = "EMA", VType="Close", round="off"}, ds)
            message("6", 1)
            
            if count == 0
ошибка между message "5" и message "6" ...
 
Цитата
Сергей Качурин написал:
и снова  C:\FinamJunior\LuaIndicators\SROC.lua:110:
Явно написано: строка 110,
че гадать-то "между пятой и шестой..."
 
А вообще это прикольный метод, отлаживать скрипт на форуме с помощью поддрежки :)
 
Уберите 111ю строку в файле SROC.lua
EMA_TMP[I-2]=nil

должно помочь
 
Sergey Gorokhov, спасибо! Всё заработало.

что это за строчка такая, если не секрет?
 
Цитата
Сергей Качурин написал:
Sergey Gorokhov  , спасибо! Всё заработало.

что это за строчка такая, если не секрет?

Считайте что это ошибка в коде. Архив на ФТП уже поправили.
Страницы: 1
Читают тему
Наверх