Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
18.11.2025 20:09:02
Цитата
VPM написал: Переписал с помощью корутин, здесь их применение наиболее показательно.
Это можно сделать короче:
Код
RUN = true
function main()
-- Функции для асинхронного запроса свечей ---
-- 1. Массовый запрос свечей BulkRequestCandles.
-- Параметр: таблица {{class_code, sec_code, interval}}
-- Результат: {{class_code, sec_code, interval, ds}}
local BulkRequestCandles = function(par)
for i = 1, #par do
par[i].ds = CreateDataSource(par[i].class_code, par[i].sec_code, par[i].interval)
end
end
----------------------------------------
-- 2. Проверка запроса свечей CheckingCandleRequest.
-- Параметр: таблица {{class_code, sec_code, interval, ds}}
-- Результат в таблице парамктров : {{class_code, sec_code, interval, ds, ok}}
-- Значения ok: true - данные начали поступать; nil данные еще не поступили;
-- false - ошибка в параметрах запроса
-- Знвчение функции: количеситво источников еще ожидающих данные --
local CheckingCandleRequest = function(par)
local N = #par
local ds
for i = 1, #par do
ds = par[i].ds
if type(ds) == 'string' then -- обнаруженная ранее ошибка в параметрах запроса
N = N - 1
else
if par[i].ok == nil then -- еще не дождались данных
if ds == nil then -- обнаружена ошибка
par[i].ds = ' *** Ошибка в параметрах запроса'
par[i].ok = false
else
-- проверка поступления данных
if ds:Size() > 0 then -- есть данные
par[i].ok = true
N = N - 1
end
end
else
N = N - 1
end
end
end
return N
end
-------------------------------------------------
local sec_list = {}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 1}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 2}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 10}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'SBER', interval = 20}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 10}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 2}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'GAZP', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'LKOH', interval = 5}
sec_list[#sec_list+1] = {class_code = 'QJSIM', sec_code = 'FEES', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'SiZ5', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 5}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'RIZ5', interval = 15}
sec_list[#sec_list+1] = {class_code = 'SPBFUT', sec_code = 'SRZ5', interval = 30}
BulkRequestCandles(sec_list)
--------------
local DS = false
while RUN do
-- Проверка поступления свечей (без блокирования цикла обработки)
if CheckingCandleRequest(sec_list) == 0 and not DS then
DS = true
-- Отладочная печать --
for i = 1, #sec_list do
if sec_list[i].ok == true then
message(sec_list[i].sec_code ..' ds:size() = ' .. sec_list[i].ds:Size()
..' interval = ' .. sec_list[i].interval)
else -- Ошибка задания параметров
message(sec_list[i].sec_code..' interval = ' .. sec_list[i].interval
.. sec_list[i].ds )
end
end
end
-- Выполнение заданий скрипта --
sleep (100)
end
end
function OnStop(signal)
RUN = false
return 5000
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
17.11.2025 16:27:10
Цитата
Nikolay написал: Закажете сразу, да. Но выйдете из метода только после ожидания.
Не обязательно написанное мной реализовывать в одном методе. Метод1:
Цитата
TGB написал: Параметром при этом может быть таблица со списком class_code, sec_code, tf. В цикле запрашиваются ds[i],
Метод2:
Цитата
TGB написал: в цикле выполняется проверки поступления данных (как это делается в выложенной функции) и выдается результат в виде таблицы параметра с добавленным полем ds.
И все делается, как вы описали, без блокировки.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
17.11.2025 15:18:51
Цитата
Nikolay написал: Просто к слову - это блокирующая реализация. По опыту, данные могут приходить долго.
Я написал как запрашивать сразу много тикеров, хоть 1000:
Цитата
TGB написал: Ее легко изменить для запроса данных по многим тикерам: Параметром при этом может быть таблица со списком class_code, sec_code, tf. В цикле запрашиваются ds[i], а затем в цикле выполняется проверки поступления данных (как это делается в выложенной функции) и выдается результат в виде таблицы параметра с добавленным полем ds.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
17.11.2025 14:31:22
Цитата
VPM написал: А как же проверить? Убедиться что все работает?
Функция запроса данных свечей по тикеру с учетом возможных задержек:
Ее легко изменить для запроса данных по многим тикерам: Параметром при этом может быть таблица со списком class_code, sec_code, tf. В цикле запрашиваются ds[i], а затем в цикле выполняется проверки поступления данных (как это делается в выложенной функции) и выдается результат в виде таблицы параметра с добавленным полем ds.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
06.11.2025 09:54:02
Цитата
VPM написал: TGB , Ну вот, Можете же, нормально изъясняться в пределах общения, без излишней надменности.
Вы почитали историю? Там есть ответы на все ваши (характерные для начинающих) вопросы. Похоже, нет.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
06.11.2025 09:43:13
Цитата
VPM написал: Это — мощный объектно-ориентированный фреймворк для рыночных данных на Lua, для QUIK.
Не буду утверждать точно (в отличие от вас я всегда сомневаюсь ), но мне кажется, что это ваши очередные иллюзии.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
06.11.2025 09:27:37
VPM, и все таки мне интересно, вы понимаете, что, если корутина, при своем вызове выполняет, пусть 50 простых (не циклических) операций (эквивалентных по затратам процессорного времени ~2 вызовам пустых функций), то КПД использования процессорного времени вашего ПК: 25 / 125 = 20 %. Вы понимаете, что ресурс процессорного времени является общим? И если вы его расходуете в своем скрипте, то медленнее выполняются функции QUIK. Покажите, где у вас корутина в цикле выполняет > 20 простых операций. Вы же "печетесь":
Цитата
VPM написал: Вы можете показать оптимальный подход в квик, для получения и обработки оперативных данных, именно оперативных?
Вы понимаете, термин оптимальный? По простому, лучше не бывает. В каких условиях (ограничениях)? Зачем вы пишите о том, чего не понимаете?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
06.11.2025 08:43:50
Цитата
VPM написал: вы обрабатываете события последовательно перебираете очередь или есть приоритеты, если есть то чем обосновываете?
Nikolay вам объяснил, что не надо обрабатывать события. Зачем вам изучать жизнь событий? Когда для принятия решений достаточно (наряду с определением текущего состояния вашего счета, индикаторами принятия решений): определить как и когда выполняются ваши заявки. Все это можно увидеть в таблицах состояния QUIK (orders, stop_orders и т.д.), которые вы можете опрашивать циклически. Это вы можете делать в том порядке, который вам нужен в вашей стратегии торгов. Единственный коллбек, который имеет смысл обрабатывать (с учетом того, что он может потеряться) это OnTransReply, так как в нем может быть информация о причине невыполнения вашей транзакции. Все остальные коллбеки - от "лукавого". Нужно понимать что "реактивность" (задержка выполнения команд) QLua ~1- 60 сек. Все это не однократно обсуждалось на этом форуме: читайте историю (все украли до нас ).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
05.11.2025 13:16:56
Цитата
VPM написал: Можно делать yield-циклы с sleep(1000) без потери отзывчивости терминала.
А тогда почему бы не sleep(10000)? Сделайте у себя и не забудьте потом рассказать об успехах торговли роботом. Терминал у вас точно будет отзывчатым. Вообще, я не стал бы вас комментировать, но на форуме могут быть дети , в вы такое несете.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
В ~100 раз. Вы философ . 2. У вас есть понятие, что при использовании корутин надо синхронизироваться, если в них используются общие изменяемые данные? То есть следить за тем, чтобы данные недоделанные в одной корутине не использовались в другой. Вы когда-нибудь занимались параллельным программированием?
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
31.10.2025 09:41:14
Свежее свидетельство долгого восстановления взаимодействия рабочего места QUIK с сервером:
Цитата
Nikolay написал: При этом данные после такой чистки загружаются минуты.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
По вашим же тестам накладные расходы на вызов корутин в 97.33 раз больше, чем на вызов функций (coroutine=584.000 мс , func=6.000 мс ). Чтобы для вас было наглядно, при всяком вызове корутины, прежде чем она начнет что-то делать, делается 97 пустых вызовов функций.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 12.05.2020
28.10.2025 22:29:29
Цитата
nikolz написал: сделал прикольный тест на оценку быстродействия корутин.
Вы обнаружили существенную деградацию эффективности реализации корутин в Lua 5.4.1. Причем при выполнении модифицированного мною вашего теста она больше, чем вы пишите: накладные расходы на вызов корутин больше по сравнению с вызовом функции ~150 раз. В Lua 5.1 эта разница была ~4 раза. Кому интересно, можно проверить в QUIK 8.4.1. Код теста:
Код
function main()
local N =100000
local function foo ()
local yield = coroutine.yield
while 1 do
yield()
end
end
local function foo1 () return end
-----
local out = 'Результат теста: количество вызовов = ' .. N .. ', время вызова сопрограммы '
local resume = coroutine.resume
local co = coroutine.create(foo)
local TT1 = os.clock()
for i =1, N do resume(co) end
TT1 = (os.clock() - TT1) * 1000
out = out .. TT1 .. ' млс.'
-- message('coroutine = ' .. (os.clock() - TT) * 1000)
local TT2 = os.clock()
for i =1, N do foo1(10) end
TT2 = (os.clock() - TT2) * 1000
-- message('function = '.. (os.clock() - TT) * 1000)
out = out .. ', функции ' .. TT2 .. ' млс. T1/T2 = ' .. TT1/TT2
message(out)
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Пользователь
Сообщений: Регистрация: 12.05.2020
14.10.2025 08:08:47
Цитата
paluke написал: Не только DestroyTable(), любые операции с таблицей не выполняются.
Цитата
TGB написал: Работа с таблицами QUIK выполняется в служебном потоке, отличном от main. В том же, в котором выполняется OnStop. И пока выполняется OnStop никакие операции с таблицами QUIK не возможны (поток работы с таблицами занят OnStop ).
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
13.10.2025 19:13:30
Дополнительно для анализа долгого запуска QUIK: 1) 2) 3)
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
13.10.2025 16:53:28
Цитата
Oleg Kuzembaev написал: Ранее уже ответили вам письмом на почту.
Здравствуйте. У меня в почте письма нет. Пришлите, пожалуйста повторно.
DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Пользователь
Сообщений: Регистрация: 12.05.2020
13.10.2025 16:14:37
Цитата
nikolz написал: Если он вызывается в main то вызов это и есть исполнение.
nikolz писатель ? Читайте:
Цитата
TGB написал: она не лезет в таблицы QUIK, а создает коллбек закрытия таблицы, который обрабатывается в потоке терминала,
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
12.10.2025 09:17:59
Цитата
TGB написал: 1) При проверке многократной (> 8 раз) остановки/запуска скрипта, в котором используется сторонний графический пакет IUP, QUIK (версия 12.6.1.2, Lua 5.4), после разного количества экспериментов, в моменты останова/запуска, падает: Дамп info_dmp_20251007_150748.dmp вышлю почтой.
На это нет ответа. ---- Предложения: 1) После завершения OnStop не обрабатывать только коллбеки, зарегистрированные в main. Коллбеки создаваемые в main продолжать отрабатывать (смотрите ветку . 2) Реализовать/проверить сихронизацию основного потока QUIK с потоком main при его остановки (не обращаться из основного потока к данным завершенного потока).
DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Зачем полагать, когда можно проверить. Переставьте DestroyTable в OnStop.
2.
Цитата
nikolz написал: Функция DestroyTable в данном примере вызывается в потоке Main.
Вы точно знаете как устроена DestroyTable? Не точно, но скорее всего, это реализовано следующим образом. При том, что DestroyTable вызывается в main, она не лезет в таблицы QUIK, а создает коллбек закрытия таблицы, который обрабатывается в потоке терминала, но он занят более интересным делом : остановкой скрипта (удаляет поток main и перестает обрабатывать коллбеки, созданные в нем, так как исчезнет контекст их выполнения).
DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Пользователь
Сообщений: Регистрация: 12.05.2020
11.10.2025 19:01:44
Цитата
Ростислав Дм. Кудряшов написал: В каком потоке управления выполняется вызов функции DestroyTable()
Работа с таблицами QUIK выполняется в служебном потоке, отличном от main. В том же, в котором выполняется OnStop. И пока выполняется OnStop никакие операции с таблицами QUIK не возможны (поток работы с таблицами занят OnStop ). OnStop в любом случае завершает скрипт, поэтому DestroyTable не выполнена и созданная в скрипте таблица существует после завершения скрипта. Если что то надо делать с таблицами по кнопке завершить, то это надо делать в функции OnStop.
DestroyTable (и Clear) закрывает скрипт вместо таблицы, Тема описана в Названии и в Тексте сообщения
Будет выход из цикла и функции main при закрытии таблицы и это правильно. В данном случае ошибки в Qlua нет.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
09.10.2025 20:56:43
Цитата
Oleg Kuzembaev написал: В таком случае, пришлите нам архив вашего Рабочего места QUIK на почту поддержки
Посылал на ваше имя последние настройки QUIK, с которыми проверял длительность его перезапуска.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
09.10.2025 10:30:05
Цитата
Oleg Kuzembaev написал: В таком случае, пожалуйста, конкретизируйте в чем именно ваш вопрос/пожелание к будущим версиям терминала?
Пожелание относительно длительности запуска/перезапуска QUIK на работающем ПК с характеристиками 8 ядер, 4 Ггц, память 32 Гб, диск SSD: <= 3 сек.
Неккоректная работа CreateDataSourse
Пользователь
Сообщений: Регистрация: 12.05.2020
09.10.2025 08:43:39
Цитата
Serchk написал: И переменная a при запуске постоянно возвращает nil значение
Данные приходят не сразу. Можно использовать функцию:
Код
--- Cl - класс, Sec - код бумаги, Int - таймфрейм.
--- T - ожидание поступления данных источника в сек. (по умолчанию 15 сек.)
local CreateDS = function(Cl, Sec, Int, T)
T = (T or 15) * 10
local ds, Error = CreateDataSource(Cl, Sec, Int)
for i = 1, T do
if not ((Error == "" or Error == nil) and ds:Size() == 0) then break end
if i >= T then error('Не дождались DS: ' .. Sec .. '. Ошибка: ' .. tostring(Error)) end
sleep(100)
end
return ds
end
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
09.10.2025 08:18:48
Цитата
Oleg Kuzembaev написал: В Рабочем месте QUIK существует настройка "Восстанавливать связь автоматически через". Как понятно из ее названия, она позволяет подключиться к торговому серверу снова через заданный пользователем промежуток времени в случае потери соединения. Настройка "При восстановлении использовать только параметры последнего соединения" позволит подключиться к тому серверу, с которым было утрачено соединение.
У меня все включено. QUIK запускается с опцией -clear.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
08.10.2025 21:36:22
Цитата
Egor Zaytsev написал: Просьба подсказать, претензия в том, что после подключения к серверу по настройке Восстанавливать связь автоматически QUIK долго получает данные? Если да, то на какие именно данные ориентируетесь? Проблема исключительно только утром?
Ситуации: 1) При проверке многократной (> 8 раз) остановки/запуска скрипта, в котором используется сторонний графический пакет IUP, QUIK (версия 12.6.1.2, Lua 5.4), после разного количества экспериментов, в моменты останова/запуска, падает: Дамп info_dmp_20251007_150748.dmp вышлю почтой. Могу наделать сколько нужно. Причина 0xc0000005 - Потоком была предпринята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа. Это происходит только в рабочем экземпляре QUIK. В песочнице с такой же версией этого нет. В работе проблем с пакетом IUP не обнаружено (использую давно, но ранее при проверке запуска/перезапуска делал это 3-4 раза.). Экспериментально выяснил, что перенос закрытия IUP (iup:Close()) из служебного потока OnStop в пользовательский поток main, ситуацию исправляет. QUIK падать перестает. Но почему iup:Close() "ломает" поток OnStop? Опять что-нибудь с синхронизацией? Похоже, это очередная ситуация, подтверждающая то, что мною написано в п. 2) комментария . В комментарии предлагается вариант реализации п. 2). В комментарии есть предложение, как при реализации п. 2), сохранить существующий интерфейс QLua c QUIK. ------- При экспериментировании замучился ожидать перезапуски QUIK и об этом следующий пункт.
2) Задержка при запуске/перезапуске QUIK на моем ноутбуке, с ранее перечисленными характеристиками: ~1 мин. Это много и неоднократно в разные года обсуждалось в различных ветках. Мои комментарии трассировки запуска рабочего QUIK выделены символами ##.
Код
KW 08.10.25 16:50:36:220 ## Остановлен QUIK (16:50:36:220)
--- @ Остановлен по стоп бот D:\0 D\0 TGB\B_Q\Bots\B1 @ ---
## Через ~ 1 сек. QUIK запущен
==================================
KW 08.10.25 16:51:02:693 ## Начало работы скрипта (длительность от начала запуска 26 сек.)
Begin_Require: 08.10.25 16:51:02:693. End_Require: 08.10.25 16:51:02:696 ## Загружены все пакеты скрипта (длительность загрузки 3 млс.)
KW 08.10.25 16:51:02:717 ACCOUNT, CLASS_CODES, CLIENT_CODES, FIRM_ID: ## Получены реквизиты и скрипт готов продолжать работать
KW 08.10.25 16:51:02:717 #572:TRADER_lib Нет подключения к серверу
KW 08.10.25 16:51:02:717 #575:TRADER_lib С сервера не поступают необходимые данные
KW 08.10.25 16:51:02:717 #578:TRADER_lib Ждет возобновления связи
KW 08.10.25 16:51:25:197 #590:TRADER_lib Соединение с сервером восстановлено, ждет 10 сек. подгрузки данных
KW 08.10.25 16:51:35:201 #608:TRADER_lib Возобновил работу ## (16:51:35:201) Итого: длительность перезапуска ~ 1 мин.
Переформулирую два заданные ранее вопросы в один: Для взаимодействия сервера с терминалом QUIK существует протокол его быстрого восстановления при разрывах его по любой причине? Я не представляю, где проблемы с быстрым перезапуском QUIK с учетом того, что: 1) в ОС (Windows) многое кэшируется (на моем ноуте 32 Гб. и перезапуск выполняется сразу после падения QUIK); 2) реализован более менее приличный протокол быстрого восстановления взаимодействия.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
06.10.2025 12:43:26
Цитата
VPM написал: Сопрограммы в Lua — это мост между двумя мирами: 1. Мир для программиста: Удобный, последовательный, понятный код. 2. Мир для машины: Гибкое, асинхронное, неблокирующее выполнение.
Написано так красиво , что я не удержался, чтобы что-нибудь не добавить: 3. Есть задачи, которые могут быть реализованы с использованием сопрограмм проще, чем с использованием только функций. Например, подключение IUP в выложенном вами скрипте. Однако, следует учитывать, что сопрограммы (нити - псевдопотоки) отличаются от потоков, в основном, только следующим: 1) они не могут выполняться параллельно; 2) переключение между ними программное (yield), а не внешнее как в потоках (по прерываниям в любом их месте); 3) для их синхронизации не требуются тяжеловесные примитивы (критические секции и т.д.), достаточно использования переменных (так как нет параллелизма). При использовании сопрограмм всегда надо помнить: если в нескольких сопрограммах изменяются общие данные, то нужно заниматься их синхронизацией. Таким образом, используя сопрограммы вы попадаете в пусть специфическую, но многопоточную среду, почти со всеми проблемами программирования потоков. Использование сопрограмм это моделирование многопоточного поведения скрипта в однопоточной среде исполнения. Программировать сопрограммы сложнее, чем функции. Чем сложнее программа, тем больше в ней ошибок. То что можно сделать просто в виде функций, вряд ли стоит делать на сопрограммах, если это не для развлечения.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
05.10.2025 08:21:38
Цитата
Ростислав Дм. Кудряшов написал: Не поленись, а запусти на своём ПК пример переключения спорограмм-корутин между IUP и main(). И убедишься, что невытесняющая (кооперативная) многозадачность порой лучше вытесняющей.
С этого места, пожалуйста, поподробнее. Как вам удалось сумев запустить единственный готовый пример, определить что он порой лучше вытесняющей многозадачности? С чем вы его сравнивали? Или вы можете определять лучшее без сравнения? Откуда к вам приходят такие озарения ? Поделитесь.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
04.10.2025 22:40:12
1.
Цитата
Ростислав Дм. Кудряшов написал: Статья не разъясняет, "для чего и как". Поэтому нет причины углубляться в скрипт.
Ростислав Дм. Кудряшов написал: параллельное исполнение скрипта main() и ручных манипуляций в IUP с непрерывной связью между этими нитями (threads) в обоих направлениях.
Где вы прочитали, что корутины в Lua выполняются параллельно? Интересно, как в одном потоке можно с помощью корутин реализовать параллелизм (одновременность) их выполнения? Но на всякий случай цитата Р. Иерузалимски: "в любой момент времени программа с сопрограммами выполняет только одну из своих сопрограмм".
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Согласен, в работающем роботе достаточно возможностей пользовательских таблиц QUIK. Идеальный, зарабатывающий робот должен это делать без вводных и без лишнего вывода, только отчеты о прибыли в журнале с аналитикой, полезной пользователю. Реально, желателен вывод роботом сообщений о наступлении событий, требующих вмешательство пользователя. Все это без проблем реализуемо на таблицах QUIK. Графический пакет я использовал для реализации средств создания скриптов, что сделать на таблицах QUIK сложновато.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
04.10.2025 11:47:41
Цитата
Nikolay написал: Просто замечание, что если предлагаете какое-то открытое решение, то зачем скрывать код, его подключающее.
С этим можно бы согласиться, но есть вариант 1, в котором нет скрытых кодов.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
04.10.2025 10:41:20
Цитата
Nikolay написал: Я понял про что это библиотека. Я говорил, что нет исходников.
Мною рекомендуется использовать первый вариант и для него пакет QluaUser.dll не требуется.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
04.10.2025 09:09:10
Цитата
Nikolay написал: Просто к слову, т.к. используется неизвестная библиотека QluaUser.dll то запускать это не видя исходники будут сложно. По крайней мере мне, не знаю как другим.
Цитата
TGB написал: -- Вариант 1: запуск IUP в потоке main (надо подключать только IUP, но цикл обработки скрипта программировать -- в таймере IUP: помечено #### ). -- Вариант 2: запуск IUP в отдельном потоке отличном от main(кроме IUP, обязательно подключать пакет QluaUser). -- Вариант 1 более безопасный, чем 2. Так как однопоточный, и не требующий синхронизации диалога с -- основной работой скрипта.
Два варианта использования графического пакета IUP (Lua 5.4) в QUIKе
Пользователь
Сообщений: Регистрация: 12.05.2020
03.10.2025 20:50:09
Инструкция в коде примера:
Код
--- Использование графического пакета IUP (Lua 5.4...) в QUIKе (! ограничение IUP:
-- только в одном из запущенном скрипте экземпляра QUIK).
-- Доступны все возможности пакета IUP (подключаемой версии).
-- Вариант 1: запуск IUP в потоке main (надо подключать только IUP, но цикл обработки скрипта программировать
-- в таймере IUP: помечено #### ).
-- Вариант 2: запуск IUP в отдельном потоке отличном от main(кроме IUP, обязательно подключать пакет QluaUser).
-- Вариант 1 более безопасный, чем 2. Так как однопоточный, и не требующий синхронизации диалога с
-- основной работой скрипта.
-- Ссылка для скачивания пакетов iup.dll, iuplua54.dll, QluaUser.dll (мой):
-- https://cloud.mail.ru/public/7xAm/jaCgULqGo Перед использованием пакетов, надо их разблокировать.
-- Пакеты переслать в папку экземпляра QUIK, хранящую файл info.exe.
_RUN_ = true
function main()
-- Пример формы IUP со двумя вкладками ---
local Pause = 1000
local thread = false -- false - выполнение диалога в потоке main; true - запуск IUP в отдельном потоке --
local cpath = (getWorkingFolder() .. '\\?54.dll;' .. getWorkingFolder() .. '\\?_5_4.dll;'.. getWorkingFolder() .. '\\?.dll;' .. package.cpath)
---
package.cpath = cpath
require("iuplua")
local QluaUser = require('QluaUser') -- Это для запуска диалога IUP в отдельном потоке ---
if thread then
QluaUser = require('QluaUser')
end
local function iup_form()
local timer = iup.timer { time = Pause } ---- Вместо sleep таймер формы ( млсек.) ---
timer.run = "NO"
function timer:action_cb()
if not _RUN_ then
timer.run = "NO"
iup:ExitLoop() -- Завершает текущий диалог
end
if not thread then -- Основной цикл обработки скрипта в таймере IUP ---
-- Тело основного цикла скрипта -- ####
message('iup выполняется в потоке main. Тело основного цикла скрипта должно выполняеться здесь (в таймере iup)')
-------------------
end
end
-- Creates boxes
local vboxA = iup.vbox{iup.fill{}, iup.label{title="TABS AAA", expand="HORIZONTAL"}, iup.button{title="AAA"}}
local vboxB = iup.vbox{iup.label{title="TABS BBB"}, iup.button{title="BBB"}}
-- Sets titles of the vboxes
vboxA.tabtitle = "AAAAAA"
vboxB.tabtitle = "BBBBBB"
-- Creates tabs
local tabs = iup.tabs{vboxA, vboxB}
-- Creates dialog
local dlg = iup.dialog{iup.vbox{tabs; margin="10x10"}; title="Test IupTabs", size="150x80"}
-- Shows dialog in the center of the screen
dlg:showxy(iup.CENTER, iup.CENTER)
timer.run = "YES"
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
end
timer.run = "NO"
end
if thread then
QluaUser.ThreadNew(iup_form)
else
iup_form()
iup.Close()
iup = nil
end
while _RUN_ do -- Основной цикл обработки скрипта в main ---
-----------------------
if thread then
message('iup был запущен в отдельном потоке. Тело основного цикла скрипта выполняется в потоке main.')
else
message('После завершения потока iup, продолжается выполняется поток main.')
end
sleep(Pause)
-----------------------
end
end
---
function OnStop(flag)
_RUN_ = false
sleep(2000)
if iup then iup.Close() end
return 3000
end
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Из текста фрагмента протокола видно, но, наверное, надо пояснить: мною в меню "Система > Соединения.. > Восстанавливать связь автоматически" было указано начало c 6.50.
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
29.09.2025 08:47:44
На вопросы в общей постановке, ответа я не вижу. 1. Отвечать не отвечают, но реагируют . Протокол начала утренней сессии 29.09.25: KW 29.09.25 06:50:10:519 --- OnCleanUp (прилетел) ----------------- KW 29.09.25 06:50:32:746 #590:TRADER_lib Соединение с сервером восстановлено, ждет 10 сек. подгрузки данных KW 29.09.25 06:50:42:754 #608:TRADER_lib Возобновил работу
2. Проблема с длительностью запуска QUIK пока осталась. Для быстрого восстановления функционирования программ используются контрольные точки. Это значения переменных программ, возникшие при их выполнении и сохраненные в энергонезависимой памяти для возможности быстрого продолжения их работы, начиная с сохраненного состояния, после их перезапуска по любой причине (сбой аппаратуры, программная ошибка, и т.д.). Например: 1) Windows (программный монстр), используя контрольную точку, просыпается из режима сна за ~1сек. 2) Chrome (большая программа) c 50 вкладками открывается через ~2 сек. 3) В моих многоскриптовых роботах, со скриптами (в количестве:3-6), взаимодействующими между собой, есть режим, в котором после начала запуска/перезапуска, они готовы к продолжению прерванной работы менее чем через 15 млс. ---- На сервере есть контрольные точки терминалов (QUIKов) для быстрого продолжения работы с ними после любого его перезапуска? В QUIKе есть контрольная точка для быстрого продолжения работы с сервером после любого перезапуска QUIK?
Автозапуск скрипта LUA при старте QUIK
Пользователь
Сообщений: Регистрация: 12.05.2020
27.09.2025 21:52:32
Цитата
Андрей написал: А уточните, пожалуйста, функция, которую вы упоминаете, финализирует только таблицы? открытые файлы лучше отдельно закрыть?
У меня все объекты и таблицы и файлы финализируются следующим образом (фрагмент моего кода, обеспечивающего финализацию):
Код
--- Стек объектов финализации (автоматическая финализация) ---
-- В этот стек помещать для финализируемых объектов функции их очистки (сразу при создании объектов) в формате:
-- {<Функция финализации объекта>, {<Параметры финализации объекта через запятую>}}; таблица с параметрами может отсутствовать
local FINALIZATION_META
FINALIZATION_STEK = {}
--- Реализована возможность финализации "вручную":
-- 1) mess = true - финализация без выдачи сообщения;
-- 2) no_mess = 'string' - финализация c выдачи сообщения no_mess;
function FINALIZATION_STEK_FUNFIN(stek_fin, no_mess) -- ! Функция вызывается при любом варианте завершения скрипта --
if type(stek_fin) ~= 'table' then return end
if not next(stek_fin) then return end
-------- Выдача сообщений различных вариантов финализации ---
if not no_mess or type(no_mess) == 'string' then
-- message('FINALIZATION_STEK_FUNFIN - здесь выдать сообщение ADMIN: *** Завершение с не перехваченной ситуацией')
if B_Q_DLL and OPEN_CONTROL_BOT then
local mess
if type(no_mess) == 'string' then
mess = no_mess
else
mess = '\n *** Завершение с не перехваченной ситуацией в скрипте: ' .. (SCRIPT_NAME or '??')
..'\n Дополнительные подробности смотрите в журнале скрипта и диагностике QUIK.'
end
message(mess, 3)
---
end
end
--------------------------------------------
local ob_l
for i = #stek_fin, 1, -1 do -- обработка стека очистки объектов финализации ---
ob_l = stek_fin[i] -- #### 15.12.24
stek_fin[i] = nil -- #### 15.12.24
if type(ob_l) == 'table' and type(ob_l[1]) == 'function' then
if ob_l[2] then
ob_l[1](table.unpack(ob_l[2]))
else
ob_l[1]()
end
end
end
FINALIZATION_META.__gc= 0 -- отключение финализации ---
end
----
-- При подключении финализирующей метатаблицы в ней обязательно должно быть поле __gc
-- (! значения отличные от функции не будут обрабатываться, но функцию можно присвоить позже),
-- иначе не будет пометки для финализации (список финализации формируется при подключении метатаблиц с полем __gc)
FINALIZATION_META = {__gc = FINALIZATION_STEK_FUNFIN}
setmetatable(FINALIZATION_STEK, FINALIZATION_META)
--- Запись в стек функции финализации ---
function FINALIZATION_STEK_PUSH(tbl_rez) -- tbl_rez = {<Функция финализации объекта>, {<Параметры финализации объекта>}}
FINALIZATION_STEK[#FINALIZATION_STEK + 1] = tbl_rez
end
Но, может для вас окажется достаточно добавить sleep(1000) или большую задержку.
Автозапуск скрипта LUA при старте QUIK
Пользователь
Сообщений: Регистрация: 12.05.2020
27.09.2025 20:20:20
Цитата
Андрей написал: Видимо придется по одному действию возвращать в обработку остановки бота и смотреть, что приводит к его закрытию.
Мне пришлось столкнуться с похожей ситуацией когда в одном из скриптом стал использовать таблицы QUIK для визуализации. Посмотрите в эту сторону (код завершения моего скрипта, после добавления которого он стал перезапускаться вместе с QUIK):
Код
while _RUN_ do
< Тело основного цикла скрипта>
end
if TBL_QUIK then -- Если использовались таблицы
-- Финализация (не допускать одновременного выполнения в пользовательском и основном потоке QUIK) ---
FINALIZATION_STEK_FUNFIN(FINALIZATION_STEK, true)
----
-- #### Задержка sleep нужна чтобы установить признак запуска скрипта при перезапуске QUIK.
-- Иначе при перезапуске QUIK не будет перезапущен скрипт.--
-- При нормальном завершении QUIK, если есть таблицы QUIK, они удаляются (и вызываются коллбеки QTABLE_CLOSE)
-- Если при этом нет задержки, то скрипт завершается и не выставляется признак необходимости его перезапуска
-- при запуске QUIK. Признак TBL_QUIK устанавливается в основной пользовательской таблице QUIK.
-- Длительность задержки выбрана экспериментально.
sleep(sleep_TBL_QUIK_ or 1000)
end
FINALIZATION_STEK_FUNFIN(FINALIZATION_STEK, true) у меня финализирует по стековому принципу все открытые объекты, которые по-хорошему, требуют своего закрытия (в том числе созданные таблицы QUIK). Финализация выполняется при завершении скрипта по любой причине. Это делается с использованием метатаблицы финализации.
Ошибка при поиске пиков\впадин кастом индикатора
Пользователь
Сообщений: Регистрация: 12.05.2020
26.09.2025 12:24:05
Цитата
VPM написал: bit.band — чистая побитовая операция на целых, выполняется через С-библиотеку, работает на порядок быстрее, особенно если много итераций.
Вы это проверяли? bit.band это вызов функции, в теле которой выполняется битовая операция "И". Сам вызов до начала выполнения тела функции это довольно тяжелая операция, выполняющаяся дольше любой арифметической операции. В Lua 5.4 соотношение длительности выполнения приблизительно следующее: 1) % = 1 2) bit.band = 4,49 3) & (битовая операция "И" вместо bit.band , начиная c Lua 5.3) = 0,63
Можете попробовать использовать ранее выложенный мной, но слегка модифицированный код индикатора Kijun-sen, который работает в ~20 раз быстрее, чем чем то, что выложил Roman Koledin:
Код
Settings = {
Name = "*Kijun-sen",
kijun_period = 26, -- Период Kijun-sen (можно изменить)
line = {{
Name = "Kijun-sen",
Color = RGB(0, 0, 200),
Type = TYPE_LINE,
Width = 2
}}
}
local kijun_period = Settings.kijun_period
local QueueH, QueueL = {}, {}
local const_L = 999999999
function Init()
QueueH, QueueL = {}, {}
for i = 0, kijun_period - 1 do
QueueH[i] = 0; QueueL[i] = const_L
end
return 1
end
function OnChangeSettings()
kijun_period = Settings.kijun_period
QueueH, QueueL = {}, {}
for i = 0, kijun_period - 1 do
QueueH[i] = 0; QueueL[i] = const_L
end
end
---
local TT
local N_C = 500
local max_high, min_low
function OnCalculate(index)
-- -- Вычисление времени обработки свеч (500 свечкй за ~4 млс. в 5 раз быстрее моего же *Kijun-sen_opt)--
-- if index == kijun_period + 1 then
-- TT = os.clock()
-- end
-- if index == N_C + kijun_period then
-- message('Kijun-sen. Время обработки ' .. N_C .. ' свечей (млс.) = ' .. (os.clock() - TT) * 1000)
-- end
-- -----------------------------------
if index == 1 then
max_high = H(1) or 0
min_low = L(1) or const_L
QueueH[1], QueueL[1] = max_high, min_low
else
current_high = H(index) or 0
current_low = L(index) or const_L
local ind = index % kijun_period -- место в векторе --
local QueueH_end
local QueueL_end
if index > kijun_period then -- сохранение уходящих значений --
QueueH_end = QueueH[ind]
QueueL_end = QueueL[ind]
end
QueueH[ind], QueueL[ind] = current_high, current_low -- сохранение текущих в векторе --
-- --------
if current_high >= max_high then -- Пришел максимальный --
max_high = current_high
else
if index > kijun_period then -- начальный период завершен --
-- Максимум "ушел" из скользящего периода --
if QueueH_end >= max_high then -- поиск максимального в векторе
max_high = current_high
for j = 0, kijun_period - 1 do
current_high = QueueH[j]
if current_high > max_high then max_high = current_high end
end
end
end
end
---
if current_low <= min_low then -- Пришел минимальный
min_low = current_low
else
if index > kijun_period then
-- Ушел из скользящего периода минимальный --
if QueueL_end <= min_low then -- поиск минимального
min_low = current_low
for j = 0, kijun_period - 1 do
current_low = QueueL[j]
if current_low < min_low then min_low = current_low end
end
end
end
end
end
return (max_high + min_low) / 2
end
Если бы я был архитектором QUIK, Что стоило бы изменить в QUIK по-крупному
Пользователь
Сообщений: Регистрация: 12.05.2020
25.09.2025 10:56:01
Протокол начала утренней сессии (типичный случай): KW 25.09.25 03:15:00:724 #578:TRADER Ждет возобновления связи KW 25.09.25 07:00:14:716 --- OnCleanUp (прилетел) ----------------- KW 25.09.25 07:00:38:873 #590:TRADER Соединение с сервером восстановлено, ждет 10 сек. подгрузки данных KW 25.09.25 07:00:48:873 #608:TRADER Возобновил работу --- Задержка возможности что-то делать 48 сек. ---- В этой ветке я написал о том, что существующая архитектуре QUIK порождает проблемы. И вот практическое подтверждение этому. Мне потребовалось что-то сделать в начале утренней сессии. Ноут 8 ядер 4 Ггц, SSD-скорость последовательного чтения 3 Гб. В пересчет на флагман советской индустрии БЭСМ-6 (~1000000 операций в сек.) задержка (48 * 1000 сек.) более 13 часов с начала утренней сессии . 1. Что делает QUIK 13 часов? ----- 2. Код в любом месте любого скрипта: for i = 1, 4000000000 do end "обездвиживает" QUIK на 10 секунд (длительность зависит от производительности ПК), он не отвечает. Я понимаю, что такой код писать нехорошо, но как написан QUIK, что зацикливание в пользовательском скрипте полностью его "обездвиживает"? 3. При переключении индикаторов, QUIK на какое-то время впадает в "ступпор". Можно ли сделать так, чтобы этого не было? Или это нерешаемая задача? 4. Перезапуск QUIKа выполняется долго (в пересчете на БЭСМ-6 ~13 часов :)). Как удалось этого добиться ?
Ошибка при поиске пиков\впадин кастом индикатора
Пользователь
Сообщений: Регистрация: 12.05.2020
24.09.2025 12:58:19
Цитата
nikolz написал: Если нравится, можете сказать "спасибо".
Этот индикатор не Kijun-sen. Вы сравнивали его с исправленным, долго работающим индикатором пользователя Roman Koledin? Это же делается просто.
nikolz написал: if i%Settings.kijun_period==0 then max_high = H(i); min_low = L(i) end
ошибка, так как Settings.kijun_period = nil. 2. Вместо скользящей вами предлагается "прыгающая" . Начальные значения каждого периода берутся в качестве экстремумов. Но может быть вы предлагаете свой прыгающий индикатор? ----------- Ниже выложен код реализации индикатора Kijun-sen приблизительно в 3,5 раза более эффективный по времени выполнения, чем то, что выложил Roman Koledin:
Код
Settings = {
Name = "*Kijun-sen_opt",
kijun_period = 26, -- Период Kijun-sen (можно изменить)
line = {{
Name = "Kijun-sen_opt",
Color = RGB(0, 0, 200),
Type = TYPE_LINE,
Width = 2
}}
}
function Init() return 1 end
local kijun_period = Settings.kijun_period
function OnChangeSettings()
kijun_period = Settings.kijun_period
end
---
local TT
local N_C = 500
function OnCalculate(index)
-- -- Вычисление времени обработки свеч --
-- if index == kijun_period + 1 then
-- TT = os.clock()
-- end
-- if index == N_C + kijun_period then
-- message('Kijun-sen. Время обработки ' .. N_C .. ' свечей (млс.) = ' .. (os.clock() - TT) * 1000)
-- end
if index==1 then
max_high = H(1)
min_low = L(1)
else
current_high = H(index)
current_low = L(index)
--------
if current_high > max_high then -- Пришел максимальный
max_high = current_high
else
if index > kijun_period then
-- Ушел из скользящего периода максимальный --
if H(index - kijun_period) >= max_high then -- поиск максимального
max_high = current_high
for j = index - kijun_period + 1, index - 1 do
current_high = H(j)
if current_high > max_high then max_high = current_high end
end
end
end
end
---
if current_low < min_low then -- Пришел минимальный
min_low = current_low
else
if index > kijun_period then
-- Ушел из скользящего периода минимальный --
if L(index - kijun_period) <= min_low then -- поиск минимального
min_low = current_low
for j = index - kijun_period + 1, index - 1 do
current_low = L(j)
if current_low < min_low then min_low = current_low end
end
end
end
end
end
return (max_high + min_low) / 2
end
Ошибка при поиске пиков\впадин кастом индикатора
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2025 12:30:32
Цитата
TGB написал: Надо: if index < kijun_period - 1 then
Не убрал 1. Должно: if index < kijun_period then
Ошибка при поиске пиков\впадин кастом индикатора
Пользователь
Сообщений: Регистрация: 12.05.2020
21.09.2025 12:27:38
Цитата
Roman Koledin написал: if index < kijun_period - 1 then
Надо: if index < kijun_period - 1 then. index начинается с 1.