Вызов RSI

Страницы: 1
RSS
Вызов RSI
 
Добрый день.
В базе кодов есть индикатор RSI написанный разработчиками. У меня не получается вызвать его обычным способом. Спотыкается на строчке внутри индикатора:
Код
val_Up[I] = (val_Up[I-1] * (P-1) + Up[I]) / P
Вызываю так:
Код
DataSource("TQBR","RASP",INTERVAL_M5)   
local num_candles=ds:Size()             
func=RSI()
local a=func(num_candles, {Period=12, VType="Typical", round=7}, ds)

Вот сам индикатор. Спасибо за подсказки.
Код
Settings = {
Name = "*RSI (Relative Strength Index)", 
round = "off",
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
 
Здравствуйте,
Цитата
Космонавт написал:
Спотыкается на строчке внутри индикатора:
Спотыкается это как?
Цитата
Космонавт написал:
DataSource("TQBR","RASP",INTERVAL_M5)  
Что это такое?
 
Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.
Скорее всего проблема именно в этом.
Прогоните цикл для корректного расчета
for i=1,ds:Size() do
a=func(i, {Period=12, VType="Typical", round=7}, ds)
end
 
а как обратиться к конкретному бару? Скажем последнему или предпоследнему?
из вашего кода получается что переменная a постоянно будет менять значение, так как идёт перебор i-элемента
 
На своём низком уровне понимания я разобрался.
Получилось так:
Код
function main()
dofile ("C:\\Program Files (x86)\\Lua\\5.1\\lua\\RSI.lua")
  while is_run do
    stime=getSTime()
    if stime==nil then stime=0 end
    sleep (1)

if stime>100000 and stime<184000 then --не считаем вне сессии
  func = RSI()

for sec in string.gmatch(ticker_list,"%a+") do
local rsi_count={}
ds = CreateDataSource(class, sec, INTERVAL_M5) 
sleep (1000)
    num_candles=ds:Size()
  for i=1,num_candles do
    rsi_count[i]=func(i, {Period=14, VType="Typical"}, ds)
  end 

        indicator[sec].rsi_0 = rsi_count[num_candles]
        indicator[sec].rsi_1 = rsi_count[num_candles-1]
        indicator[sec].rsi_2 = rsi_count[num_candles-2]

и так далее

что самое противное (и не понятное), в нижеприведённом виде не работает! Ниже попытка считать не все бары, а только 50 последних.
Код
    num_candles=ds:Size()
  for i=num_candles-50,num_candles do
    rsi_count[i]=func(i, {Period=14, VType="Typical"}, ds)
  end 
И ещё не понятно, рационально ли рассчитывать RSI  в колбеке SetUpdateCallback? Я хочу запрашивать обновлённый RSI довольно редко - раз в секунду, скорость не нужна. С этой точки зрения, правильно ли помещать CreateDataSource внутри main в цикле перебора бумаг?
Спасибо за советы.
 
Цитата
Космонавт написал:
а только 50 последних.

Ответ уже был дан.
Цитата
Sergey Gorokhov написал:
Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.

Цитата
Космонавт написал:
И ещё не понятно, рационально ли рассчитывать RSI  в колбеке SetUpdateCallback?
Рационально или нет решать Вам.

Цитата
Космонавт написал:
С этой точки зрения, правильно ли помещать CreateDataSource внутри main в цикле перебора бумаг?

CreateDataSource достаточно вызвать 1 раз, не важно где.
Постоянно гонять его в цикле совершенно никакого смысла нет.
 
Сергей, Вы не уловили нить вопроса.
Я хочу расчитать RSI с периодом 12. Нет смысла брать все бары. Поэтому я хочу взять только последние 50.
 
Космонавт,
Это Вы не уловили нить ответа.
RSI требует согласно формуле, свои предыдущие значения.
Это особенность данного индикатора.
Даже если Вам надо только 50 последних свечей он в принципе не сможет Вам их дать не проведя расчет предыдущих.
Просто такая формула.
 
Вы заблуждаетесь. Вот формула RSI из вашего же руководства КВИКа

 
Космонавт,

Вот именно что в расчетах используется скользящая средняя.

То есть в третий раз повторяем ответ:
Цитата
Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.
 
Придётся Вас "добить" формулой EMA.
У её расчётов есть начало и конец

 
Цитата
Космонавт написал:
Придётся Вас "добить" формулой EMA.

Как по Вашему что такое "EMAi-1" ??
Вы не поверите, но это предыдущее значение EMA
 
Космонавт,

Специально для Вас, пример по проще.

есть формула
Xn=Xпред + 1

где Xпред это предыдущее значение X

Как по формуле узнать последние 50 значений X из 100 имеющихся?
Никак. Просто потому что для расчета надо знать чему равно X1 и от него уже подсчитать все остальные.

Вот по этому, еще в четвертый раз повторяем.
Цитата
Sergey Gorokhov написал:
Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.

Если Вам нужно получить последние 50 свечек, будьте добры предварительно подсчитать и первые свечки.
Просто такая формула.
 
Цитата
Sergey Gorokhov написал:
Xn=Xпред + 1
где Xпред это предыдущее значение X

Чтобы понятней было перепишем формулу так:
Xn=Xn-1+1
Страницы: 1
Читают тему
Наверх