Подскажите как грамотно подписаться в одном скрипте на два таймфрейма?
Код
rsi_tf=INTERVAL_M5
mov_tf=INTERVAL_M1
Код
function main()
for key,sec in pairs(fut_list) do
DataSource(class,sec,rsi_tf)
DataSource(class,sec,mov_tf)
end
end
Код
function mycallbackforallstocks(class,sec,index)
end
function DataSource(class,sec,interval)
ds[sec] = CreateDataSource(class,sec,interval)
ds[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class,sec,...) end)
return ds[sec]
end
Let_it_go написал: надо ли заводить вторую таблицу типа ds?
Это зависит от того что вы будете дальше делать с данными. Если Вам нужно дальше работать с источником ds то да надо создавать отдельный ds, если нет, то нет.
Взгляните пожалуйста на такой вариант. Не происходит ли тут лишних действий, всё ли экономно в плане получения и подсчёта индикаторов?
Код
ds={}
ds_minutes={}
Код
function mycallbackforallstocks(class,sec,index)
end
function DataSource(class,sec,interval)
ds[sec] = CreateDataSource(class,sec,interval)
ds[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class,sec,...) end)
return ds[sec]
end
function DataSource_minutes(class,sec,interval)
ds_minutes[sec] = CreateDataSource(class,sec,interval)
ds_minutes[sec]:SetUpdateCallback(function(...) mycallbackforallstocks(class,sec,...) end)
return ds[sec]
end
Код
function main()
for key,sec in pairs(fut_list) do
DataSource(class,sec,rsi_tf)
DataSource_minutes(class,sec,mov_tf)
end
.............
while is_run do
for key,sec in pairs(fut_list) do
sleep (1000)
func = RSI()
local rsi_count={}
num_candles=ds[sec]:Size()
last_price[sec]=ds[sec]:C(num_candles)
for i=1,num_candles do
rsi_count[i]=func(i, {Period=rsi_period, VType="Typical"}, ds[sec])
end
.....................
--Стандартное отклонение
func = SD()
dev=func(ds_minutes[sec]:Size(), {Period=mov_period, VType="Typical"}, ds_minutes[sec])
.......................
Let_it_go написал: Не происходит ли тут лишних действий, всё ли экономно в плане получения и подсчёта индикаторов?
Происходит. Например не понятно, зачем Вам две функции DataSource и DataSource_minutes. В чем смысл, ведь они делают одно и тоже? Далее, для индикатора RSI() не обязательно передавать в функцию весь ds целиком, достаточно только предыдущее значение (i-1) и текущее. А для индикатора SD() только текущее (ds_minutes[sec]:Size()).
Речь о том, что вместо: Out = func(i, {Period=SP, Metod = M, VType="Close"}, ds)
можно писать так: Out = func(i, {Period=SP, Metod = M, VType="Any"}, {[i] = C(i)})
Но надо помнить, что если в индикаторе, требуются значения предыдущих свечей, то надо их указать, например так: Out = func(i, {Period=SP, Metod = M, VType="Any"}, {[i] = C(i), [i-1] = C(i-1)})
при этом VType надо указать именно "Any", а если надо "Typical", то указать его через функцию Value, например так: Out = func(i, {Period=SP, Metod = M, VType="Any"}, {[i] = Value(i,"Typical",ds)})
Здравствуйте, Сергей. Добрался до того, чтобы посидеть над этими записями с форума. Не получается запихивать в индикатор только последнее значение. Начал с простого - Стандартное отклонение. В таком виде работает:
переменная i - это перебор значений в цикле. В моём случае она не определена. Она нужна только для EMA,RSI и других подобных индикаторов. Для стандартного отклонения она не требуется. Поэтому ваш пример не рабочий в моём случае.
Let_it_go, Потому что функции у Вас старые. Используйте последнее обновление.
И еще одно замечание Все функции требуют предварительного расчета начиная с индекса 1. Т.е. даже если нужен только последний индекс, все равно требуется провести цикл расчета начиная с самого первого индекса.
Обновил. Теперь ничего не работает, все роботы стали глючить. Например перестал рассчитываться RSI Вот вид, который был рабочим до обновления функций:
Код
func = RSI()
local rsi_count={}
num_candles=ds[sec]:Size()
for i=1,num_candles do
rsi_count[i]=func(i, {Period=rsi_period, VType="Typical"}, ds[sec])
end
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua")
num_candles=ds[sec]:Size()
func = MA()
for i=1,num_candles do
ma_out=func(i, {Period=3, Metod = EMA, VType=ANY}, ds_main[sec])
message (i.."="..ma_out,1)
end
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua")
num_candles=ds_main[sec]:Size()
func = MA()
for i=1,num_candles do
ma_out=func(i, {Period=3, Metod = EMA, VType=ANY}, ds_main[sec])
message (i.."="..ma_out,1)
end
Передавать последний элемент тоже не вариант. Результат такой же.
Код
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua")
num_candles=ds_main[sec]:Size() --параметр получен, с ним всё ок.
func = MA()
for i=1,num_candles do
ma_out=func(i, {Period=3, Metod = EMA, VType=ANY}, {[i]=ds_main[sec]:C(i)})
message (i.."="..ma_out,1)
end
Sergey Gorokhov написал: Речь о том что надо написать так: dev=func(num_candles_mov, {Period=mov_period, VType="Any"}, {[num_candles_mov] = ds_main[sec]:C(num_candles_mov)})
В Lua переменные типа таблицы являются ссылочными и поэтому передаются в функции по ссылке (без создания новой таблицы) А вот Ваш код как раз тратит лишнюю память на создание новой таблицы.
dofile(getWorkingFolder().."\\LuaIndicators\\SD.lua")
dofile(getWorkingFolder().."\\LuaIndicators\\RSI.lua")
rsi_tf=INTERVAL_M5
mov_tf=INTERVAL_M1
class = 'TQBR'
fut_list = {'SBER','GAZP'}
rsi_period = 14
mov_period = 14
secs = {}
function OnInit(script)
is_run = true
end
function OnStop()
is_run = false
return 2000
end
function main()
for _,sec in pairs(fut_list) do
DataSource(class,sec,rsi_tf)
DataSource(class,sec,mov_tf)
end
local sec1, ds_rsi, ds_mov, num_rsi, num_mov, dev
while is_run do
sleep(1000)
for _,sec in pairs(fut_list) do
sec1 = secs[sec]
ds_rsi = sec1[rsi_tf]
ds_mov = sec1[mov_tf]
num_rsi = ds_rsi:Size()
for i = ds_rsi.lastI, num_rsi do
-- lastI надо пересчитывать т.к. последняя свеча будет изменяться неоднократно
sec1.rsi_count[i] = sec1.RSI(i, {Period=rsi_period, VType="Typical"}, ds_rsi)
message(sec ..' rsi_count - '.. i ..' : '.. tostring(sec1.rsi_count[i]))
end
ds_rsi.lastI = num_rsi
num_mov = ds_mov:Size()
for i = ds_mov.lastI, num_mov do
-- lastI надо пересчитывать т.к. последняя свеча будет изменяться неоднократно
dev = sec1.SD(i, {Period=mov_period, VType="Typical"}, ds_mov)
message(sec ..' dev - '.. i ..' : '.. tostring(sec1.rsi_count[i]))
end
ds_mov.lastI = num_mov
end
end
end
--[[ -- если автомат работает в цыкле можно применить SetEmptyCallback()
function mycallbackforallstocks(ds, I) -- ds = self, I = Index
local class = ds.class
local sec = ds.sec
local interval = ds.interval
end
--]]
function DataSource(class,sec,interval)
local ds = CreateDataSource(class,sec,interval)
ds.class = class
ds.sec = sec
ds.interval = interval
ds.lastI = 1
-- ds:SetUpdateCallback(function(...) mycallbackforallstocks(self.class,self.sec,...) end)
ds:SetEmptyCallback()
if not secs[sec] then secs[sec] = {} end
secs[sec][interval] = ds
secs[sec].RSI = RSI()
secs[sec].rsi_count = {}
secs[sec].SD = SD()
return
end
Так как для последних свечек данные будут меняться несколько раз (причем для каждого набора отдельно), надо пожалуй проверять на действительное изменение данных или на изменение индексов свечек.
Можно из цыкла перенести обработку в функцию mycallbackforallstocks но надо учитывать что она будет вызываться для каждого набора по мере его изменения (в том числе неоднократно для последней свечи
Владимир, спасибо за ответ. Но это старая ветка. Вопрос изложенный в начале давно решён. Сейчас на повестке дня две других проблемы: 1. После обновления функций из INDICATORS.ZIP перестали работать скрипты. 2. Так и не получается передавать в индикатор только последний элемент. В приведённом вами примере используется прежний (нерациональный) способ передачи, от которого я хочу отказаться. dev = sec1.SD(i, {Period=mov_period, VType="Typical"}, ds_mov) Вместо ds_mov надо передавать одно число типа такого варианта (но он не работает) Out = func(i, {Period=SP, Metod = M, VType="Any"}, {[i] = C(i)})
Let_it_go написал: 2. Так и не получается передавать в индикатор только последний элемент. В приведённом вами примере используется прежний (нерациональный) способ передачи, от которого я хочу отказаться. dev = sec1.SD(i, {Period=mov_period, VType="Typical"}, ds_mov)
Вы совсем не правы именно передача всего массива наиболее оптимальна. При этом не делается копия исходного массива, а передается только одно число - ссылка на исходный массив. А попытки создать урезанный массив с последними значениями приводят к лишним накладным расходам
Запустите скрипт
Код
function privet(t)
message('function privet : t = '.. tostring(tab1))
t.privet = 'Привет из функции'
end
function main()
message('*** start')
tab1 = {o='1', h='2'}
message('tab1 = '.. tostring(tab1))
privet(tab1)
message('tab1.privet = '.. tostring(tab1.privet))
message('*** end')
kvLogClose()
end
Спасибо, буду разбираться. Я не кодер, поэтому страдаю от непонимания простых вещей. Все же надеюсь, что в эту ветку заглянет Сергей Горохов и внесёт ясность.
Let_it_go написал: Владимир, спасибо за ответ. Но это старая ветка. Вопрос изложенный в начале давно решён. Сейчас на повестке дня две других проблемы: 1. После обновления функций из INDICATORS.ZIP перестали работать скрипты.
Вы запускали мой скрипт из сообщения №20. У меня им корректно рассчитались RSI и SD для двух бумаг на последних версиях INDICATORS.ZIP
dofile(getWorkingFolder().."\\LuaIndicators\\MA.lua")
function main()
func = MA()
t_id = AllocTable()
AddColumn(t_id,1,"Price",true,QTABLE_INT_TYPE,10)
AddColumn(t_id,2,"MA",true,QTABLE_INT_TYPE,10)
CreateWindow(t_id)
SetWindowCaption(t_id,"MA")
ds = CreateDataSource("TQBR", "LKOH", INTERVAL_M5)
sleep(100)
for i=1,ds:Size() do
ma_out=func(i, {Period=3, Metod = EMA, VType=ANY},{[i]=ds:C(i)})
tmp=InsertRow(t_id,-1)
SetCell(t_id,tmp,1,tostring(ds:C(i)),ds:C(i))
SetCell(t_id,tmp,2,tostring(ma_out),ma_out)
end
end