Добрый день. Хочу вычислять скользящую среднюю внутри кода. Что при этом нужно учитывать? Период 14, часовик, по ценам close Казалось бы всё просто, но есть особенности: 1. Старые свечки можно не обрабатывать, а обрабатывать только текущую. 2. Но обрабатывать старые всё же придётся, ведь рисуются новые свечки, поэтому каждый раз при формировании новой свечи придётся разок пересчитать старые. Помогите пожалуйста выразить это в красивом коде. Спасибо.
Сейчас формула такая. На примере 5-периодной Moving Average:
Код
..............................
ds=CreateDataSource(p_classcode, p_seccode, INTERVAL_M1)
ds:SetUpdateCallback(cb)
while is_run do
length=ds:Size()
sum=0
for i=0,4,1 do
sum=sum+ds:C(length-i)
end
moving5=sum/5
sleep(100)
end
end
Космонавт написал: Сейчас формула такая. На примере 5-периодной Moving Average:
Код
.. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
ds = CreateDataSource (p_classcode, p_seccode, INTERVAL_M1)
ds: SetUpdateCallback (cb)
while is_run do
length = ds: Size ()
sum = 0
for i = 0 , 4 , 1 do
sum = sum + ds:C(length - i)
end
moving5 = sum/ 5
sleep ( 100 )
end
end
Есть два момента, которые необходимо учитывать: ---------------------------------------------- 1) Расчет надо делать для двух состояний: а) свеча закрыта б) свеча открыта. Либо лишь состояние а), которое надо обнаружить. состояние б) существует лишь на последней свече и лишь в режиме торгов. Поэтому у Вас расчет последней свечи содержит ошибку. -------------------------------------------------------------------- 2) Не надо использовать циклы. Циклы -это зло в системах реального времени. Можно вычислить мувинг затратив лишь 1 деление +1 вычитание+1 сложение для любого значения параметра N. У Вас N всего 4, а некоторые (обращались ко мне с такой проблемой) используют 1000000 (сто тысяч) Вот и посчитайте мколько времени у Вас будет считаться мувинг встроенным индикатором или вашим ( у обращавшихся квик виснул ) -----------------------------
Здравствуйте, У нас есть такой пример индикатора без циклов, он не адаптирован под CreateDataSource, но может дать идею решения:
Скрытый текст
Код
Settings = {
Name = "*SMA",
Period = 9,
line = {{Name = "SMA1",Type = TYPE_LINE, Color = RGB(255, 0, 0)}}
}
function Init()
SUM_TMP={}
return #Settings.line
end
function OnCalculate(i)
local Out = nil
P=Settings.Period
if i==1 then SUM_TMP={} end
SUM_TMP[i]=(SUM_TMP[i-1] or 0)+C(i)
if i >= P then
Out = (SUM_TMP[i]-(SUM_TMP[i-P] or 0))/P
end
return Out
end
Сергей, спасибо за интересный пример. Обратил внимание на вот эту конструкцию. А Вы не могли бы пояснить, как он работает? как она обрабатывает оператор OR в данном случае? Если я правильно понимаю, она суммирует либо то, что перед ним, либо то что после, но по какому критерию?
Sergey Gorokhov написал: SUM_TMP =(SUM_TMP[i-1] or 0)+C(i)
Сергей, спасибо за интересный пример. Обратил внимание на вот эту конструкцию. А Вы не могли бы пояснить, как он работает? как она обрабатывает оператор OR в данном случае? Если я правильно понимаю, она суммирует либо то, что перед ним, либо то что после, но по какому критерию?
Если SUM_TMP[i-1] не существует (nil) то вместо него берется 0
Космонавт написал: Сергей, спасибо за пример, но не понятно как функции OnCalculate(i) удаётся обратиться ко всем требуемым 9 свечкам. Что передаётся в переменную i ?
Большое спасибо за ответы! Разрешите задать ещё вопрос. У меня робот перебирает много акций, и рассчитывать индикаторы надо для каждого из них. Вот как это выглядит сейчас. У меня ведь грубая ошибка - я каждый раз внутри цикла по новой подписываюсь на свечки и ставлю колбек? Подскажите пожалуйсте где грамотно размещать заказ свечек и обновлений? Функция MA - это готовый пример с сайта ARQA
Код
ticker_list = "AFLT,ALRS,BANE,CHMF,FEES,GAZP,GMKN,HYDR,IRAO,LKOH,MAGN,MFON,MGNT,MOEX,MTSS,NLMK,NVTK,RASP,ROSN,RSTI,RTKM,SBER,SNGS,SNGSP,TATN,URKA,VTBR"
is_run = true
function OnStop(s)
is_run = false
return 1000
end
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua") --взято с сайта ARQA
function main()
while is_run do
for sec in string.gmatch(ticker_list,"%a+") do
ds = CreateDataSource("TQBR", sec, INTERVAL_M1)
ds:SetUpdateCallback()
sleep(100)
func = MA()
ma_out=func(ds:Size(), {Period=60, Metod = "SMA", VType="Typical", round=4}, ds)
end
end
end
Какие колбеки? и зачем Вы их выносите? Вы же сами сказали что не хотите подписываться на свечки в цикле. Так не подписывайтесь. Про колбеки никто ничего не говорил.
Ок, переформулирую вопрос. 1. Этот код работает, но он работает медленнее чем брать данные с графика через идентификатор. Почему? Где самый тяжёлый участок кода? 2. Мне надо запустить ds = CreateDataSource("TQBR", sec, INTERVAL_M1) единожды, верно? 3. Мне надо запустить ds:SetUpdateCallback() тоже единожды, верно? 4. Мне надо перебрать много бумаг. Если я сделаю так,
Код
for sec in string.gmatch(ticker_list,"%a+") do
ds = CreateDataSource("TQBR", sec, INTERVAL_M1)
ds:SetUpdateCallback()
end
а потом основной цикл программы внутри while is run
for sec in string.gmatch(ticker_list,"%a+") do
запускаются функции, проверяются условия срабатывания, идёт торговля
end
это правильно? Ведь ds будет всё время принимать значение новой бумаги и будет каша. Спасибо за ответы
Космонавт написал: Ведь ds будет всё время принимать значение новой бумаги и будет каша.
Ничего не мешает сделать несколько ds, для каждой бумаги свой. Например если вместо переменной использовать таблицу ds[sec] = CreateDataSource("TQBR", sec, INTERVAL_M1)
Sergey Gorokhov написал: Ничего не мешает сделать несколько ds, для каждой бумаги свой. Например если вместо переменной использовать таблицу ds[sec] = CreateDataSource("TQBR", sec, INTERVAL_M1)
я пробовал, но тогда данные не заходят в функцию с вашего сайта:
Космонавт написал: Николай, спасибо за ответ. Приведите пожалуйста формулу мувинга, которую Вы рекомендуете, там где 1 деление +1 вычитание+1 сложение.
вот код мувинга без циклов:
Код
Settings = {
Name = "*nkSMA",
Period = 9,
line = {{Name = "nkSMA",Type = 1, Color = RGB(255, 0, 0)}}
}
function Init()
return #Settings.line
end
local P,i1,NP;
function OnCalculate(i)
local Out=C(i);
if i==1 then
S={}; P=Settings.Period; NP=1/P;
else
if i<=P then Out=(Out+i1*S[i1])/i;
else Out=S[i1]+ NP*(Out-C(i-P)); end
end
i1=i; S[i]=Out;
return Out
end