В существующих (на момент 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).
Коды модуля и скрипта-примера его использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | --[[ TGB ---- Модуль реализации обработки событий QUIK с использованием очередей событий фондового рынка и событий таблиц QUIK --- Краткая спецификация модуля. 1. Реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди, одна из которых обслуживает колбеки фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером; 2. При работе обработке колбеков есть две функции: <функция подписки на события фондового рынка> и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события в соответствии с существующими именами колбеков; реализация подписки сведена к автоматическому созданию (скрытых) от пользователя функций колбеков, записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди; 3. Для работы с очередями по новой схеме есть две функции чтения соответственно очередям; при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>. При работе по этой схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы. ---- !! Колбеки OnInit и OnStop обрабатываются как обычно. ------------------------- --]] ---- Функции работы с очередями------ --- При использовании между потоком колбеков и потоком main потокобезопасные ---<a id="post-preview" class="preview button" href="https://quikluacsharp.ru/?p=3858&preview=true" target="wp-preview-3858" rel="noopener">Просмотреть</a> local new = function () return {first = 1 , last = 0 } end --- local push = function (self, v) local last = self.last + 1 self[last] = v self.last = last return last end --- local pop = function (self) local first = self.first if first > self.last then return nil end local v = self [first] self.first = first + 1 self[first] = nil return v, first end --- local size = function (self) return self.last - self.first + 1 end ----- --------- Создание очередей----------- local Queue_QUIK = new() local Queue_QUIK_tbl = new() ----- Функции запроса текущих размеров очередей ------- local function sizeQueue_evn_QUIK() return size (Queue_QUIK) end local function sizeQueue_evn_QUIK_tbl() return size (Queue_QUIK_tbl) end -- Конец Функции работы с очередями --------------------------------------- local function f_nil () end --- Переменные событий фондового рынка ------- OnAccountBalance = f_nil --- изменение позиции по счету OnAccountPosition = f_nil --- изменение позиции по счету OnAllTrade = f_nil --- новая обезличенная сделка OnCleanUp = f_nil --- смена торговой сессии OnClose = f_nil --- закрытие терминала QUIK или выгрузка файла qlua.dll OnConnected = f_nil --- установление связи с сервером QUIK OnDepoLimit = f_nil --- изменение бумажного лимита OnDepoLimitDelete = f_nil --- удаление бумажного лимита OnDisconnected = f_nil --- отключение от сервера QUIK OnFirm = f_nil --- получение описания новой фирмы OnFuturesClientHolding = f_nil --- изменение позиции по срочному рынку OnFuturesLimitChange = f_nil --- изменение ограничений по срочному рынку OnFuturesLimitDelete = f_nil --- удаление лимита по срочному рынку -- OnInit = f_nil --- инициализация функции main OnMoneyLimit = f_nil --- изменение денежного лимита OnMoneyLimitDelete = f_nil --- удаление денежного лимита OnNegDeal = f_nil --- новая заявка на внебиржевую сделку или изменение параметров существующей заявки на внебиржевую сделку OnNegTrade = f_nil --- новая сделка для исполнения или изменение существующей сделки для исполнения OnOrder = f_nil --- новая заявка или изменение параметров существующей заявки OnParam = f_nil --- изменение текущих параметров OnQuote = f_nil --- изменение стакана котировок -- OnStop = f_nil --- остановка скрипта из диалога управления OnStopOrder = f_nil --- новая стоп-заявка или изменение параметров существующей стоп-заявки OnTrade = f_nil --- новая сделка или изменение параметров существующей сделки OnTransReply = f_nil --- ответ на транзакцию ------ local unsubscribe_tbl = ---- Функции отписки ---- { ['OnAccountBalance'] = function () OnAccountBalance = f_nil end , ['OnAccountPosition'] = function () OnAccountPosition = f_nil end , ['OnAllTrade'] = function () OnAllTrade = f_nil end , ['OnCleanUp'] = function () OnCleanUp = f_nil end , ['OnClose'] = function () OnClose = f_nil end , ['OnConnected'] = function () OnConnected = f_nil end , ['OnDepoLimit'] = function () OnDepoLimit = f_nil end , ['OnDepoLimitDelete'] = function () OnDepoLimitDelete = f_nil end , ['OnDisconnected'] = function () OnDisconnected = f_nil end , ['OnFirm'] = function () OnFirm = f_nil end , ['OnFuturesClientHolding'] = function () OnFuturesClientHolding = f_nil end , ['OnFuturesLimitChange'] = function () OnFuturesLimitChange = f_nil end , ['OnFuturesLimitDelete'] = function () OnFuturesLimitDelete = f_nil end -- , ['OnInit'] = function () OnInit = f_nil end , ['OnMoneyLimit'] = function () OnMoneyLimit = f_nil end , ['OnMoneyLimitDelete'] = function () OnMoneyLimitDelete = f_nil end , ['OnNegDeal'] = function () OnNegDeal = f_nil end , ['OnNegTrade'] = function () OnNegTrade = f_nil end , ['OnOrder'] = function () OnOrder = f_nil end , ['OnParam'] = function () OnParam = f_nil end , ['OnQuote'] = function () OnQuote = f_nil end -- , ['OnStop'] = function () OnStop = f_nil end , ['OnStopOrder'] = function () OnStopOrder = f_nil end , ['OnTrade'] = function () OnTrade = f_nil end , ['OnTransReply'] = function () OnTransReply = f_nil end } ---------------- local subscribe_tbl = ---- Функции подписки ---- { ['OnAccountBalance'] = function () OnAccountBalance = function (...) push (Queue_QUIK, {'OnAccountBalance', os.time(), {...}} ) end end , ['OnAccountPosition'] = function () OnAccountPosition = function (...) push (Queue_QUIK, {'OnAccountPosition', os.time(), {...}} ) end end , ['OnAllTrade'] = function () OnAllTrade = function (...) push (Queue_QUIK, {'OnAllTrade', os.time(), {...}} ) end end , ['OnCleanUp'] = function () OnCleanUp = function (...) push (Queue_QUIK, {'OnCleanUp', os.time(), {...}} ) end end , ['OnClose'] = function () OnClose = function (...) push (Queue_QUIK, {'OnClose', os.time(), {...}} ) end end , ['OnConnected'] = function () OnConnected = function (...) push (Queue_QUIK, {'OnConnected', os.time(), {...}} ) end end , ['OnDepoLimit'] = function () OnDepoLimit = function (...) push (Queue_QUIK, {'OnDepoLimit', os.time(), {...}} ) end end , ['OnDepoLimitDelete'] = function () OnDepoLimitDelete = function (...) push (Queue_QUIK, {'OnDepoLimitDelete', os.time(), {...}} ) end end , ['OnDisconnected'] = function () OnDisconnected = function (...) push (Queue_QUIK, {'OnDisconnected', os.time(), {...}} ) end end , ['OnFirm'] = function () OnFirm = function (...) push (Queue_QUIK, {'OnFirm', os.time(), {...}} ) end end , ['OnFuturesClientHolding'] = function () OnFuturesClientHolding = function (...) push (Queue_QUIK, {'OnFuturesClientHolding', os.time(), {...}} ) end end , ['OnFuturesLimitChange'] = function () OnFuturesLimitChange = function (...) push (Queue_QUIK, {'OnFuturesLimitChange', os.time(), {...}} ) end end , ['OnFuturesLimitDelete'] = function () OnFuturesLimitDelete = function (...) push (Queue_QUIK, {'OnFuturesLimitDelete', os.time(), {...}} ) end end -- , ['OnInit'] = function () OnInit = function (...) push (Queue_QUIK, {'OnInit', os.time(), {...}} ) end end , ['OnMoneyLimit'] = function () OnMoneyLimit = function (...) push (Queue_QUIK, {'OnMoneyLimit', os.time(), {...}} ) end end , ['OnMoneyLimitDelete'] = function () OnMoneyLimitDelete = function (...) push (Queue_QUIK, {'OnMoneyLimitDelete', os.time(), {...}} ) end end , ['OnNegDeal'] = function () OnNegDeal = function (...) push (Queue_QUIK, {'OnNegDeal', os.time(), {...}} ) end end , ['OnNegTrade'] = function () OnNegTrade = function (...) push (Queue_QUIK, {'OnNegTrade', os.time(), {...}} ) end end , ['OnOrder'] = function () OnOrder = function (...) push (Queue_QUIK, {'OnOrder', os.time(), {...}} ) end end , ['OnParam'] = function () OnParam = function (...) push (Queue_QUIK, {'OnParam', os.time(), {...}} ) end end , ['OnQuote'] = function () OnQuote = function (...) push (Queue_QUIK, {'OnQuote', os.time(), {...}} ) end end -- , ['OnStop'] = function () OnStop = function (...) push (Queue_QUIK, {'OnStop', os.time(), {...}} ) end end , ['OnStopOrder'] = function () OnStopOrder = function (...) push (Queue_QUIK, {'OnStopOrder', os.time(), {...}} ) end end , ['OnTrade'] = function () OnTrade = function (...) push (Queue_QUIK, {'OnTrade', os.time(), {...}} ) end end , ['OnTransReply'] = function () OnTransReply = function (...) push (Queue_QUIK, {'OnTransReply', os.time(), {...}} ) end end } ----- --- Вывод данных о состоянии подписки на события фондового рынка --- local function condition_subscribe () local tbl= {} --- tbl['OnAccountBalance'] = OnAccountBalance ~= f_nil or nil tbl['OnAccountPosition'] = OnAccountPosition ~= f_nil or nil tbl['OnAllTrade'] = OnAllTrade ~= f_nil or nil tbl['OnCleanUp'] = OnCleanUp ~= f_nil or nil tbl['OnClose'] = OnClose ~= f_nil or nil tbl['OnConnected'] = OnConnected ~= f_nil or nil tbl['OnDepoLimit'] = OnDepoLimit ~= f_nil or nil tbl['OnDepoLimitDelete'] = OnDepoLimitDelete ~= f_nil or nil tbl['OnDisconnected'] = OnDisconnected ~= f_nil or nil tbl['OnFirm'] = OnFirm ~= f_nil or nil tbl['OnFuturesClientHolding'] = OnFuturesClientHolding ~= f_nil or nil tbl['OnFuturesLimitChange'] = OnFuturesLimitChange ~= f_nil or nil tbl['OnFuturesLimitDelete'] =OnFuturesLimitDelete ~= f_nil or nil -- tbl['OnInit'] = OnInit ~= f_nil or nil tbl['OnMoneyLimit'] = OnMoneyLimit ~= f_nil or nil tbl['OnMoneyLimitDelete'] = OnMoneyLimitDelete ~= f_nil or nil tbl['OnNegDeal'] = OnNegDeal ~= f_nil or nil tbl['OnNegTrade'] = OnNegTrade ~= f_nil or nil tbl['OnOrder'] = OnOrder ~= f_nil or nil tbl['OnParam'] = OnParam ~= f_nil or nil tbl['OnQuote'] = OnQuote ~= f_nil or nil -- tbl['OnStop'] = OnStop ~= f_nil or nil tbl['OnStopOrder'] = OnStopOrder ~= f_nil or nil tbl['OnTrade'] = OnTrade ~= f_nil or nil tbl['OnTransReply'] = OnTransReply ~= f_nil or nil return tbl end ---------------------------------------------------------------- ---- Обработка событий QUIK ---- ---- local tbl_QUIK_fun --- Для хранения функции обработки событий таблиц QUIK --- local tbl_fun --- Для хранения таблицы функции обработки событий фондового рынка --- local period = 500 -- период счетчика для выдачи сообшений о задержке обработки событий фондового рынка --- local event_counter = 0 -- текущее значение циклов "разгребания" очередей событий --- local event_counter_max = 0 -- максимальное количество событий обработанных за один вызов функции обработки очередей -- local event_counter_mess = 0 -- счетчик для выдачи сообщений -- local read_latency_max = 0 -- максимальная задержка чтения очередей событий (сек.)-- ------------------------------------------------------------------ local tbl_QUIK = {} ---- Общая таблица состояния обработки таблиц QUIK --- ---- Функция обаботки колбеков таблиц QUIK ---- local function callback_tbl_QUIK(...) --- (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2 local par ={...} par = par[1] if tbl_QUIK[par] then -- Запись в очередь событий таблиц QUIK. os.time () - дата_время записи --- push (Queue_QUIK_tbl, {par, os.time(), {...}} ) end end -- Подписка на события таблицы QUIK --- local function subscribe_tbl_QUIK (t_id, f_t) if tbl_QUIK[t_id] then return 1 end if tbl_QUIK_fun == nil and f_t == nil then error ('!!! Ошибка в вызове subscribe_tbl_QUIK. Не задана функция обработки таблиц QUIK' ) end if f_t and type (f_t) ~= 'function' then error ('!!! Ошибка в вызове subscribe_tbl_QUIK. Второй параметр не функция ' ) end if f_t and tbl_QUIK_fun then if f_t ~= tbl_QUIK_fun then error ('!!! Ошибка в вызове subscribe_tbl_QUIK. Функция обработки таблиц QUIK отличается от ранее заданной ') end end ---- tbl_QUIK_fun = tbl_QUIK_fun or f_t if SetTableNotificationCallback ( t_id, callback_tbl_QUIK) == 1 then tbl_QUIK[t_id] = 1 return 0 else message('!!! Ошибка задания колбека для таблицы: ' .. t_id) error('!!! Ошибка задания колбека для таблицы: ' .. t_id) return nil end end -- Отписка от событий таблицы QUIK ---- local function unsubscribe_tbl_QUIK (t_id) -- Отписка от событий таблицы QUIK --- if tbl_QUIK [t_id] then tbl_QUIK [t_id] = nil end if next (tbl_QUIK) == nil then tbl_QUIK_fun = nil end end -- Состояние подписки на события таблицы QUIK ---- local function condition_subscribe_tbl_QUIK () --- Состояние подписки на события таблиц QUIK --- return tbl_QUIK end --------------------------------------------------------------------------------------------------------- -- Подписаться на события фондового рынка -- --- Ключи таблицы - имена событий ---- local function subscribe (tbl) if tbl_fun == nil then error ('!!! Ошибка в вызове subscribe. Следует установить таблицу функций обработки событий фондового ( в функции install_event_handling_functions ') end local err ={}, f for k, v in next, tbl do f = subscribe_tbl [k] if f then f() else err[#err +1] = k end end return err end -- Отписаться от событий фондового рынка -- --- Ключи таблицы - имена событий ---- local function unsubscribe (tbl) local err ={}, f for k, v in next, tbl do f = unsubscribe_tbl [k] if f then f() else err[#err +1] = k end end return err end ---- --- Установить функции обработки событий ---- local function install_event_handling_functions(tbl_f, period_f) if type (tbl_f) ~= 'table' then error ('!!! Ошибка в вызове install_event_handling_functions. Параметр не таблица ' ) end period = period_f or 500 ---- по умолчанию 500 -- tbl_fun = tbl_f event_counter = 0 event_counter_mess = 0 event_counter_max = 0 read_latency_max = 0 --- Подписка на события фондового рынка --- --- ! Ключи таблицы - имена событий ---- unsubscribe (unsubscribe_tbl) ---- Отписаться от всех событий subscribe (tbl_f) --- Подписка на события всей таблицы tbl_fun (для записей с функциями обработки событий) end ---- Функция обработки всех событий QUIK: function handle_events(lim) ----- -- Параметр lim (по умолчанию равен 1000000) определяет максимальное количестко событий, обрабатаваемых за один вызов функции -- --- Если очереди событий пусты, то функция завершается. -- Результат (их три): 1) количество обработанных событий; 2) максимальное количество событий за один вызов функции; -- 3) максимальная задержка (в сек.) между записью и чтением событий local function handle_events(lim) lim = lim or 1000000 local f_ms --- Чтение очередей событий ----- local ms_tbl = pop (Queue_QUIK_tbl) local ms, first_q = pop (Queue_QUIK) local os_time, os_time_d repeat if ( not (ms_tbl or ms) ) then break end --- ### 2-ой вариант (! из-за ошибки в Lua 5.3 до 15.10.21). Нет событий. --- -- while (ms_tbl or ms ) do --- ### 1-ый вариант. Есть события --- os_time = os.time() -- os.time() event_counter = event_counter + 1 event_counter_mess = event_counter_mess + 1 if event_counter_mess >= period then event_counter_mess = 0 message ( '!! Длительный цикл обработки событий >= ' .. event_counter ) end --- Обработка событий таблиц QUIK --- if ms_tbl then os_time_d = os_time - ms_tbl [2] if read_latency_max < os_time_d then read_latency_max = os_time_d end if tbl_QUIK_fun then tbl_QUIK_fun (table.unpack (ms_tbl[3])) end -- Запуск функции обработки событий таблиц QUIK --- end ----------- События фондового рынка --- if type (tbl_fun) == 'table' then if ms then os_time_d = os_time - ms [2] if read_latency_max < os_time_d then read_latency_max = os_time_d end f_ms = tbl_fun[ms[1]] if f_ms then f_ms (table.unpack (ms[3])) end -- Запуск функции обработки событий фондового рынка --- end end if event_counter >= lim then break end --- Чтение очередей событий ----- ms_tbl = pop (Queue_QUIK_tbl) --Queue_QUIK_tbl: pop() -- ms_tbl = {t_id, os.time (), {NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2}} ms, first_q = pop (Queue_QUIK) --Queue_QUIK: pop() -- end --- ### 1-ый вариант. --- until false --- ### 2-ой вариант. ---- --- Ведение счетчиков циклов обработки событий ---- if event_counter_max < event_counter then event_counter_max = event_counter end event_counter_rt = event_counter event_counter = 0 event_counter_mess = 0 read_latency_max = 0 --------------------------------------------------------------------------------------- return event_counter_rt, event_counter_max, read_latency_max end ----------------------------------------------- return { sizeQueue_evn_QUIK = sizeQueue_evn_QUIK -- Текущий размер очереди событий рынка --- , sizeQueue_evn_QUIK_tbl = sizeQueue_evn_QUIK_tbl -- Текущий размер очереди событий таблиц QUIK --- , subscribe = subscribe -- Подписаться на события фондового рынка -- , unsubscribe = unsubscribe -- Отписаться от событий фондового рынка -- , condition_subscribe = condition_subscribe -- Сотояние подписки на события фондового рынка -- , subscribe_tbl_QUIK = subscribe_tbl_QUIK -- Подписаться на события таблиц QUIK -- , unsubscribe_tbl_QUIK = unsubscribe_tbl_QUIK -- Отписаться от событий таблиц QUIK -- , condition_subscribe_tbl_QUIK = condition_subscribe_tbl_QUIK -- Сотояние подписки на таблицы QUIK -- , install_event_handling_functions = install_event_handling_functions -- Установить функции обработки событий ---- , handle_events = handle_events -- Функция обработки всех событий QUIK ----- } --- -------------------------------------- |
============================================================================
Скрипт-пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | -- Шаблон использования модуля even_handling_module local even_handling_module = require('even_handling_module') -- Подключение модуля обработки событий QUIK --- --- local dump_tbl = even_handling_module.dump_tbl local subscribe = even_handling_module.subscribe local unsubscribe = even_handling_module.unsubscribe local condition_subscribe = even_handling_module.condition_subscribe local subscribe_tbl_QUIK = even_handling_module.subscribe_tbl_QUIK local unsubscribe_tbl_QUIK = even_handling_module.unsubscribe_tbl_QUIK local condition_subscribe_tbl_QUIK = even_handling_module.condition_subscribe_tbl_QUIK local sizeQueue_evn_QUIK = even_handling_module.sizeQueue_evn_QUIK local sizeQueue_evn_QUIK_tbl = even_handling_module.sizeQueue_evn_QUIK_tbl local install_event_handling_functions = even_handling_module.install_event_handling_functions local handle_events = even_handling_module.handle_events IsRun = true function main() ---------- --- Работа с событиями таблиц QUIK ----- ----- Функция обработки событий таблиц QUIK ----- -- FUNCTION (NUMBER t_id, NUMBER msg, NUMBER par1, NUMBER par2) --- -- t_id – идентификатор таблицы; msg – код сообщения; par1 и par2 – значения параметров определяются типом сообщения msg ---- local function tbl_QUIK_fun (t_id, msg, par1, par2) message ( 'tbl_QUIK_fun (t_id: ' .. t_id .. ', msg: ' .. msg .. ', par1: ' .. tostring(par1) .. ', par2: ' .. tostring(par2) ) end ----- TableQUIK=AllocTable() -- Создание таблицы QUIK -- AddColumn(TableQUIK, 1, "Легенда", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK, 2, "Год", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK, 3, "Месяц", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK, 4, "День", true, QTABLE_STRING_TYPE, 6) CreateWindow(TableQUIK) for i=1,10 do -- Цикл заполняет ячейки InsertRow(TableQUIK,-1) for j=1,4 do SetCell(TableQUIK, i, j, tostring(i).."-"..tostring(j)) end end TableQUIK1=AllocTable() -- Создание таблицы QUIK -- AddColumn(TableQUIK1, 1, "Легенда", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK1, 2, "Год", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK1, 3, "Месяц", true, QTABLE_STRING_TYPE, 6) AddColumn(TableQUIK1, 4, "День", true, QTABLE_STRING_TYPE, 6) CreateWindow(TableQUIK1) for i=1,10 do -- Цикл заполняет ячейки InsertRow(TableQUIK1,-1) for j=1,4 do SetCell(TableQUIK1, i, j, tostring(i).."-"..tostring(j)) end end --- subscribe_tbl_QUIK (TableQUIK, tbl_QUIK_fun) --- Подписка на события TableQUIK subscribe_tbl_QUIK (TableQUIK1, tbl_QUIK_fun) --- Подписка на события TableQUIK1 -- unsubscribe_tbl_QUIK (TableQUIK) --- Отдписка от событий TableQUIK -- unsubscribe_tbl_QUIK (TableQUIK1) --- Отдписка от событий TableQUIK --- Конец Работа с событиями таблиц QUIK ----- --- Работа с событиями фондового рынка ---- --- Функции обработки событий фондового рынка --- local function F_OnParam(p1, p2) -- message ( 'Тикер: ' .. tostring(p2)) end -- local function F_OnAllTrade(t) message ( 'F_OnAllTrade: ' ) end local function F_OnConnected(t) message ( 'F_OnConnected: ' .. tostring (t) ) end ---- и т.д ---- ------------------------------------------------------------------- ------ !!! Для перехода на обработку событий в очередях, в скрипте достаточно к именам функций колбеков добавить префикс 'F_' --- Таблица функций обработки событий фондового рынка (параметры как в соответствующих колбеках) ----- local tbl_fun = { ['OnAccountBalance'] = F_OnAccountBalance --- Имя функции обработки события OnAccountBalance -- , ['OnAccountPosition'] = F_OnAccountPosition -- и т.д. --- , ['OnAllTrade'] = F_OnAllTrade , ['OnCleanUp'] = F_OnCleanUp , ['OnClose'] = F_OnClose , ['OnConnected'] = F_OnConnected , ['OnDepoLimit'] = F_OnDepoLimit , ['OnDepoLimitDelete'] = F_OnDepoLimitDelete , ['OnDisconnected'] = F_OnDisconnected , ['OnFirm'] = F_OnFirm , ['OnFuturesClientHolding'] = F_OnFuturesClientHolding , ['OnFuturesLimitChange'] = F_OnFuturesLimitChange , ['OnFuturesLimitDelete'] = F_OnFuturesLimitDelete -- , ['OnInit'] = F_OnInit , ['OnMoneyLimit'] = F_OnMoneyLimit , ['OnMoneyLimitDelete'] = F_OnMoneyLimitDelete , ['OnNegDeal'] = F_OnNegDeal , ['OnNegTrade'] = F_OnNegTrade , ['OnOrder'] = F_OnOrder , ['OnParam'] = F_OnParam , ['OnQuote'] = F_OnQuote -- , ['OnStop'] = F_OnStop , ['OnStopOrder'] = F_OnStopOrder , ['OnTrade'] = F_OnTrade , ['OnTransReply'] = F_OnTransReply } --- Второй параметр - период счетчика для выдачи сообшений о задержке обработки событий фондового рынка -- install_event_handling_functions (tbl_fun, 100) -- Установка таблицы функций обработки событий фондового рынка --- ---- for i, v in next, condition_subscribe() do message( 'Скрипт подписан на событие фондового рынка ' .. i ) end --- Работа с событиями фондового рынка ---- local event_counter local T_OS_high_sleep local T_sleep = 30 ------------------- while IsRun do ---- Функция обработки всех событий QUIK: function handle_events(lim) ----- -- Параметр lim (по умолчанию равен 1000000) определяет максимальное количестко событий, обрабатаваемых за один вызов функции -- --- Если очереди событий пусты, то функция завершается. -- Результат (их три): 1) количество обработанных событий в вызове функции; 2) максимальное количество обработанных событий за один вызов функции; -- 3) максимальная задержка (в сек.) между записью и чтением событий (в вызове функции). event_counter, event_counter_max, read_latency_max = handle_events() ---- Обработка всех событий QUIK ---- if event_counter > 0 then -- В очередях были события ---- -- message ( 'event_counter: ' .. event_counter .. '; read_latency_max: ' .. read_latency_max ) end ---- Обработка в main остального ----- ---- Конец Обработка в main остального ----- sleep(20) end ------------------ end function OnStop() IsRun = false DestroyTable(TableQUIK) DestroyTable(TableQUIK1) return 10000 -- !! По истечении этого интервала времени (в млсек.), данного скрипту на завершение работы, функция main() завершается принудительно. -- При этом возможна потеря системных ресурсов. ! Если функция не выдает значение, то по умолчанию оно 5000 (5 сек.) end |