И это еще не все, небольшая часть. Конечно понимаю, что есть служебные, но в таком количестве, зачем они конечному пользователю? Возможно нужно фильтровать ответы по этому параметру, смущает то, что можно важную информацию потерять? Посмотрел в документации ни чего, про то что трогать не нужно. А может есть полезные из них для авто трейдинга? В общем вопросов больше чем ответов.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
18.04.2026 11:09:16
VPM, Вот еще что, на вскидку этот Ваш подход можно опробовать на CODEX от OPENAI. Мне кажется, там что - то подобное делается при создании навыков. Один агент и множество навыков сильно все упрощает. Тем более пока есть вариант бесплатный, можно пробовать. Навыки можно заимствовать от других пользователей. По крайней мере сильно смахивает на Вашу модель и при этом под силу одному разработчику.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
18.04.2026 09:35:59
nikolz, То что Вы описываете сильно смахивает на работу фонда с бригадами специалистов из разных областей. Молчу уже про надежность такой распределенной системы, здесь все таки основной вопрос А ЗАЧЕМ? Для проведения экспериментов ну возможно любопытно? Но я то рассуждаю о торговых программах доступных частному трейдеру. Где основное мерило успеха рост капитала, не получение прибыли а рост капитала. И все сразу становится на сои места.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
17.04.2026 20:01:10
Связка QUIK (QLua) + Московская биржа (MOEX) технически подходит для реализации такой архитектуры. Но есть одно огромное НО - QLua не может быть ядром такой системы. QLua можно использовать как транспортный шлюз (OrderExecutor), в то время как искусственный интеллект и логику выносят во внешнюю среду. И я с этим полностью согласен. Писать нейросети и AI-агентов прямо в QUIK на Lua идея так себе. Lua в QUIK однопоточный, не имеет библиотек для работы с ИИ и быстро "захлебнется" от сложных вычислений. Выносить вычисления во внешний контур (Python/С) не мой подход. В своем подходе HFT техники тяну по ряду причин, одна из которых быстрый тест. Вторая, низкая ликвидность на MOEX, привела к тому что рынок загнали в коридор (фондовый), плохо работают среднечастотные и долгосрочных стратегии. Смена парадигмы, от жесткого программирования правил к торговле на основе намерений (intent-based trading ) и так можно реализовать. Ведь задачу можно свести к модульности и независимости, где компоненты общаются через цели, а не прямые команды, это должно повышать адаптивность и защищать от ошибок. А математику упростить.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
17.04.2026 15:50:10
Да чуть не забыл. IntentStore — отдельный слой, буфер намерений, интентов (очередь, приоритеты). Тот самый третий не лишний!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
17.04.2026 15:09:59
«Кручу, верчу, запутать хочу»
Мой бег по кругу нашел себе новую проблематику зацикленность под общим названием Execution (Исполнение). Или почему третий не всегда лишний. И это не из области "сообразить на троих", это когда соревнуются две команды и нужен объективный независимы судья. В нашем случае соревнования идут между потоками QUIK / Lua, а кто судья?
Что кручу, верчу. Архитектурный слой Исполнения отвечающей принципу разделения ответственности.
У меня сейчас выглядит так: а) strategy: * считает alpha * говорит: "хочу позицию X" б) PositionManager: * хранит истинную позицию (truth) * хранит цель (target) * дергает ExecutionEngine с) ExecutionEngine * превращает target > ордера * управляет жизненным циклом (lifecycle) д) OrderExecutor * гарантирует принцип - точно один раз (exact-once) * управляет заявками. Это уже нормальный 4-уровневый стек выполнения. Оказалось что этого не достаточно.
Есть скрытая проблема такой архитектуры, PositionManager стал на уровень маршрутизации (routing layer), что означает > PositionManager = dispatcher. А это опасно. Почему это проблема, PositionManager теперь: хранит truth, но также управляет поток выполнения (execution flow), а это уже смешение > состояние портфеля + оркестр выполнения. И архитектура начинает "ломаться".
# проблема №1 — двойной путь управления (control path) есть: Path A. Strategy > PositionManager > ExecutionEngine Path B (неявный будущий риск). Strategy > ExecutionEngine это почти гарантированный будущая ошибка.
Просмотр prop-desk стандартов дал однозначный ответ, как можно надежно выстраивать данную архитектуру. Правильная индустриальная модель (важно!) должна учитывать одну абстракцию, а именно УРОВЕНЬ НАМЕРЕНИЯ (критически недостающий элемент) текущей архитектуры.
Тогда новая правильная модель архитектуры будет содержать:
Strategy v PositionManager v (creates intent) ExecutionIntentStore v ExecutionEngine v OrderExecutor
Почему НУЖЕН ExecutionIntent чтоб не упереться в потолок! Без intent layer получаешь: * логика выполнения размазана между модулями; * PositionManager начинает расти; * ExecutionEngine становится "умным монстром"; * состояния гонки между стратегиями. Следовательно, PositionManager НЕ должен вызывать ExecutionEngine напрямую! И мой забег выходит на новый круг.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
10.04.2026 14:23:07
TGB, Спасибо, идея понятна обязательно опробую у себя!
Коллбек OnTrade
Пользователь
Сообщений: Регистрация: 15.06.2023
10.04.2026 14:21:43
Буквально в начале недели прочитал релиз от ВТБ, в котором приводилось отношение 3/4 счетов физических лиц <= 10 000 рублей! В свою очередь меня это сильно удивило. О каком пассивном доходе здесь может идти речь? Все съедят комиссии! У себя даже модель собрал под рабочим названием “жить на купоны + кредитка”. И принципиально модель нельзя путать с инвестиционной, кардинальные отличия.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 17:02:50
В моем нынешнем варианте (который пытаюсь довести "до ума") скорость цикла main делаю адаптивной к загрузке очереди.
Код
local qsize = get_queue_size(ctx.queue)
if qsize > 10000 then sleep(1)
elseif qsize > 1000 then sleep(5)
elseif qsize > 100 then sleep(10)
else sleep(20) end
Но пока очередь не переполнялась то и выводов нет. Размер очереди задаю изначально. Но это так пока эксперименты?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 16:52:54
Может я не все детали уловил, есть же вариант асинхронной (корутины) для обработки таблиц таких загруженных, как таблицу обезличенных сделок? А фильтровать параметры через SearchItems? Ну как вариант. Если много инструментов мне думается важны предельно допустимые нагрузки на QUIK? Можно все повесить. А скорость цикл main она просчитывается 1000 мс / (30 - 50 сделок). Можно как стандарт брать.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 15:37:20
Что же это получается, 30 - 50 сделок в секунду с поиском их при помощи SearchItems в потоке QUIK, ну допустим в 10 раз быстрее чем сделает Lua. Здесь главная задача остается не перегружать основной поток. Так как я уже задумался про обработку таблицы всех сделок этим способом. То нужны критерии нагрузок?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 15:24:46
Да Усек, "Функция SearchItems — это встроенный в QUIK «движок» быстрого поиска. Главная её фишка в том, что она перебирает строки таблицы на уровне C++, что в десятки раз быстрее, чем обычный цикл for в Lua."
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 15:15:20
А чем хуже тогда этот вариант?
Код
function main()
local last_trade_count = getNumberOf("trades") -- Запоминаем кол-во сделок при старте
while is_run do
local current_count = getNumberOf("trades")
if current_count > last_trade_count then
-- Проходим по всем новым сделкам
for i = last_trade_count, current_count - 1 do
local trade = getItem("trades", i)
message("Новая сделка (Pull): " .. tostring(trade.sec_code) .. " по цене " .. trade.price)
end
last_trade_count = current_count
end
sleep(30) -- Пауза мл.секунд, чтобы не вешать процессор
end
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 14:43:29
А можете не большой пример кода опроса показать, через SearchItems? Что то у нас с ним ни как отношения не сложатся. Уж больно мудрёная функция какая - то.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 13:08:28
nikolz, Спасибо за демонстрации подходов, на мой взгляд нет большой надобности в наших задачах выстраивать какие - то изыски? У меня все просто для задачи executor: FSM, event queue, orphan buffer, recovery, net-order support. Сейчас такой вариант:
Код
-- ============================================================
-- 1. Order State Machine (FSM)
-- ============================================================
local OrderState = {}
OrderState.__index = OrderState
function OrderState:new(trans_id, params)
local o = {
state = "NEW", -- NEW, SENT, ACK, PARTIAL, FILLED, CANCEL_PENDING, CANCELLED, REJECTED
trans_id = trans_id,
order_num = nil,
strategy = params.strategy,
sec = params.sec,
side = params.side,
qty = params.qty,
price = params.price,
filled = 0,
created_at = os.time(),
last_update = os.time(),
is_net = params.is_net or false,
}
setmetatable(o, self)
return o
end
function OrderState:on_sent()
self.state = "SENT"
self.last_update = os.time()
end
function OrderState:on_ack(order_num)
self.order_num = order_num
self.state = "ACK"
self.last_update = os.time()
end
function OrderState:on_trade(trade_qty)
if self.state == "CANCELLED" then
self.logger:warn("Trade after cancel, still processing")
end
-- обновление filled
if self.filled >= self.qty then
self.state = "FILLED"
else
if self.state ~= "CANCELLED" then
self.state = "PARTIAL"
end
end
end
function OrderState:on_cancel()
if self.state == "FILLED" then return end
if self:is_active() then
self.state = "CANCEL_PENDING"
end
end
function OrderState:on_cancelled()
self.state = "CANCELLED"
self.last_update = os.time()
end
function OrderState:on_reject()
self.state = "REJECTED"
self.last_update = os.time()
end
function OrderState:on_timeout()
if self:is_active() then
self.state = "CANCELLED"
self.last_update = os.time()
end
end
function OrderState:is_active()
return self.state == "SENT" or self.state == "ACK" or self.state == "PARTIAL"
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 12:46:24
Nikolay, Кажется уловил Вашу идею, все дело в буффере. Именно он опять возвращает в событийную модель через опрос + буффер, вместо callbacks + буффер? И решаются вопросы тайминга?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
08.04.2026 12:24:30
Nikolay, То что таблица trades это фактический журнал сделок, я понимаю. Почему я акцентировал внимание. Я о той грани, что отделяет статику от динамики. В статике да Вы все правильно описали, согласен целиком, а в динамике — нет?
Расхождение возникает не в полноте истории данных, а в семантике доступа их получения, в моменте её доступности.
1) Мы получаем: МНОЖЕСТВО сделок (set) 2) Мы получаем: ПОТОК сделок (stream) Смыслы для программирования можно свести к следущим: Подход 1. Pull (SearchItems) Подход 2: Push (OnTrade) А это фундаментально разные модели.
Если для модели, (как Вы и предлагаете) порядок НЕ важен значит таблицы (set) достаточно не поспоришь. Но ведь реальная проблема не в истории сделок, а в моменте наблюдения.
Формально, SearchItems даёт полную историю, НО не гарантирует, что она уже полная в момент запроса? Ну например гонка терминал / сервер (может быть?) T0: сделка произошла на бирже T1: мы взываем SearchItems T2: QUIK обновил таблицу trades, мы НЕ увидели эту сделку.
В то время как OnTrade просто доставка события.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 20:24:31
Заглянул в материальную часть. То, что по сути описал Nikolay, - это модель State-based FSM (pull + buffer), а не event-driven FSM. Нужно более детально разобрать отличие? Так как мой первоначальный замысел и реализация все таки крутится в парадигме event-driven FSM.
Предложенная модель: 1. Отправили транзакцию 2. Ждём появления order (любой источник) 3. Смотрим состояние order 4. При необходимости подтягиваем trades 5. Двигаем FSM И главное, не важно, в каком порядке пришли данные!
Переформулирую принцип данной модели: "FSM НЕ должен зависеть от порядка событий !НО должен потреблять события как источник истины"?
Что смущает? Заявлено в подходе "можно просто прочитать таблицу сделок через SearchItems” Когда делаешь: SearchItems("trades", ...) получаешь текущее состояние таблицы НО НЕ полную историю изменений?
Что при этом теряешь: 1. Не знаешь - уже учитывал этот trade или нет 2. Дельту. было fill = 30 стало fill = 50, не знаешь - это +20? или пересчёт? или дубликат? 3. Частичные исполнения в динамике. (Для FSM важно PARTIAL > PARTIAL > FILLED, а snapshot даёт balance = X)
А что с подходом Event-driven (моя текущая) + точная история (trade_num) + идемпотентность + корректный partial fill
- нужно решать out-of-order?
Что не так?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 19:36:47
Видимо Алиса не знакома с Теорией решения изобретательских задач (ТРИЗ). Где базовая логика начинается с: "Любая сложная задача - это Противоречие❗"
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 12:35:37
Цитата
TGB написал: Это массовая подача заявок с ограничением < 50 заявок в секунду? И до этого вы бы не додумались, если бы вы не прочитали про HFT?
А что это за ограничения? У брокера? Но даже на этой скорости исполнения заявок 1000 мс / 50 = 20 мс. нужно четко корректное исполнение. Что не так то?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 12:30:03
Nikolay, У меня ломается система, пытаюсь установить причины и довести событийную модель "до ума". Возможно и перестарался с проблематикой надежности, но уже "дую на воду". И почему бы не колбеки использовать? В любом случае основные проблемы: асинхронность прихода и их потеря установленны.
А "Hybrid model: Event-driven (основа) + Snapshot reconciliation (страховка)", мне пока представляется наиболее правильной для использования в QUIK?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 11:54:55
Идея (упрощённая модель) не использовать OnOrder / OnTrade ориентироваться на: а) OnTransReply; б) периодический просмотр таблиц orders / stop_orders; с) фильтр по TRANS_ID. - звучит вроде логично, но это polling-модель, не учитывает ряд критических проблем.
Попробую их формализовать. Это ровно то место, где ломается вся система!
Критическая проблема №1 "trans_id не живёт дальше заявки". ------------------------- Ты опираешься на: trans_id > order > состояние Но в реальности: OnTrade НЕ содержит trans_id значит: ты не можешь связать сделку с заявкой через trans_id?
Критическая проблема №2 "Таблицы QUIK - поток событий". ------------------------- Ты предлагаешь: проверять orders / stop_orders при изменении количества записей. Проблема:
1) Нет гарантии атомарности? T0 - появился order T1 - сразу прошёл trade T2 - ты прочитал таблицу ! ты увидишь: order уже частично исполнен НО не увидишь последовательность событий?
2) Ты теряешь событийную причинность? FSM требует: ACK > TRADE > PARTIAL > FILLED А таблица даёт тебе: balance уменьшился ! ты не знаешь: * сколько было трейдов * в каком порядке * были ли дубли * был ли cancel между ними
Критическая проблема №3 "Дедупликация невозможна" ------------------------- В event-driven модели:processed_trades[trade_num] В polling-модели: ты просто читаешь итоговое состояние ! ты не можешь: * отфильтровать дубли * гарантировать idempotency?
Критическая проблема №4 "Out-of-order ты вообще не контролируешь"? ------------------------- QUIK: OnTrade > раньше OnOrder Модель: таблица > уже обновлена ! ты даже не узнаешь, что был out-of-order?
Критическая проблема №5 "частичное исполнение (Partial fills) ломают модель" ------------------------- Реальность: order 100 > trade 30 > trade 20 > trade 50 Таблица: balance = 0 ! ты НЕ знаешь, было 3 сделки или 1 или 10?
Критическая проблема №6 "отмена/замена (Cancel/Replace) становится некорректным" ------------------------- cancel > trade > cancel confirm Polling увидит: order исчез ! ты НЕ узнаешь: был ли fill перед cancel сколько именно исполнилось?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 11:16:45
TGB, Речь идет о подходах используемых HFT — High-Frequency Trading, а не технологиях.
Цитата
VPM написал: QUIK накладывает свои особенности, а у кого их нет, такова действительность. В своем подходе остановился на HFT исполнении и событийной модели, (опросы в качестве уточнений и восстановления). Конечно это не чистый HFT (ни для соревнований с фондами типа "Atto Trading Technologies LLC", которые уже говорят о наносекундах), у нас "QUIK latency" - высокий и нет прямого доступа к бирже. Но ряд подходов широко не обсуждаемых, можно использовать. Главным образом появляется возможность универсального движка, к которому можно цепляться как инвестиционными стратегиями, так HFT конечно в рамках QUIK. Этот подход требует и особой надежности системы (коду нужно крутиться продолжительное время)
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 11:06:54
Nikolay, Но ведь в любом случае ОПРОС будет более затратной операцией, чем реакция на событие. А значит нужна как минимум оптимизация процесса? nikolz,
Цитата
nikolz написал: Опрос делается не по времени, а если изменился размер таблицы, т е запоминаете размер, в main на каждом цикле сравниваете с текущим, если изменился то опрашиваете.
Цитата
nikolz написал: Например ,создаю таблицу активных заявок по каждому инструменту и обновляю ее по колбеку OnOrder и не использую таблицу заявок терминала ВООБЩЕ. Что существенно быстрее работает.
Что то типа такого?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 10:55:18
TGB, В данный момент обсуждаю задачу как инженер разработчик, и не понимаю Ваш сарказм? Причем здесь "сумасшествие" если вопрос стоит об универсальном, оптимальном движке? Собственно как Вы любите. Возможно я не очень четко описал проблематику, или Вы у nikolz, научились читать только то что Вам нужно. Еще раз. Ряд торговых задач решается только с HFT подходом даже в рамках QUIK (свечи из DS не нужны) именно текущее состояние восстанавливаем. Другие свечные стратегии тоже могут использовать движок.
Цитата
TGB написал: Для принятия решений в роботе вам недостаточно текущего состояния вашего счета (которое отображается в его таблицах)
Ну конечно не достаточно, а виной тому асинхронный приход событий и заполнение таблиц. Ну например: Критическая проблема. Out-of-order ты вообще не контролируешь? QUIK: OnTrade → раньше OnOrder модель: таблица → уже обновлена
!ты даже не узнаешь, что был out-of-order. Такое может быть?
Или вот еще: Дедупликация невозможна. * В event-driven модели: processed_trades[trade_num] * В polling-модели: просто читаешь итоговое состояние не возможно: 1) отфильтровать дубли; 2) гарантировать, обеспечить (idempotency) , чтобы многократное выполнение одной операции приводило к тому же результату, что и первое, не меняя состояние системы повторно. Может быть?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 09:50:30
Тогда нужен правильный опробованный алгоритм, и архитектура этой polling-модели?
Но ведь QUIK скорее event-driven система, причем асинхронная, недетерминированная система? Следовательно, единственный способ сделать её детерминированной — это FSM + event pipeline.
Как у меня сейчас, главный тезис: * Таблицы QUIK — это snapshot состояния; * Callback — это история событий.
Отсюда и единственно возможная архитектура и родилась к которой пришёл (и почему она сложная): * OnTransReply > intent * OnOrder > связь trans_id > order_num * OnTrade > факт исполнения ! это минимально достаточная модель, не "overengineering", включающая только те функции, которые необходимы для решения конкретной задачи.
Почему идея упростить, не отвечает данной постановки задачи? Потому что решаем задачу, "восстановления детерминированной истории исполнения, из не детерминированного потока событий QUIK"?
А проверка таблиц (polling) полезна и необходимо использовать в задачах:
1. Recovery / reconciliation. if exchange_position ~= internal_position then trigger_recovery() end 2. Watchdog. if order висит слишком долго > проверить таблицу 3. Fail-safe. если callback потерян > подтянуть через snapshot
Что не так делаю?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
07.04.2026 08:10:26
TGB, Согласен, Вы правы, можно проще, мой предыдущий подход излишне сложен. Но это стремление к максимальной отказоустойчивости и скорости.
Если использовать OnTransReply как единственный источник информации об отправке ордера, а для получения order_num и статуса исполнения периодически опрашивать таблицу orders (или stop_orders), фильтруя по trans_id. OnOrder и OnTrade в такой схеме не нужны, если задача позволяет мириться с небольшой задержкой (до 1 секунды) между исполнением и реакцией системы. Это менее подвержено ошибкам, связанным с "out-of-order" событиями и наверняка проще. Для HFT это не подходит, но для обычной алготорговли – вполне!
Тогда Упрощённый алгоритм (без OnOrder/OnTrade) будет выглядеть: OnTransReply – только логируем успех/ошибку отправки. При успехе запоминаем trans_id как pending. Периодический опрос таблицы orders (например, раз в 0.5-1 секунду) – выбираем заявки с trans_id из нашего списка pending. Получаем order_num, статус, исполненный объём. Обновление позиций – при обнаружении изменений в balance (исполненная часть) вызываем PositionManager:update_position(...). OnTrade не нужен – вся информация о сделках есть в таблице orders (поля balance, qty).
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
06.04.2026 10:45:38
Не открою большого секрета, что QUIK создавался и написан под брокерские команды. Отличительной чертой которых, является наличие узко специализированных специалистов, в то время как частному инвестору приходиться со всем справляться самому. В этом есть и преимущество, так и недостатки. Основной - это сложность построения инженерных торговых стратегий. Язык выбранный для автоматизации, на мой не профессиональный взгляд выбран оптимально, подходит тем и другим. Но вот реализация? Но этому собственно и посвящен настоящий сайт (а что тут еще есть?). Документация выложенная для пользователя, ну мягко говоря написана не на "русском языке".
Мое долгое вступление веду к тому, что для "частника" решившего заняться автоматизацией торгового процесса, или даже построением своей торговой системы, очень важна архитектура программы! Если задачей является, не просто "Кнопка срубить бабло", а инженерная стратегия арбитража или хедж - фонда, то процедурный стиль плохо подходит. Остается модульный стиль с четким разделением ответственности, и едиными стандартами данных на выходах. Это просто позволяет не переписывать код, а использовать одни и те - же уровни. Следовательно, можем создавать модульную математическую библиотеку внутри Lua - мозг системы.
QUIK накладывает свои особенности, а у кого их нет, такова действительность. В своем подходе остановился на HFT исполнении и событийной модели, (опросы в качестве уточнений и восстановления). Конечно это не чистый HFT (ни для соревнований с фондами типа "Atto Trading Technologies LLC", которые уже говорят о наносекундах), у нас "QUIK latency" - высокий и нет прямого доступа к бирже. Но ряд подходов широко не обсуждаемых, можно использовать. Главным образом появляется возможность универсального движка, к которому можно цепляться как инвестиционными стратегиями, так HFT конечно в рамках QUIK. Этот подход требует и особой надежности системы (коду нужно крутиться продолжительное время). Отладка, вот где проявляется то как устроен QUIK, что он возвращает, а документацией "Зачитаешься!". Вот и у меня, который раз виден финиш, и на новый круг в забеге. Всем хорошего код!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.04.2026 17:22:00
"Умный в гору не пойдет, Умный гору обойдет"
Особенности QUIK или ровно то место, где ломается вся торговая система, основанная на событийной модели!
Ключевая проблема QUIK (которую поймал). Факты: * brokerref: > может отсутствовать в OnTrade; > может быть обрезан; > может не совпасть; * trans_id > вообще может не приходит в OnTrade; * order_num > единственный стабильный идентификатор заявки.
Попытка использовать getOrderByNumber, вообще оказалась критической дырой (опасный костыль)
local order_info = getOrderByNumber(trade.class_code, trade.trade_num) Это НЕ гарантируется QUIK! Почему? trade_num / order_num 1) нет гарантии наличия связи; 2) может вернуть nil или не тот ордер.
Правильное решение нашлось. НЕ искать order_num через trade_num. Вместо этого, использовать OnOrder как источник истины.
Производственный конвейер (Production pipeline) 1. В OnTransReply trans_id > сохраняем (pending); 2. В OnOrder order_num < связываем с trans_id; А вот где рождается настоящая связь! 3. В OnTrade trade.order_num > находим ордер.
Следовательно, правильная модель связывания следующая Strategy > OrderExecutor > QUIK: QUIK: trans_id > order_num > trade_num OnTrade: trade > order_num > НАШ ORDER
Связка через order_num — это не просто улучшение, это - > единственный надёжный способ устранить position drift в QUIK, зафиксирую это как архитектурный стандарт!
Как задать комментарий в заявке?
Пользователь
Сообщений: Регистрация: 15.06.2023
02.04.2026 17:47:14
Напоролся на эту же проблему - brokerref не передаётся в OnTrade, попытка идентифицировать ордер только по brokerref, закончилась неудачей? В результате мой PositionManager не может связать сделку с ожидающим ордером! Что это такое не знаю? Это проблема QUIK или отдельного брокера "не передаёт brokerref в OnTrade для сделок, исполненных по лимитным ордерам"?
У себя слепил из того что было:
Код
function OnTrade(trade)
if not ctx or not ctx.instruments[trade.sec_code] then return end
ctx.logger:info("OnTrade: %s %s qty=%d price=%.2f flags=0x%X brokerref=%s",
trade.class_code, trade.sec_code, trade.qty, trade.price, trade.flags, trade.brokerref or "")
-- Получаем номер заявки, связанной со сделкой
local order_num = nil
if trade.order_num and trade.order_num ~= "" then
order_num = trade.order_num
elseif trade.trade_num and trade.trade_num ~= "" then
-- Пытаемся получить информацию о заявке по номеру сделки, если номер заявки недоступен напрямую
local order_info = getOrderByNumber(trade.class_code, trade.trade_num)
if order_info and order_info.order_num then
order_num = order_info.order_num
end
end
local event = ctx.pool:acquire()
event.type_id = EVENT.TRADE
event.sec_id = ctx.distributor.sec_to_id[trade.sec_code] or 0
event.sec_code = trade.sec_code
event.sec = trade.sec_code
event.price = trade.price or 0
event.qty = trade.qty or 0
event.trade_num = trade.trade_num or 0
event.flags = trade.flags or 0
event.time = ctx.time:now()
event.volume = trade.qty or 0
event.brokerref = trade.brokerref
event.order_num = order_num -- сохраняем номер заявки
ctx.queue:push(event)
local pm = ctx.position_managers[trade.sec_code]
if pm then
pm:update_from_trade(trade, order_num) -- передаём order_num
end
if ctx.executor then
ctx.executor:on_trade(trade)
end
end
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 15.06.2023
06.03.2026 09:45:48
Посмотрим внимательней на код из примера выше. Если подходить более строго, в текущем виде это не стек, а очередь (bounded queue - ring buffer). Так как стек (LIFO) подразумевает push/pop, а в примере используется паттерн: append → хранить N последних → читать историю
А это уже, скользящее окно (rolling window) — удобная структура для: * индикаторов; * нормализации; * сигналов; * инженерной разработки функций. Так и в prop-архитектуре обычно используют RingBuffer / RollingWindow, а не сам Stack.
имеет сложность O(n), потому что table.remove(1) сдвигает всю таблицу (и про это на форуме писано переписано). Имеет значение и частота вызова, если это вызывается каждый тик, будет лишняя нагрузка.
2. Обычно в Production-решениях используется кольцевой буфер (Ring Buffer). Сложность: push = O(1) Версия utils/ring_buffer.lua
Код
local RingBuffer = {}
RingBuffer.__index = RingBuffer
function RingBuffer:new(size)
local o = {
buffer = {},
size = size,
head = 0,
count = 0
}
setmetatable(o, self)
return o
end
function RingBuffer:push(value)
self.head = (self.head % self.size) + 1
self.buffer[self.head] = value
if self.count < self.size then
self.count = self.count + 1
end
end
function RingBuffer:get(i)
if i > self.count then
return nil
end
local idx = (self.head - self.count + i - 1) % self.size + 1
return self.buffer[idx]
end
function RingBuffer:last()
if self.count == 0 then
return nil
end
return self.buffer[self.head]
end
function RingBuffer:values()
local out = {}
for i = 1, self.count do
out[i] = self:get(i)
end
return out
end
function RingBuffer:clear()
self.buffer = {}
self.head = 0
self.count = 0
end
return RingBuffer
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
03.03.2026 10:21:49
Да нет Ziveleos, . Вы подметили суть. Сравнивать dofile и require можно долго, но без loadfile картина была неполной. И это важное уточнение. Вы не просто "напомнили", а добавили критически важный слой в понимание темы.
dofile и require — это высокоуровневые обёртки над мощным механизмом loadfile. По аналогии из механики: loadfile — это рычаг, а dofile и require — просто разные насадки на этот рычаг для разных задач.
Внесу пояснения, чтобы зафиксировать этот "полный цикл":
1. Фундамент — loadfile - это базовая функция. Она делает самое главное (и самое тяжелое) — читает файл с диска, компилирует его в байт-код и возвращает результат в виде *функции*. Но она её не выполняет.
2. Утилитарный уровень — dofile - это просто удобная обёртка. Она сделала всю работу за нас, но лишила нас контроля. Это "выстрелил и забыл".
3. Архитектурный уровень — require - Это уже не просто утилита, а менеджер зависимостей. Он использует loadfile для загрузки, и добавляет поверх этого кэширование.
А вот механика про перезагрузку модуля, загруженного через require, — это вообще высший пилотаж. Встречается для горячей перезагрузки кода в сложных приложениях (играх). Этот подход позволяет обновлять логику стратегии, не теряя состояние всей программы, что критически важно для долгоиграющих процессов.
Если есть свой пример для торговых приложений приведите?
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 15.06.2023
02.03.2026 11:00:07
Просто пример:
Код
-- Класс Stack (LIFO)
Stack = {}
Stack.__index = Stack
function Stack:new(max_size)
local o = {
elements = {}, -- таблица-хранилище
max_size = max_size or 5, -- по умолчанию храним 5 элементов
count = 0
}
setmetatable(o, Stack)
return o
end
-- Добавить элемент наверх (push)
function Stack:push(value)
table.insert(self.elements, value)
self.count = self.count + 1
-- Если превышен максимальный размер, удаляем самый старый (снизу)
if self.count > self.max_size then
table.remove(self.elements, 1) -- удаляем первый (самый старый)
self.count = self.max_size
end
end
-- Удалить и вернуть верхний элемент (pop)
function Stack:pop()
if self.count == 0 then return nil end
local value = table.remove(self.elements) -- удаляем последний
self.count = self.count - 1
return value
end
-- Посмотреть верхний элемент без удаления (peek)
function Stack:peek()
if self.count == 0 then return nil end
return self.elements[self.count]
end
-- Получить все элементы в порядке от старого к новому (для отображения)
function Stack:get_all()
return self.elements
end
-- Получить все элементы в обратном порядке (новые сверху)
function Stack:get_all_reversed()
local rev = {}
for i = self.count, 1, -1 do
table.insert(rev, self.elements[i])
end
return rev
end
-- Текущий размер
function Stack:size()
return self.count
end
Как использовать в скрипте. Вместо отдельных массивов и ручного управления размером создаём стеки:
Код
-- В начале скрипта, после конфигурации
local deltaP_stack = Stack:new(20) -- для нормализации (20 значений)
local deltaQ_stack = Stack:new(20)
local c_stack = Stack:new(5) -- для отображения последних 5 значений
local alpha_stack = Stack:new(5)
local signal_stack = Stack:new(5)
-- для отображения исходных данных (опционально)
local deltaP_display_stack = Stack:new(5)
local deltaQ_display_stack = Stack:new(5)
local deltaOI_display_stack = Stack:new(5)
local deltaNB_display_stack = Stack:new(5)
local deltaNA_display_stack = Stack:new(5)
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 15.06.2023
02.03.2026 10:39:07
nikolz, Вы правы, это классическая и очень правильная структура. Стек — идеальный выбор для хранения фиксированного числа последних значений (5, 20 и т.д.) благодаря дисциплине LIFO и операциям сложности O(1).
Но, если мы хотим реализовать стек в чистом Lua для QUIK, то не можем использовать встроенный stack, но можем создать его на основе таблицы. По чему ОПП удобно, таблица знает о себе все. Да можно быстрей, но архитектуру выбираем сами под задачу. Ведь так?
Для образного понимания смысла, мне нравятся проводить аналогии. В этом случае, можно сравнить 2 автомобиля. 1. 60 годов, для диагностики неисправностей которого требовался опытный механик. 2. современный авто где без подключения к компьютеру уже не разобраться. Так и использование мета таблиц в луа, это просто современный авто.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
01.03.2026 19:37:37
TGB, Мне вообще не понятно, зачем ими управлять, ведь это событие? Ну если первый способ, еще логичен включение как точки входа. То остальное зачем?
Очереди и двойные очереди в луа, Пример из книги Р.Е.
Пользователь
Сообщений: Регистрация: 15.06.2023
01.03.2026 19:32:33
Йцукен, Речь шла прежде всего про универсальность, какой еще подход дает возможность, из одного подхода создавать разные очереди? Тут удивляться не чему, одна базовая и делай из нее под свою задачу что нужно. А если это модуль то и сколько нужно. Возможно инженерия кода и заслуживает замечаний, но речь идет о самом подходе. В Вашем примере меня сильно смущает вот этот момент self[idx] = nil дыр не будет? А если все в порядке, то почему бы нет, все на первый взгляд элегантно?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 12:58:07
Ziveleos, Роберту Иерузалимски сравнивает dofile / loadfile. Мы же обсуждаем архитектуру production-системы. Это разные уровни задачи.
* loadfile действительно мощный инструмент когда, допустим нужно перезагрузить стратегию без перезапуска всего скрипта. * require — все таки правильно для модульной архитектуры.
OrderManager, RiskManager, StateMachine, Logger - это именно модули, а их лучше (правильно) подключать через require, так как возвращаем модуль, и тут не поспоришь.
Да и моя изначальная задача не в подключениях, а в контроле зависимостей. Но в любом случае, Вы подсветили полную картину подключений.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 12:01:21
А если такой вариант рассмотреть, создать специальный модуль или глобальную таблицу, которая будет управлять всеми зависимостями. Этот подход также может решить проблему избыточной передачи зависимостей, так как мы будем централизованно контролировать, какие библиотеки и модули подключаются?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 11:21:44
Да, загрузили надо мне внимательней разобраться и переосмыслить подход.
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 11:14:44
Кажется уловил разницу. а) dofile: * каждый вызов → заново читает файл * заново выполняет код * выполняется в глобальном окружении? * нет кэширования? * нет изоляции Это процедурный стиль.
б) require: * выполняет файл один раз * кэширует результат в package.loaded * возвращает модуль * позволяет строить граф зависимостей * предотвращает двойную инициализацию То есть это полноценная модульная система. Так?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 10:58:05
1. Не понял в чем разница? 2. Да, спасибо за вариант, про собственный флаг, даже не задумывался, взял на вооружение!
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 10:09:17
А вот то что я описываю, интересует в первую очередь этот момент.
Код
[QUOTE][USER=16131]VPM[/USER] написал:
-- Инициализация модулей в правильном порядке (с учётом зависимостей)
-- 1. ExecutionLedger (зависит только от Logger, ссылка на StateMachine пока не используется)
ExecutionLedger.init({ logger = Logger, stateMachine = StateMachine })
-- 2. OrderManager (зависит от ExecutionLedger и Logger)
OrderManager.init({
ExecutionLedger = ExecutionLedger,
Logger = Logger
})
-- 3. StateMachine (зависит от OrderManager, RiskManager, SignalEngine, utils, Logger)
-- RiskManager и SignalEngine ещё не инициализированы, но init только сохраняет ссылки — это допустимо.
StateMachine.init({
utils = utils,
OrderManager = OrderManager,
RiskManager = RiskManager,
SignalEngine = SignalEngine,
Logger = Logger,
ExecutionLedger = ExecutionLedger -- <-- добавить
})
-- 4. RiskManager (зависит от StateMachine, SignalEngine, utils, Logger)
RiskManager.init({
utils = utils,
StateMachine = StateMachine,
SignalEngine = SignalEngine,
Logger = Logger,
config = {
daily_loss_limit = daily_loss_limit,
max_consecutive_losses = max_consecutive_losses,
max_position_size = max_position_size,
max_total_exposure = max_total_exposure,
broker_comiss_stock = broker_comiss_stock,
broker_comiss_fut = broker_comiss_fut,
exchange_comiss_stock = exchange_comiss_stock
}
})
-- 5. SignalEngine (зависит от utils, StateMachine, Logger и конфига)
SignalEngine.init({
utils = utils,
StateMachine = StateMachine,
Logger = Logger,
config = {
broker_comiss_stock = broker_comiss_stock,
exchange_comiss_stock = exchange_comiss_stock,
broker_comiss_fut = broker_comiss_fut,
exchange_pay = exchange_pay,
div = div, -- таблица дивидендов должна быть загружена ранее
div_before_expiry = div_before_expiry,
nalog = nalog,
rate = rate,
min_edge_abs = min_edge_abs
}
})
-- 6. Watchdog (зависит от Logger, StateMachine, OrderManager, ExecutionLedger)
Watchdog.init({
Logger = Logger,
StateMachine = StateMachine,
OrderManager = OrderManager,
ExecutionLedger = ExecutionLedger,
config = {
order_timeout = order_timeout,
execution_timeout = 10
}
})
-- 7. Recovery (если есть)
Recovery.init({
Logger = Logger,
StateMachine = StateMachine
})
Recovery.recover()[/QUOTE]
Именно здесь, ни кто не по беспокоит, ни какие колбеки не прилетят, пока зависимости в модулях не установлены. А речь идет про разделение ответственности в модулях.
Что я делаю не так?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 10:03:44
Ну хорошо, давайте по порядку. Вот вариант от TGB, Так?
Код
Сборка в главном скрипте
-- main.lua
require("core.order_engine")
require("adapter.quik_exchange")
require("adapter.callbacks")
require("strategies.simple_strategy")
function main()
-- 1. Инициализация адаптера
local exchange = QuikExchange:new("SPBFUT12345", "SPBFUT", "SiH5")
-- 2. Инициализация ядра
local engine = OrderEngine:new(exchange)
-- 3. Передаём ссылку в callbacks
set_engine(engine)
-- 4. Создаём стратегию
local strategy = Strategy:new(engine)
-- 5. Главный цикл
while true do
local price_param = getParamEx(exchange.class, exchange.sec, "LAST")
local price = tonumber(price_param.param_value)
if price then
strategy:on_price(price)
engine:process()
end
sleep(100)
end
end
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
27.02.2026 08:30:00
TGB, Ну так огромная! А именно в локализации глобальных переменных для данного проекта. Да медленнее но Гарантированно!
Цитата
Nikolay написал: Поэтому OnInit - это технический колбек, просто сигнализирующий, что код исполненный выше в body скрипта при его запуске, не привел к ошибкам.
Возможно так понятней о чем разговор, это кусочки кода
Код
dofile(path .. '\\QL.lua')
dofile(path .. "\\ContanGO\\Проект\\config.lua")
local utils = dofile(path .. "\\ContanGO\\Проект\\core\\utils.lua")
local Logger = dofile(path .. "\\ContanGO\\Проект\\core\\logger.lua")
local OrderManager = dofile(path .. "\\ContanGO\\Проект\\core\\order_manager.lua")
local StateMachine = dofile(path .. "\\ContanGO\\Проект\\core\\state_machine.lua")
local Recovery = dofile(path .. "\\ContanGO\\Проект\\core\\recovery.lua")
local SignalEngine = dofile(path .. "\\ContanGO\\Проект\\core\\signal_engine.lua") -- пока не реализован, но должен считать edge
local RiskManager = dofile(path .. "\\ContanGO\\Проект\\core\\risk_manager.lua") -- проверка лимитов
local Watchdog = dofile(path .. "\\ContanGO\\Проект\\core\\watchdog.lua")
local ExecutionLedger = dofile(path .. "\\ContanGO\\Проект\\core\\execution_ledger.lua")
И дальше:
Код
function OnInit()
-- Логирование (ваш код)
Logger.init(log_file)
Logger.log("INIT", "", "Starting robot")
-- Дополнительное логирование (опционально)
do
local log = _G.getScriptPath()..'\\arbitrage.log'
toLog(log, "Start INIT robot arbitrage")
end
-- Объявление глобальных таблиц для хранения данных по инструментам
exchange_pay = {}
div_date = {}
div_before_expiry = {}
-- Инициализация контекстов для каждой акции из списка
for stock in string.gmatch(ticker_list, "%a+") do
local fut_code = futures_map[stock] or utils.findNearestFutures("SPBFUT", stock, 5)
if fut_code then
local lot_size = utils.safeParam("SPBFUT", fut_code, "LOTSIZE") or 1
StateMachine.initContext(stock, fut_code, lot_size)
-- Комиссия биржи
exchange_pay[stock] = utils.safeParam("SPBFUT", fut_code, "EXCH_PAY") or 0
-- Дата дивидендов (нужна реализация функции getDividendDate)
div_date[stock] = getDividendDate(stock)
-- Дивиденд до экспирации?
if div_date[stock] then
local exp_date = utils.safeParam("SPBFUT", fut_code, "MAT_DATE")
div_before_expiry[stock] = exp_date and (tonumber(div_date[stock]) < tonumber(exp_date))
else
div_before_expiry[stock] = false
end
Logger.log("INIT", stock, string.format("Fut=%s lot=%d", fut_code, lot_size))
else
Logger.log("ERROR", stock, "No futures found")
end
end
-- Инициализация модулей в правильном порядке (с учётом зависимостей)
-- 1. ExecutionLedger (зависит только от Logger, ссылка на StateMachine пока не используется)
ExecutionLedger.init({ logger = Logger, stateMachine = StateMachine })
-- 2. OrderManager (зависит от ExecutionLedger и Logger)
OrderManager.init({
ExecutionLedger = ExecutionLedger,
Logger = Logger
})
-- 3. StateMachine (зависит от OrderManager, RiskManager, SignalEngine, utils, Logger)
-- RiskManager и SignalEngine ещё не инициализированы, но init только сохраняет ссылки — это допустимо.
StateMachine.init({
utils = utils,
OrderManager = OrderManager,
RiskManager = RiskManager,
SignalEngine = SignalEngine,
Logger = Logger,
ExecutionLedger = ExecutionLedger -- <-- добавить
})
-- 4. RiskManager (зависит от StateMachine, SignalEngine, utils, Logger)
RiskManager.init({
utils = utils,
StateMachine = StateMachine,
SignalEngine = SignalEngine,
Logger = Logger,
config = {
daily_loss_limit = daily_loss_limit,
max_consecutive_losses = max_consecutive_losses,
max_position_size = max_position_size,
max_total_exposure = max_total_exposure,
broker_comiss_stock = broker_comiss_stock,
broker_comiss_fut = broker_comiss_fut,
exchange_comiss_stock = exchange_comiss_stock
}
})
-- 5. SignalEngine (зависит от utils, StateMachine, Logger и конфига)
SignalEngine.init({
utils = utils,
StateMachine = StateMachine,
Logger = Logger,
config = {
broker_comiss_stock = broker_comiss_stock,
exchange_comiss_stock = exchange_comiss_stock,
broker_comiss_fut = broker_comiss_fut,
exchange_pay = exchange_pay,
div = div, -- таблица дивидендов должна быть загружена ранее
div_before_expiry = div_before_expiry,
nalog = nalog,
rate = rate,
min_edge_abs = min_edge_abs
}
})
-- 6. Watchdog (зависит от Logger, StateMachine, OrderManager, ExecutionLedger)
Watchdog.init({
Logger = Logger,
StateMachine = StateMachine,
OrderManager = OrderManager,
ExecutionLedger = ExecutionLedger,
config = {
order_timeout = order_timeout,
execution_timeout = 10
}
})
-- 7. Recovery (если есть)
Recovery.init({
Logger = Logger,
StateMachine = StateMachine
})
Recovery.recover()
Logger.log("INIT", "", "All modules initialized")
end
И что здесь не так?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.02.2026 20:28:52
TGB, Ну Вы опять, как школьник вызубривший урок наизусть, и ни грамма отступить от догмы, ну как тут не поверить, что перед нами отличник?
Ваши заключения абсолютно верны, и подход с использованием main для инициализации и работы в многозадачной среде действительно более эффективен в случае с QUIK, где важна производительность и отсутствие блокировок. Ну все этим пользуются, и я не исключение.
Но разве разговор про это? Ведь выше все подробно описал и даже пример минимальной структуры привел. Найдите там блокирующее body?
В кои веке, удалось найти что QUIK, что однозначно гарантирует. Ничего не произойдёт в скрипте пока OnInit не просигнализирует.
Nikolay, вот пишет "Поэтому OnInit - это технический колбек, просто сигнализирующий, что код исполненный выше в body скрипта при его запуске, не привел к ошибкам. Ничего более. Делается это один раз при запуске. Поэтому там и могут быть только сугубо технические действия именно при запуске скрипта и ничего более."
Это как фазовый гарантированный переход! Из всего выше сказанного следует добавить фразу - "OnInit имеет смысл лишь как минимальная часть настройки среды"?
Мне нужна была гарантированная инициализация зависимостей в модулях между собой для контроля, простой их тусовки и замены. Дело в том, что тяжело в SciTe удержать контроль над зависимостями, а тут еще и наглядность. Именно здесь и проявляет свой характер OnInit (здесь прозрение, что хоть что есть гарантированного в QUIK и можно ставить себе на службу).
Nikolay, Ваши замечания как всегда точны и логичны. Дело тут в том что в моем варианте зона body не рассматривалась, это просто зона локализации данных и переменных. Ну а последующие восстановления ни куда не деться будем тянуть из цикла маин, тут просто вариантов нет? Или я опять что то упускаю из вида?
Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 15.06.2023
26.02.2026 11:34:19
OnInit, или просто прозрение, которым хочется поделиться. Ни так давно (по меркам вечности), на страницах этого форума зашел спор, суть которого можно выразить фразой "На фига козе баян".
Высказывались опытные разработчики скриптов, мнение разделись, одни утверждали: > "OnInit не нужен, всё можно сделать в main", другие что нужен, но зачем, так ни кто и не объяснил. Я придерживался простого мнения: кому нужен пользуемся, кому не нужен не пользуемся. Пока не встал у меня вопрос, "Как отслеживать зависимости между модулями"? Пришлось детально разбираться. И вот что получилось.
Если смотреть на архитектуру QUIK Lua строго с точки зрения production-дизайна — OnInit не просто "не лишняя", а ключевая точка композиции системы. Посмотрим системно.
1. Что реально делает QUIK.
Архитектурно терминал работает так: 1. Загрузка скрипта 2. Вызов OnInit(script_path) 3. Создание отдельного потока > main() 4. Далее event callbacks (OnOrder, OnTrade, OnQuote, ...) вызываются только если main() жив
Ключевой момент. > Все callback’и не будут вызываться, если main завершился? Следовательно, main() — это lifecycle-контроллер. А OnInit() — это фаза конфигурации до старта runtime.
2. Почему в production OnInit крайне полезен. Ошибочное мнение. > "OnInit не нужен, всё можно сделать в main"? Можно. Но это плохая архитектура. А правильная архитектурная роль OnInit — это:
2.1. Корень композиции зависимостей (Composition Root ) Именно здесь правильно: * собирать зависимости * инстанцировать модули * связывать Core - Adapter - Strategy * валидировать конфигурацию * логировать старт
Это аналог: * Spring Boot bootstrap * ASP.NET Composition Root * Dependency Injection container setup Это три фундаментальных понятия современной backend-разработки, описывающих, как приложение запускается, собирается из компонентов и управляет своими зависимостями.
2.2. Fail-fast зона не менее важная. Если что-то не так: * нет доступа к счёту * отсутствует класс инструмента * нет прав * ошибка конфигурации Лучше упасть до старта main, чем в рабочем цикле.
2.3. Разделение фаз | Фаза | Что происходит | | ---------- | -------------------------- | | OnInit | Конфигурация | | main | Runtime | | Callbacks | Event-driven обработка | Это даёт чистую архитектуру.
3. OnInit особенно удобно.
3.1. Связывание зависимостей (Wiring). function OnInit(script_path)
4. Для чего НЕ стоит использовать OnInit. Не надо: запускать торговый цикл, делать в нем бесконечные sleep, ну и конечно обрабатывать рынок. Это не среда выполнения (runtime).
5. Production-подход к структуре QUIK-скрипта. И тогда просмативается правильный структурный подходС (skeleton):
-- ====================== -- Global references -- ====================== local App = {}
-- ====================== -- OnInit -- ====================== function OnInit(script_path) App = Bootstrap(script_path) end
-- ====================== -- main runtime loop -- ====================== function main() App:run() end
-- ====================== -- Event callbacks -- ====================== function OnOrder(order) App:onOrder(order) end
function OnTrade(trade) App:onTrade(trade) end
function OnStop() App:onStop() end Следовательно, так можем, централизовать систему, упрощаем тестирование, делает архитектуру масштабируемой.
6. Архитектурное мнение (строго production класса). Если мы хотим строить, multi-instrument, risk-aware, state machine driven, persistent trading system, то OnInit обязателен как "корень композиции" (composition root). Без него система будет выглядеть процедурно и хаотично.
7. Ну и моя идея. > "В ней удобно выстраивать зависимости модулей между собой для наглядности и контроля". Оказалась, абсолютно правильный инженерный подход, уровеня промышленной архитектуры. Разработчик, который фактически мыслит в терминах, Граф зависимостей (Dependency Graph), Управление жизненным циклом (Lifecycle management), Контролируемая начальная загрузка (Controlled bootstrap)
8. Что имеем, итоговое заключение. OnInit, не обязателен технически, и обязателен архитектурно в production подходе. Он делает систему, детерминированной, контролируемой, масштабируемой, безопасной, ну конечно удобной для отслеживания зависимостей самих модулей.
свободные средства для срочного рынка на едином счете
свободные средства для срочного рынка на едином счете
Пользователь
Сообщений: Регистрация: 15.06.2023
25.02.2026 17:18:42
Цитата
nikolz написал: Есть две рекомендации 1) Перезаказать данные2) Пересоздать таблицу клиентского портфеля-------но если у вас в стакане все не активно, то проблема у сбера и они это знают и решают Если Вы сделаете как я написал, то проблему решат за 2 часа.
Уж ни знаю что случилось, пере заказал данные и фондовый заработал, на долго? не знаю, но это уже чудо. VPM, Спасибо
свободные средства для срочного рынка на едином счете
Пользователь
Сообщений: Регистрация: 15.06.2023
25.02.2026 16:58:43
Ну финам бкс, там ворочают такими счетами, что мне и не снились. Да, переводы не совсем удобны, но и нет привязки к одному банку. А Если учесть что фондирование сегодня на уровнях 1%, то нужно хорошо подумать, что лучше?
свободные средства для срочного рынка на едином счете
Пользователь
Сообщений: Регистрация: 15.06.2023
25.02.2026 16:34:58
Попробовал "Алор" кое что есть интересное, но пока не однозначно. Классический брокер, средней руки, деньги ходят по реквизитам, кто знаком поделитесь мнением?