Модуль реализации интерфейса обработки событий QUIK с использованием очередей событий

Автор записи: TGB

В существующих (на момент 15.10.21) версиях QUIK, его основной (и единственный) служебный поток обслуживания скриптов пользователя запускает их на выполнение (по команде из меню <Загруженные скрипты>). Этот же служебный поток, транслирует скриптам пользователя события, возникающие в QUIK, запуская все функции обратного вызова (колбеки), всех запущенных на исполнение его скриптов. Таким образом, в каждом работающем скрипте пользователя существует его поток main, а все его колбеки запускаются в отдельном, (единственном) служебном потоке QUIK.
Существуют два вида колбеков:
1) колбеки обслуживающие события фондового рынка;
2) колбеки обслуживающие события, возникающие в созданных пользователем таблицах QIUK.
То, что служебный поток QUIK один обслуживает колбеки всех, запущенных на исполнение скриптов пользователя, является проблемой: если функции колбеков некоторого скрипта выполняются долго, или в них возникают длительные блокировки, то перестают обслуживаться колбеки остальных, работающих скриптов пользователя. Кроме того, в скриптах пользователя необходимо учитывать факт параллелизма выполнения потока main и служебного потока QUIK, выполняющего колбеки. То есть, заниматься, сложным для непрофессионала, параллельным программированием.
Из, всего выше сказанного, можно сделать вывод о том, что: в том виде, как он представлен, в текущий момент времени, интерфейс обработки событий в QLua «сырой» для использования его «широким кругом» пользователей.
Для устранения выше озвученных проблем разработчиком QUIK рекомендуется использовать потокобезопасные очереди для передачи параметров, запус-каемых колбеков, потокам main, в которых должны выполняться функции реакции на такие колбеки (документ «Использование Lua в Рабочем месте QUIK»).
Как это можно реализовать, в удобном и эффективном для пользователя виде, представлено ниже в виде:
1) кода модуля even_handling_module.lua ;
2) шаблона использования этого модуля.
Особенности реализации модуля even_handling_module.lua:
1) код модуля написан на «чистом» QLua;
2) очереди передачи параметров колбеков в скриптах пользователя в его потоки main (в разных скриптах это разные потоки) потокобезопасные и при этом они реализованы без использования синхронизации;
3) при реализации записи/чтения очередей, количество операций (на языке Lua) < 6 и не зависит от текущего размера очередей.
Выше перечисленные особенности реализации модуля even_handling_module.lua обеспечивают минимальное влияние на служебный поток QUIK того, что выполняется в скриптах пользователя, а также удобство использования модуля в скриптах пользователя.
Детальное описание использования модуля even_handling_module.lua приведено в его коде и коде шаблона, описывающего схему обработки событий QUIK.
Для подключения модуля к шаблону его надо сохранить в файле под именем even_handling_module.lua в папку хранения кода запуска QUIK (info.exe).
Коды модуля и скрипта-примера его использования:

Смотреть полностью...

Индикатор экстремум

Автор записи: kalikazandr

Облегченная версия индикатора, определяет локальные макс/мин цены на графике. Надеюсь, индикатор станет полезен для ваших торговых алгоритмов.

жми

в версии quik 8.7 имеется баг с настройками индикатора, проверялось на версии 8.13

Индикатор

--C:/QUIK/LuaIndicators/extr.lua
dofile(getWorkingFolder() .. "\\LuaIndicators\\Include\\myExtr.lua")
Settings = {}
Settings.Name = "*extr"
Settings.nDepth = 3000 --[[для определения стартового бара]]
Settings.nMinHL = 0 --[[минимальное движение цены для определения экстремума]]
Settings.line =
{
 {
 Name = "TRIANGLE_UP",
 Type = TYPE_TRIANGLE_UP,
 Color = RGB(255, 0, 0),
 Width = 4
 },
 {
 Name = "TRIANGLE_DOWN",
 Type = TYPE_TRIANGLE_DOWN,
 Color = RGB(0, 255, 0),
 Width = 4
 }
}
 
function Init()
 extr = myExtr()
 return 2
end
 
local oi, min_hl
function OnCalculate(index)
 
 if index == 1 then
 min_hl = tonumber(Settings.nMinHL)
 
 if min_hl and min_hl &lt;= 0 then min_hl = nil end
 if not min_hl then return message("Индикатору extr нужен параметр nMinHL &gt; 0",3) end
 
 local depth = tonumber(Settings.nDepth) or Size()
 local s = Size() - depth
 oi = s &lt; 1 and 1 or s
 
 extr(oi, min_hl, index)
 end
 --[[считает только что закрывшийся бар, в текущем активном не считает]]
 if not min_hl or index &lt;= oi then return end
 
 extr(oi, min_hl, index)
 oi = index
end

Модуль индикатора

--C:/QUIK/LuaIndicators/Include/myExtr.lua
function myExtr()
   local HH, LL, mH, mL, imH, imL
   local function SetL(oH, oL, oi, min_hl)
      if oH > mH then
         mH, imH = oH, oi
         if not LL then
            if oH - mL >= min_hl then
               LL = mL
               SetValue(imL, 1, LL)
               mL, imL = oL, oi
               HH = nil
            end
         else
            mL, imL = oL, oi
         end
         if HH and oH >= HH then HH = nil end
      end
   end
   local function SetH(oH, oL, oi, min_hl)
      if oL < mL then
         mL, imL = oL, oi
         if not HH then
            if mH - oL >= min_hl then
               HH = mH
               SetValue(imH, 2, HH)
               mH, imH = oH, oi
               LL = nil
            end
         else
            mH, imH = oH, oi
         end
         if LL and oL <= LL then LL = nil end
      end
   end
   return function (oi, min_hl, i)
      if i <= oi then
         mH, mL = H(oi), L(oi)
         imH, imL = oi, oi
         HH, LL = nil, nil
         return
      end
 
      local oH, oL = H(oi), L(oi)
      if imL < imH then
         SetL(oH, oL, oi, min_hl)
         SetH(oH, oL, oi, min_hl)
      else
         SetH(oH, oL, oi, min_hl)
         SetL(oH, oL, oi, min_hl)
      end
   end
end