Система принятия решений и/или Нечеткая логика(FuzzyLogic), Нечеткая логика или Система принятия решений в трейдинге
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2025 11:21:28
Забудьте про слова асинхронность, потоки и т.д. Для начала необходимо зафиксировать все ситуации, которые могут привести к проблемам. А потому же решать вопросы про архитектуру. У Вас же все наоборот.
Представьте, что Вы в начале 90-ых, когда почти все писалось синхронно. Задачи же решались.
Цитата
Ожидание ответа в цикле main приводит к проблеме - зависанию
Потому что так делать нельзя. Любой блокирующий цикл - это зло.
OnTransReply - это колбек, ответ на отправку транзакции. Это не результат, а все лишь ответ. Он нужен чтобы прочитать ошибку отправки, чтобы не ждать ордер далее, т.к. он уже не появится. Все. В этом плане - это единственный колбек, который не вызывает вопросов. Поэтому если отправили транзакцию на ордер, то результат - это не колбек OnTransReply, а появление записи по этому ордеру в таблице ордеров. Колбек же OnOrder - это уже следствие появления этой записи, а не наоборот. Любители обработки колбеков вынуждены решать вопросы с их приходом: гарантированность, последовательность, многократный приход, пропуск колбека за время простоя. Т.е. если Вы решили их использовать, то сначала решите все эти вопросы на бумаге, потом уже в коде.
И подход решения этих проблем не связан с асинхронность. Я подозреваю, что Вы за этим термином понимаете просто "непоследовательность". Но это не решает вопрос, тем более, если пишите скрипт для одного инструмента. Вот когда их много, тогда уже необходимо задумываться о разбивке одной задачи на подзадачи. Например, установить 100 ордеров при старте торговой сессии.
Задача сведется к подзадачам:
- Отправить транзакцию, с учетом лимита на число транзакций в секунду.
- Прочитать ответ транзакции. Найти ордер по транзакции. Это одна задача, т.к. ордер может появится раньше. Если ответ транзакции первый и там ошибка, то вернуться к пункту один или прекратить выполнение, в зависимости от алгоритма.
- Если это ордер с ожиданием сделок (рыночный), то если есть флаг исполнения ордера ожидать сделки по ордеру до исполнения количества. Но можно и не ждать, если алгоритм позволяет игнорировать это.
- Попутно проверять состояние ордера, т.к. он может быть снят и, возможно, его необходимо восстановить.
-- и т.д.
Т.о. выполнение задачи может быть долгим, но смысл разбиения в том, чтобы пока одна подзадача ждет результат (ждет не в блокирующем цикле), другая начала выполнение. И этот подход - это просто оптимизация. Как Вы это будете решать - дело ваше. Можете ждать колбек, может сами сканировать флаги, таблицы на новые записи.
Если вернуться к "Ожидание ответа в цикле main приводит к проблеме - зависанию", то решение - это по приходу колбека OnTransReply записать в некую таблицу результат по номеру транзакции. А уже подзадача проверки просто проверит в этой таблице на наличие записи. И сделает она это тогда, когда к этой подзадаче вернетесь, т.е. никакого ожидания с циклом. Тем более, что совершенно не понятно какое время ожидания указать. Много видел примеров с ожиданием 30 секунд. Всегда было интересно откуда эта цифра, а почему не 45? А если ордер пришел раньше ответа транзакции, то и проверка будет уже не особо нужна.
Что касается перезапуска скрипта, то здесь все очевидно - сохранение состояния скрипта, чтение при запуске, актуализация состояния по текущим данным после запуска. За время простоя ордера могли исполнится, быть сняты, руками закрыта, открыта позиция и т.д. Т.о. задача проверить все сохраненные данные и принять решения по выявленным расхождениям. Без решения этой задачи скрипт становится достаточно опасным для использования.
Т.о. рабочий скрипт будет 80% времени заниматься служебными задачами - контролем соединения; состоянием сессии; статусом торгов по инструменту; обслуживать интерфейс, если он есть; обновлять данные с сервера; проверять статусы ордеров, если не используются колбеки; проверять изменения позиции, баланса по деньгам и т.д. А так называемый алгоритм, который всего лишь автоматизирует торговые команды - это не самая большая часть скрипта. Поэтому складывается впечатление, что Вы начинаете не с того. Уж тем более не столь важно как технически реализован алгоритм, если скрипт не позволяет пользователю себя остановит и продолжить с того же места, не умеет останавливаться когда торговая сессия не идет и т.д.
Пользователь
Сообщений: Регистрация: 15.06.2023
03.11.2025 11:59:26
Nikolay, Ну я не знаю где у этой гидры хвост, а где голова. Я строю модульный вариант. 80% решается в другом модуле DataManager + get API (Получился не большой универсальный Фреймворк) окончательный этот вариант или нет, не могу сказать пока, ключевое здесь возможность многократного использования. Того же добиваюсь от AOL - для автоматической системы надежность и вообще как он сделан имеет ключевое значение, если он не рабочий, Все остальное ни имеет смысла как бы оно не работало! Мне нужен универсальный, надежный, для многократного использования (принцип - "написал и забыл") , для одного инструмента - это просто упрощение.
Если я Вас правильно понимаю, фоновые решения предлагаете решать через "замыкания"? И решения поиска ордеров и сделок в таблицах квик?
Пользователь
Сообщений: Регистрация: 27.01.2017
03.11.2025 13:00:37
Я не навязываю никаких решений. Боле того, не использую термин "фоновое", т.к. такого нет в Lua.
Задачи с ожиданием решаются через переключение. Как это делать - вопрос второй, хотите корутины - делайте. Дискуссия была про то, что корутины это не единственное, и уж те более не идеальное решение. Не более.
Если есть ожидание, то просто переключаетесь на другую подзадачу и она становится активной. Прошлая не становится фоновой, а просто на стеке запоминается ее состояние, чтобы при переключении на неё, можно было бы выполнять её не с самого начала заново. Но это не делает её фоновой, т.к. она ничего не делает, как только мы вышли из неё.
Если у Вас уже есть решение по обработки серверных данных, то и используйте его. Речь была про то, что это решение должно быть независимым от реализации алгоритма. Это просто набор методов, предоставляющий интерфейс. Соответственно скрипт должен просто дергать его методы, принимать решения по ответам.
Пользователь
Сообщений: Регистрация: 15.06.2023
03.11.2025 14:00:06
Но Вы же сами пишите, с чем можно сталкиваться, то не пришло, то не то пришло, а с таймерами вообще не понятно что делать, сколько ждать, ждать или не ждать? (Вечный философский вопрос: "Быть или не Быть?" ). Да и вопрос встает как опрашивать, последовательно перебирая, но ведь приходят ни пойми как? Накидал асинхронный вариант с машиной состояний и процедурный (после всех выкрутасов конечно проще, но отвечает ли в полной мере на все вопросы?).
Пользователь
Сообщений: Регистрация: 30.01.2015
03.11.2025 14:05:51
Цитата
Nikolay написал: Поэтому если отправили транзакцию на ордер, то результат - это не колбек OnTransReply, а появление записи по этому ордеру в таблице ордеров. Колбек же OnOrder - это уже следствие появления этой записи, а не наоборот.
Вы ошибаетесь, как раз наоборот Сначала будет колбек,OnOrder, а потом появится запись в таблице заявок.
Как это придет в терминал не детерминировано. Зато известно за что отвечает колбек OnOrder - за изменение информации о ордере. Информация записывается в таблицу ордеров и вызывается колбек. Я пока еще не видел сообщений от разработчиков о том, что колбек всегда приходит раннее информации о ордере в таблице ордеров. Допускаю что это приходит в одном информационном пакете. Как его разберет терминал тоже неизвестно. Т.е. вероятно, что может прийти ранее. А может и нет.
Пользователь
Сообщений: Регистрация: 30.01.2015
03.11.2025 14:17:22
Цитата
Nikolay написал: Любая процедура, вызванная из main не блокирует QUIK. Любая. Хоть завернутая в корутину, хоть вызванная напрямую, хоть в замыкании.
Присоединяюсь
Пользователь
Сообщений: Регистрация: 30.01.2015
03.11.2025 15:14:07
Замечу, что замыкание можно заменить обычной функцией с передачей ей таблицы с параметрами, которые хранятся в замыкании. Такая реализация проще в понимании и полностью эквивалентна замыканию.
Пользователь
Сообщений: Регистрация: 15.06.2023
04.11.2025 13:06:34
И так обсудили разные подходы по организации полного жизненного цикла заявки. Каким подходом пользоваться, каждый определяет для себя сам. Это архитектурная дилемма. Так как окончательного мнения у меня не сложилось, буду пользоваться наиболее понятными для меня подходами. Задача все еще прежняя, собрать модульную структуру в которой торговые стратегии работают независимо отдавая приказы на исполнение. И технологическая, все это дело обслуживает.
Таким образом можно выделить 3 главных блока, которые взаимодействуют ка между собой так и с апи квик. А. полный жизненный цикл заявки. Б. полный жизненный цикл сделки. С. полный жизненный цикл money.
Следовательно в блоках можно условно выделить основное взаимодействие, это пары: 1. заявка / сделка = depo; 2. актив depo / актив money, что в свою очередь можно представить как depo + money = capital.
Следовательно, следующая задача, нужно организовать жизненный цикл money.
Пользователь
Сообщений: Регистрация: 15.06.2023
04.11.2025 13:17:05
В этом случае образуется еще одна пара depo / money, которая непосредственно влияет на capital, и требует добавления еще одного жизненного цикла, чтобы контролировать и управлять деньгами, используемыми в торговых операциях. Это важная составляющая системы для адекватного управления капиталом, рисками и средствами, доступными для торговли.
Принципиальное понимание, весь торговый капитал делится на 2 составляющие:
Активный и Пассивный капитал:
Пассивный капитал — это средства, которые зарезервированы для покрытия рисков и не используются напрямую в торговле. Эти деньги могут быть зарезервированы для предотвращения убытков или для удовлетворения маржинальных требований, если используем плечо.
Активный капитал — это средства, которые мы используем для торговых операций. Из этих средства нужно будет выделить на конкретные тикеры (позиции), которые будут торговаться. Чем больше активных позиций (тикеров), тем больше капитал должен быть задействован для каждой торговой операции.
Жизненный цикл Money:
Суть этого цикла — это управление средствами, которые будут выделяться для торговли. Этот процесс включает в себя:
Распределение средств по активным позициям и тикерам.
Контроль за балансом между активами и средствами, доступными для торговли.
Актуализация данных по торговым операциям (открытым позициям, маржинальным требованиям и т.д.).
Перераспределение средств между различными торговыми активами (тикерами).
Таким образом, жизненный цикл money будет связан с жизненным циклом ордеров и сделок, но будет ориентирован на правильное распределение и отслеживание средств для торговли.
Пользователь
Сообщений: Регистрация: 15.06.2023
04.11.2025 13:47:43
Возможные подходы к организации жизненного цикла "Money". Есть несколько основных подходов для организации такого жизненного цикла, которые могут зависеть от сложности системы и наших бизнес-правил.
1. Цикл распределения средств (активно-торговые деньги). Это подход, при котором для каждого тикера или позиции выделяется определенная сумма из активного капитала, которая будет использоваться для торговли на этом тикере.
Пример: * У вас есть капитал ( C ), и вы хотите распределить его по 10 тикерам. * Таким образом, каждый тикер получит сумму ( C / 10 ) для торговли.
Пример кода:
Код
function Trading:allocate_money_for_trading()
local total_active_capital = self:get_active_capital() -- Общее количество активных средств
local total_tickers = self:get_number_of_tickers() -- Количество активных тикеров
local capital_per_ticker = total_active_capital / total_tickers
-- Для каждого тикера выделяем средства
for i = 1, total_tickers do
self:allocate_ticker_capital(i, capital_per_ticker)
end
end
function Trading:allocate_ticker_capital(ticker_id, amount)
-- Логика выделения средств для конкретного тикера
log_info(string.format("Для тикера %d выделено %.2f средств на торговлю.", ticker_id, amount))
-- Дополнительная логика управления средствами для конкретного тикера...
end
2. Управление капиталом на основе рисков. Этот подход более сложный и ориентирован на распределение капитала в зависимости от рисков, связанных с каждым активом. В этом случае капитал может быть выделен не равномерно между тикерами, а в зависимости от их волатильности, ликвидности или других факторов риска.
Пример: * Для более рисковых тикеров (например, с большой волатильностью) вы выделяете меньшую сумму, чтобы уменьшить возможные потери. * Для более стабильных тикеров (с низкой волатильностью) выделяется больше средств.
Пример кода:
Код
function Trading:allocate_money_based_on_risk()
local total_active_capital = self:get_active_capital()
local ticker_risks = self:get_ticker_risks() -- Структура риска для каждого тикера
-- Распределяем капитал пропорционально рискам
for i, risk in ipairs(ticker_risks) do
local capital_for_ticker = self:calculate_risk_adjusted_capital(total_active_capital, risk)
self:allocate_ticker_capital(i, capital_for_ticker)
end
end
function Trading:calculate_risk_adjusted_capital(total_capital, risk)
-- Логика расчета капитала с учетом рисков
return total_capital * (1 - risk)
end
3. Цикл обновления и перераспределения капитала (динамическое распределение). Этот подход заключается в том, что мы регулярно обновляем капитал, выделенный на торговлю, в зависимости от текущего состояния рынка и состояния активных позиций. Например: * Когда прибыль с позиции увеличивается, мы можем перераспределить часть этого капитала на другие, более прибыльные тикеры. * Если риски становятся слишком высокими, мы можем заморозить капитал на определенных тикерах, чтобы уменьшить возможные потери.
Пример кода:
Код
function Trading:reallocate_capital_based_on_market_conditions()
local total_active_capital = self:get_active_capital()
local market_conditions = self:get_market_conditions() -- Получаем текущие рыночные условия
for i, condition in ipairs(market_conditions) do
if condition == "high_volatility" then
self:reduce_capital_for_ticker(i)
elseif condition == "stable_market" then
self:increase_capital_for_ticker(i)
end
end
end
function Trading:reduce_capital_for_ticker(ticker_id)
-- Логика уменьшения капитала для данного тикера
log_info(string.format("Уменьшаем капитал для тикера %d из-за высокой волатильности.", ticker_id))
end
function Trading:increase_capital_for_ticker(ticker_id)
-- Логика увеличения капитала для данного тикера
log_info(string.format("Увеличиваем капитал для тикера %d из-за стабильного рынка.", ticker_id))
end
Есть и другие подходы, но на этом этапе нам важно собрать полный жизненный цикл, а оптимизацией можно и потом заняться.
Что следует учесть:
1. Консистентность данных. Когда мы перераспределяем капитал или пересчитываем активы, нужно следить за тем, чтобы не возникало несоответствий между состоянием капитала и фактическими позициями. Например, если у нас были открыты позиции, и мы перераспределяем капитал, важно корректно обновить их состояние.
2. Прочие элементы жизненного цикла: * Отслеживание маржи. Если используется маржа (например, при использовании заемных средств для торговли), нам нужно контролировать, сколько капитала выделяется на поддержание маржи для открытых позиций. * Риски и лимиты. Управление рисками — это ключевая часть жизни капитала. Нужно учитывать лимиты на потери для каждого тикера и корректно перераспределять капитал, если актив выходит за пределы допустимого.
Следовательно. Для эффективной работы жизненного цикла money стоит предусмотреть следующие моменты:
* Разделить управление пассивным и активным капиталом, чтобы избежать использования средств, зарезервированных для покрытия рисков. * Разработать систему перераспределения средств на основе рисков, объемов торгов и других факторов. * Учитывать механизмы блокировки и гарантии, которые могут возникать при торговле с маржой или при достижении предельных значений по позициям. * Обеспечить регулярное обновление данных по активному капиталу и следить за состоянием ликвидности.
Таким образом, жизненный цикл money должен быть организован с учетом наших специфических требований по управлению средствами, рисками и капиталом, что обеспечит гибкость и точность в процессе торговли. Как задачка?
Пользователь
Сообщений: Регистрация: 30.01.2015
04.11.2025 15:15:32
Цитата
VPM написал: И так обсудили разные подходы по организации полного жизненного цикла заявки. Каким подходом пользоваться, каждый определяет для себя сам. Это архитектурная дилемма. Так как окончательного мнения у меня не сложилось, буду пользоваться наиболее понятными для меня подходами. Задача все еще прежняя, собрать модульную структуру в которой торговые стратегии работают независимо отдавая приказы на исполнение. И технологическая, все это дело обслуживает.
Таким образом можно выделить 3 главных блока, которые взаимодействуют ка между собой так и с апи квик. А. полный жизненный цикл заявки. Б. полный жизненный цикл сделки. С. полный жизненный цикл money.
Следовательно в блоках можно условно выделить основное взаимодействие, это пары: 1. заявка / сделка = depo; 2. актив depo / актив money, что в свою очередь можно представить как depo + money = capital.
Следовательно, следующая задача, нужно организовать жизненный цикл money.
Уу меня получилась два конечных автомата и менеджер задач. 1) обрабатывает события по OnOrder, OnStopOrder,OnTanseReblay, и все колбеки в которых нет sec_сode. 2) обрабатывает колбеки, в которых есть sec_code, кроме указанных ранее. 3) менеджер задач запускает задачи торгуемых инструментов. 2) и 3) объединены в одну функцию для оптимизации скорости работы и затрат памяти. --------------------- Список существующих задач определяемся в файле init ----------------------------------- Каждая задача записывается в отдельном файле как отдельная функция ------------------------------ Объем скрипта составляет 500 операторов(строк), из который 300 исполняются лишь при старте скрипта.
Пользователь
Сообщений: Регистрация: 15.06.2023
04.11.2025 15:23:37
Что бы не изобретать очередной велосипед возьму свою систему управления капиталом. Вот структура и согласование модулей между собой:
1. Иерархия модулей.
VinceCapitalManager (верхний уровень) v Наследует AdaptiveCapitalManager (средний уровень) v Наследует CapitalManager (базовый уровень)
2. Поток данных между модулями.
CapitalManager > AdaptiveCapitalManager:
- `total_capital`, `active_capital`, `passive_capital` - `money_positions`, `depo_positions` - `allocated_capital` - распределение по инструментам - Статистика использования капитала
AdaptiveCapitalManager > VinceCapitalManager:
- Рыночные режимы и волатильность - Метрики риска (VaR, Expected Shortfall) - Производительность инструментов (Sharpe, просадки) - Система алертов
В этом случае все что от меня требуется, подключиться к разрабатываемой торговой системе, то есть по сути согласовать 3 жизненных цикла, простая торговая стратегия все та же, выдает приказы (Что сделаешь Важная командует)
Пользователь
Сообщений: Регистрация: 15.06.2023
04.11.2025 15:38:08
Важное замечание! В рамках системы Винса, когда мы говорим о управлении капиталом, важно учитывать не только отдельные тикеры или активы, но и влияние каждого из них на общий капитал.
Механизм «постоянного доминирования» — это не просто расчет доли капитала для каждого инструмента по отдельности, а полноценное управление всей портфельной позицией с учетом того, как изменения в одной части капитала влияют на общий баланс и в совокупности на капитал как таковой. К моему велосипеду еще нужны педали?