Здравствуйте! Проблема в том, что spred иногда выносит в макс или в мин (не все данные приходят одновременно) на доли секунды, и max_price и low_price тоже соответственно искажаются, потом spred принимает нормальное значение а max и low - нет... Индикатор рассчитывается от +50 до -50, Settings.a ставлю 10 ("max_price = spread + Settings.a" ), т.к. spred считается по двум значениям, которые иногда приходят не одновременно, то получается spred уходит либо в +50 либо в -50, потом возвращается, но из-за Settings.a = 10 max и low получаются не корректны. Например: предыдущий spred был +10, на следующей свече из-за корявых данных происходит скачек в +50 и сразу возврат в например +11, но max остается на показании +11 + Settings.a = 21, а должен быть на +11... Проще наверное считать max/low по предыдущей свече, ну т.е. не в реальном времени а по закрытой свече. Помогите с кодом пожалуйста!
Код
--- Вычислить спред.
-- @param index номер свечи на графике
-- @return значение спреда или nil, если оно неопределено
local function getSpread(index)
local timeCode = getTimeCode(T(index))
local securityPrice = C(index)
if securityPrice == nil then
return nil
end
-- Получение свечей дополнительных инструментов
local candle1 = getCandleByTimeCode(Settings.tag1, timeCode)
local candle2 = getCandleByTimeCode(Settings.tag2, timeCode)
if candle1 == nil or candle2 == nil then
return nil
end
-- Получение цен дополнительных инструментов
local price1 = candle1.close
local price2 = candle2.close
if price1 == nil or price2 == nil then
return nil
end
-- Вычисление спреда
local spread = (50 - (100 / (1 + price1 / price2)))*Settings.k
-- Вычисление максимума минимума среднего для спреда
if index == 1 then
max_price = nill
med_price = nill
low_price = nill
elseif T(index).hour < T(index-1).hour then
max_price = nill
med_price = nill
low_price = nill
end
if max_price == nill then
max_price = spread
elseif spread > max_price then
max_price = spread
low_price = spread - Settings.a
med_price = (max_price+low_price)/2
end
if low_price == nill then
low_price = spread
elseif spread < low_price then
low_price = spread
max_price = spread + Settings.a
med_price = (max_price+low_price)/2
end
if med_price == nill then
med_price = (max_price+low_price)/2
elseif spread < low_price then
med_price = (max_price+low_price)/2
elseif spread > max_price then
med_price = (max_price+low_price)/2
end
return spread, (max_price+low_price)/2 , max_price, low_price
end
function OnCalculate(index)
if index > 1 then
local spread = getSpread(index - 1)
if spread then
SetValue(index - 1, 1, spread)
SetValue(index , 2, med_price)
SetValue(index , 3, max_price)
SetValue(index , 4, low_price)
end
end
return getSpread(index), med_price , max_price, low_price
end
для начала, я исправил ошибки в Вашей программе, но не проверял. проверьте, если ошибок нет, то напишите подробнее что не так.
Код
--- Вычислить спред.
-- @param index номер свечи на графике
-- @return значение спреда или nil, если оно неопределено
local function getSpread(index)
local timeCode = getTimeCode(T(index))
local securityPrice = C(index)
if securityPrice then
-- Получение свечей дополнительных инструментов
local candle1 = getCandleByTimeCode(Settings.tag1, timeCode)
local candle2 = getCandleByTimeCode(Settings.tag2, timeCode)
if candle1 and candle2 then
-- Получение цен дополнительных инструментов
local price1 = candle1.close
local price2 = candle2.close
if price1 and price2 then
-- Вычисление спреда
local spread = (50 - (100 / (1 + price1 / price2)))*Settings.k
-- Вычисление максимума минимума среднего для спреда
if index == 1 or (T(index).hour < T(index-1).hour) then
max_price = nil
med_price = nil
low_price = nil
end
if max_price == nil then max_price = spread
elseif spread > max_price then
max_price = spread
low_price = spread - Settings.a
med_price = (max_price+low_price)/2
end
if low_price == nil then low_price = spread
elseif spread < low_price then
low_price = spread
max_price = spread + Settings.a
med_price = (max_price+low_price)/2
end
if med_price == nil then med_price = (max_price+low_price)/2
elseif spread < low_price then med_price = (max_price+low_price)/2
elseif spread > max_price then med_price = (max_price+low_price)/2
end
return spread, (max_price+low_price)/2 , max_price, low_price
end
end
end
end
Я не программист.... этот код я собрал из двух индикаторов. Функция onCalculate была в исходнике основного индикатора, я добавил max, low, med... без добавления данные не обновлялись... на истории всё норм, а на новой свече ничего не менялось...
Код проверил, всё работает! Визуально отличий не заметил, возможно в аппаратной части стал полегче. Основной параметр в этом индикаторе это - spred. max и low это своего рода канал по значениям spred, но с фиксированным расстоянием (Settings.a). Т.к. spred вычисляется по двум индикаторам (tag1 и tag2), то при открытии новой свечи иногда возникают ситуации, что на каком то из индикаторов еще нет значений, видимо это принимается за ноль, и значение spred уходит либо в максимально возможное, либо в минимально возможное значения. Это происходит только на открытии новой свечи, не всегда на каждой и очень быстро. Когда поступают данные с обоих индикаторов - spred возвращается в нормальный вид... Но значения max/low после этого не корректны!... Исправляется это перезагрузкой графика ( редактировать => ок). Решение проблемы с max/low вижу так: Вариант 1. Условия: если spred(i) > (spred(i-1) +10 или spred(i) < spred(i-1) -10, то max(i) = max(i-1) и low(i) = low(i-1) Вариант 2. Если spred(i) > max(i-1), то max(i) = spred(i) иначе max(i) = max (i-1), и аналогично для low...
Я не знаю как правильно написать эти "(i)" и "(i-1)".... Как та собака: всё понимаю, но сказать не могу...
Вот вам вариант. проверьте, если что не так, то покажите картинки и напишите что не так.
Код
function OnCalculate(index)
-- Получение свечей дополнительных инструментов
c1=getCandleByTimeCode(Settings.tag1, timeCode).close
c2=getCandleByTimeCode(Settings.tag2, timeCode).close
if c1 and c2 then
p1 = c1; p2 = c2 -- Получение цен дополнительных инструментов
spr =p1-p2 -- Вычисление спреда
if index==1 then max=spr; min=spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr>max_p then max = spr; min = spr - Settings.a;
elseif spr<min_p then min = spr; max = spr + Settings.a; end
med = (max+min)/2;
end
return spr,med,max,min
end
Юрий написал: Спасибо! Обязательно попробую! Подскажите, а как мне max/low предыдущей свечи обозначить? Типа (i-1)...
вообще-то я не понял почему Вы два инструмента читаете. ---------------- Я делаю спред так. Один инструмент - это тот , который на графике А второй инструмент - читаем В этом случае данные по первому инструменту это C(index),O(index),L(index),H(index), а предыдущая свеча по этому инструменту будет ...(index-1) ---------------- При этом индикатор помещаем в новое окно под графиком первого инструмента
Я Вас понял. У меня получается три инструмента! Первый - по нему определяется нумерация свеч, и два других - по которым я считаю "spred ", в новом окне графика первого инструмента. В первом инструменте есть C(index). Там, получается, "искать" предыдущую свечу?
Юрий написал: Я Вас понял. У меня получается три инструмента! Первый - по нему определяется нумерация свеч, и два других - по которым я считаю "spred ", в новом окне графика первого инструмента. В первом инструменте есть C(index). Там, получается, "искать" предыдущую свечу?
у Вас первый лишний если спред между двумя инструментами то третий лишний. Номер свечи надо брать из первого
function OnCalculate(index)
-- Получение свечей инструментов
c1=С(indwx);
c2=getCandleByTimeCode(Settings.tag2,timeCode).close
if c2 then
spr =C1-C2 -- Вычисление спреда
if index==1 then max=spr; min=spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr>max_p then max = spr; min = spr - Settings.a;
elseif spr<min_p then min = spr; max = spr + Settings.a; end
med = (max+min)/2;
end
return spr,med,max,min
end
function OnCalculate(index)
-- Получение свечей инструментов
c1=С(index);
c2=getCandleByTimeCode(Settings.tag2,timeCode).close
if c2 then
spr =C1-C2 -- Вычисление спреда
if index==1 then max=spr; min=spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr>max_p then max = spr; min = spr - Settings.a;
elseif spr<min_p then min = spr; max = spr + Settings.a; end
med = (max+min)/2;
end
return spr,med,max,min
end
function OnCalculate(index)
-- Получение свечей инструментов
C1=С(index);
C2=getCandleByTimeCode(Settings.tag2,timeCode).close
if c2 then
spr =C1-C2 -- Вычисление спреда
if index==1 then max=spr; min=spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr>max_p then max = spr; min = spr - Settings.a;
elseif spr<min_p then min = spr; max = spr + Settings.a; end
med = (max+min)/2;
end
return spr,med,max,min
end
function OnCalculate(index)
-- Получение свечей инструментов
C1=С(index);
C2=getCandleByTimeCode(Settings.tag2,timeCode).close
if C2 then
spr =C1-C2 -- Вычисление спреда
if index==1 then max=spr; min=spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr>max_p then max = spr; min = spr - Settings.a;
elseif spr<min_p then min = spr; max = spr + Settings.a; end
med = (max+min)/2;
end
return spr,med,max,min
end
Хм. Попробую, но мне кажется было логично что их три. Ведь те по которым расчитывается spred вообще на другом графике... Я даже практиковал там другой таймфрейм, и всё работало (если не перезагружать основной график).
Юрий написал: Хм. Попробую, но мне кажется было логично что их три. Ведь те по которым расчитывается spred вообще на другом графике... Я даже практиковал там другой таймфрейм, и всё работало (если не перезагружать основной график).
свечи формируются по времени , поэтому если тайм одинаковый то момент начала свечи будет синхронизирован при получении первой сделки после начала текущего кванта. ----------------------- Например , время 100000 и свеча будет создана при появлении первой сделки. -------------------- Если сделка не появилась, то свеча не создана. ----------------- Поэтому нет никакой разницы на каком графике инструмент.
Вот из-за того что первая сделка на разных инструментах приходит не всегда в одно и тоже время, у меня и получается вынос... Потому что один из инструментов в этот момент получается равен 0. Просто для spred это не критично, а для max/low - получается изкажение...
Юрий написал: Вот из-за того что первая сделка на разных инструментах приходит не всегда в одно и тоже время, у меня и получается вынос... Потому что один из инструментов в этот момент получается равен 0. Просто для spred это не критично, а для max/low - получается изкажение...
я это учел в своем варианте. если свечи нет, то результат не должен изменяться
Первоначальная проблема решена! Код доработан, но не полностью... Сейчас линии max/low принимают значения hidh/low (хотя используется значения только close!), а хотелось бы чтобы они принимали значение close... Т.е. если "spread" закрывается выше "max", то max = spread.close, а не "spread.high". На второй свече дня именно так и было, а начиная с третьей применяются значения "high/low"... Загадка где-то в коде, логике...
Получается если spread > max_price, то max_price сразу же становится равен spread, а надо: если spread > max_price(i-1), то max_price = spread, тогда будет красиво! Но я пока не сообразил как max_price(i-1) обозначить правильно...
Код
if index == 1 then
max_price = nill
med_price = nill
low_price = nill
elseif T(index).hour < T(index-1).hour then
max_price = nill
med_price = nill
low_price = nill
end
if max_price == nill then
max_price = spread
elseif spread > max_price then
max_price = spread
low_price = spread - Settings.a
med_price = (max_price+low_price)/2
end
if low_price == nill then
low_price = spread
elseif spread < low_price then
low_price = spread
max_price = spread + Settings.a
med_price = (max_price+low_price)/2
end
if med_price == nill then
med_price = (max_price+low_price)/2
elseif spread < low_price then
med_price = (max_price+low_price)/2
elseif spread > max_price then
med_price = (max_price+low_price)/2
end
return spread, (max_price+low_price)/2 , max_price, low_price
nikolz, Вы всё правильно пишите! Вас ввело в заблуждение название spread... В моем случае это просто название линии. Можно назвать ее monika) И тогда monika =с1*0+ 50-(100/(1+c2/c3)). Т.е. с1 в моём случае не участвует. Графики с2 и с3 открыты в другом окне, и это не влияет на работу индикатора. Я пользуюсь им не один год. Но не так давно мне попался код индикатора который рисует макс и мин дня. Я решил прикрутить его к "monike"... И тут то я и столкнулся с необходимостью решения проблемы выносов, которая всегда была. Проблему решил только условием: if ((price2 + price3)== price2) or ((price2 + price3)== price3) then. По другому не получилось... Правильно это или не правильно, не знаю... Но работает! Теперь ищу решение, чтобы макс был равен закрытию! А не достигнутого макс (high) на этой свече... Конечно же при условии, что monika пробила предыдущий макс! elseif spr>max_p then max = spr - это условие его повышает, но оно не равно закрытию. Мне нужно: if monika > max(i-1) then max = monika, но я не знаю как правильно обозначить это - max(i-1).... Я не программист... Логику понимаю, а как оформить не знаю! Тыкаюсь как слепой котенок... Получилось - хорошо! Не получилось - продолжаю тыкаться, пока не надоест)
Подскажите, что не так!... Почему на истории линии отрисовываются не корректно? После перезагрузки всё норм, на новых свечах рисует как надо. На скрине обозначил место перезагрузки графика (до/после), красными линиями подчеркнул места кривой отрисовки, зелеными - правильной отрисовки.
nikolz, Ваш код вставить не получается... ошибки выдаёт. Пробовал сократить, но всё тщетно... Вот рабочий вариант, но отрисовка кривая...
Код
local function getSpread(index)
local timeCode = getTimeCode(T(index))
local timeCode2 = getTimeCode(T(index-1))
local securityPrice = C(index)
if securityPrice then
-- Получение свечей дополнительных инструментов
local candle1 = getCandleByTimeCode(Settings.tag1, timeCode)
local candle2 = getCandleByTimeCode(Settings.tag2, timeCode)
local candle3 = getCandleByTimeCode(Settings.tag1, timeCode2)
local candle4 = getCandleByTimeCode(Settings.tag2, timeCode2)
if candle1 and candle2 and candle3 and candle4 then
-- Получение цен дополнительных инструментов
local price1 = candle1.close
local price2 = candle2.close
local price3 = candle3.close
local price4 = candle4.close
if ((price1 + price2)== price1) or ((price1 + price2)== price2) then
-- Вычисление спреда
local spread = (50 - (100 / (1 + price3 / price4)))*Settings.k else
local spread = (50 - (100 / (1 + price1 / price2)))*Settings.k
local spread2 = (50 - (100 / (1 + price3 / price4)))*Settings.k
-- Вычисление максимума минимума среднего для спреда
if index == 1 or (T(index).hour < T(index-1).hour) then
max_price = nil
med_price = nil
low_price = nil
end
if max_price == nil then max_price = spread2
elseif spread2 > max_price then
max_price = spread2
if (max_price-low_price)>Settings.a then
low_price = spread2 - Settings.a
end
med_price = (max_price+low_price)/2
end
if low_price == nil then low_price = spread2
elseif spread2 < low_price then
low_price = spread2
if (max_price-low_price)>Settings.a then
max_price = spread2 + Settings.a
end
med_price = (max_price+low_price)/2
end
if med_price == nil then med_price = (max_price+low_price)/2
elseif spread2 < low_price then med_price = (max_price+low_price)/2
elseif spread2 > max_price then med_price = (max_price+low_price)/2
end
return spread, (max_price+low_price)/2 , max_price, low_price
end
end
end
end
function OnCalculate(index)
if index > 1 then
local spread = getSpread(index - 1)
if spread then
SetValue(index - 1, 1, spread)
SetValue(index-1, 2, med_price)
SetValue(index-1, 3, max_price)
SetValue(index-1, 4, low_price)
end
end
return getSpread(index), med_price , max_price, low_price
end
nikolz написал: Вот вам вариант. проверьте, если что не так, то покажите картинки и напишите что не так.
Код
function OnCalculate (index)
-- Получение свечей дополнительных инструментов
c1 = getCandleByTimeCode(Settings.tag1, timeCode).close
c2 = getCandleByTimeCode(Settings.tag2, timeCode).close
if c1 and c2 then
p1 = c1; p2 = c2 -- Получение цен дополнительных инструментов
spr = p1 - p2 -- Вычисление спреда
if index = = 1 then max = spr; min = spr - Settings.a;
-- Вычисление максимума минимума среднего для спреда
elseif spr > max_p then max = spr; min = spr - Settings.a;
elseif spr < min_p then min = spr; max = spr + Settings.a; end
med = (max + min)/ 2 ;
end
return spr,med,max,min
end
С горем пополам, и порвав два бубна, прикрутил я этот код в тело индикатора! Но радость была не долгой... "spr = p1 - p2 -- Вычисление спреда" - при использовании в вычислении деления (р1/р2), пропадают линии - med,max,min, их просто нет на графике!... А если поставить мою формулу расчета spr, то и основная линия не рисуется.... Как то так)
Я Вам написал чтобы проверили а не копировали надписи на заборе. У вас нет вычисления timeCode (добавьте): и где вы изначально нашли функцию getCandleByTimeCode ---------------- В своей программе ,картинка выше, я использую getCandlesByIndex,
nikolz, Спасибо огромное за реальные действия, за код! Что я могу проверить, если я не программист?!... Похоже это сообщение на код или нет? Проверил - похоже! Исходник взят отсюда - создание индикаторов — форум QUIK.
Проблема толком так и не решена... Я не знаю как взять значение max(index-1)....... функцию надо или переменную, как, откуда?.... Я взял getCandleByTimeCode(index-1), считает правильно, но на истории отображается со сдвигом....
Ваш индикатор тоже потестил, Спасибо!!! Но он не считает деление... Сложение, вычитание, умножение... Деление - нет... И более сложную формулу, которую я использую, тоже нет.... А так для меня очень полезный код, для изучения Lua!
Settings=
{
Name = "DayMax/Med/Min/X",
a = 1000, -- свободный член
line =
{
{
Name = "Median",
Color = RGB(0, 0, 255),
Type = TYPE_LINE,
Width = 1
},
{
Name = "Maximum",
Color = RGB(0, 128, 0),
Type = TYPE_LINE,
Width = 1
},
{
Name = "Minimum",
Color = RGB(255, 0, 0),
Type = TYPE_LINE,
Width = 1
}
}
}
ma = nill
me = nill
mi = nill
function Init()
return 3
end
function OnCalculate(index)
if index == 1 then
ma = nill
me = nill
mi = nill
end
if ma == nill then
ma = H(index)
elseif H(index) > ma then
ma = H(index)
if (ma-mi)>Settings.a then
mi = ma - Settings.a
end
end
if mi == nill then
mi = L(index)
elseif L(index) < mi then
mi = L(index)
if (ma-mi)>Settings.a then
ma = mi + Settings.a
end
end
if me == nill then
me = (H(index) + L(index))/2
elseif L(index) < mi then
me = (H(index) + L(index))/2
elseif H(index) > ma then
me = (H(index) + L(index))/2
end
return me, ma, mi
end
Я хочу использовать для других расчетов предыдущие me, ma, mi. Подскажите, как это сделать! me(index-1) не работает....
Settings =
{
Name = "DayMax/Med/Min/X" ,
a = 1000 , -- свободный член
line =
{
{
Name = "Median" ,
Color = RGB ( 0 , 0 , 255 ),
Type = TYPE_LINE,
Width = 1
},
{
Name = "Maximum" ,
Color = RGB ( 0 , 128 , 0 ),
Type = TYPE_LINE,
Width = 1
},
{
Name = "Minimum" ,
Color = RGB ( 255 , 0 , 0 ),
Type = TYPE_LINE,
Width = 1
}
}
}
ma = nil l
me = nil l
mi = nil l
function Init ()
return 3
end
function OnCalculate (index)
if index = = 1 then
ma = nil l
me = nil l
mi = nil l
end
if ma = = nil l then
ma = H(index)
elseif H(index) > ma then
ma = H(index)
if (ma - mi) > Settings.a then
mi = ma - Settings.a
end
end
if mi = = nil l then
mi = L(index)
elseif L(index) < mi then
mi = L(index)
if (ma - mi) > Settings.a then
ma = mi + Settings.a
end
end
if me = = nil l then
me = (H(index) + L(index))/ 2
elseif L(index) < mi then
me = (H(index) + L(index))/ 2
elseif H(index) > ma then
me = (H(index) + L(index))/ 2
end
return me, ma, mi
end
Я хочу использовать для других расчетов предыдущие me, ma, mi. Подскажите, как это сделать! me(index-1) не работает....
Ваш индикатор тоже потестил, Спасибо!!! Но он не считает деление... Сложение, вычитание, умножение... Деление - нет... И более сложную формулу, которую я использую, тоже нет.... А так для меня очень полезный код, для изучения Lua!
Я понял что это в частности для меня) ещё раз Спасибо!