Добавка. Квик, по каким то причинам при появлении тика затирает все предыдущие значения чем то своим, не понятным. При чем даже если самому пробегаться на каждом баре и обновлять значения на правильные, то квик все равно их затрет, так как считает, что он умнее и лучше знает, что нам показать на графике.
Код прилагаю, чтобы можно было скопировать, а не набирать руками.
Код
Settings= {
Name = "MA",
Period = 3,
line =
{
{
Name = "MA",
Color = RGB(90, 110, 200),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
return 10000
end
Кстати, пробовал ради эксперимента вот так:
Код
Settings= {
Name = "MA",
Period = 3,
line =
{
{
Name = "MA",
Color = RGB(90, 110, 200),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
if index == Size() then
for i = 1, Size() - 1 do
SetValue(i, 1, 10000)
end
end
SetValue(index, 1, 10000)
return 10000
end
Michael Bulychev, спасибо за развернутый ответ. Но, в вашем случае призойдет то же самое, что и у меня: На первой итерации, при расчете EMA(3) на 2 баре (например), мы получим корректное значение, но рассчет ЕМА(4) на том же баре затрет кешированное значение для ЕМА(3) и на следующей итерации оно посчитается не коррекно. В вашем методе реализиции необходимо в функцию ЕМА() передавать переменную Line и поменять вычисление на:
Код
p = line[index-Settings.startPeriod] or C(index)
n = k*C(index)+(1-k)*p
Дмитрий Минеев пишет: Как это поможет решению моего вопроса?
переписать пример так, чтобы он генерировал функции, кажется сложнее, чем переписать так, чтобы была глобальная таблица, в которой хранились бы нужные данные о предыдущих значениях. Для каждого периода своя ячейка в таблице.
Дмитрий Минеев пишет: То, что вы описали - понятно. Но предложенный вами вариант не подходит. Пользователь в параметрах указывает интервал, за который будут считаться средние. Т.е. я заранее не знаю, сколько функций создавать. Есть ли другой выход? Или возможно как то создать динамический массив из функций?
Все зависит от Вашего воображения. Перепишите пример так чтобы он запоминал последнее значение индикатора в переменной.
То, что вы описали - понятно. Но предложенный вами вариант не подходит. Пользователь в параметрах указывает интервал, за который будут считаться средние. Т.е. я заранее не знаю, сколько функций создавать. Есть ли другой выход? Или возможно как то создать динамический массив из функций?
Здравсвтуйте. Вопрос по индикатору EMA, описанному в примере по ссылке. Все что описано работает. Но в моей задаче, я вычисляю среднюю EMA по нескольким периодам. Пример: averEMA = (EMA(index, 3) + EMA(index, 4) + EMA(index, 5)) / 3. Так как это функция, при расчете EMA с периодом 4 я затираю значение рассчитаной ЕМА3, на этой же итерации. А оно будет нужно на следующем баре. Код индикатора:
Код
Settings= {
Name = "averEMA",
startPeriod = 3,
endPeriod = 6,
line =
{
{
Name = "AverEMA",
Color = RGB(90, 110, 200),
Type = TYPE_LINE,
Width = 1
}
}
}
function Init()
return 1
end
function OnCalculate(index)
local s
if index == 1 then
EMA = _EMA()
line = {}
end
s = 0
for i = Settings.startPeriod, Settings.endPeriod do
local k
k = EMA(index, i)
s = s + k
end
if index <= Settings.endPeriod then
line[index] = 0
else
line[index] = s / (Settings.startPeriod - (Settings.endPeriod - 1))
end
message("---- message 1 -----")
message("EMA3 = "..tostring(EMA(index, 3)))
--message("---- message 2 -----")
--message("EMA3 = "..tostring(EMA(index, 3))..", EMA4 = "..tostring(EMA(index, 4)))
return line[index]
end
function _MA()
local cache={}
return function(iIndex, iPeriod)
local sum = 0
local p = 0
local period = iPeriod
local index = iIndex
local result = 0
local str = ""
if index == 1 then
cache = {}
end
if index < period then
cache[index] = 0
return 0
end
for i = index - period + 1, index do
sum = sum + C(i)
end
result = sum / period
cache[index] = result
return result
end
end
function _EMA()
local cache={}
local MA = _MA()
return function(ind, _p, kk)
local n = 0
local p = 0
local period = _p
local index = ind
local k = kk or 2/(period + 1)
if index == 1 then
cache = {}
end
if index <= period then
cache[index] = 0
return 0
end
if cache[index - 1] == 0
or cache[index - 1] == nil then
p = MA(index - 1, period)
else
p = cache[index - 1]
end
n = C(index) * k + (1-k)*p
cache[index] = n
return n
end
end
Результаты теста можно увидеть на скринах. В коде изменяется только строка вывода сообщения. Первый вариант: Одна строка содержит только ЕМА3 и она выводится корректно. И второй вариант, когда выводится результата вычисления ЕМА3 и ЕМА4. И в этом случае ЕМА3 корректна только на первой итерации, дальше она считается не верно. Как такого избежать?