Sleep в индикаторе

Страницы: 1
RSS
Sleep в индикаторе
 
Такое впечатление, что если повесить много даже простых индикаторов, квик начинает подтормаживать. Как часто рассчитываются индикаторы? На каждом тике?
Как можно ограничить частоту расчета? Куда бы можно было вставить слип? Не очень понятно.
 
Индикаторы пересчитываются по каждому мовому данному, фактически по каждой сделке по инструменту.
вы можете ограничить частоту расчета просто пропуская отдельные вызовы
но лучше, конечно, написать индикатор так, чтобы он не тормозил
 
Если речь идет об индикаторе, как о скрипте для рисования линий в окне графиков QUIK, то это особый вид скриптов, в которых нет своего выделенного потока main().
Почитайте "Создание индикаторов технического анализа с помощью скриптов Lua.pdf" на официальной страничке QUIK.
Вся текущая работа такого скрипта по сути сводится к тому, что QUIK вызывает вашу callback-функцию OnCalculate() каждый раз по мере изменения текущей или появления новой свечи.
Вы же должны максимально быстрым алгоритмом рассчитать значения индикатора для текущего состояния свечи и вернуть QUIKу получившееся значение индикатора. Никаких sleep() !
Кроме того, те алгоритмы, которые, например, предложены в обсуждаемых на форме INDICATORS.zip являются, на самом деле, лишь демонстрация базовых принципов написания индикатора, а не готовым продуктом. Использованные там алгоритмы можно (и нужно!) оптимизировать так, что вычисления будут происходить на порядок быстрее. (Ничуть не хочу обидеть разработчиков :)

Если же речь идет об организации расчетов значений индикатора для внутренних нужд торгового робота, написанного так, чтобы не зависеть от случайного закрытия окна, на котором рисуется интересующий индикатор, то здесь требования, как к обычному скрипту qlua: все "тяжелые" вычисления - в потоке main(), в callback-ах - лишь мгновенное сохранение поступивших данных (например, в очередях) и возврат управления обратно QUIKу. Потом уже main() должен разбираться, что делать с поступившей информацией.
Применительно к расчету индикатора для внутренних нужд робота, можно предложить следующую схему: в main() до основного цикла или внутри цикла по мере наступления событий, требующих начать расчет нового индикатора, запрашиваете у QUIKа нужный поток свечек вызовом CreateDataSource(), и вешаете обработчик события "изменение текущей / поступление новой свечки" через SetUpdateCallback().
Единственное отличие в написании этого обработчика от OnCalculate() в том, что он не должен ничего возвращать QUIKу, а новое вычисленное значение индикатора нужно каким-то устраивающим Вас образом передать в поток main().
 
swerg,
Тормозить не должен, все просто - взять готовые данные и нарисовать. Впрочем тормоза странные - все бегает, процессор на две трети пуст, но иногда тормозит правая кнопка мыши или по двойному щелчку стакан открывается с задержкой.
Цитата
пропуская отдельные вызовы
Вы имеете в виду поставить счетчик на первом баре и пока он не сработает просто пустой return? Надо попробовать.
 
Алексей,
Меня интересует просто рисовалка готовых данных. Никаких расчетов нет. Все рисуется на последнем баре - SetValue. Скорость не важна. Лишь бы при большом количестве индикаторов не тормозился сам квик.
 
Видимо пришло время поделиться кодом вашего индикатора
мало-ли что там написано
 
swerg,
Пожалуйста
Код
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 палок.
 
Цитата
валерий написал:
Алексей  ,
Меня интересует просто рисовалка готовых данных. Никаких расчетов нет. Все рисуется на последнем баре - SetValue. Скорость не важна. Лишь бы при большом количестве индикаторов не тормозился сам квик.
В выложенном Вами коде получается, что по мере совершения на бирже каждой обезличенной сделки по инструменту, к которому Вы "прикрутили" свой индикатор, у Вас заново перерисовываются все 300-500 свечек (точнее точек 2-х линий индикатора). В принципе это накладно, но если так и задумано...
Чтобы Вам что-нибудь посоветовать, нужно понимание того, как часто обновляется информация в Вашем txt файле? И какого характера это обновление: после очередной обезличенной сделки на бирже в файле может всё поменяться (тогда, собственно, ничего нового тут не придумать) или меняется/добавляется только последнее значение в таблицах pos и eq.
Также хочу уточнить, к чему относятся последние данные в таблицах: к последней завершенной свечке (т.е. к Size()-1) или к текущей формируемой?
 
Алексей,
Как правило меняются максимум только два последних значения и можно было бы попробовать подумать как не перерисовывать остальные. Но при первом расчете (применить \/ добавить \/ ОК) квик все перерисовывает, потом вроде нет... Как узнать намерения квика в каждом конкретном случае я не вижу.
Скорость обновления меня практически не волнует. И 5 сек устроит. Что было бы существеннее экономии на перерисовке. Но можно ли применять слип и куда его вставить  техподдержка молчит.
 
Цитата
swerg написал:
Индикаторы пересчитываются по каждому мовому данному, фактически по каждой сделке по инструменту.
вы можете ограничить частоту расчета просто пропуская отдельные вызовы
но лучше, конечно, написать индикатор так, чтобы он не тормозил

Облом. Не нашел способа как пропустить вызов OnCalculate. Пустой return или его отсутствие стирает всё.
 
Цитата
валерий написал:
Алексей  ,
Как правило меняются максимум только два последних значения и можно было бы попробовать подумать как не перерисовывать остальные. Но при первом расчете (применить \/ добавить \/ ОК) квик все перерисовывает, потом вроде нет... Как узнать намерения квика в каждом конкретном случае я не вижу.
Скорость обновления меня практически не волнует. И 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 и как их отловить - это другой механизм.
 
Алексей,
Кажется с вашей помощью я понял особенную логику индикаторов арки. Буду копать в указанном вами направлении. Спасибо.
 
Цитата
валерий написал:
swerg  ,
Пожалуйста
Код
  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) перерисовывать лишь те точки которые изменились.
Страницы: 1
Читают тему
Наверх