Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 14:36:08
1. Структура данных ордера.
Код
OrderManager = {
pool = {}, -- все активные ордера по TRANS_ID
timeout_sec = 10 -- время ожидания исполнения
}
Каждый ордер хранит:
Код
-- контекст ордера
local order_ctx = {
trans_id = "12345", -- уникальный локальный ID
class = "TQBR",
sec = "SBER",
operation = "B", -- B / S
price = 123.45,
qty = 1,
status = "NEW", -- NEW / SENT / PARTIALLY_FILLED / FILLED / CANCELLED / REJECTED / TIMEOUT
order_num = nil, -- номер заявки на сервере QUIK
trades = {}, -- массив исполненных частей
timestamp = os.time()
}
2. Отправка ордера (атомарный цикл).
Код
function OrderManager:send(order)
local trans_id = tostring(math.random(1000000,9999999))
order.trans_id = trans_id
order.status = "NEW"
order.timestamp = os.time()
self.pool[trans_id] = order
local txn = {
ACCOUNT = ACCOUNT,
CLIENT_CODE = CLIENT_CODE,
CLASSCODE = order.class,
SECCODE = order.sec,
ACTION = "NEW_ORDER",
OPERATION = order.operation,
PRICE = tostring(order.price),
QUANTITY = tostring(order.qty),
TYPE = "L",
TRANS_ID = trans_id
}
local result = sendTransaction(txn)
if result ~= "" then
log(string.format("[%s] x Ошибка отправки: %s", order.sec, result))
order.status = "REJECTED"
return false
else
order.status = "SENT"
log(string.format("[%s] v Ордер отправлен (TRANS_ID=%s)", order.sec, trans_id))
return true
end
end
3. Колбэк OnTransReply.
Код
function OnTransReply(tr)
local ctx = OrderManager.pool[tr.trans_id]
if not ctx then return end
if tr.status == 3 then
ctx.order_num = tr.order_num
log(string.format("[%s] v Ордер принят биржей (order_num=%s)", ctx.sec, ctx.order_num))
elseif tr.status >= 4 then
ctx.status = "REJECTED"
log(string.format("[%s] x Ордер отклонен: %s", ctx.sec, tr.result_msg))
OrderManager.pool[tr.trans_id] = nil
end
end
4. Колбэк OnOrder (обновление состояния).
Код
function OnOrder(ord)
for _, ctx in pairs(OrderManager.pool) do
if ctx.order_num and ctx.order_num == ord.order_num then
ctx.balance = ord.balance
if ctx.balance == 0 then
ctx.status = "FILLED"
log(string.format("[%s] v Ордер полностью исполнен", ctx.sec))
elseif ord.balance < ctx.qty then
ctx.status = "PARTIALLY_FILLED"
log(string.format("[%s] v Частичное исполнение: %d/%d", ctx.sec, ctx.qty-ord.balance, ctx.qty))
end
end
end
end
5. Колбэк OnTrade (фиксируем сделки).
Код
function OnTrade(trade)
for _, ctx in pairs(OrderManager.pool) do
if ctx.order_num and ctx.order_num == trade.order_num then
table.insert(ctx.trades, {
trade_num = trade.trade_num,
qty = trade.qty,
price = trade.price,
dir = trade.flags % 2 == 0 and "B" or "S"
})
end
end
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 14:25:59
Тогда, Atomic Order Lifecycle (AOL) контроллер для QUIK на Lua.
Идея: мы создаём отдельный модуль OrderManager, который обеспечивает атомарный жизненный цикл ордера независимо от стратегии. Стратегия просто говорит: «открыть лонг / шорт», а менеджер следит за статусом, частичным исполнением, таймаутами и отменами. Следовательно: [*]
Вся логика отправки, ожидания, исполнения, таймаута и отмены — централизована в OrderManager.
[*]
Стратегия просто делает запрос на ордер и получает атомарное событие исполнения.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 13:50:55
А если жизненный цикл (путь), расписать по шагам в конкретные процедуры (как Nikolay, ) подход сам напрашивается. И что делать с ожиданиями? Нужен фоновый подход?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 13:44:40
Разбираюсь с жизненным циклом заявки, наткнулся на подход Atomic Order Lifecycle (AOL) представляет собой последовательность этапов, через которые проходит ордер в торговой системе. Все этапы жизненного цикла ордера — от его создания и отправки до исполнения, таймаута или отмены — должны быть атомарными, т.е. все операции должны завершаться
* либо успехом (ордер выполнен), * либо ошибкой (ордер отменён или отказан).
Это гарантирует, что трейдер или торговая система всегда знает, в каком состоянии находится ордер и что с ним происходит.
Процесс жизненного цикла ордера в торговой системе можно разбить на следующие этапы:
Создание ордера
Отправка ордера
Ожидание принятия
Ожидание исполнения
Исполнение
Таймаут или отказ
Отмена ордера
Правильная обработка каждого из этих этапов и корректная реакция на возможные ошибки позволяют эффективно управлять ордерами и минимизировать риски на финансовых рынках. Но что делать в ситуации когда нет атомарной гарантии "all-or-nothing": ПРОБЛЕМА: Частичное исполнение нарушает атомарность? Или другая, ПРОБЛЕМА: Разные идентификаторы на разных этапах? Непонятно?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 13:34:22
Nikolay, Супер подход, на каждом шаге процедура, так? Я даже не задумывался о такой возможности.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 10:05:03
Как поступлю. Адаптируем “умный” блок (SmartOrder, reply, sdelka, обработчики событий QUIK) в уже готовый скрипт, чтобы он:
поддерживал открытие / закрытие позиций (лонг и шорт),
корректно работал через callbacks,
не зависел от ожиданий (основной поток не блокируется),
сохранял информацию о транзакциях и сделках в reply / sdelka,
и синхронизировался с реальными ордерами QUIK.
Что изменилось и почему это круто, судите сами;
Было
Стало
send_and_wait с циклом ожидания
send_order_async — не блокирует поток, обрабатывает ответ асинхронно
Прямые проверки result_msg
Переход на централизованное хранилище SmartOrder.pool
Потеря информации о транзакции
Вся история сохраняется в reply и sdelka
Не обновлялась позиция
Позиции обновляются автоматически при OnTrade
Возможна гонка данных
Каждая транзакция отслеживается независимо через свой trans_id
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 09:42:52
Теперь относительно самого кода: Что можно сделать и что важно знать?
Отрицательные / нулевые цены — проверяем и игнорируем, пока не придёт реальная сделка (OnTrade).
Пакеты приходят неупорядоченно — полагаемся на локальную метку - os.time(), при несоответствии времени пакета можно игнорировать «старые» пачки.
sendTransaction ≠ сделка — сделать транзакционный цикл: (отправка → ожидание принятия → ожидание исполнения → таймаут → отмена).
OnOrder / OnTrade — обязательные точки контроля. Без них нельзя корректно знать цену исполнения и состояние позиции?
Закрытие позиций на стоп — реализовать опционально флаг CLOSE_POS_STOP.
Адаптация к брокеру / версии QUIK — нужно проверить реальные поля, которые приходят в OnOrder / OnTrade от брокера, и использовать парсер.
Обратите внимание что в этом подходе есть скрытые зависимости и они могут вносить свою лепту.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
02.11.2025 09:24:22
Еще раз про код, для тех кто рискнет пробовать и разбираться, обратите внимание на замечания от Nikolay, все они имеют место быть, всё что перечислено реально критично для боевого робота. Нужна конкретная переработка подхода + рабочая, практичная версия кода, да и сам подход желает лучшего. Я своей целью ставил демонстрацию возможного применения корутин, и максимально сложного написания аналога с помощью подхода использования замыканий на луа без сторонних библиотек. Это просто не кая демонстрация возможностей.
Автозапуск скрипта LUA при старте QUIK
Пользователь
Сообщений: Регистрация: 15.06.2023
01.11.2025 16:18:03
Helen, Вы просто выкладывайте с чем, Вам нужно разобраться, и сообщество откликнется. Если же Вы хотите заказать разработку, то это скорее на специализированные сайты, здесь кто продает свои разработки подписываются ссылкой на сайты. Удачи.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
01.11.2025 11:58:14
С утра "чесались руки" слепил из того что было, хочу такой же с замыканиями и таблицей состояний сделать. Ну и сравнить. За анализ благодарю! А Страх и Смелость просто не обходимы!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
01.11.2025 10:05:45
Пример карутинного элегантного подхода.
ВНИМАНИЕ! РЕАЛЬНО ТОРГУЕТ! Для начала закомментируйте вывод заявок! Вместо отправке поставьте сообщение. Это просто демонстрация возможностей! "Иметь или не иметь" решаем самостоятельно.
Код
- Pобот - торговый менеджер с реальным риск-контролем QUIK
--[[ Цель. Создать систему, которая:
1. Определяет начальный капитал (из QUIK).
2. Каждые несколько секунд получает текущую оценку капитала.
3. Вычисляет просадку в процентах от начального капитала.
4. Если просадка превышает лимит (например, 2%), —
останавливает все стратегии, фиксирует в логах и выводит уведомление.
--]]
--[[Пример: простая стратегия на основе корутины!
Идея: Следим за ценой инструмента (SBER), и
если она падает больше чем на "drop_trigger %" от последней зафиксированной — покупаем 1 лот.
Если поднимается больше чем на "drop_trigger %"% — продаём 1 лот.
Все операции выполняются пошагово, без блокировки основного потока. --]]
local is_run = true
------------------------------------------------------------
-- === Конфигурация ===
------------------------------------------------------------
local ACCOUNT = ""
local CLIENT_CODE = ""
local FIRM_ID = ""
local order_type = "LIMIT"
local time_in_force = "GTC"
local LIMIT_KIND = 0 -- 0 = по деньгам
local RISK_LIMIT = -0.02 -- максимум 2% просадки
local LOT_SIZE = 1
local drop_trigger = 0.001
local take_profit = 0.002
local stop_loss = 0.001
local instruments = {
{ class = "TQBR", sec = "SBER" },
{ class = "TQBR", sec = "GAZP" },
{ class = "TQBR", sec = "ROSN" },
}
------------------------------------------------------------
-- === Логирование ===
------------------------------------------------------------
-- Объявляем log_file глобально для скрипта
local log_file; --= getScriptPath() .. "\\robot_capital_risk_log.txt"
-- Функция для логирования
local function log(msg)
local line = os.date("%Y-%m-%d %H:%M:%S") .. " | " .. msg
message(line)
local f = io.open(log_file, "a")
if f then
f:write(line .. "\n")
f:close()
else
message("x Не удалось открыть файл для записи: " .. log_file)
end
end
--[[ ЭЛЕГАНТНАЯ ФУНКЦИЯ ОКРУГЛЕНИЯ удалением ,0]]--
local round = function (num, idp)
-- Если num некорректное, вернуть как есть
if not num or type(num) ~= "number" then return num end
-- добавbv обработку очень малых чисел:
if math.abs(num) < 1e-10 then return 0 end -- ДОБАВИТЬ
-- Если idp не указан, использовать 0 (округление до целого числа)
idp = idp or 0
local mult = 10^idp
-- Универсальное Округление для любого числа
local rounded = num >= 0 and math.floor(num * mult + 0.5) / mult or num < 0 and math.ceil(num * mult - 0.5) / mult or 0
-- Если число целое, убрать .0
if rounded == math.floor(rounded) then
return math.floor(rounded)
end
return rounded
end
local function fit(price, step, scale)
local result = math.floor(price / step) * step;
log('result = '..tostring(round(result, scale)) );
return round(result, scale)
end
------------------------------------------------------------
-- === Модуль Risk Manager (по реальному капиталу) ===
------------------------------------------------------------
-- Получаем текущий капитал клиента (денежный баланс в рублях или общие активы)
local function get_current_capital()
--* Свободно - Доступно для вывода средств при сохранении обеспеченности позиций либо открытия позиций по немаржинальным активам, с учетом заблокированных средств под активные заявки, с точностью валюты цены инструмента. Соответствует значению параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель». Для срочного рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения по клиентским счетам»
-- lim_non_margin STRING Оценка денежных средств, доступных для покупки немаржинальных инструментов
if instruments and instruments[1] and instruments[1].class == "TQBR" then
-- Если не удалось — пробуем через портфель
local pf = getPortfolioInfoEx(FIRM_ID, CLIENT_CODE, 2)
if pf and pf.lim_non_margin then
-- return tonumber(pf.assets)
--message( "Свободные средства для покупки немаржинальных активов: ".. tostring(pf.lim_non_margin) )
return tonumber(pf.lim_non_margin)
end
end
if instruments and instruments[1] and instruments[1].class == "SPBFUT" then
local limits = getLimitInfo(FIRM_ID, CLIENT_CODE)
if limits and limits["План. чист. поз."] then
local free_for_futures = tonumber(limits["План. чист. поз."])
message(string.format("Свободные средства для открытия чистых позиций на срочном рынке: %.2f руб.", free_for_futures))
else
message("Не удалось получить информацию о свободных средствах для открытия позиций на срочном рынке.")
end
end
-- Если ничего не удалось получить — вернём nil
return nil
end
local Risk = {
start_capital = nil,
current_capital = nil,
total_change = 0.0
}
-- Инициализация начального капитала
function Risk:init()
self.start_capital = get_current_capital()
if not self.start_capital then
log("x Не удалось определить начальный капитал!" .. tostring(self.start_capital) )
self.start_capital = 1
else
log(string.format("v Стартовый капитал: %.2f руб.", self.start_capital))
end
end
-- Проверка текущего состояния
function Risk:check()
local capital = get_current_capital()
if not capital then
coroutine.yield()
return
end
self.current_capital = capital
self.total_change = (capital - self.start_capital) / self.start_capital
log(string.format("v Текущий капитал: %.2f руб. (%.2f%%)",
capital, self.total_change * 100))
if self.total_change <= RISK_LIMIT then
log(string.format("v Просадка %.2f%% превысила лимит %.2f%% — остановка торгов!",
self.total_change * 100, RISK_LIMIT * 100))
is_run = false
end
end
------------------------------------------------------------
-- === Отправка заявок ===
------------------------------------------------------------
local function send_order(class, sec, direction, price)
local order = {
CLASSCODE = class,
SECCODE = sec,
ACCOUNT = ACCOUNT,
CLIENT_CODE = CLIENT_CODE,
OPERATION = direction,
PRICE = tostring(price),
QUANTITY = tostring(LOT_SIZE),
TYPE = "L",
ACTION = "NEW_ORDER",
TRANS_ID = tostring(math.random(1000000, 9999999))
}
local res = sendTransaction(order)
if res ~= "" then
log(string.format("[%s] x Ошибка при заявке: %s", sec, res))
else
log(string.format("[%s] v %s по %.2f (%d)", sec,
direction == "B" and "Куплено" or "Продано", price, LOT_SIZE))
end
end
------------------------------------------------------------
-- === Стратегия по одному инструменту ===
------------------------------------------------------------
local function strategy(class, sec)
local base_price = nil
log(string.format("[%s] v Старт стратегии", sec))
local step = tonumber(getParamEx(class, sec, "sec_price_step").param_value)
local scale = tonumber(getParamEx(class, sec, "sec_scale").param_value)
while is_run do
local price = tonumber(getParamEx(class, sec, "LAST").param_value)
if not price or price <= 0 then
coroutine.yield()
else
if not base_price then
base_price = price
log(string.format("[%s] Базовая цена: %.2f", sec, price))
end
while is_run do
local cur = tonumber(getParamEx(class, sec, "LAST").param_value)
if cur and cur > 0 then
local drop = (cur - base_price) / base_price
if drop <= -drop_trigger then
log(string.format("[%s] v Падение %.2f%% > Покупка", sec, drop * 100))
cur = fit(cur, step, scale)
send_order(class, sec, "B", cur)
local entry = cur
-- Контроль позиции
while is_run do
local now = tonumber(getParamEx(class, sec, "LAST").param_value)
if now then
local change = (now - entry) / entry
if change >= take_profit then
log(string.format("[%s] Тейк +%.2f%% > Продажа", sec, change * 100))
now = fit(now, step, scale)
send_order(class, sec, "S", now)
base_price = now
break
elseif change <= -stop_loss then
log(string.format("[%s] Стоп %.2f%% > Продажа", sec, change * 100))
now = fit(now, step, scale)
send_order(class, sec, "S", now)
base_price = now
break
end
end
coroutine.yield()
end
log(string.format("[%s] Позиция закрыта, возвращаемся к ожиданию.", sec))
break
end
end
coroutine.yield()
end
end
coroutine.yield()
end
log(string.format("[%s] x Стратегия завершена", sec))
end
------------------------------------------------------------
-- === Менеджер стратегий ===
------------------------------------------------------------
local Manager = {}
Manager.tasks = {}
function Manager:add_strategy(class, sec)
local co = coroutine.create(function()
strategy(class, sec)
end)
table.insert(self.tasks, {co = co, class = class, sec = sec})
log(string.format("[%s] v Добавлена стратегия", sec))
end
function Manager:run_all()
local check_interval = os.time()
while is_run do
-- Проверка капитала каждые 5 секунд
if os.time() - check_interval >= 5 then
Risk:check()
check_interval = os.time()
end
for _, task in ipairs(self.tasks) do
local co = task.co
if coroutine.status(co) == "dead" then
log(string.format("[%s] Перезапуск стратегии", task.sec))
task.co = coroutine.create(function()
strategy(task.class, task.sec)
end)
else
local ok, err = coroutine.resume(co)
if not ok then
log(string.format("[%s] Ошибка: %s", task.sec, tostring(err)))
task.co = coroutine.create(function()
strategy(task.class, task.sec)
end)
end
end
end
sleep(300)
end
log("x Менеджер остановлен (риск или пользователь).")
end
------------------------------------------------------------
-- === Основной запуск ===
------------------------------------------------------------
function main()
math.randomseed(os.time())
log("v Запуск торгового менеджера с реальным риск-контролем...")
Risk:init()
for _, inst in ipairs(instruments) do
Manager:add_strategy(inst.class, inst.sec)
end
Manager:run_all()
end
------------------------------------------------------------
-- === Завершение ===
------------------------------------------------------------
function OnStop()
is_run = false
log("v Скрипт остановлен пользователем.")
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 17:48:24
Да это ранее мы обсуждали, пока настройки передаю, не сильно затратно, но более надежно (ни куда не пропадают при "прыгании" по инструментам, тф.) . ООП в индикаторах тоже попробовал, мнения определенного пока не сложилось, понравилось что таблицы луа органично ложатся на этот подход, классная расширяемость модульность, такое в впечатление что он под луа и создавался (шучу), что не понравилось накладные больше, значительно сложней в отладке. Сейчас пишу небольшие задачи в двух вариантах подходов. Пытаюсь как мы с Вами сейчас разобраться, что для меня приемлемей.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 17:08:04
Nikolay, Я с Вами не спорю, и ни чего не утверждаю, просто пытаюсь разобраться в возможностях LUA, то что подразумевается под понятием оптимизация, когда какой метод применять? Для себя некую шпаргалку сделать, пределы использования подхода. Да, обсуждение полезно, не много по другому взглянул на подходы. Замыкание использовал в основном при написании индикаторов там это логично. Ну чтобы с Вами окончательно согласиться или нет, нужна собственная история, буду пробовать. Надеюсь что не только мне было интересно и познавательно, но и многим нашим коллегам. Вам большое спасибо за предметное обсуждение.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 16:45:28
Поле -* Свободно - Доступно для вывода средств при сохранении обеспеченности позиций либо открытия позиций по не маржинальным активам, с учетом заблокированных средств под активные заявки, с точностью валюты цены инструмента.
Соответствует значению параметра «НаПокупкуНеМаржин» в таблице «Клиентский портфель».
Для срочного рынка соответствует значению параметра «План. чист. поз.» в таблице «Ограничения по клиентским счетам». параметр - lim_non_margin STRING Оценка денежных средств, доступных для покупки не маржинальных инструментов .
По факту - это средства доступные для торговли (для проведению торговых операций), А каково, как оформлено, судите сами?
Ну что тут скажешь, не в нашу копилочку талантов! Ну не специально же люди так старались?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 16:06:20
Все о великом да о великом! А элементарные вещи: Как при торговле на маржинальном счете Акциями, получить "Свободный денежный остаток"? Во Задача! Сколько лет уже пользуюсь QUIK но ответ на этот вопрос взывает смятение. Элементарный вопрос для каждого, оценить капитал в распоряжении. Стоимость Активов в бумагах + Свободные денежные средства = Активы клиента.
Как получить Эти "Свободные денежные средства", без выкрутасов? Во Задача?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 14:53:07
TGB, Вы в начале полностью прочитайте обсуждение, а затем рекомендации выдавайте. Если рассмотреть пример с фреймворком то он значительно легче, если подобную логику выстраивать подходом с замыканиями.
По образованию инженер тяжело расстаюсь с техникой. А мой еще хоть куда, даст фору некоторым что сегодня в продаже. Это лучшая пока машинка из всех что были у меня (Sony, Toshiba, Asus ..) хотя и 3 поколение i7 прекрасно справляется с 3 квиками 5 браузерами и еще всякой всячиной. Проблема есть с WiFi старое поколение ограничена скорость приема данных 200, а нужно 1000.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 14:13:29
TGB, А Вам это о чем то говорит: ОС > Терминал > Lua? У Вас мощная машина, а у меня старенький 13 летний? 2. Еще в позапрошлом ВЕКЕ придумали "семафор" и он прекрасно справляется с пропусками поездов до сих пор. А пользоваться или нет параллельным программированием - решает пользователь для себя сам. Что касается меня так я примитивный пользователь - СЕМАФОР!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
31.10.2025 12:48:18
Да, но в подходе с замыканиями - приходится вручную хранить состояние "этапа" в цикле "подожди, пока". А код постепенно превращается в "машину состояний". При добавлении новых этапов он становится всё громоздче и сложней. Отсюда и вывод для простых задач!
В подходе с корутинами. Никаких ручных "этапов" — код читается как обычный последовательный сценарий. Можно использовать yield где угодно, чтобы "заморозить" выполнение. Можно легко добавить ожидание событий, сетевые операции и т.д. Логика выглядит линейно, но выполняется асинхронно.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 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 это единственный безопасный способ организовать "многозадачность" без внешних библиотек.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 18:15:49
Подсобрался с мыслями. Можно некий итог подвести.
Различия двух подходов, про применение см. выше мнение не поменял.
1. Подход с замыканием. Нет возможности приостанавливать сложные задачи на середине выполнения. Сложно реализовать ожидание событий или таймеров внутри задачи без внешнего кода. Каждая задача должна сама заботиться о том, как уступать управление (через sleep в основном цикле).
2. Подход с корутиной. Внутри корутины можно писать сложные алгоритмы и «разбивать» их на шаги. Более гибкая модель. Можно приостанавливать задачу на любом шаге. Можно легко комбинировать несколько фоновых задач в одном цикле. Более похоже на настоящие асинхронные потоки. Сложнее. Немного больше накладных расходов на создание и управление корутиной (хотя для QUIK это не критично). coroutine.yield() - приостанавливает выполнение задачи, позволяя основному циклу выполняться и управлять её запуском.
Пока разбирались на кидал лёгкий планировщик фоновых задач для QUIK. Всем пока хорошего кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 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
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 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
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 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 — она живёт, имеет собственный контекст и исполняется пошагово.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 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() — просто планировщик, который возобновляет корутины.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 15:42:13
Цитата
Nikolay написал: А значит выполняться она может тоже только через вызовы в основном цикле mian. И тоже частота вызовов регулируется задержкой цикла main.Собственно ваш любимый hacktrade так и работает.
Вы не поняли сути hacktrade, как раз он как пример такой асинхронности.
1. При первом в ходе создается корутина и мы работаем в ее цикле, а у нее никаких задержек, (кроме накладных), в ней идет вся торговая логика расчеты, вычисление и так далее. Останавливаем исполнение когда выполнены условия на отправку заявки и заявка отправлена (выполняется yield).
2. Структурно код стал на выполнение в цикле маин (с задержками sleep) функционально идет работа с заявкой. Где тут последовательность? Самая что не на есть асинхронность.
Выполнение кода структурно разделено на две составляющие: А) Поиск условия выполнения заявки (в цикле корутины); Б) Не посредственное исполнение заявки (взаимодействие с апи квик - в цикле маин).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 14:53:51
Смотрим внимательно, сравниваю эти два подхода.
На первый взгляд оба примера — "фоновые циклы" в QUIK, но они не эквивалентны и не взаимозаменяемы?
Это разные подходы к организации фоновой работы:
Вариант 1 — "корутина как фоновый поток".
local co = coroutine.create(worker) while is_run do coroutine.resume(co) sleep(1000) end
Вариант 2 — "итераторы (замыкания) как фоновые задачи".
local worker1 = counter(1, 5, print) local worker2 = counter(2, 20, print)
while is_run do if worker1 and worker1() then worker1 = nil end --... sleep(100) end
Различие по сути:
| Критерий | Вариант 1 (корутина) | Вариант 2 (итераторы/счётчики) | | ---------------------------- | ------------------------------------ | ------------------------------ | | Тип выполнения | Асинхронное (через yield) | Синхронное (через цикл) | | Внутреннее состояние | Контекст сохраняется автоматически | Состояние хранится в замыкании | | Можно делать yield внутри | Да | Нет | | Можно использовать sleep() | Только в main, не в worker | В основном цикле | | Уровень сложности | Средний | Простой | | Производительность | Чуть выше накладных вызовов | Зависит от частоты цикла | | Где применять | Долгие фоновые задачи | Мелкие периодические проверки |
Вывод. Не взаимозаменяемы!
Первый вариант — "реальный фон через корутину" (асинхронная модель). Второй — "упрощённый псевдопараллельный цикл" (итераторы).
Мнение.
1. Если нужно имитировать многопоточность (параллельно опрашивать QUIK, считывать данные и т.п.) -> вариант с корутиной. 2. Если просто нужно выполнять несколько лёгких задач с разной частотой -> вариант с замыканиями/итераторами.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 13:57:35
Нет, дело тут не в счетчике, счетчик в моем примере это просто минимальная операция для примеров. Дело в этом:
Цитата
Nikolay написал: Вместо теста скорости можно вставить любую периодическую задачу: * запрос рыночных данных (getParamEx), * обновление таблиц QUIK, * контроль позиций и алертов, * логирование в файл.и так далее.
Корутина превращает прямолинейную реализацией - последовательное чтение функций, в не линейное исполнение разных задач. В едином потоке луа появляется, как бы несколько раздельно выполняемых задач. Мы же можем к сопрограммам написать и менеджер, по их управлению.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 12:39:49
Цитата
Nikolay написал: Корутина с остановкой удобна, если надо запомнить состояние и вернуться к выполнению
Так это и есть ключ. Помнит место остановки и туда возвращается. Если подобное исполнение делать с помощью функции, нужно что то наверное в парадигме машины состояний. А затем придется еще этим состояниями управлять.
По чему мне нравится подход с корутинами. Логику можно строить так, как мы с Вами это сейчас обсуждаем. Вот прямо могу написать код обсуждения, асинхронно получить время, послушать новости, и еще чего то там. Мне кажется круто! Кстати навело на мысль попробовать в отдельной корутине отслеживать состояние ордеров, сейчас двух факторная по транс ид и номеру ордера из колбеков, а что если не зависимо все подтвердили тогда только учитываем? Попробую.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 12:12:00
Дело тут не в терминологии, а в особенностях применения сопрограмм в Lua, и те возможностях которые возникают от их применения. Исполнять код по принципу "который нужно, когда нужно"!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 11:30:59
Вот и Вы туда же? Цель:
Цитата
VPM написал: сделать фоновый поток в QUIK с использованием корутины, без блокировки терминала и с периодическим выводом результата.
Скорость ограничена скорость получения данных, "Не прыгнешь выше своей головы":
Цитата
VPM написал: И главное здесь, сама система: "Биржа - Сервер - Терминал - Скрипт"
Измерение скорости в наших условиях для наших задач, нужно только для оптимизации скрипта. А у нашего "Профессора", идет путаница, он пытается обрабатывать большие массивы, где безусловно важным факторам является скорость операций, с нашими повседневными задачами, ограниченными по скорости передачи данных. Это и пытаюсь донести, обижается? Насчет смысла, смыл писать эффективный код, как же нет?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 11:10:38
Nikolay, На примере код TGB, выложил два простых скрипта, различных по своей архитектуре. Приведите пример Вашего подхода, возможно он действительно будет оптимальной и лучше? Я ведь на самом то деле, ни чего не отрицаю и ни утверждаю, а декларирую возможности Lua, и возможности создавать шедевры. Давайте сравним, всем будет интересно! Возможно я заблуждаюсь?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 10:42:37
Ну и последнее. Для Профессора и не только.
Приведу пример, как сделать фоновый поток в QUIK с использованием корутины, без блокировки терминала и с периодическим выводом результата.
--- Цель. Скрипт main() должен:
* стартовать и создать фоновый поток, * этот поток будет каждые несколько секунд выполнять тест, * не блокировать работу QUIK, * безопасно завершаться при остановке скрипта.
Код
--- Рабочий пример фонового скрипта QUIK с корутиной
local is_run = true -- глобальный флаг для остановки фоновой задачи
function main()
message("Скрипт запущен. Идёт фоновое измерение производительности...")
-- создаём корутину (фоновую задачу)
local co = coroutine.create(worker)
-- основной цикл QUIK
while is_run do
local ok, err = coroutine.resume(co)
if not ok then
message("Ошибка в корутине: " .. tostring(err))
break
end
sleep(1000) -- основной поток спит 1 сек между циклами
end
message("Скрипт остановлен.")
end
-- фоновая функция
function worker()
local N = 100000
local c, f = 0, 0
local function foo()
f = f + 1
end
local co_task = coroutine.create(function()
while true do
c = c + 1
coroutine.yield()
end
end)
while is_run do
local TT1 = os.clock()
for i = 1, N do
local ok, err = coroutine.resume(co_task)
if not ok then
message("Ошибка в co_task: " .. tostring(err))
break
end
end
TT1 = (os.clock() - TT1) * 1000
local TT2 = os.clock()
for i = 1, N do
foo()
end
TT2 = (os.clock() - TT2) * 1000
local out = string.format(
"Фон: N=%d, coroutine=%.3f мс (c=%d), func=%.3f мс (f=%d), T1/T2=%.2f",
N, TT1, c, TT2, f, TT1 / TT2
)
message(out)
sleep(3000) -- измерение каждые 3 секунды
end
end
function OnStop()
is_run = false
message("Останавливаем фоновую задачу...")
end
Вывод:
TYPE DATE TIME MESSAGE
1 1 29.10.2025 10:31:19 Скрипт запущен. Идёт фоновое измерение производительности...
2 1 29.10.2025 10:31:20 Фон: N=100000, coroutine=584.000 мс (c=100000), func=6.000 мс (f=100000), T1/T2=97.33
3 1 29.10.2025 10:31:23 Фон: N=100000, coroutine=604.000 мс (c=200000), func=7.000 мс (f=200000), T1/T2=86.29
4 1 29.10.2025 10:31:27 Фон: N=100000, coroutine=586.000 мс (c=300000), func=7.000 мс (f=300000), T1/T2=83.71
5 1 29.10.2025 10:31:30 Фон: N=100000, coroutine=553.000 мс (c=400000), func=7.000 мс (f=400000), T1/T2=79.00
6 1 29.10.2025 10:31:34 Фон: N=100000, coroutine=614.000 мс (c=500000), func=7.000 мс (f=500000), T1/T2=87.71
7 1 29.10.2025 10:31:38 Фон: N=100000, coroutine=550.000 мс (c=600000), func=7.000 мс (f=600000), T1/T2=78.57
8 1 29.10.2025 10:31:41 Фон: N=100000, coroutine=555.000 мс (c=700000), func=7.000 мс (f=700000), T1/T2=79.29
9 1 29.10.2025 10:31:45 Фон: N=100000, coroutine=544.000 мс (c=800000), func=6.000 мс (f=800000), T1/T2=90.67
10 1 29.10.2025 10:31:45 Останавливаем фоновую задачу...
11 1 29.10.2025 10:31:49 Скрипт остановлен.
--- Как это работает:
| Часть | Что делает | | ------------ | ---------------------------------------------------------------------------------------- ------------------------------------------| | main() | Запускается QUIK ом. Создаёт и запускает корутину worker(). | | worker() | Основная логика теста — циклически выполняет измерения и выдаёт результат в message(). | | sleep() | Позволяет не блокировать интерфейс и экономит CPU. | | OnStop() | Срабатывает при остановке скрипта пользователем — корректно завершает цикл. |
--- Что можно делать в фоне?
Вместо теста скорости можно вставить любую периодическую задачу: * запрос рыночных данных (getParamEx), * обновление таблиц QUIK, * контроль позиций и алертов, * логирование в файл. и так далее.
Корутины в QUIK — это идеальный инструмент для таких сценариев, они позволяют делать "псевдопотоки", не мешая интерфейсу и другим скриптам!!!
Это и есть основной смысл и задача Корутин в QUIK! Надеюсь убедил? Всем хорошего кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 09:54:54
Помним! Время работы корутин в QUIK может зависеть от множества факторов: * нагрузки платформы, * количества исполняющихся скриптов, * задержек в сети и так далее.
Код
--[[Помним!
Время работы корутин в QUIK может зависеть от множества факторов:
* нагрузки платформы,
* количества исполняющихся скриптов,
* задержек в сети
и так далее.
--]]
-- Переписанный пример с использованием корутин и пустой функции в QUIK в формате кода Lua:
--local message = message or print;
local run = true
function main()
local N = 100000
local c,f = 0,0
-- создаем корутину, которая будет выполнять асинхронную задачу
local co = coroutine.create(function()
local yield = coroutine.yield
while true do
-- можно выполнять любую логику
c = c + 1
yield() -- здесь задача будет приостанавливаться
end
end)
-- простая функция, которая ничего не делает
local function foo1()
f = f + 1
return f
end
local out = 'Результат теста: количество вызовов = ' .. N .. ', время вызова сопрограммы '
while true do
-- замер времени для корутины
local TT1 = os.clock()
for i = 1, N do
local ok, err = coroutine.resume(co) -- возобновляем выполнение корутины
if not ok then
message("Ошибка при выполнении корутины: " .. err)
break
end
end
TT1 = (os.clock() - TT1) * 1000
message("TT1: " .. TT1 .."; c = " .. c)
-- замер времени для обычной функции
local TT2 = os.clock()
for i = 1, N do
foo1()
end
TT2 = (os.clock() - TT2) * 1000
message("TT2: " .. TT2 .."; f = " .. f)
-- вывод результата
out = out .. string.format("%.3f мс, функции %.3f мс, T1/T2 = %.2f", TT1, TT2, TT1 / TT2)
message(out)
return
end
run = false
end
Результаты у одного брокера:
TYPE DATE TIME MESSAGE
1 1 29.10.2025 9:47:15 TT1: 555.00000000029; c = 100000
2 1 29.10.2025 9:47:15 TT2: 7.9999999998108; f = 100000
3 1 29.10.2025 9:47:15 Результат теста: количество вызовов = 100000, время вызова сопрограммы 555.000 мс, функции 8.000 мс, T1/T2 = 69.38
Ну по крайней мере, что то похожее на обсуждение!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 08:38:10
TGB, В QUIK задача function main() создать поток в котором исполняется скрипт (с корутинами, либо без них) , именно так не иначе, Но Вы то зачем так, как "Профессор" передергиваете?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 08:10:23
Совсем упустил. Просто на помню Профессору: "Нечеткое множество — это объект, а нечеткая логика — это система правил для работы с такими объектами." Так я про систему правил, ни ни про множество! И тут Профессор все передернул, а зачем? Помним "Образ/Подобие", "Объект/Система".
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
29.10.2025 08:01:24
Профессионалу от дилетанта:
1. Начну с начала (хотя у Вас почему то суть в конце?). Суть: "Было бы неплохо, если бы можно было бы обсуждать на форуме конкретные алгоритмы для торговых роботов на луа для QUIK," Читаем название Вкладки "Программирование на языке Lua". Написать три буквы "L, U, A" с точки зрения "профессора по написанию торговых роботов на луа для QUIK" - это высший пилотаж в обсуждении?
2. "Видящий да увидит, слышащий да услышит!". Темы которые я иногда затрагиваю напрямую относятся к торговым алгоритмам, а подходы описанные за чистую Вы не найдете ни в одном учебнике. Судить о них позволяет мое базовое образование (времен когда еще в медицине давали клятву Гипократа, а поколения не делились по признакам знания высказывания "Сообразить на троих"). Идеи выложенные на форуме не каждому дано понять, и здесь нужно просто понимать, что у Все разные способности, кто то хороший доктор, кто то адвокат, а торговать могут все?
3. Не большой секрет. Торговать на бирже в рамках данного форума, подключить э. устройство к серверу QUIK, и в путь (не нужно ни куда ходить?).
4. Про любимую тему профессора, замеры скоростей. В первую очередь нужно научиться отличать "Образ/Подобие". Ни слова про оптимизацию скриптов, а про быстродействие и скорости в ущерб функциональности, удобству, универсальности. И главное здесь, сама система: "Биржа - Сервер - Терминал - Скрипт", поймете это само собой все отпадет.
Ну и конечно в Ваших разработках всяческой удачи. Читаем пункт 1.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.10.2025 14:29:28
Уважаемый nikolz, Вы поймите одну простую истину, здесь пользователи собрались, для ТОРГОВЛИ, а не для изучения языков программирования, тем более таких как Си.
Что касается меня так, я уже не помню как писать на Бейсик и Фортран, уж не приходится говорить о Си. C Lua разбираюсь по тому что он встроен в терминал, с таким же успехом разбирался бы с любым другим. На нем можно проверять свои торговые идеи, и не только, атематические торговые программы, с гордым названием Робот. Я пишу про это. Для этого не нужен ни Си ни какой другой язык, Lua с избытком. Даже он в некоторых случаях сложен, если учитывать как реализован сам торговый терминал. Язык встроенный необходим нам для автоматизации торговых решений. Если уж писать то грамотно, приходится придерживаться нескольких основополагающих принципов.
А для того чтоб торговать вообще не нужны ни какие языки, да и образования достаточно царской - приходской школы, арифметики. И причем тут Ваши изыски?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
28.10.2025 08:35:14
Цитата
nikolz написал: Еще надежнее вообще без функций на луа.
Большинство так и пишет.
Цитата
nikolz написал: 17.2 пустая корутина 0.6 пустая функция 0.4 пустой if
Скорость исполнения полезно знать, но не нужно путать задачи?
* If - встроенный оператор сравнения, и так понятно что самая быстрая операция (фильтрация, больше не для чего ни годится); * функция - разделение кода по функциональности, (полную задачу делим, хотя бы чтоб можно было читать); * корутина - это сервис для исполнения минимального кода, что бы была возможность "за ходить в гости в точку С, а не просто шагать из А до Б".
Вот и смысл: "А И Б сидели на трубе, А - упало, Б - пропало, кто остался на требе?"
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
24.10.2025 12:27:50
Nikolay, Вы знаете, тестил до 100 корутин одновременно (правда не долго), у меня сложилось хорошее впечатление, если вылетает то нет блокировки всего кода. Показывает не исправность одного датчика, ошибка конкретизируется.
Вот пример Вы установили на свой скрипт пароль, корутина постоянно проверяет, а как с замыканием? Или проверяем подключение к серверу через isConnected, колбекам не доверяем? И таких задач набирается прилично. Но основное это то что можно торговую логику так закрутить, что сам диву даешься.
Насчет колбеков у меня тоже много вопросов. И основной для КОГО сделано? Мы пришли все таки торговать, а не решать задачи программирования. По мне так интерфейс пользователя, вон как в Метасток или того проще, с возможностью разворачивания для спецов. А в такой реализации, как сейчас, все должны быть спецами, а не торгашами.
Кстати проблема с отслеживанием статусов HackTrade, возникала давно, но при работе с портфелем и редких сделках, все откладывал, а тут прямо реально достала. Заодно делаю рефакторинг framework у, чтоб получал данные с подпиской на свечи с удобным интерфейсом пользователя. Не очень удобно реализована работа если нужно получать с разных тайм фреймов. Может выложу позже на обсуждение? Пока нравится по крайней мере наиболее удобная у меня версия.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
24.10.2025 11:05:11
framework это просто упрощение при создании торговой логике. Избавляет от взаимодействия с квик, (принцип один раз отладил и забыл, только подключаем).
Что делает framework, решает две основные задачи: 1. Получение данных из квик из разных источников; 2. управление заявкой. Под задачи управления: отправка, снятие, перестановку заявок, обработку их статусов ну и так далее. (Именно эту проблему я и поймал - обработку статусов, что и ломало весь код.)
Вариант от Nikolay, как то я с ним не очень подружился, хотя необходим для поднятия и восстановления истории.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
24.10.2025 10:40:44
nikolz, Так оно так и есть, создаем конфигурацию к робот, строим необходимую торговою логику или используем заготовки торговых стратегий и в бой.
Можно и дальше пойти написать менеджер для торговых стратегий, который от рыночной ситуации будет менять стратегии.
Например вот файл конфигурации к стратегии описанной выше:
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
23.10.2025 21:58:24
nikolz, Да Вы все правильно говорите. Наверняка мой код не оптимален можно большего быстродействия добиться, все это так. Я еще тот писатель.
Речь здесь идет совершенно о другом: про надежность, про универсальность подхода и быстрое простое создание стратегии. Задача частного трейдера мало чем отличается от профессионального трейдинга. Только в профессиональном работают отделами, каждый из которых отвечает за свою область. А частный за все сразу. Вопрос у кого больше шансов наделать ошибок? Использование подходов с фреймворк помогает упростить, частнику ряд задач и заниматься непосредственно трейдингом.
Моя задача сводилась к элементарной задаче в трейдинге, снижению цены позиции в убыточной сделке на одном инструменте, (правильно так, уменьшения диапазона между текущей ценой и ценной набранной позиции). Для этого случая идеально подходит "торговая стратегия сетка + HackTrade - (frameworkупрощение при создании, как исполнитель, гарантировано набирает позицию), нужно дописать несколько модулей RiskManager, MoneyManager, GridManager. И дело в шляпе.
RiskManager, MoneyManager, GridManager это тоже модули подключаемые. То есть мы имеем в своем распоряжении некий конструктор. Под который создается торговая стратегия. В моем распоряжении сейчас: - Арбитражные стратегии - несколько инструментов; - Маркет-мейкинг - сетки заявок в разных вариантах; - Мульти-инструментальные стратегии - портфельный подход; - Парный трейдинг - связанные инструменты; - Хеджирование - противоположные позиции. Создание стратегии за 3 минуты. И мы уже "на боевом коне" и нас голыми руками не взять. Так ка время остается и на расчеты рисков, целей, и можно занимаемся деятельность трейдера, управлением Капитала.
Вот пример интерфейса конечного пользователя (конечный автомат) и это уже рабочий код (по сути трендовая), ну что еще проще может быть:
Код
dofile("hacktrade.lua")
function Robot()
feed = MarketData{
market = "MCODE",
ticker = "TCKR",
}
order = SmartOrder{
market = "MCODE",
ticker = "TCKR",
account = "ACNT1234567890",
client = "775533",
}
ind = Indicator{tag="MYIND"}
while true do
if feed.last > ind[-2] then
order:update(feed.last, 1)
elseif feed.last < ind[-2] then
order:update(feed.last, -1)
end
Trade()
end
end
2. Про быстродействие даже говорить не хочется, это территория профессиональных участников с другими технологическими возможностями. Там где я считаю свою миллисекунду у меня купят совершат еще несколько сделок за счет меня и мне же продадут, ну или примерно так. А насчет производительности и времени исполнения скрипта оно достаточно приличное под мои задачи. Но Вы всегда можете показать свои эффективные решения я только за обсуждение.
3. Про "так как coroutine не вычисляются параллельно, а исполняются в бесконечном цикле main", Вы ни как не поймете, что в этом то заключается вся ПРЕЛЕСТЬ. Именно это позволяет строить логику кусочно и выполнять код тогда, когда это нужно. Это и есть асинхронность исполнения кода, что позволяет добиваться уникальности в логике и алгоритмах.
4. Мой восторг по поводу скрипта HackTrade выражается не слом "сказка" а словом "Гениально"!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
23.10.2025 13:05:12
Сказка4. «Через тернии к звёздам». "Тернии" опустим, все таки личное, а многое, с чем столкнёшься используя этот подход, уже ясно из описания самого подхода. А отказаться от него вообще не вариант, сейчас поясню!
Сразу «к звёздам»! Во избежание получения эффекта опасности "лапши из булевых флагов" (где то попалась терминология, хорошо описывает проблематику), когда система управляется разрозненными переменными, были собраны принципиально разные варианты философии с умными stateful-заявками.
HackTrade Pro version 2.0 - Много заявочная версия. Эта переработанная версия сохраняет обратную совместимость с оригинальным HackTrade 1.4, но добавляет: 1. Современную OOP архитектуру с классами Order, OrderManager; 2. Безопасную машину состояний для ордеров; 3. Систему событий для реактивного программирования; 4. Расширенную статистику и аналитику; 5. Улучшенное управление сетками ордеров. Доводил "сломано много копий", рабочий получилась 2.3 но не обоснована сложа, хотя и рабочая. Данную версию отнесу в "Тернии".
Наиболее интересным получился HackTrade Pro version 3.0. Хорошо сохраняет оригинальную концепцию. Реализованы ключевые принципы, заточенные под задачи алгоритмического трейдинга: - Конечное число состояний. Система может находиться в конкретном состоянии (есть активный ордер, нет ордера, ордер на покупку/продажу); - Четкие переходы: Метод process() проверяет текущее состояние и решает, нужно ли выставлять, отменять или перевыставлять заявку; - Предсказуемость: В каждый момент времени известно, что пытается сделать заявка и каково ее целевое состояние.
Сравнение. Вот как подход соотносится с классической машиной состояний:
| Аспект | "HackTrade Pro 3.0 (SmartOrder)" | "Классическая State Machine" | | --- | --- | --- | | "Суть подхода" | Специализированная машина состояний для трейдинга | Универсальная модель (например, XState) | | "Состояния" | `position`, `planned`, `price` (данные + цель) | Четкие состояния: `pending`, `executed`, `cancelled` | | "Переходы" | Автоматические через `process()` | Через явные события (event-driven) | | "Гибкость" | Высокая для торговых задач | Общая, для любых систем | | "Сложность" | Низкая, минимальный boilerplate | Выше, требует настройки |
Что сохранено из оригинального HackTrade: 1. Stateful умные заявки - помнят свое состояние (position, planned, `price); 2. Автоматическое управление - сами выставляют/снимают/перевыставляют заявки; 3. Динамическая адаптация - при изменении update() автоматически корректируют активные заявки; 4. Гарантированное исполнение - стремятся достичь целевой позиции несмотря на рыночные изменения; 5. Обратная совместимость - тот же API ( order:update(price, quantity) ) 6. Простота использования - создание заявки в 3 строки кода. Что улучшил: 1. Добавил обработку ошибок и "edge cases" 2. Улучшил безопасность с проверками nil значений
HackTrade Pro 3.0 - Много заявочная версия, поддерживает торговые стратегии:
- Арбитражные стратегии - несколько инструментов; - Маркет-мейкинг - сетки заявок в разных вариантах; - Мульти-инструментальные стратегии - портфельный подход; - Парный трейдинг - связанные инструменты; - Хеджирование - противоположные позиции.
Надеюсь не сильно утомил своими сказочками, это рассказ про то, как один небольшой но принципиальный недочет, отнимает массу времени и помогает "Кумекать" Всем хорошего кода.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
23.10.2025 11:11:32
Пару слов про подход. ------------------------------- Технологическая философия оригинального HackTrade с умными stateful-заявками, его инженерия, это не что иное как реализация варианта специализированной машины состояний для трейдинга. Да. "SmartOrder" — это state machine, воплощенная в виде умной заявки, а не в виде абстрактного графа состояний. Это практический подход, который сохраняет все преимущества state machines — предсказуемость, надежность и отсутствие невозможных состояний — в контексте, реальной торговле на бирже. Эта "stateful-заявка (SmartOrder)", которая сама управляет своим жизненным циклом, что является классическим применением паттерна state machine. Ну согласитесь ведь гениально! Конечным автоматом в этой философии выступает, алгоритм торговой стратегии (мы создаем функцию "Robot"). С простым и очень понятным пользовательским интерфейсом.
По своей сложности. Очень сложно! В реализации подхода задействовано все чем силен скриптовый язык Lua: * таблицы реализованные как объекты подход (ОПП) с мета методами; * основной цикл программы разбит сопрограммами, что превращает выполнение в асинхронное; * модульность добавляет универсальность. Тяжело не только разобраться, но еще сложнее отладить.
SmartOrder спроектирован, так что обслуживает одну умную заявку, но не что не мешает создавать пул из умных заявок. Для большинства роботов нe хватит одной умной заявки, но мы можем создавать их больше, например для сетки маркет - мейкера, когда в рынке стоят сразу несколько заявок.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
22.10.2025 19:01:27
Сказка3. "ни словами сказать ни пером описать".
Напомню свое решение торговой системы: HackTrade + RiskManager + MoneyManager + GridManager (торговая стратегия сетка) + GUI.
HackTrade = Умные заявки (SmartOrder). "Представлена реализация stateful-заявок, которые помнят своё внутреннее состояние и могут динамически принимать изменения параметров. Этот подход сильно отличается от традиционных лимитных заявок. Заявка в фреймворке HackTrade представляет собой динамическую лимитную заявку с изменяемой ценой. При этом также может меняться количество и даже направление. Главное, то нужно запомнить, "умная заявка" будет пытаться набирать указанное количество лотов по заданной цене. Даже если вы снимите заявку торговой систем, SmartOrder породит новую и продолжить добирать заданное ранее количество (представьте, что SmartOrder - это заявка, которая гарантированно набирает зaданный объём)".
`SmartOrder` структурно, представляет собой объект (ОПП), который управляет динамическими лимитными заявками. Он следит за состоянием заявки, может корректировать цену и объём заявки и принимать решения на основе того, как рынок ведёт себя (например, снимать заявки, когда цена или объём изменяются)
Работа с ордерами в сводится к 2 моментам: * Если заявка активна, но не соответствует текущим данным (например, цена изменилась), происходит её отмена и пересоздание с новыми параметрами. * Если заявка ещё не была отправлена (поле `self.order` пусто), то создаётся новая лимитная заявка.
Пример работы алгоритма:
1. Инициализация заявки. При запуске робота создаётся объект `SmartOrder`, который получает уникальный `trans_id`. В дальнейшем этот объект будет управлять состоянием заявки.
2. Обновление заявки. Когда происходит обновление с новыми параметрами (например, новая цена или объём), метод `update` обновляет эти данные, и заявка готова к выполнению или корректировке.
3. Обработка заявки. В методе `process()` происходит анализ текущей заявки. Если она не соответствует нужным условиям (например, её нужно отменить), то вызывается соответствующая операция для отмены старой заявки и создания новой с актуальными параметрами.
4. Отправка заявки на рынок. Когда необходимо выставить заявку, это делается через метод `sendTransaction`, который отправляет команду на сервер для создания или отмены заявки.
Моя идея заключалась: SmartOrder = LevelGrid, то есть присваиваются все свойства SmartOrder, следовательно LevelGrid становится объектом (ОПП) и управляется алгоритмом SmartOrder.
Все не объяснимое начинается здесь.
Цитата
Nikolay написал: При этом trans_id может появится не с первого колбека, а, скажем, со второго.
От себя добавлю или неизвестно когда? В своих реализациях, насмотрелся такого "ни словами сказать ни пером описать".
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
22.10.2025 18:45:05
nikolz, Спасибо за уточнение. Да, Вы абсолютно правильно отметили. В контексте торговых систем, такие идентификаторы как trans_id и order_num часто используются для уникальной идентификации заявок и операций, но их назначение и контекст отличаются.
trans_id: Это идентификатор транзакции, который обычно используется для отслеживания транзакций внутри самой торговой системы или между различными её частями. Этот ID генерируется на стороне клиента (например, на уровне торгового робота) и может быть использован для уникальной идентификации всех операций, связанных с данной заявкой. Это полезно для внутреннего учёта робота или системы и может быть использован для отмены или модификации заявок.
order_num: Это идентификатор, который обычно генерируется на стороне биржи или брокера и используется для уникальной идентификации заявки в их системе. Когда заявка отправляется на биржу, она получает свой номер — order_num. Этот номер важен для взаимодействия с внешней торговой системой (биржей или брокером), например, для отмены заявки или запроса статуса заявки.
Мое понимание. Пример: Когда робот создаёт заявку, он может использовать trans_id, чтобы отслеживать все операции с этой заявкой. Если заявка требует изменения или отмены, этот идентификатор будет использоваться для корректного обращения к ней. Пример: После того как заявка была отправлена на биржу, она получает свой order_num, который будет использоваться для её отслеживания на бирже, а также для отмены или изменения заявки через API биржи.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
22.10.2025 13:09:39
Nikolay, Отличное замечание! Спасибо за уточнение! Вы абсолютно правы - в реальной торговле важно правильно работать с идентификаторами. Это очень важное замечание, которое имеет большое значение для правильного построения системы и логики работы с ордерами в рамках торговых систем!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
22.10.2025 11:10:04
Сказка2. Решение моментальное - использовать оба идентификатора. Почему важно использовать оба идентификатора:
1. "'trans_id'" — уникальный идентификатор транзакции, который используется для идентификации заявки на более высоком уровне (в рамках системы торговли или брокера). Этот идентификатор часто используется для отслеживания всей жизненной циклы заявки, например, когда она была создана, изменена или отменена.
2. "'order_num'" — уникальный идентификатор самой заявки в рамках торговой системы. Он уникален для каждого ордера и нужен для точной идентификации и управления заявками (например, отмена или модификация заявки). Также 'order_num' используется при возврате данных о состоянии ордера после его выполнения.
Почему нельзя использовать только один из идентификаторов (например, 'order_num'): Статус и состояние. Состояние заявки (например, активна/отменена) нужно отслеживать в контексте как 'trans_id', так и 'order_num', чтобы правильно обработать ситуацию, если заявка была отменена, частично исполнена или изменена?
Тогда правильная структура и использование двух идентификаторов: 1. Для каждой заявки должен быть свой уникальный 'trans_id'" (для управления жизненным циклом). 2. Для каждой заявки также должен быть свой уникальный 'order_num'", который будет использоваться для отправки ордеров на рынок и их модификации. 3. Важно отслеживать состояние заявки с использованием обоих идентификаторов", чтобы правильно учитывать возможные изменения, отмены или частичные исполнения.
Обновленный подход к обработке заявок: Если хотим точно отслеживать и обрабатывать заявки в пуле, то следует использовать "и 'trans_id', и 'order_num'" для каждой заявки.
Итог: а) 'trans_id'" и "'order_num'" — это два взаимосвязанных идентификатора для каждой заявки. Каждый из них выполняет свою роль: * 'trans_id' связан с транзакцией (управление на уровне системы), * 'order_num' — с ордером на рынке (конкретная заявка). б) Оба идентификатора должны быть сохранены и использованы" для правильной обработки заявок и их состояния, чтобы избежать путаницы и обеспечить точное управление заявками и транзакциями в пуле.