В версии QUIK 12.2.1.2 (а, похоже, и в более ранних) при запуске любого коллбека отключается сборка мусора (collectgarbage('stop')), а после его отработки включается (collectgarbage('restart')). В общем, решение разумное, повышающее надежность, но не сохраняющее состояние сборки мусора скрипта. Это неправильно. Надо: 1) сохранять состояние сборки мусора скрипта перед выполнением коллбека; 2) отключать сборку сборку мусора; 3) выполнять коллбек; 4) восстанавливать состояние сборки мусора.
При попытке подключиться (с полученным логином и паролем) к демоверсии (Quik_Junior_v11.4.1) выдается сообщение: "Срок лицензии истек". В чем причина? Почему? Я лишенец ?
1. Инструкция приведена в комментариях теста модуля.
2. Код теста:
Код
-- Инструкция
-- 1. Скачать папку LuaIndicators (Примеры функций расчета индикаторов терминала QUIK на языке Lua) с сайта
-- https://arqatech.com/ru/support/files/ и переслать в папку расположения info.exe.
-- 2. Модуль подключения индикаторов(под именем mod_IND.lua) переслать в папку расположения info.exe.
-- 3. Запустить тест test_IND.
-- ----
-- P.S.
-- 1. Учитывать, что при расчете индикаторов первые значения (1 .... Период расчета индикатора - 1)
-- обычно nil.
-- 2. Результат расчета индикатора может иметь несколько значений и это определяется функцией OnCalculate
-- кода используемого индикатора папки LuaIndicators.
-- 3. В модуле mod_IND.lua представлены три примера объявления заголовочных функций описаний параметров
-- подключаемых индикаторов. Параметры такой функции это список полей из таблицы Settings соответствующего
-- индикатора папки LuaIndicators, для которых требуется задать значения, определяющие поведение создаваемого
-- замыкания.
---------------------------------------------------------------------
timeout = 300
is_run = true
function main()
-- GetDataSource подключается к графику --
local function GetDataSource(class_code, sec_code, timeframe)
local ds, Error = CreateDataSource(class_code, sec_code, timeframe)
-- Ждет 10 сек., пока данные будут получены с сервера --
for i = 1, 1000 do if not ((Error == "" or Error == nil) and ds:Size() == 0) then break end; sleep(10) end
if Error ~= "" and Error ~= nil then
message(debug.getinfo(1).currentline..': Ошибка подключения к графику: '..Error)
return nil
end
return ds
end
-------------------------------- Тест индикаторов -------------------------------------------------
local INDICATORS = require('mod_IND')
---------------------------------------------------------------------------------------------------
-- Подключение к источнику данных (графику)
local DS = GetDataSource(getClassInfo('QJSIM') and 'QJSIM' or 'TQBR', 'SBER', INTERVAL_M1)
if not DS then return end -- не удалось подключиться к источнику данных ---
local size = DS:Size()
message('size = ' .. size)
-------------------------------------------------------------------------------------------------
-- <Функция создания индикаторов> (<Параметры индикатора>)
-- Результат: функция-замыкание расчета индикатора.
------
-- Вызов полученного замыкания:
-- <Функция-замыкание>(<Очередное значение для расчета индикатора>)
-- Результат (возможно несколько значений, определяемых видом индикатора): значения индикатора,
-- определяемые параметрами создания замыкания на основе кода индикатора в папке ...Lua\\LuaIndicators.
-- !! В кодах индикаторов результат определяется функцией OnCalculate.
---------
-- ! Для сброса индикатора-замыкания в начальное состояние, его надо пересоздать.
---------------------------------------------------------------------------------------------------
local AC_IND1 = INDICATORS.AC(
3, -- Период короткой скользящей
5, -- Период длинной скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local AC_IND2 = INDICATORS.AC( -- return value
5, -- Период короткой скользящей
9, -- Период длинной скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local MA_IND1 = INDICATORS.MA( -- return value
5, -- Период скользящей
'SMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local MA_IND2 = INDICATORS.ADX( -- return {['ADX'], ['+DI'], ['-DI']}
7, -- Период короткой скользящей
'EMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
-- Использование индикатора ---
for i = 1, size do
AC_IND1(DS:C(i))
end
for i = 1, size > 15 and 15 or size do
AC_IND2(DS:C(i))
end
for i = 1, size > 15 and 15 or size do
local tbl = {MA_IND1(DS:C(i))}
message('MA_IND1 : ' .. tostring(tbl[2]))
end
for i = 1, size > 100 and 100 or size do
MA_IND2(DS:H(i))
end
---- Сброс индикатора (запрос нового замыкания) ---
MA_IND2 = INDICATORS.MA( -- return value
100, -- Период скользящей
'EMA' -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
-- Тест индикаторов Конец ----------------------------------------
while is_run do
sleep(timeout)
end
end
function OnStop()
is_run = false
return 10000 -- (млс.) ожидание завершения потока main прежде чем принудительное его завершение ---
end
------------------------------------------------------------------------------------------------ 2. Код модуля:
Код
--- Модуль подключения индикаторов папки LuaIndicators с сайта ARQA (https://arqatech.com/ru/support/files/):
-- Примеры функций расчета индикаторов терминала QUIK на языке Lua.
--------------------------------------------
local IND = {}
---------------------------------------------------------------------------------------------------
--- КОНСТАНТЫ -------------------------------------------------------------------------------------
local SMA,MMA,EMA,WMA,SMMA,VMA = 'SMA','MMA','EMA','WMA','SMMA','VMA'
local OPEN,HIGH,LOW,CLOSE,VOLUME,MEDIAN,TYPICAL,WEIGHTED,DIFFERENCE,ANY = 'O','H','L','C','V','M','T','W','D','A'
---------------------------------------------------------------------------------------------------
---------------- Подключение к роботу индикаторы из папки LuaIndicators (с файлами кодов индикаторов) ------------
local pach_IND = getWorkingFolder() .. '\\LuaIndicators' -- Путь к кодам индикаторов --
-- ! Код индикатора из папки LuaIndicators помещаются в исходном виде внутрь оболочки-фабрики (на Lua),
-- обеспечивающей создание индикаторов-замыканий с параметрами заданными при вызове такой фабрики.
-- ! Пролог: начало функции-фабрики: ------
local Prologue = [[ -- создание окружения фабрики ---
local PRM = {...} ---
PRM = PRM[1] -- Таблица параметров индикатора ---
------------------------------------------------------
-- Таблица окружения создаваемого замыкания индикатора --
-- Начальная инициализация тиблицы-окружения замыканий-индикаторо (объектами, используемыми в вычислении индикаторов)
-- выполняется из ! текущего окружения фабрики. Существенно только то, что эти объекты должны существовать.
local ENV_IND = {
-- Объекты из _ENV, необходимые для расчета индикаторов --
tonumber = tonumber
, tostring = tostring
, type = type
, select = select
, table = table
, pack = pack or table.pack --
, unpack = unpack or table.unpack --
, string = string
, math = math
, package = package
, require = require
, debug = debug
, next = next
, os = os
, io = io
, RGB = RGB
, message = message
, getWorkingFolder = getWorkingFolder
, getScriptPath = getScriptPath
-- !! Переменнпой ENV_begin таблиц-окружения замыканий-индикаторов будет присвоено окружение-родитель (с чего все началось)
, ENV_begin = type(ENV_begin) == 'table' and ENV_begin or _ENV -- при первом формировании таблицы-окружения ENV_begin = _ENV
}
local ENV_ENV = _ENV -- Сохранения окружения --
_ENV = ENV_IND -- Переключение окружения перед инициализацией замыкания индикатора ---
]]
-- -- ! Эпилог: в конце функции-фабрики: ------
local Epilogue = [[
---- Начало эпилога ---
if not PRM then
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: не заданы параметры индикатора ' .. tostring(Settings.Name), 3)
return
end
---
for k, v in next, PRM do -- присвоение параметров индикатора --
if not Settings[k] then
-- #### Выдача сообщения об ошибки ---
message(debug.getinfo(1).currentline .. ' ! ОШИБКА в параметрах индикатора ' .. tostring(Settings.Name), 3)
end
Settings[k] = v
end
Init() -- Инициализация фабрики параметрами индикатора ---
-- Перегрузка function GetValueEX ---
function GetValueEX(I,VT, DS)
return ds_IND
end
-- Перегрузка function CandleExist(I,ds) -- проверка существования свечи ---
function CandleExist(I,ds)
return true
end
local Index_IND = 0 -- Внутренний счетчик обращения к индикатору (внешняя локальная переменная замыкания)---
------
_ENV = ENV_ENV -- Восстановление окружения ---
return -- возврат замыкания расчета очередного значения шндикатора --
function (DS) -- функция-замыкание для вычисления индикатора --
_ENV = ENV_IND -- ENV_IND - переменная хранения окружения, созданного для замыкания индикатора
ds_IND = DS -- Передача значения в расчет индикатора ----
Index_IND = Index_IND + 1
return OnCalculate(Index_IND)
end
]]
local Indicator_factories = {} -- таблица функций-фабрик создания индикаторов {<Имя индикатора> = <Функция>} --
----
-- Функция создает фабрики индикаторов на основе кодов из папки LuaIndicators --
-- Результат функция-замыкание индикатора: F_IND ---
-- Вызов функции: F_IND(val)
-- где val - очередное значение источника индикатора --
-- а результат функции: значения индикатора (их может быть несколько, в зависимости от вида индикатора)
local function Get_Indicator(Indic, Settings)
local func = Indicator_factories[Indic]
if not func then -- Ищется код индикатора и создается его фабрика ---
-- Создание фабрики индикатора (поиск кода индикатора, добавление пролога и эпилога,
-- компиляция и добавление в Indicator_factories)
local folder_of = pach_IND .. '\\' .. Indic .. '.lua'
local kod_IND
--- Чтениие источника ---
local kodZ, io_open, err = pcall( io.open, folder_of, 'r')
if io_open then
kod_IND = io_open:read('*a')
assert(io_open:close())
else
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: нет кода индикатора ' .. tostring(Indic), 3)
return
end
kodZ, func, err = pcall(load, Prologue .. kod_IND .. Epilogue)
if not func then
message(debug.getinfo(1).currentline .. ' ! ОШИБКА: трансляции код индикатора ' .. tostring(Indic) .. '. Подробности: ' .. tostring(err), 3)
return
end
---
Indicator_factories[Indic] = func --
end
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова данной функции ---
return func(Settings) -- результат функция-замыкание индикатора ---
end
---------------------------------------------------------------------------------------------------
-- <Функция создания индикаторов> (<Параметры индикатора>)
-- Результат: функция-замыкание расчета индикатора.
------
-- Вызов полученного замыкания:
-- <Функция-замыкание>(<Очередное значение для расчета индикатора>)
-- Результат (возможно несколько значений, определяемых видом индикатора): значения индикатора,
-- определяемые параметрами создания замыкания на основе кода индикатора в папке ...Lua\\LuaIndicators.
-- !! В кодах индикаторов результат определяется функцией OnCalculate.
-----
-- ! Для сброса индикатора-замыкания в начальное состояние, его надо пересоздать.
---------------------------------------------------------------------------------------------------
--------------- Далее представлены три примера объявления заголовочных функций описаний параметров
-- подключаемых индикаторов. Параметры такой функции это список полей из таблицы Settings соответствующего
-- индикатора папки LuaIndicators, для которых требуется задать значения, определяющие поведение создаваемого
-- замыкания. Результат: значения функции OnCalculate (их может быть несколько) оответствующего индикатора.
-- AC (Accelerator/Decelerator Oscillator)
IND.AC = function(
SHORT_Period, -- Период короткой скользящей
LONG_Period, -- Период длинной скользящей
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
SHORT_Period = SHORT_Period,
LONG_Period = LONG_Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции--
return Get_Indicator('AC', Settings)
end
--Average Directional Movement Index ("ADX")
IND.ADX = function(
Period, -- Период
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
Period = Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции-
return Get_Indicator('ADX', Settings)
end
--Moving Average ("MA") ( 50000 циклов, Period = 100, Metod = SMA: 340 млс.)
IND.MA = function(
Period, -- Период
Metod -- Метод расчета скользящих (SMA, MMA, EMA, WMA, SMMA, VMA)
)
local Settings = {
Period = Period,
Metod = Metod
}
-- Возвращает экземпляр функции индикатора с состоянием, определяемым параметрами вызова текущей функции-
return Get_Indicator('MA', Settings)
end
-- И так далее (по образу и подобию уже представленных) ---
return IND
В Новосибирске, когда то была хорошая школа IT-шников. И что-то, наверное, от нее осталось. Я надеюсь, что архитектором QUIK в текущий момент является один из выпускников этой школы. В QUIK все равно будут вноситься изменения (чтобы оставаться «наплаву»). И мне видится, что улучшить QUIK, помимо исправления существующих, неизбежных ошибок, можно внеся в него следующие изменения/дополнения: 1) В текущей версии в одном основном потоке обслуживаются: - запуск всех Lua-скриптов пользователя; - запуск коллбеков всех Lua-скриптов пользователя; -- обработка всех коллбеков таблиц QUIK (это не таблицы Lua); -- обработка всех индикаторов пользователя. Притом, что в текущий момент у подавляющего количества ПК много ядер ЦП, написанное выше явный перебор. Мне, представляется, что нет проблем перечисленное выше обрабатывать в отдельных потоках. Иначе, это ограничение пользователя в использовании возможностей его ПК. 2) Интерфейс взаимодействия QUIK c Lua-скриптом пользователя, реализованный в виде коллбекков, предполагает многопоточный режим использования Lua,. порождающий неприятные проблемы параллельного программирования (для решения которых сами же разработчики предлагают использовать потокобезопасную очередь между коллбеками и потоком main). Мне представляется, что имеет смысл вместо коллбеков использовать активную очередь событий, При этом не требуется использовать Lua в многопоточном, редко используемом и не очень стабильном режиме. При этом не будет проблем с подключением новых версий Lua. Более того, скрипты пользователя будут выполняться несколько быстрее из-за отсутствия синхронизации, требуемой в многопоточном варианте использования Lua. 3) В QUIK реализована функциональность просмотра графика котировок бумаг QUIK. Но отсутствует возможность просмотра котировок бумаг, сохраненных во внешних файлах. С учетом существующей функциональности QUIK, как мне представляется, реализация этой возможности не потребует больших усилий.
Средства разработки многопоточных скриптов в QUIK., OS_Quesha, свидетельство регистрации в Роспатенте № RU 2020612905. Бесплатная для некоммерческого использования.
Ссылка на коды и документацию OS_Quesha (на текущий момент для версий 7<= QUIK < 8.5 и >= 8.11 Lua 5.3.5): https://cloud.mail.ru/public/2zn2/2tZgedUu4 --------------------------------------- Программа представляет собой специализированную операционную систему реального времени, работающую в среде программного комплекса QUIK. Она предназначена для разработки многопоточных роботов торговли ценными бумагами в QUIK. Программа реализует в скриптовом языке программирования QLua параллелизм выполнения его функций, взаимодействующих между собой, в рамках одной его инсталляции, обеспечивая использование многопроцессорности вычислительных систем. Из программы доступен весь программный интерфейс QUIK, существующий для скриптов QLua. --------------------- Общая схема обработки данных в OS_Quesha следуюшая. Циклические функции, запускаемые в отдельных потоках (аналогичные функции main в QLua) входят в свой основной цикл обработки. Но вместо sleep используется API-функция OS_Quesha ожидания либо истечения интервала времени (паузы циклической функции), либо появления данных во входных очередях таких функций. Взаимодействие циклических функций между собой после запуска на выполнение в потоках, сводится к чтению своих очередей и записи своих данных в чужие очереди. Вся необходимая синхронизация параллелизма выполнения происходит внутри специальных функций чтения/записи очередей. Эти очереди, при записи в них данных, выдают сигналы, активирующие те потоки, для которых они являются входными. Дополнительно, предоставляются средства синхронизации, которые могут потребоваться при использовании модифицируемых общих данных потоков, но, по возможности, этого лучше избегать. В этой схеме активация потоков (их динамика) определяется движением данных в их очередях, а <паузы циклических функций> * <коэффициент, заданный в настройках> являются параметрами контроля блокировок и зацикливания этих циклических функций. Описанная выше схема обработки данных, характерная для многих систем реального времени, к которым относятся и роботы фондового рынка, обеспечивает, наряду с распараллеливанием вычислений, реализацию удобной (для разработчиков) модели таких вычислений. Причем, удобство этой модели вычислений, во многих случаях конкретных применений, является более существенным фактором, чем, собственно, параллелизм вычислений. ----- В скрипте-шаблоне создания роботов с использованием OS_Quesha, в виде исходника "TS_QUIK.lua", входящего в состав документации OS_Quesha, запускается 16 потоков, часть из которых являются служебными (реализация диалога с пользователем, генерация таймерных событий, ведение логов, контроль состояния системы, обработка фоновых заданий и т.д.). Остальные потоки пользовательские (их количество определяется схемой обработки данных пользователя, заданной в шаблоне, в табличной форме). Шаблон демонстрирует использование средств OS_Quesha при создании робота. Конкретно, в шаблоне реализовано (в отдельных потоках): 1) схема обработки колбеков в виде очередей событий QUIK, минимизирующих влияние последующей обработки событий на основной поток запуска скриптов и генерации событий QUIK; 2) сохранение истории одноминутных и пятиминутных котировок ценных бумаг в базах sqlite; 3) оперативное сохранение текущих котировок 22-ух (по 18 параметрам) торгуемых бумаг в циклических буферах с задержкой < 1 млсек относительно момента возникновения событий OnParam; 4) выполнение заданий по расписанию; 5) тестовое взаимодействие OS_Quesha с внешним процессом (Robot_KIT.exe) по дуплексному каналу передачи/получения сообщений с интенсивностью 1500 сообщений в секунду с задержкой между их приемом и передачей менее 5 млсек; 6) несколько тестовых циклических функций - примеров реализации таких функций.
Дополнительные ресурсы ЦП, потребляемые в QUIK при запуске шаблона, менее 1 % (более детальное описание потребляемых при этом вычислительных ресурсов приведено в инструкции OS_Quesha.pdf, входящей в состав документации). -------------------------------------------------------------------------
Основные функции OS_Quesha. 1. Организация настраиваемой многопоточной обработки данных: - создание потоков для выполнения QLua-функций на основе описания схемы обработки данных в табличной форме; - реализация таймерных событий (с разрешением в 2 млсек); - контроль блокировок и зацикливания в потоках, утечки оперативной памяти, а также состояния очередей взаимодействия потоков/псевдопотоков. 2. Создание настраиваемого диалога с пользователем. Пользователь имеет возможность добавлять в форму диалога свои меню. 3. Ведения журналов OS_Quesha (диалога и отладки) с милисекундным разрешением. 4. Запуск на выполнения Lua-функций в фоновом режиме в отдельных потоках. 5. Работа с контрольными точками (для продолжения работы с прерванного, по любой причине, места). 6. Обеспечение интерфейса ( в виде шаблона исходников на C++) с dll для подключения к системе функций, реализуемых в среде C++. 7. Ведение истории котировок (одноминутных и пятиминутных) в базах SQLite. 8. Ведение текущих дневных котировок в векторах оперативной памяти. 9. Эффективная схема обработки событий QUIK в виде циклических потокобезопасных очередей получения данных колбеков (реализованных без синхронизации). 10. Обеспечение интерфейса реализации торговых индикаторов на основе текущих котировок. 11. Обеспечение виртуальной торговли ценными бумагами. 12. Описание и реализация плана торгов. 13. Обеспечение отладки разрабатываемых параллельных программ и их функций. 14. Обеспечение интерфейса взаимодействия ( в виде шаблонов исходников) с приложениями разрабатываемыми средствами C#, vb и запускаемыми (с целью изоляции от QUIK) в отдельных процессах. 15. Обеспечение парсинга сайтов для информационной поддержки торговли. Документация. Основная документация представлена в виде исходника скрипта-шаблона "TS_QUIK.lua", в котором имеются подробные комментарии по использованию средств OS_Quesha при реализации, представленной в этом шаблоне некоторой обобщенной схемы обработки (в том числе колбеков). Этот шаблон может служить основой для создания конкретных торговых роботов. Кроме того существует инструкция OS_Quesha.pdf, которая может быть вызвана и из диалога системы: <Система> -> <Справка> либо просмотрена в папке C:\OS_Quesha\OS_Quesha_files. ----- Коды. Исполняемые коды представлены в виде исходника TS_QUIK.lua (общего для всех поддерживаемых версий QUIK) и оттранслированных кодов, соответствующих версиям QUIK. Общий объем исполняемых кодов OS_Quesha для любой, поддерживаемой версии QUIK менее 5 мб. ----- Установка программы сводится к распаковке ее файлов, копированию полученной папки на диск C, а также добавлению скрипта TS_QUIK.lua в меню QUIK «Доступные скрипты». После установки можно запускать скрипт TS_QUIK.lua. Появится диалоговая форма программы с разнообразными меню. При первом запуске TS_QUIK.lua в папку с info.exe копируются пакеты из папки ….\Файлы папки QUIK, соответствующии используемой версии QUIK. Все это описано в прилагаемой инструкции по установке и запуску OS_Quesha. ----- Настройки программы. Настройки OS_Quesha на конкретное использование представлены в виде: 1) глобальных переменных, хранящихся в sqlite-базе; 2) локальных определений объектов системы, описанных в тексте скрипта, в основном, в виде таблиц.
===============================================
Если у кого-то будут вопросы, замечания или предложения, то я постараюсь как-то на них отвечать. Наверное, ответы на некоторые вопросы можно найти и в прилагаемой к программе документации. --------------------------------------------- Превентивно отвечу на три вопроса, которые, по-моему, скорее всего, могут возникнуть при чтении данного комментария у многих.
1. О каком параллелизме можно говорить, если в QLua версий QUIK > 8.4 (! в отличие от младших, по номеру, версий) VM-Lua не реентерабельна, а является разделяемым, синхронизируемым ресурсом? Ответ (относится к QLua 5.3.5 версии QUIK >= 8.5). Если в коде скрипта полностью исключить обращение к C-функциям (в том числе к sleep), то о параллелизме можно было бы забыть. Но так как C-функции в любом скрипте есть (хотя бы из-за присутствия sleep) и реентерабельны, то они могут выполняться в отдельных потоках параллельно между собой и с VM-Lua, обслуживающими (в режиме разделения) Lua-коды скрипта. С учетом выше сказанного «тяжелые» вычисления могут быть, если это требуется, без особых проблем реализованы на C/C++, и они могут выполняться параллельно. При этом надо учитывать, что все C-API функции Lua при своем вызове переходят (с последующим возвратом в предыдущий режим), всегда в режим VM-Lua, в том числе, и при использовании их в C-функциях. По сути, в OS_Quesha обеспечивает следующую схему обработки данных. В нескольких потоках исполняются функции, в которых могут быть чередующиеся фрагменты C-кодов и Luа-кодов. И только при исполнении фрагментов Luа-кодов идет обращение к VM-Lua с блокировкой, как к разделяемому ресурсу. В остальных случаях коды могут выполняться параллельно. Для удобства реализации функций на C/C++ в составе OS_Quesha есть С- пакет QluaUser.dll, c его исходниками. Исходя из всего вышесказанного, общая стратегия построения многопоточного скрипта при использовании OS_Quesha следующая. Функция main оперативно поддерживает интерфейс c QUIK, раздавая тяжелые вычисления в другие потоки, и это демонстрируется в шаблоне TS_QUIK.lua. --------------- 2. Кому может пригодиться эта программа? И какие ее особенности, которые могут быть полезны разработчикам роботов в первую очередь? Ответ. 2.1 OS_Quesha является набором инструментов для разработки роботов в QUIK и одновременно средой их функционирования. Для ее использования, как и любого инструмента, требуется ознакомиться с инструкцией по ее применению. Исходник шаблона, сильно упрощает ее применение, но все равно требуется какое-то время на ее изучение. Поэтому, если ваш робот простой и не требует возможности, предоставляемых OS_Quesha, то, скорее всего, его проще создать в виде обычного QLua-скрипта. 2.2 Основные особенности программы, которые могут быть интересны разработчикам роботов, следующие: 1) полная инкапсуляция параллелизма функционирования потоков в API OS_Quesha, обеспечивающих эффективность (реализована специально разработанная схема синхронизации), корректность синхронизации и безопасность взаимодействия функций, выполняемых в разных потоках; 2) настаиваемый диалог пользователя с роботом; 3) встроенный контроль времени выполнения функций роботов, блокировок, зацикливаний в потоках, утечки оперативной памяти, а также состояния очередей взаимодействия потоков. 4) встроенные средства отладки межпотокового взаимодействия, а также разрабатываемых функций; при этом обеспечивается возможности: - оперативного настраиваемого фильтрующего вывода данных из любых очередей взаимодействия потоков в журнал отладки; - оперативной печати любых глобальных переменных работающего робота (в том числе таблиц произвольной вложенности); - оперативного запуска скриптов, в работающей системе с доступом из них к ее среде исполнения, обеспечивающего удобство отладки фрагментов разрабатываемого робота; - централизованной обработки возникающих ошибок; 5) наличие средств реализации контрольных точек, с которых может быть продолжено функционирование робота после его перезапуска по любой причине; 6) раздельное ведение журнала диалога и журнала отладки с записью сообщений с миллисекундным разрешением; 7) реализация схемы обработки колбеков, в которой после записи параметров колбека во входную очередь функции main, ей сразу выдается сигнал на обработку колбека; 8) низкое потребление ресурсов на собственное функционирование OS_Quesha (подробности в статье, на которую есть ссылка в начале комментария). --------------- 3. Насколько стабильна OS_Quesha? Ответ. Одним из объективных показателей стабильности (надежности) любой программы является длительность ее эксплуатации без проявления ошибок, после устранения очередной, обнаруженной в ней ошибки. Для версий QUIK < 8.5 в ядре программы (реализованном на C++), работающем круглые сутки в различных режимах, и являющимся самой сложной частью OS_Quesha, исправление, устраняющее последнюю по времени, обнаруженную в нем ошибку, было выполнено в мае 2019 года. Кроме того в QUIK версии 8.4 проведены тестовые, стрессовые прогоны программы, в которых она без перезапуска работала месяцами. Технические подробности проведения тестовых прогонов описаны в инструкции OS_Quesha.pdf. Для версии QUIK 8.11 Lua 5.3.5 (ядро OS_Quesha не менялось, а только перетранслировалось из-за изменения версии Lua), на текущий момент времени, выполнены 3-х суточные тестовые прогоны OS_Quesha (аналогичные тем, которые были выполнены для младших версий QUIK). Проблем не обнаружено.
Переход на QUIK 8.5..... для многих пользователей порождает проблемы связанные как с нестабильностью новой версии, так и с необходимостью перевода своих прикладных программ c Lua 5.1 на Lua 5.3. Пусть бы энтузиасты "покувыркались" бы с новыми версиями, а консерваторы занимались бы своими делами. 19-ти разрядные № заявок в старых версиях реализовать не сложно и это хорошо бы сделать. Разработчику QUIK это было бы только в плюс.