Такое впечатление, что если повесить много даже простых индикаторов, квик начинает подтормаживать. Как часто рассчитываются индикаторы? На каждом тике? Как можно ограничить частоту расчета? Куда бы можно было вставить слип? Не очень понятно.
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
09.02.2017 18:01:53
Индикаторы пересчитываются по каждому мовому данному, фактически по каждой сделке по инструменту. вы можете ограничить частоту расчета просто пропуская отдельные вызовы но лучше, конечно, написать индикатор так, чтобы он не тормозил
Пользователь
Сообщений: Регистрация: 16.01.2017
09.02.2017 21:39:52
Если речь идет об индикаторе, как о скрипте для рисования линий в окне графиков QUIK, то это особый вид скриптов, в которых нет своего выделенного потока main(). Почитайте "Создание индикаторов технического анализа с помощью скриптов Lua.pdf" на официальной страничке QUIK. Вся текущая работа такого скрипта по сути сводится к тому, что QUIK вызывает вашу callback-функцию OnCalculate() каждый раз по мере изменения текущей или появления новой свечи. Вы же должны максимально быстрым алгоритмом рассчитать значения индикатора для текущего состояния свечи и вернуть QUIKу получившееся значение индикатора. Никаких sleep() ! Кроме того, те алгоритмы, которые, например, предложены в обсуждаемых на форме INDICATORS.zip являются, на самом деле, лишь демонстрация базовых принципов написания индикатора, а не готовым продуктом. Использованные там алгоритмы можно (и нужно!) оптимизировать так, что вычисления будут происходить на порядок быстрее. (Ничуть не хочу обидеть разработчиков :)
Если же речь идет об организации расчетов значений индикатора для внутренних нужд торгового робота, написанного так, чтобы не зависеть от случайного закрытия окна, на котором рисуется интересующий индикатор, то здесь требования, как к обычному скрипту qlua: все "тяжелые" вычисления - в потоке main(), в callback-ах - лишь мгновенное сохранение поступивших данных (например, в очередях) и возврат управления обратно QUIKу. Потом уже main() должен разбираться, что делать с поступившей информацией. Применительно к расчету индикатора для внутренних нужд робота, можно предложить следующую схему: в main() до основного цикла или внутри цикла по мере наступления событий, требующих начать расчет нового индикатора, запрашиваете у QUIKа нужный поток свечек вызовом CreateDataSource(), и вешаете обработчик события "изменение текущей / поступление новой свечки" через SetUpdateCallback(). Единственное отличие в написании этого обработчика от OnCalculate() в том, что он не должен ничего возвращать QUIKу, а новое вычисленное значение индикатора нужно каким-то устраивающим Вас образом передать в поток main().
Пользователь
Сообщений: Регистрация: 01.06.2015
09.02.2017 23:59:41
swerg, Тормозить не должен, все просто - взять готовые данные и нарисовать. Впрочем тормоза странные - все бегает, процессор на две трети пуст, но иногда тормозит правая кнопка мыши или по двойному щелчку стакан открывается с задержкой.
Цитата
пропуская отдельные вызовы
Вы имеете в виду поставить счетчик на первом баре и пока он не сработает просто пустой return? Надо попробовать.
Пользователь
Сообщений: Регистрация: 01.06.2015
10.02.2017 00:06:35
Алексей, Меня интересует просто рисовалка готовых данных. Никаких расчетов нет. Все рисуется на последнем баре - SetValue. Скорость не важна. Лишь бы при большом количестве индикаторов не тормозился сам квик.
Пользователь
Сообщений: Регистрация: 02.02.2015
миру мир!
10.02.2017 06:29:36
Видимо пришло время поделиться кодом вашего индикатора мало-ли что там написано
Settings =
{
Name = "+PE",
fname = "OSCp",
line=
{
{
Name = "eq - ",
Color = RGB(40, 80, 190),
Type = TYPE_LINE,
Width = 1
},
{
Name = "pos - ",
Color = RGB(255, 60, 50),
Type = TYPE_LINE,
Width = 2
}
}
}
function Init()
return #Settings.line
end
function OnCalculate(index)
local fnm = "\\" .. Settings.fname .. ".txt"
if index == Size() then
local callResult, result = pcall(dofile, getScriptPath() .. fnm)
if not callResult then
return
end
SetValue(index-#eq, 1, nil)
SetValue(index-#pos, 2, nil)
local cnt = 0
for i = index-#eq+1, index-1 do
cnt = cnt + 1
SetValue(i, 1, eq[cnt])
SetValue(i, 2, pos[cnt])
end
return eq[#eq], pos[#pos]
end
end
В файле для дуфайл - типа этого: pos={0.00,0.00,0.00,1.00,1.00,} eq={0.43,0.43,0.43,0.45,0.44,} только длиннее - 300-500 палок.
Пользователь
Сообщений: Регистрация: 16.01.2017
11.02.2017 02:26:51
Цитата
валерий написал: Алексей , Меня интересует просто рисовалка готовых данных. Никаких расчетов нет. Все рисуется на последнем баре - SetValue. Скорость не важна. Лишь бы при большом количестве индикаторов не тормозился сам квик.
В выложенном Вами коде получается, что по мере совершения на бирже каждой обезличенной сделки по инструменту, к которому Вы "прикрутили" свой индикатор, у Вас заново перерисовываются все 300-500 свечек (точнее точек 2-х линий индикатора). В принципе это накладно, но если так и задумано... Чтобы Вам что-нибудь посоветовать, нужно понимание того, как часто обновляется информация в Вашем txt файле? И какого характера это обновление: после очередной обезличенной сделки на бирже в файле может всё поменяться (тогда, собственно, ничего нового тут не придумать) или меняется/добавляется только последнее значение в таблицах pos и eq. Также хочу уточнить, к чему относятся последние данные в таблицах: к последней завершенной свечке (т.е. к Size()-1) или к текущей формируемой?
Пользователь
Сообщений: Регистрация: 01.06.2015
11.02.2017 11:47:33
Алексей, Как правило меняются максимум только два последних значения и можно было бы попробовать подумать как не перерисовывать остальные. Но при первом расчете (применить \/ добавить \/ ОК) квик все перерисовывает, потом вроде нет... Как узнать намерения квика в каждом конкретном случае я не вижу. Скорость обновления меня практически не волнует. И 5 сек устроит. Что было бы существеннее экономии на перерисовке. Но можно ли применять слип и куда его вставить техподдержка молчит.
Пользователь
Сообщений: Регистрация: 01.06.2015
11.02.2017 18:24:10
Цитата
swerg написал: Индикаторы пересчитываются по каждому мовому данному, фактически по каждой сделке по инструменту. вы можете ограничить частоту расчета просто пропуская отдельные вызовы но лучше, конечно, написать индикатор так, чтобы он не тормозил
Облом. Не нашел способа как пропустить вызов OnCalculate. Пустой return или его отсутствие стирает всё.
Пользователь
Сообщений: Регистрация: 16.01.2017
13.02.2017 03:39:17
Цитата
валерий написал: Алексей , Как правило меняются максимум только два последних значения и можно было бы попробовать подумать как не перерисовывать остальные. Но при первом расчете (применить \/ добавить \/ ОК) квик все перерисовывает, потом вроде нет... Как узнать намерения квика в каждом конкретном случае я не вижу. Скорость обновления меня практически не волнует. И 5 сек устроит. Что было бы существеннее экономии на перерисовке. Но можно ли применять слип и куда его вставить техподдержка молчит.
Sleep() категорически не поможет. Код OnCalculate() выполняется в основном потоке QUIKа. Слипом вы просто подвесите QUIK. Идея, заложенная разработчиками QUIKa, заключается в том, что через механизм вызова callback-функции OnCalculate(), QUIK сообщает какую свечку Вам сейчас надо обработать, и ожидает, что Вы вернете значение индикатора именно для этой свечки. Это только для особых индикаторов, формируемых с запаздыванием (например, фракталы), была предоставлена функция SetValue(). При этом подразумевается, что "задним числом" может поменяться значение индикатора только для конечного кол-ва свечек, но никак не вся история индикатора (кому нужен индикатор, история которого постоянно меняется задним числом?)
1-й вариант (противоречит логике работы QUIK): Если у Вас ГАРАНТИРОВАНО меняется не более 2-х последних свечек, то и перерисовываейте индикатор только для них. Точнее, перерисовывайте (SetValue) только для предпоследней свечки, а значение индикатора для текущей свечки возвращайте как результат OnCalculate(). Как в первый раз вывести весь индикатор? Как только получите index == Size(), нарисуйте его весь и установите флаг, что все отрисовали. Соответственно, при поступлении от QUIK последующих вызовов OnCalculate() Вы уже будете перерисовывать только две последние свечи. Также обязательно отлавливайте ситуацию index == 1. Это значит, что QUIK по одной из многочисленных причин (не важно каких) решил заставить Вас пересчитать весь индикатор. Делайте то, что он просит, т.е. сбросьте вышеупомянутый флаг отрисовки.
2-й вариант (в логике QUIK): У Вас же должно быть жесткое соответствие для какой (по времени) свечки соответствуют какие по счету значения в таблицах из файла *.txt? Quik у Вас запрашивает через OnCalculate() значение индикатора для свечки со временем T(index), ну так и верните ему значение индикатора, соответствующее этому времени. А чтобы каждый раз не считывать с диска файл *.txt надо придумать механизм принятия решения, когда же именно его считывать. Для этого надо понимать как часто он меняется (или как часто Вы хотите выводить новую информацию на график), т.е. вывод через равные интервалы времени - это один механизм. Или надо понимать в связи с какими событиями происходит смена содержимого *.txt и как их отловить - это другой механизм.
Пользователь
Сообщений: Регистрация: 01.06.2015
13.02.2017 15:52:55
Алексей, Кажется с вашей помощью я понял особенную логику индикаторов арки. Буду копать в указанном вами направлении. Спасибо.
Settings =
{
Name = "+PE" ,
fname = "OSCp" ,
line =
{
{
Name = "eq - " ,
Color = RGB ( 40 , 80 , 190 ),
Type = TYPE_LINE,
Width = 1
},
{
Name = "pos - " ,
Color = RGB ( 255 , 60 , 50 ),
Type = TYPE_LINE,
Width = 2
}
}
}
function Init ()
return # Settings.line
end
function OnCalculate (index)
local fnm = "\ \" .. Settings.fname .. ".txt"
if index = = Size () then
local callResult, result = pcall(dofile, getScriptPath () .. fnm)
if not callResult then
return
end
SetValue (index - # eq, 1 , nil )
SetValue (index - # pos, 2 , nil )
local cnt = 0
for i = index - # eq + 1 , index - 1 do
cnt = cnt + 1
SetValue (i, 1 , eq[cnt])
SetValue (i, 2 , pos[cnt])
end
return eq[ # eq], pos[ # pos]
end
end
В файле для дуфайл - типа этого: pos={0.00,0.00,0.00,1.00,1.00,} eq={0.43,0.43,0.43,0.45,0.44,} только длиннее - 300-500 палок.
Могу посоветовать следующее: 1) дорисовывать последнюю точку и удалять первую, а не перерисовывать все. 2) перерисовывать лишь те точки которые изменились.