Добрый день. В базе кодов есть индикатор 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
Пользователь
Сообщений: Регистрация: 23.01.2015
15.12.2016 10:43:23
Здравствуйте,
Цитата
Космонавт написал: Спотыкается на строчке внутри индикатора:
Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям. Скорее всего проблема именно в этом. Прогоните цикл для корректного расчета for i=1,ds:Size() do a=func(i, {Period=12, VType="Typical", round=7}, ds) end
Пользователь
Сообщений: Регистрация: 05.02.2015
21.12.2016 20:45:45
а как обратиться к конкретному бару? Скажем последнему или предпоследнему? из вашего кода получается что переменная a постоянно будет менять значение, так как идёт перебор i-элемента
Пользователь
Сообщений: Регистрация: 05.02.2015
21.12.2016 23:20:15
На своём низком уровне понимания я разобрался. Получилось так:
Код
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 в цикле перебора бумаг? Спасибо за советы.
Sergey Gorokhov написал: Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.
Цитата
Космонавт написал: И ещё не понятно, рационально ли рассчитывать RSI в колбеке SetUpdateCallback?
Рационально или нет решать Вам.
Цитата
Космонавт написал: С этой точки зрения, правильно ли помещать CreateDataSource внутри main в цикле перебора бумаг?
CreateDataSource достаточно вызвать 1 раз, не важно где. Постоянно гонять его в цикле совершенно никакого смысла нет.
Пользователь
Сообщений: Регистрация: 05.02.2015
22.12.2016 08:13:03
Сергей, Вы не уловили нить вопроса. Я хочу расчитать RSI с периодом 12. Нет смысла брать все бары. Поэтому я хочу взять только последние 50.
Пользователь
Сообщений: Регистрация: 23.01.2015
22.12.2016 08:19:08
Космонавт, Это Вы не уловили нить ответа. RSI требует согласно формуле, свои предыдущие значения. Это особенность данного индикатора. Даже если Вам надо только 50 последних свечей он в принципе не сможет Вам их дать не проведя расчет предыдущих. Просто такая формула.
Пользователь
Сообщений: Регистрация: 05.02.2015
22.12.2016 08:26:45
Вы заблуждаетесь. Вот формула RSI из вашего же руководства КВИКа
Как по формуле узнать последние 50 значений X из 100 имеющихся? Никак. Просто потому что для расчета надо знать чему равно X1 и от него уже подсчитать все остальные.
Вот по этому, еще в четвертый раз повторяем.
Цитата
Sergey Gorokhov написал: Индикатор RSI строится по EMA, которому нужен расчет по предыдущим значениям.
Если Вам нужно получить последние 50 свечек, будьте добры предварительно подсчитать и первые свечки. Просто такая формула.
Пользователь
Сообщений: Регистрация: 23.01.2015
22.12.2016 08:48:09
Цитата
Sergey Gorokhov написал: Xn=Xпред + 1 где Xпред это предыдущее значение X
Чтобы понятней было перепишем формулу так: Xn=Xn-1+1