Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 15:42:13
Цитата
Nikolay написал: А значит выполняться она может тоже только через вызовы в основном цикле mian. И тоже частота вызовов регулируется задержкой цикла main.Собственно ваш любимый hacktrade так и работает.
Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.
1. При первом в ходе создается корутина и мы работаем в ее цикле, а у нее никаких задержек, (кроме накладных), в ней идет вся торговая логика расчеты, вычисление и так далее. Останавливаем исполнение когда выполнены условия на отправку заявки и заявка отправлена (выполняется yield).
2. Структурно код стал на выполнение в цикле маин (с задержками sleep) функционально идет работа с заявкой. Где тут последовательность? Самая что не на есть асинхронность.
Выполнение кода структурно разделено на две составляющие: А) Поиск условия выполнения заявки (в цикле корутины); Б) Не посредственное исполнение заявки (взаимодействие с апи квик - в цикле маин).
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 16:09:42
Нашел. Вот когда то я сохранял для себя понимание. Что то с родни Вашему подходу.
Lua предоставляет "лёгкие потоки" — coroutines (сопрограммы). Это кооперативные задачи, которые работают внутри одного потока исполнения, но могут приостанавливать и возобновлять выполнение, передавая управление.
--Ключевая идея лёгкого потока (coroutine)
local is_run = true local threads = {}
function worker(name, delay) local i = 0 while is_run do i = i + 1 message(string.format("[%s] шаг %d", name, i)) for _ = 1, delay do coroutine.yield() end end end
while is_run do for _, co in ipairs(threads) do if coroutine.status(co) ~= "dead" then coroutine.resume(co) end end sleep(200) end end
function OnStop() is_run = false end
Это — мини-диспетчер потоков на чистом Lua. Каждый "поток" (worker) — корутина с собственным ритмом, а цикл в main() играет роль планировщика.
* Корутину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово.
* А main() — просто планировщик, который возобновляет корутины.
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 16:42:53
Цитата
VPM написал: Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.
Я на него смотрел еще в году так 16-ом. Как он работает предельно понятно. Подход далеко не новый, да и с чего ему быть новым если корутины в Lua появились в далеком 5.0 от 2003
Цитата
А main() — просто планировщик, который возобновляет корутины
Правильно. А значит с тем же успехом можно планировать и вызовы процедур, созданных иначе. Какая разница что вызывать - корутину или процедуру. Вызывается из одного и того же места, с тем же ритмом и скоростью. Отличия только в обертке одних в корутины, а другие нет.
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 17:00:02
Да но есть ключевое отличие. yield() - приостанавливает только задачу, не весь скрипт как sleep.
--- Ключевая идея лёгкого потока (coroutine - кооперативная задача). Этот код создаёт лёгкий поток (фактически, сопрограмму), который выполняется по шагам, каждый шаг — между yield() и resume().
Код
local co = coroutine.create(function()
for i = 1, 5 do
print("Работаю...", i)
coroutine.yield() -- приостанавливаем "поток"
end
end)
while coroutine.status(co) ~= "dead" do
coroutine.resume(co) -- возобновляем
sleep(100)
end
Код
--- Пример «лёгкого фонового потока» в QUIK
local is_run = true
-- "Лёгкий поток" для фоновой задачи
local function background_task()
local count = 0
while is_run do
count = count + 1
message("Фоновая задача: шаг " .. count)
coroutine.yield() -- уступаем управление
end
end
function main()
local co = coroutine.create(background_task)
message("Запуск фонового лёгкого потока...")
while is_run do
coroutine.resume(co) -- возобновляем поток
sleep(1000) -- имитация "асинхронного" поведения
end
end
function OnStop()
is_run = false
message("Остановка фонового потока.")
end
-- * Корутину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово.
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 17:17:43
Тогда давайте еще раз, на пальцах. Берем этот пример и "брюки превращаются":
localis_run=true -- "Лёгкий поток" для фоновой задачи localfunctioncreate_task() localcount=0 returnfunction() count=count+1 message("Фоновая задача: шаг " ..count) return-- уступаем управление end end functionmain() localco=create_task() message("Запуск фонового лёгкого потока...") whileis_rundo co() -- возобновляем поток sleep(1000) -- имитация "асинхронного" поведения end end functionOnStop() is_run=false message("Остановка фонового потока.") end
Как говорится - найдите десять отличий.
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 17:36:02
Отличие прежнее.
Вы в потоке маин вызываете псевдоним функции выше, после выполнения функции цикл приостанавливается sleep(1000) . В то время как в примере с корутиной имеется свой легки поток без задержек, а coroutine.yield() -- уступаем управление (подвешивает задачу) не создавая ни каких задержек, но цикл то маин выполняется. И таких задач можно вешать сколько угодно, в то время как в Вашем варианте после каждой задачи задержка.
Код
-- "Лёгкий поток" для фоновой задачиlocal function background_task()
local count = 0
while is_run do
count = count + 1
message("Фоновая задача: шаг " .. count)
coroutine.yield() -- уступаем управление
end
end
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 17:39:52
Нет такого. Я просто переделал Ваш пример. У Вас там есть задержка. Уберите, если хотите и не будет никаких задержек.
Вы в потоке маин вызываете псевдоним функции выше, после выполнения функции цикл приостанавливается sleep(1000) . В то время как в примере с корутиной имеется свой легки поток без задержек, а coroutine.yield() -- уступаем управление (подвешивает задачу) не создавая ни каких задержек, но цикл то маин выполняется. И таких задач можно вешать сколько угодно, в то время как в Вашем варианте после каждой задачи задержка.
Код
-- "Лёгкий поток" для фоновой задачиlocal function background_task()
local count = 0
while is_run do
count = count + 1
message ( "Фоновая задача: шаг " .. count)
coroutine.yield () -- уступаем управление
end
end
У Вас тоже задержка в main() на 1 секунду, т.е. в общем потоке скрипта, будет точно также задерживаться. У Вас и у Nikolay абсолютно синхронно будут исполняться вызовы, только у него быстрее будет проходить сам вызов в десятки раз.
- Роботы и индикаторы
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 17:58:29
Ну хорошо вот другой пример:
Код
function main()
threads[1] = coroutine.create(function() worker("A", 2) end)
threads[2] = coroutine.create(function() worker("B", 5) end)
while is_run do
for _, co in ipairs(threads) do
if coroutine.status(co) ~= "dead" then
coroutine.resume(co)
end
end
sleep(200)
end
end
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 18:15:49
Подсобрался с мыслями. Можно некий итог подвести.
Различия двух подходов, про применение см. выше мнение не поменял.
1. Подход с замыканием. Нет возможности приостанавливать сложные задачи на середине выполнения. Сложно реализовать ожидание событий или таймеров внутри задачи без внешнего кода. Каждая задача должна сама заботиться о том, как уступать управление (через sleep в основном цикле).
2. Подход с корутиной. Внутри корутины можно писать сложные алгоритмы и «разбивать» их на шаги. Более гибкая модель. Можно приостанавливать задачу на любом шаге. Можно легко комбинировать несколько фоновых задач в одном цикле. Более похоже на настоящие асинхронные потоки. Сложнее. Немного больше накладных расходов на создание и управление корутиной (хотя для QUIK это не критично). coroutine.yield() - приостанавливает выполнение задачи, позволяя основному циклу выполняться и управлять её запуском.
Пока разбирались на кидал лёгкий планировщик фоновых задач для QUIK. Всем пока хорошего кода.
Пользователь
Сообщений: Регистрация: 27.01.2017
29.10.2025 18:46:28
Нет. Это все не так. Корутина точно также работает. Где в корутине yield, в процедуре return. Где коде coroutine.resume - просто вызов процедуры. Все с точностью до стоки кода. Никаких чудес. Полная аналогия.
По вашим же тестам накладные расходы на вызов корутин в 97.33 раз больше, чем на вызов функций (coroutine=584.000 мс , func=6.000 мс ). Чтобы для вас было наглядно, при всяком вызове корутины, прежде чем она начнет что-то делать, делается 97 пустых вызовов функций.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 11:44:47
TGB, Ну так это без тестов пoнятно конечно, чуть больше, т.к. стек корутины сохраняется.
Александр М, Да Вы правы, все так, по той же самой причине - стек корутины сохраняется! Данный пример с count, это простейшее действие, а корутину создаем для решения сложных, затратных задач, где нужно не зависимая от основного цикла обработка данных (фон). Так что довод не корректен, так как при решении сложной задачи будет нивелирован, а возможно и получен выигрыш (как в обсуждаемом примере с фреймворком).
* Что делает замыкание? Создало локальную переменную.
* Что делает корутина? Создало независимы поток (без задержек и не блокирует QUIK с минимальной нагрузкой на CPU)
Преимущества очевидны: 1. Не блокирует QUIK. 2. Можно запустить много задач одновременно (мониторинг, логирование, анализ, обновление лимитов). 3. Лёгкая расширяемая структура — можно добавлять задачи динамически. 4. Поддерживает интервалы выполнения (как cron).
Посмотрим, что такое «лёгкий поток» — coroutines (сопрограммы) в контексте Lua? Это кооперативные задачи, которые работают внутри одного потока исполнения, но могут приостанавливать и возобновлять выполнение, передавая управление вручную. yield() - приостанавливает только задачу, не весь скрипт.
По каким признакам это "лёгкий поток"? 1. Лёгкий по памяти. Корутине нужно всего несколько КБ стека. 2. Быстрый. Не создаёт системных потоков/контекстов. 3. Кооперативный. Поток сам решает, когда уступить управление. 4. Полный контекст исполнения. Сохраняются локальные переменные, состояние и позиция. 5. Пауза без блокировки QUIK. yield() приостанавливает только задачу, не весь скрипт.
* Каротину можно считать лёгким потоком Lua — она живёт, имеет собственный контекст и исполняется пошагово. * А `main()` — просто планировщик, который возобновляет _ Ну так это без тестов пoнятно конечно, чуть больше, т.к. стек корутины сохраняется.
Резюме. В Lua корутины — это лёгкие, управляемые потоки. Они позволяют выполнять фоновую работу, не блокируя основной цикл QUIK. В QUIK это единственный безопасный способ организовать "многозадачность" без внешних библиотек.
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 12:33:31
Любая процедура, вызванная из main не блокирует QUIK. Любая. Хоть завернутая в корутину, хоть вызванная напрямую, хоть в замыкании. Также любая процедура сама принимает решение когда выйти из неё. Для этого есть оператор return. В корутине для этого используется yield. return тоже просто возвращает управление в точку вызова процедуры, тоже не останавливая скрипт.
Любое действие через корутины может быть формализовано через процедуры, с точно такой же последовательностью выполнения и получения результатов. Любое.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 12:48:18
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока". А код постепенно превращается в "машину состояний". При добавлении новых этапов он становится всё громоздче и сложней. Отсюда и вывод для простых задач!
В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение. Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
В ~100 раз. Вы философ . 2. У вас есть понятие, что при использовании корутин надо синхронизироваться, если в них используются общие изменяемые данные? То есть следить за тем, чтобы данные недоделанные в одной корутине не использовались в другой. Вы когда-нибудь занимались параллельным программированием?
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 14:13:29
TGB, А Вам это о чем то говорит: ОС > Терминал > Lua? У Вас мощная машина, а у меня старенький 13 летний? 2. Еще в позапрошлом ВЕКЕ придумали "семафор" и он прекрасно справляется с пропусками поездов до сих пор. А пользоваться или нет параллельным программированием - решает пользователь для себя сам. Что касается меня так я примитивный пользователь - СЕМАФОР!
Зачем же вы его мучаете тяжелыми корутинами ? Когда можно легко обойтись легкими функциями. Вам же Nikolay все объяснил.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 14:53:07
TGB, Вы в начале полностью прочитайте обсуждение, а затем рекомендации выдавайте. Если рассмотреть пример с фреймворком то он значительно легче, если подобную логику выстраивать подходом с замыканиями.
По образованию инженер тяжело расстаюсь с техникой. А мой еще хоть куда, даст фору некоторым что сегодня в продаже. Это лучшая пока машинка из всех что были у меня (Sony, Toshiba, Asus ..) хотя и 3 поколение i7 прекрасно справляется с 3 квиками 5 браузерами и еще всякой всячиной. Проблема есть с WiFi старое поколение ограничена скорость приема данных 200, а нужно 1000.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 16:06:20
Все о великом да о великом! А элементарные вещи: Как при торговле на маржинальном счете Акциями, получить "Свободный денежный остаток"? Во Задача! Сколько лет уже пользуюсь QUIK но ответ на этот вопрос взывает смятение. Элементарный вопрос для каждого, оценить капитал в распоряжении. Стоимость Активов в бумагах + Свободные денежные средства = Активы клиента.
Как получить Эти "Свободные денежные средства", без выкрутасов? Во Задача?
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 16:44:33
Цитата
VPM написал: В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение. Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
Да нет ничего сложного писать такие же легкие функции и без корутин. Если под легкостью подразумевается "загнать в корутину длинную портянку с множественными yield", то это спорный вопрос, насколько это легко воспринимается.
Цитата
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока".
Ничего хранить вне замыкания не надо, оно само хранит на стеке свое состояние. Просто вызываете метод и он помнит окружение. Это кстати один из базовых методов организации своих колбеков, помещенных в очередь исполнения. Создали окружение, запихнули в очередь. И выполняете. Когда закончится выполнение, он сам вызовет колбек, который помнит все, чтобы отработать. Никаких дополнительных действий.
Думаю, что спорить дальше не стоит. Как уже писал, я корутины использую только для своих итераторов (hack-trade, кстати, и есть бесконечный итератор) или если надо пробросить varargs ... на следующий уровень. Более нужды нет. Любая длительная операция, требующую ожидания неопределенное время, выполняется через очередь задач, построенную на простых функциях, где-то замыканиях.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 16:45:28
Поле -* Свободно - Доступно для вывода средств при сохранении обеспеченности позиций либо открытия позиций по не маржинальным активам, с учетом заблокированных средств под активные заявки, с точностью валюты цены инструмента.
Соответствует значению параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель».
Для срочного рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения по клиентским счетам». параметр - lim_non_margin STRING Оценка денежных средств, доступных для покупки не маржинальных инструментов .
По факту - это средства доступные для торговли (для проведению торговых операций), А каково, как оформлено, судите сами?
Ну что тут скажешь, не в нашу копилочку талантов! Ну не специально же люди так старались?
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 17:08:04
Nikolay, Я с Вами не спорю, и ни чего не утверждаю, просто пытаюсь разобраться в возможностях LUA, то что подразумевается под понятием оптимизация, когда какой метод применять? Для себя некую шпаргалку сделать, пределы использования подхода. Да, обсуждение полезно, не много по другому взглянул на подходы. Замыкание использовал в основном при написании индикаторов там это логично. Ну чтобы с Вами окончательно согласиться или нет, нужна собственная история, буду пробовать. Надеюсь что не только мне было интересно и познавательно, но и многим нашим коллегам. Вам большое спасибо за предметное обсуждение.
Пользователь
Сообщений: Регистрация: 27.01.2017
31.10.2025 17:15:10
Ну так в индикаторах замыкания используются не зря. Это позволяет хранить стек между вызовами OnCalculate. Сделки смогут проходит раз в час. И вызовы будут помнить все, что было час назад. И не надо городить глобальных переменных, ничего передавать не надо (в этом плане примеры от ARQA некорректны, т.к. передают каждый раз настройки). Т.е. это конструктор некого алгоритма расчета. Да, это можно реализовать через корутины, а кто-то будет упорно доказывать, что это надо решать через классы, они ведь тоже помнят контекст. Тем более, что целое поколение всем вдалбливали, что ООП - это основа, основ. Но как все в истории повторяется, теперь уже не так активно стали это говорить, и даже больше, ООП - это не очень удачная затея в целом.
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 17:48:24
Да это ранее мы обсуждали, пока настройки передаю, не сильно затратно, но более надежно (ни куда не пропадают при "прыгании" по инструментам, тф.) . ООП в индикаторах тоже попробовал, мнения определенного пока не сложилось, понравилось что таблицы луа органично ложатся на этот подход, классная расширяемость модульность, такое в впечатление что он под луа и создавался (шучу), что не понравилось накладные больше, значительно сложней в отладке. Сейчас пишу небольшие задачи в двух вариантах подходов. Пытаюсь как мы с Вами сейчас разобраться, что для меня приемлемей.