Возможности Мастера MQL5, которые вам нужно знать (Часть 87): Управление капиталом с масштабированием по волатильности на основе монотонной очереди в MQL5
Введение
Алгоритмические трейдеры и разработчики советников на MQL5 часто сталкиваются с конкретным воспроизводимым сбоем: стратегии, работающие при тестировании на исторических данных, теряют работоспособность в реальной торговле или в средах, чувствительных к задержкам, при расширении рыночного диапазона. Основная причина обычно заключается в статическом определении размера позиции – фиксированных лотах или правилах фиксированного процента – в сочетании с запаздывающими оценками волатильности. Алгоритмы скользящего окна, включая полный перебор, кучи и повторные вызовы CopyHigh/CopyLow, создают заметную задержку на VPS, особенно на малых таймфреймах и при торговле несколькими символами. Последствия ясны и измеримы: чрезмерный риск во время новостных всплесков или при низкой ликвидности, более крупные убытки по отдельным сделкам и более глубокие просадки средств на счете.
В статье предлагается практическое решение для внедрения: пайплайн управления капиталом с минимальной вычислительной задержкой. Он вычисляет экстремумы диапазона по Дончиану со сложностью O(N) с помощью монотонной очереди – двусторонней очереди (deque) – и устраняет задержку скользящего окна. Затем легковесный RBF-фильтр нелинейно валидирует качество сигнала перед окончательным определением объема. Практическим результатом является готовый к интеграции модуль MQL5 – CMoneyMonotonicQueueRBF::Optimize – с настраиваемыми параметрами: m_window_size, m_base_volatility, m_use_rbf. Он вычисляет текущую волатильность, вычисляет scale_factor = base_volatility / current_volatility, приводит объем к допустимому шагу брокера и ограничивает объем минимальным и максимальным значениями, предусмотренными брокером, и при необходимости умножает результат на выход RBF в диапазоне [0,1]. Этот подход предназначен для разработчиков советников, которым нужны превентивное масштабирование риска в реальном времени и воспроизводимый протокол тестирования для сравнений в Тестере стратегий.
Проблема
При определении размера позиции не следует ограничиваться фиксированными лотами и правилами фиксированного процента. Кроме того, в зависимости от доступных вычислительных ресурсов VPS, измерение волатильности в реальном времени может затруднять принятие решений из-за вычислительных задержек. Традиционные расчеты волатильности в скользящем окне могут вызывать такие задержки, особенно в средах высокочастотной торговли на малых таймфреймах. В стандартных реализациях канала Дончиана нередко используется полный перебор массива со сложностью O(N), поэтому с увеличением периода анализа растут задержки выполнения.
Для многих торговых систем даже несколько миллисекунд задержки влияют на скорость размещения ордеров и способность минимизировать убытки от проскальзывания.Ситуацию также усугубляет ретроспективный подход к управлению рисками. Большинство методов управления рисками основаны на традиционном подходе: они оценивают и анализируют исторические результаты сделок вместо того, чтобы учитывать текущую микроструктуру рынка в реальном времени. Алгоритмы, уменьшающие объем после серии убытков, обычно запаздывают, поскольку не масштабируют риск с учетом растущей волатильности. Decrease Factor часто срабатывает после неудачной серии сделок, когда счет уже принял на себя большую часть последствий рыночного сдвига.
Для устранения этих проблем в статье предлагается перейти к управлению капиталом с минимальной вычислительной задержкой. Этот подход необходим для эффективной корректировки риска, которая учитывает волатильность заранее, а не реагирует на уже понесенные убытки. Значимость этого подхода состоит во внедрении двухуровневого механизма защиты. В этом подходе используется высокоэффективная монотонная очередь для отслеживания волатильности в реальном времени и сеть радиальных базисных функций для нелинейной проверки риска. В статье показывается, что сочетание современных структур данных и машинного обучения помогает трейдерам эффективнее сохранять капитал с учетом вычислительных требований современных финансовых рынков.
Алгоритмическая оптимизация – математика монотонной очереди
Отслеживание волатильности в реальном времени может создавать значительную вычислительную нагрузку, которая нередко становится главным ограничением для трейдеров, работающих на малых таймфреймах с высокой частотой. Чтобы получать показатели волатильности из индикаторов, например канала Дончиана, торговая система должна определять максимум и минимум цены в скользящем окне длиной K. Традиционные методы полного перебора требуют сканирования всего окна и дают временную сложность O(N·K). Даже при использовании оптимизированных методов на основе двоичных деревьев поиска или куч сложность остается O(N × log K). Этих методов может быть достаточно для низкочастотных задач. Однако если система одновременно обрабатывает несколько символов на очень малом таймфрейме, они могут вносить ощутимую задержку.
Монотонная очередь дает более эффективное с математической точки зрения решение: она позволяет находить экстремумы скользящего окна с общей сложностью O(N). Такая эффективность достигается поддержанием двусторонней очереди (deque), элементы которой сохраняются в строгом монотонном порядке. Если значения упорядочены по убыванию при поиске максимумов или по возрастанию при поиске минимумов, для любого заданного периода анализа обеспечивается доступ со сложностью O(1).
Эффективность монотонной очереди объясняется амортизированным анализом. Каждый элемент ценового ряда добавляется в очередь ровно один раз и извлекается из нее не более одного раза. Хотя операция push использует вложенные циклы для поддержания монотонности, общее число операций для N элементов ограничено 2N. Это заменяет зависимость от размера исторического окна K чисто линейной зависимостью от общего числа точек данных N.
Таблица сравнения
| Алгоритм | Временная сложность (на обновление) | Общая сложность (N элементов) | Чувствительность к задержкам |
|---|---|---|---|
| Полный перебор | O(K) | O(N · K) | Высокая |
| Максимальная куча / двоичное дерево поиска | O(log K) | O(N log K) | Средняя |
| Монотонная очередь | O(1) (амортизированная) | O(N) | Минимальная |
Благодаря этой структуре данных пользовательский класс управления капиталом может практически мгновенно обновлять параметры волатильности после получения новой котировки. Благодаря этому логика масштабирования риска работает с наиболее актуальной микроструктурой рынка с минимальной задержкой.
Базовым компонентом пользовательского класса управления капиталом служит класс CMonotonicQueueMax. Высокая скорость – важный фактор, однако эффективность использования памяти также имеет значение. Класс реализован следующим образом:
CMonotonicQueueMax(int window) : m_head(0), m_tail(0), m_window(window) { ArrayResize(m_deque_values, window); ArrayResize(m_deque_indices, window); }
Конструктор предварительно выделяет память для массивов m_deque_values и m_deque_indices. Поскольку при инициализации размер массивов задается точно по размеру окна, система избегает потерь производительности, часто связанных с динамическим перераспределением памяти во время торговой сессии.
Метод push реализует амортизированную логику O(1) с помощью двух важных проверочных циклов. Это показано в коде ниже:
void Push(int index, double value) { // Remove elements not within the temporal window while(m_head < m_tail && m_deque_indices[m_head] <= index - m_window) m_head++; // Remove sub-optimal elements to maintain strict monotonic decreasing order while(m_head < m_tail && m_deque_values[m_tail - 1] <= value) m_tail--; // Append current element m_deque_values[m_tail] = value; m_deque_indices[m_tail] = index; m_tail++; }
Первый цикл обеспечивает актуальность данных, оставшихся в очереди. Если индекс элемента в начале очереди меньше или равен текущему индексу минус размер окна, эта точка данных устарела, а указатель головы очереди увеличивается. Второй цикл while поддерживает монотонно убывающий порядок. Перед добавлением новое значение сравнивается со значениями в хвосте очереди. Если текущее значение в хвосте меньше или равно поступающему значению, оно удаляется, а указатель хвоста уменьшается. Математическая логика проста: меньшее и более старое значение не может быть максимумом, если в том же окне присутствует большее и более новое значение.
Наконец, новое значение и соответствующий индекс записываются в текущую позицию хвоста очереди. Затем указатель хвоста увеличивается. Поскольку функция Push поддерживает строго убывающий порядок, максимальное значение всегда находится в голове очереди. Это обеспечивает получение максимумов для расчета волатильности со сложностью O(1). В коде намеренно отсутствует класс CMonotonicQueueMin, так как приведенное ниже математическое свойство позволяет обойтись без него.
min(x) = -max(-x)
Реализация пользовательского класса управления капиталом на MQL5
Переход от теоретической структуры данных O(N) к ее рабочей реализации в модуле управления капиталом на MQL5 выполняется функцией Optimize() этого класса. Теперь рассмотрим, как масштабирование по волатильности в реальном времени используется для определения и корректировки размера позиции. Функция Optimize реализована следующим образом:
//+------------------------------------------------------------------+ //| Optimizing lot size via Monotonic Queue and RBF Gatekeeper | //+------------------------------------------------------------------+ double CMoneyMonotonicQueueRBF::Optimize(double lots) { double lot = lots; double current_volatility = 0.0; if(m_window_size > 0) { double high[], low[]; ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); // 1. $O(N)$ Monotonic Queue Volatility Extraction if(CopyHigh(m_symbol.Name(), PERIOD_CURRENT, 0, m_window_size, high) == m_window_size && CopyLow(m_symbol.Name(), PERIOD_CURRENT, 0, m_window_size, low) == m_window_size) { CMonotonicQueueMax mq_high(m_window_size); CMonotonicQueueMax mq_low_inverted(m_window_size); for(int i = m_window_size - 1; i >= 0; i--) { mq_high.Push(m_window_size - 1 - i, high[i]); mq_low_inverted.Push(m_window_size - 1 - i, -low[i]); } double max_high = mq_high.Max(); double min_low = -mq_low_inverted.Max(); current_volatility = max_high - min_low; // Volatility scaling logic if(current_volatility > m_base_volatility && current_volatility > 0) { double scale_factor = m_base_volatility / current_volatility; lot = NormalizeDouble(lot * scale_factor, 2); } } // 2. Non-Linear RBF Risk Validation if(m_use_rbf) { if(m_handle_rsi != INVALID_HANDLE) { double rsi_buffer[1]; if(CopyBuffer(m_handle_rsi, 0, 0, 1, rsi_buffer) == 1) { // Construct State Vector: Normalize inputs for the Gaussian kernel double state_vector[2]; state_vector[0] = MathMin(current_volatility / (m_base_volatility * 5.0), 1.0); // Normalized Volatility state_vector[1] = rsi_buffer[0] / 100.0; // Normalized RSI // Gatekeeper Output: Multiply current lot by the probability coefficient double rbf_coefficient = m_rbf.Calculate(state_vector); lot = NormalizeDouble(lot * rbf_coefficient, 2); } } } } //--- Broker compliance limits double stepvol = m_symbol.LotsStep(); lot = stepvol * NormalizeDouble(lot / stepvol, 0); double minvol = m_symbol.LotsMin(); if(lot < minvol) lot = minvol; double maxvol = m_symbol.LotsMax(); if(lot > maxvol) lot = maxvol; return(lot); }
Реализация начинается с объявления динамических буферов для хранения экстремумов цен. Массивы задаются как серии, поэтому самая глвая свеча имеет индекс 0 и соответствует текущему состоянию рынка и текущим ценам. Проверяется, что CopyHigh и CopyLow возвращают не менее m_window_size значений. В противном случае Optimize завершается досрочно. Это защитный механизм, предотвращающий в последующих операциях выход за границы массива.
В методе Optimize объявляются два экземпляра класса CMonotonicQueueMax. Цикл for проходит по полученным ценовым данным и заполняет эти экземпляры очереди. Использование mq_low_inverted уже рассматривалось выше при объяснении общей формулы. Добавление отрицательных значений минимумов цен -low[i] в очередь позволяет стандартной логике Max-Queue находить минимум за период. Поэтому не требуется создавать отдельную Min-Queue или класс CMonotonicQueueMin. Это упрощает код без ущерба для математической строгости.
Теперь перейдем к логике определения и масштабирования волатильности. В этой части реализована основная логика обратного масштабирования. Метод сравнивает текущий диапазон с настроенным входным параметром советника m_base_volatility. После обнаружения расширения рынка вычисляется коэффициент масштабирования. Умножение исходного объема на этот коэффициент позволяет советнику поддерживать денежный риск на относительно постоянном уровне, несмотря на расширение ценового диапазона. Например, если волатильность удвоится относительно базового уровня, размер лота уменьшится вдвое.
Расчеты в конце функции Optimize гарантируют, что рассчитанный объем готов к исполнению. Объем нормируется по параметру символа Lot Step, а также ограничивается минимальным и максимальным допустимым объемом. Это предотвращает недопустимые объемы сделок, которые были бы отклонены сервером брокера.
Нелинейная проверка риска – сеть RBF
Монотонная очередь обеспечивает вычислительно эффективное отслеживание расширения рынка. Однако для проверки масштабирования объема нужна модель, способная интерпретировать нелинейные структуры. В качестве интеллектуального фильтра используется сеть радиальных базисных функций RBF. Она классифицирует выходы модуля оценки волатильности с учетом трендовых индикаторов и осцилляторов.
RBF-сеть – специализированный тип искусственной нейронной сети, использующий радиальные базисные функции в качестве функций активации. В отличие от многослойных перцептронов, использующих глобальную аппроксимацию, RBF-сеть применяет локальную аппроксимацию. Поэтому она хорошо подходит для финансовых временных рядов со сменой рыночных режимов. Структура RBF-сети обычно состоит из трех слоев:
- Входной слой. Используется вектор входных данных с вещественными значениями типа double, включающий текущую ширину диапазона, рассчитанную монотонной очередью. В дополнение к текущим данным в вектор можно добавить значения RSI или отклонения Envelopes.
- Скрытый слой. Это набор нейронов, каждый из которых использует гауссову радиальную базисную функцию.
- Выходной слой. Он представляет собой линейную комбинацию выходов скрытого слоя. Возвращает итоговый коэффициент масштабирования риска.
Математически гауссово ядро, определяющее отклик скрытого слоя, задается следующим образом:

Где:
- X – входной вектор;
- C – центр соответствующего нейрона;
- Gamma – параметр, управляющий шириной колоколообразной кривой.
RBF-сеть вычисляет евклидово расстояние между текущим состоянием рынка и ее обученными центрами прибыльных состояний. Это гарантирует, что объем выделяется только тогда, когда текущая геометрия рынка соответствует известному статистическому преимуществу.
Выбор RBF вместо альтернативных архитектур глубокого обучения обусловлен двумя научно обоснованными факторами:
- Скорость сходимости. Параметры скрытого слоя RBF можно задавать с помощью обучения без учителя, то есть кластеризации. Это позволяет значительно ускорить циклы обучения в среде MQL5 по сравнению со стандартным обратным распространением ошибки.
- Отсев аномальных данных. Из-за локального характера гауссовой функции при переходе рынка в новую область или в условия волатильности "черного лебедя" активация нейронов будет стремиться к нулю.
В пользовательском классе управления капиталом RBF реализована как фильтр. Она размещается между первоначальным расчетом объема и финальным исполнением сделки. Этот процесс выполняется в следующей детерминированной последовательности:
- монотонная очередь определяет объем с помощью описанного выше обратного масштабирования по волатильности;
- затем RBF-сеть получает вектор состояния, включающий волатильность и нормированное значение RSI;
- сеть возвращает значение в диапазоне от 0.0 до 1.0;
- объем, рассчитанный после волатильностного масштабирования, затем умножается на коэффициент RBF.
Если рынок находится в условиях высокой волатильности, но RSI указывает на чрезмерно растянутое состояние рынка, которое RBF-сеть оценивает как вход с низкой вероятностью, выходной коэффициент RBF дополнительно уменьшит объем. Благодаря этому советник не просто реагирует на величину рыночной волатильности, но и оценивает качество сигнала через распределение вероятностей. Это дает многомерный подход к сохранению капитала.
Эмпирические тесты на исторических данных
Для подтверждения теоретических аргументов в пользу монотонной очереди уместен сравнительный анализ производительности. Используется Тестер стратегий MetaTrader 5. Цель – изолировать влияние алгоритма масштабирования по волатильности, сохранив одинаковую сигнальную логику RSI и Envelopes в контрольном и экспериментальном классах управления капиталом. Статистические различия между этими двумя отчетами служат определенным подтверждением способности системы снижать риск без изменения исходной частоты сделок.
Контрольный отчет получен для советника, использующего встроенный в IDE класс управления капиталом Size-Optimized. Этот встроенный класс уменьшает объем после серии убыточных сделок. В нем отсутствует чувствительность к волатильности в реальном времени. Ниже приведен отчет по символу GBP/JPY за период с 01.03.2023 по 15.04.2026 после оптимизации:

Система совершила 16 сделок с чистым убытком -1 730. Этот отрицательный результат отражен в профит-факторе всего 0,58: валовые убытки стратегии значительно превысили валовую прибыль. Максимальная просадка средств счета достигла критического уровня и превысила 30%. Подробный анализ списка сделок показывает, что убыток по самой крупной убыточной сделке составил -1 193. Это позволяет предположить, что из-за отсутствия обратного масштабирования по волатильности советник удерживал завышенный размер позиции в период расширения рынка. В результате одно неблагоприятное движение нанесло средствам счета несоразмерный ущерб. Также проведены тесты алгоритма монотонной очереди, дополненного фильтром RBF-сети. Результаты приведены в следующем отчете:

В приведенном выше тестовом отчете представлены результаты работы того же сигнала входа, что и в предыдущем отчете. Используется другой класс управления капиталом – CMoneyMonotonicQueueRBF. Наиболее заметная особенность этого отчета – стабильное количество сделок. Было совершено ровно 16 сделок, что показывает заметное влияние распределения объема на результаты торговли. Советник сумел перейти от убыточного результата к прибыльному, получив чистую прибыль 463,18. Профит-фактор также вырос до 1,44, а ожидаемая доходность стала положительной и составила 28,95. Максимальная просадка средств счета сократилась до 12,19%.
Форвардные прогоны для контрольного и тестового отчетов охватывают период с июля 2025 года по 15.04.2026. Влияние монотонной очереди со скользящим окном O(N) отчетливо видно в распределении сделок. Убыток по самой крупной убыточной сделке сократился до -677,48 против -1 193 в предыдущем отчете. Следовательно, уменьшение объема по мере расширения канала Дончиана способствовало этому результату. Этот класс управления капиталом эффективно ограничивает денежные потери от неудачных входов, особенно в условиях высокой волатильности.
Данные этих двух отчетов показывают явную связь между эффективностью алгоритма и сохранением капитала. Неудача контрольной группы не была вызвана плохими сигналами как таковыми: класс с монотонной очередью показал прибыль при том же количестве сделок (16). Разница между просадками 31% и 12% показывает, что монотонная очередь выполнила важное требование проекта: она поддерживала постоянный денежный риск. Обратная зависимость между рыночным диапазоном и размером позиции рассчитывается мгновенно с помощью обращений со сложностью O(1).
Выводы
Цель этого исследования управления капиталом состояла в объединении высокоэффективных вычислительных структур с адаптивной логикой масштабирования риска для устранения уязвимостей неадаптивного управления капиталом. Класс CMonotonicQueueRBF создает основу для систематического устранения уязвимостей, выявленных в начале анализа. Сочетание структур данных O(N) и нелинейной фильтрации – необходимый шаг в развитии подходов к сохранению капитала в нестационарных финансовых условиях.
Основная рассмотренная проблема – критическая уязвимость торговых систем, использующих статический объем при расширении рынка. Эта проблема решается с помощью формулы коэффициента обратного масштабирования:
scale_factor = m_base_volatility / current_volatility
Как показало сравнение контрольного и тестового советников, этот коэффициент обеспечивает сокращение размера позиции по мере расширения ценовых диапазонов. Это формирует более стабильный профиль денежного риска и предотвращает непропорциональное сокращение средств на счете, типичное для сильных рыночных событий.
Второй проблемой была неприемлемая задержка, характерная для устаревших расчетов со скользящим окном. Использование монотонной очереди сократило сложность отслеживания волатильности с O(N·K) до O(N). Два проверочных цикла метода Push поддерживают строго убывающий порядок, благодаря чему система получает доступ к экстремумам периода со сложностью O(1). Это устраняет вычислительную задержку, связанную с полным перебором массива, и обеспечивает обновление параметров риска синхронно с каждым новым ценовым баром.
Наконец, вместо исторических счетчиков убытков из торговой истории используется микроструктура рынка в реальном времени. Вместо ожидания серии реализованных убытков для уменьшения объема пользовательский класс отслеживает ширину канала Дончиана, чтобы заранее учитывать риск. Отчеты Тестера стратегий частично подтверждают эффективность превентивного метода: 16 сделок с просадкой 12,19% против 31% в контрольном отчете.
Заключение
На практике эта архитектура предоставляет воспроизводимую схему управления капиталом с низкой задержкой и реализацию на языке MQL5, готовую к интеграции и тестированию. Ключевые результаты:
- Снижение сложности: поиск максимума и минимума в скользящем окне сокращается с O(N·K) или O(N log K) до амортизированного O(N). Монотонная очередь обеспечивает доступ со сложностью O(1) на обновление, благодаря чему волатильность почти мгновенно обновляется с каждой новой котировкой.
- Детерминированное правило масштабирования: размер позиции обратно корректируется по формуле scale_factor = base_volatility / current_volatility, что ограничивает денежный риск по мере расширения рыночного диапазона.
- Фильтрация качества сигнала: опциональная RBF-сеть преобразует нормированную волатильность и состояние индикатора, например RSI, в коэффициент [0,1]. Он дополнительно корректирует объем, если геометрия рынка выходит за пределы обученных центров прибыльных состояний.
- Компоненты и точки интеграции: статья содержит класс CMoneyMonotonicQueueRBF и процедуру Optimize() – вычисление current_volatility, применение scale_factor, контроль шага, минимума и максимума объема, применение RBF, – а также рекомендации по внедрению в советники Мастера MQL5.
- Тестируемые показатели: сравните чистую прибыль, профит-фактор, ожидаемую доходность, максимальную просадку средств счета и наибольший убыток по отдельной сделке в контрольном запуске и запуске с улучшенным управлением капиталом в Тестере стратегий.
Ограничения и дальнейшие шаги: копирование данных при каждом вызове CopyHigh/CopyLow и чтение буферов индикаторов остаются возможными источниками задержек, поэтому их следует профилировать на целевом VPS. Центры RBF и значение параметра gamma необходимо задать или определить в ходе обучения (рекомендуется кластеризация или обучение без учителя), а затем проверить полученную модель на вневыборочных данных. Тем не менее сочетание модуля волатильности со сложностью O(N) и компактного нелинейного фильтра дает разработчикам советников практический путь к превентивному сохранению капитала с минимальными задержками в нестационарных рыночных условиях.
| имя | описание |
|---|---|
| wz_87_b | Советник, собранный Мастером MQL5 с пользовательским классом управления капиталом на основе монотонной очереди |
| wz_87_ctrl | Советник, собранный Мастером MQL5 со встроенным классом оптимизированного управления Size-Optimized |
| MoneyMonotonicRBF.mqh | Пользовательский класс управления капиталом на основе монотонной очереди |
| MoneySizeOptimized.mqh | Встроенный в IDE пользовательский класс управления капиталом |
Прилагаемый код предназначен для сборки в советник с помощью Мастера MQL5. Новые читатели могут ознакомиться с руководствами здесь и здесь, чтобы узнать, как выполнить такую сборку.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/22338
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Создание торговых систем с искусственным интеллектом на MQL5 (Часть 9): Создание диспетчера сигналов ИИ
Создание торговых систем с искусственным интеллектом на MQL5 (Часть 8): Доработка интерфейса с анимацией, метриками времени и инструментами управления ответами
Изучение стандартной библиотеки MQL5 (Часть 7): Создание интерактивных меток позиций с помощью класса CCanvas
Изучение Стандартной библиотеки MQL5 (Часть 6): Оптимизация сгенерированного советника
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования