preview
Нейросети в трейдинге: От единственного прогноза к пространству рыночных сценариев (ORION)

Нейросети в трейдинге: От единственного прогноза к пространству рыночных сценариев (ORION)

MetaTrader 5Торговые системы |
178 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Введение

Финансовый рынок редко развивается по единственному заранее определённому сценарию. В каждый момент времени текущее состояние допускает несколько продолжений: цена может сохранить импульс, перейти к коррекции, задержаться в диапазоне или резко сменить направление. Все эти варианты могут быть правдоподобны, хотя фактически реализуется только один из них.

Именно здесь возникает одно из главных противоречий прогнозирования финансовых временных рядов. Большинство моделей обучается выдавать одну ожидаемую траекторию. Такой результат удобно сравнивать с фактическими данными и передавать торговой политике, но единственный прогноз вынужден представлять сразу несколько возможных будущих, которые нередко противоречат друг другу.

Представим типичную ситуацию. После сильного движения рынок входит в область неопределённости. Продолжение тренда всё ещё возможно, но столь же реалистично выглядят коррекция или консолидация. Если модель минимизирует среднюю ошибку и обязана выдать один прогноз, она может выбрать компромисс между этими вариантами. Получится статистически аккуратная траектория, которая не соответствует ни одному реальному сценарию.

В реальной торговле такой компромисс особенно неприятен. Он может выглядеть разумно на графике ошибки, но плохо работать как торговый план. Если модель сгладила конфликт между ростом и снижением, Актер получает не альтернативы, а усреднённый сигнал. На его основе сложнее оценить допустимый откат, выбрать размер позиции и понять, когда исходная гипотеза уже разрушена.

Для практической торговли это особенно важно. Недостаточно знать вероятное направление движения. Важно понимать: какое встречное движение ещё не разрушает исходный замысел; где проходит граница неверного сценария; насколько сильно расходятся альтернативные варианты будущего. Поэтому торговой системе полезно видеть не только ожидаемую траекторию, но и структуру неопределённости вокруг неё.

Даже отдельная оценка уверенности решает проблему лишь частично. Низкая уверенность может означать шумные данные, незнакомый режим или существование нескольких почти равноправных будущих. Для торгового решения это разные ситуации. Одно дело, когда все сценарии указывают в одном направлении и различаются только масштабом движения. Совсем другое — когда рынок находится на развилке между ростом и снижением.

Отсюда возникает естественный вопрос: обязательно ли заставлять модель выбирать единственное будущее там, где сам рынок такого выбора ещё не сделал? В этом проекте рассмотрим другой подход. Вместо одной прогнозной траектории будем формировать несколько самостоятельных рыночных сценариев, каждый из которых описывает возможную последовательность будущих состояний на заданном горизонте.

Эта идея хорошо согласуется с фреймворком ORION, предложенным в работе «ORION: A Holistic End-to-End Autonomous Driving Framework by Vision-Language Instructed Action Generation». Авторы решают задачу автономного вождения, но архитектурный принцип полезен и для финансовых рынков: не требовать немедленного действия от сложного представления сцены, а сначала сформировать пространство возможных траекторий.

В нашей адаптации сценарное пространство отвечает на вопрос о том, как может развиваться рынок, а торговая политика решает, что делать с учётом этих вариантов и текущего контекста. Поэтому важно не просто размножить прогнозные головы, а добиться специализации сценариев и не позволить им схлопнуться в несколько копий одного усреднённого будущего. Именно эту задачу мы начинаем решать в данной работе.

Статья построена как первый практический шаг. Сначала мы знакомимся с авторской логикой ORION: разделяем восприятие, память, планирование и генерацию траекторий. Затем переносим её в рыночную постановку и создаём вычислительный фундамент для нескольких сценариев, их вероятностей, неопределённости и разреженного распределения ответственности.


Алгоритм фреймворка ORION

Фреймворк ORION решает задачу автономного вождения, но начинает с проблемы, хорошо знакомой и в торговле. Система должна понять сложную текущую сцену, учесть важные события прошлого и на основании этого построить дальнейшую траекторию. Между пониманием ситуации и действием существует разрыв: рассуждение работает со смысловыми признаками сцены, тогда как действие выражается последовательностью числовых координат будущего движения.

Авторы рассматривают это как разрыв между пространством рассуждений и пространством действий. Поэтому они не заставляют семантическое представление сразу выдавать числовой результат. Между пониманием сцены и конечной траекторией помещается генеративный планировщик, который переводит высокоуровневое состояние планирования в распределение возможных действий. В исходной работе это мультимодальные траектории автомобиля. Для рынка аналогом становятся альтернативные варианты дальнейшего движения цены.

Именно это разделение делает ORION полезным для нашей серии. В трейдинге ошибка часто возникает не потому, что модель совсем не видит направление, а потому, что она слишком рано превращает неполное представление рынка в конечную операцию. Между состоянием рынка и сделкой нужен промежуточный слой, где будущие варианты ещё не сведены к одной команде.

На концептуальном уровне алгоритм можно представить как последовательное согласование нескольких представлений. Сначала визуальный энкодер преобразует текущую сцену в латентные признаки. Для финансовой задачи аналогично можно кодировать котировки, объёмы, признаки волатильности или карту состояния рынка. Затем QT-Former извлекает полезные признаки сцены и подключает исторический контекст.

В ORION используются разные типы обучаемых запросов. Запросы сцены Qs формируют обобщённое представление текущей ситуации, а запросы восприятия Qp помогают сохранить более конкретную информацию о наблюдаемой среде. Сначала они взаимодействуют через Self-Attention, а затем обращаются к признакам сцены через Cross-Attention. В рыночной постановке это можно понимать как разные вопросы к одному участку рынка: направление импульса, структура волатильности, признаки истощения движения или положение цены относительно недавних экстремумов.

Такое устройство хорошо согласуется с рыночной интуицией. Один и тот же бар не существует отдельно от контекста. Для одной стратегии он может быть признаком продолжения импульса, для другой — сигналом перегрева, для третьей — обычным шумом внутри диапазона. Разные запросы позволяют модели рассматривать сцену не как монолитный вектор, а как набор признаков, важных для разных аспектов будущего движения.

В авторской работе запросы восприятия связаны со вспомогательными задачами обнаружения объектов, оценки дорожной обстановки и прогнозирования движения участников сцены. Для финансовых рядов похожую роль могут играть вспомогательные признаки режима, волатильности или структуры движения. Они не обязаны непосредственно определять вход в позицию. Их задача — заставить энкодер сохранять информацию, которая действительно описывает рынок, а не только случайно уменьшает торговую ошибку на обучающей выборке.

Далее в работу включается память. Авторы вводят запросы истории Qh и долгосрочный банк памяти M, где хранятся не исходные кадры, а компактные латентные представления предыдущих состояний. Запросы истории извлекают из банка релевантный контекст с учётом относительного временного кодирования. Затем они снова обращаются к текущей сцене. Получается двухступенчатый процесс: сначала модель спрашивает прошлое, что из него важно сейчас, а затем заново смотрит на настоящее через найденный контекст.

В этом месте важно не смешивать память с обычным расширением входного окна. Скользящее окно просто добавляет прошлые бары. Память ORION хранит уже обработанные состояния и позволяет запросам истории выбрать из них релевантные. Для рынка это ближе к тому, как трейдер вспоминает не всю ленту котировок подряд, а конкретные режимы, уровни и реакции цены, похожие на текущую ситуацию.

Для трейдера такая логика понятна. Цена может вернуться к области, от которой ранее начался сильный импульс, или рынок может вновь приблизиться к уже наблюдавшемуся режиму высокой волатильности. Текущий бар сам по себе мало что говорит, но его значение меняется в контексте прошлого. В исходном ORION обновлённые исторические запросы возвращаются в память по политике FIFO. Для нашей адаптации важнее сам принцип: история должна активно участвовать в интерпретации настоящего, а не просто накапливаться в длинном окне наблюдений.

Затем текущие признаки сцены и обновлённая история преобразуются двухслойными MLP в токены. Эти токены вместе с текстовой инструкцией передаются большой языковой модели. Для дальнейшего алгоритма особенно важен специальный токен планирования S. Он аккумулирует контекст, накопленный в ходе рассуждения, и становится условием для генерации будущей траектории. Модель не передаёт планировщику весь внутренний контекст, а формирует компактное состояние именно для планирования.

В рыночной задаче не обязательно буквально переносить LLM. Важен принцип разделения ролей. Энкодер отвечает на вопрос, что происходит на рынке. Память уточняет, что из прошлого важно сейчас. Модуль рассуждения формирует компактное состояние планирования. И только после этого отдельный генеративный модуль определяет, какие траектории будущего совместимы с этим состоянием. Такой подход не позволяет напрямую смешать прогноз и торговое действие.

Именно здесь начинается генеративная часть ORION. Авторы исходят из того, что пространство рассуждений и пространство действий имеют разную природу. Состояние S является высокоуровневым латентным вектором, а траектория — упорядоченной последовательностью точек. Поэтому вместо жёсткого отображения одного состояния в один ответ модель формирует условное распределение возможных действий.

В основной версии используется вариационный автоэнкодер. Состояние планирования S и фактическая целевая траектория T проецируются в общее латентное пространство с гауссовскими распределениями. Для обеих проекций применяются двухслойные MLP, а согласование выполняется через дивергенцию Кульбака — Лейблера. Во время обучения реальная траектория показывает, где должен находиться правильный вариант будущего, а состояние планирования учится формировать совместимое распределение без прямого знания будущего.

Это важный мост между рассуждением и действием. Токен планирования не обязан содержать полную будущую траекторию. Он должен содержать достаточно информации, чтобы генеративный модуль мог восстановить область правдоподобных продолжений. Поэтому в нашей адаптации этот принцип превращается в условие для сценарного пространства: текущее состояние и память задают контекст, а сценарии раскрывают разные варианты будущего движения.

После этого ORION использует GRU-декодер для восстановления конечной траектории. Для трейдера важнее общий смысл конструкции: модуль анализа не обязан самостоятельно строить точную форму будущего на каждом шаге. Его задача — выразить текущее состояние, а специализированный планировщик раскрывает его в возможные продолжения. Это принципиально, потому что для торговли важна не только конечная точка. Один и тот же рост через десять баров может пройти почти без отката или начаться с глубокой просадки, что требует совершенно разных решений по позиции и риску.

Авторы подчёркивают, что генеративная модель сама по себе ещё не гарантирует качества планирования. Поэтому функция потерь учитывает не только восстановление траектории, но и компоненты, связанные с безопасностью движения и границами допустимой области. Для рынка буквальное копирование этих штрафов не требуется, но принцип сохраняется: качество сценария нельзя оценивать только средней ошибкой. Важно учитывать форму траектории, промежуточные неблагоприятные движения и согласованность заявленной неопределённости с фактической ошибкой.

Обучение ORION также построено поэтапно. Сначала согласуются визуальное и языковое пространства, затем — пространство рассуждений и действий, после чего проводится сквозная донастройка. Для финансовых рынков такая последовательность особенно разумна: сначала можно добиться устойчивого представления рынка и осмысленной работы с историей, затем обучить сценарный прогноз, и только после этого передать пространство будущих траекторий торговой политике.

Здесь необходимо провести границу между авторским ORION и нашей адаптацией. Исходная работа использует мультимодальный генеративный планировщик, но не вводит систему рыночных прототипов, разреженную ответственность сценариев или отдельные запросы покупки и продажи. Эти механизмы относятся уже к нашей архитектуре. Мы сохраняем фундаментальную идею ORION: не смешивать наблюдение, планирование и действие раньше времени, а будущее представлять как пространство возможных траекторий.

Такая граница нужна для корректности. Мы не утверждаем, что авторский ORION в исходном виде решает задачу трейдинга. Он даёт архитектурный принцип: не смешивать понимание сцены, состояние планирования и конечное действие. Всё, что связано с рыночными прототипами, ответственностью сценариев и последующей работой Актера, относится уже к нашей адаптации.

Авторская визуализация фреймворка ORION


Реализация средствами MQL5

Перед реализацией необходимо чётко отделить авторский ORION от нашей рыночной адаптации. В исходной работе модель объединяет визуальный энкодер, QT-Former, большую языковую модель и условный генеративный планировщик. Наша задача иная: рынок не имеет заранее заданной полосы движения и не подчиняется действиям торговой системы. Поэтому сценарный модуль должен отвечать на вопрос, как может развиваться рынок, а Актер — что делать с учётом этих вариантов, текущего состояния счёта и открытых позиций.

Перед нами большая работа, и выполнять её с чистого листа нет смысла. В качестве основы используем модель из проекта CogDriver, где уже построены механизмы анализа рыночной сцены, временной памяти и прогнозного плана. Теперь этот фундамент нужно обогатить семантикой нескольких будущих траекторий.

Простого размножения прогнозных голов недостаточно: при одинаковых входах, целях и функции потерь они быстро сходятся к похожим решениям. Поэтому каждый сценарий должен получить собственную отправную точку, построить индивидуальную траекторию, оценить неопределённость и конкурировать с другими сценариями за право объяснить фактически реализовавшееся будущее. Обучение при этом получат только несколько наиболее подходящих вариантов.

Начнём с двух новых OpenCL-кернелов. ScenarioForecastForward готовит входы для генератора, роутера и блока неопределённости, а затем собирает их выходы в готовые сценарные траектории. ScenarioResponsibilities сравнивает эти траектории с фактическим будущим, формирует разреженную ответственность и подготавливает обучающие сигналы. Для каждого прототипа нам нужны три результата: траектория, масштаб неопределённости и априорная вероятность сценария.

Кернел ScenarioForecastForward запускается отдельно для каждого сценария. Индекс сценария берётся из глобального идентификатора потока, поэтому каждый рабочий поток отвечает за один элемент сценарного пространства.

__kernel void ScenarioForecastForward(__global const float *input,
                                      __global const float *prototypes,
                                      __global float *generator_input,
                                      __global float *router_input,
                                      __global float *confidence_input,
                                      __global const float *generator_output,
                                      __global const float *router_output,
                                      __global const float *confidence_output,
                                      __global float *z,
                                      __global float *u,
                                      __global float *pi,
                                      const int scenarios,
                                      const int horizon,
                                      const int dimension,
                                      const int phase,
                                      __global float *log_pi,
                                      __global float *log_u,
                                      const int variables)
  {
   const int k = get_global_id(0);
   if(k >= scenarios || scenarios <= 0 || variables <= 0 || horizon <= 0 || dimension <= 0)
      return;

Кроме числа сценариев, кернел получает горизонт планирования horizon, размерность латентного пространства dimension и число последовательностей variables. Работа разделена на две фазы. При phase == 0 формируются входные буферы для трёх нейронных ветвей.

Такое решение оставляет пространство для дальнейшего расширения. В дальнейшем в качестве переменных можно передавать не только один латентный вектор, но и несколько связанных представлений: состояние сцены, память, прогнозный план или дополнительные признаки риска. На уровне кернела логика при этом остаётся той же: каждый сценарий обрабатывается отдельно и получает собственную траекторию.

   if(phase == 0)
     {
      for(int v = 0; v < variables; v++)
       for(int d = 0; d < dimension; d++)
        {
         float prototype_mean = 0.0f;
         for(int h = 0; h < horizon; h++)
           {
            const int prototype_shift = ((k * variables + v) * horizon + h) * dimension + d;
            const int condition_shift = ((k * variables + v) * horizon + h) * 2 * dimension;
            generator_input[condition_shift + d] = input[v * dimension + d];
            generator_input[condition_shift + dimension + d] = prototypes[prototype_shift];
            confidence_input[condition_shift + d] = input[v * dimension + d];
            confidence_input[condition_shift + dimension + d] = prototypes[prototype_shift];
            prototype_mean += prototypes[prototype_shift];
           }
         const int router_shift = k * 2 * variables * dimension;
         router_input[router_shift + v * dimension + d] = input[v * dimension + d];
         router_input[router_shift + variables * dimension + v * dimension + d] = 
                                                            prototype_mean / (float)horizon;
        }
      return;
     }

Генератор на каждом шаге горизонта получает текущее состояние и прототип выбранного сценария. Текущее состояние задаёт исходную точку, а прототип — рассматриваемый вариант будущего. Поэтому при одинаковом рынке разные сценарии получают разные условия генерации. Мы не закрепляем за прототипами роли вручную: один может со временем специализироваться на продолжении импульса, другой — на коррекции, третий — на консолидации.

Именно прототип не даёт сценариям стартовать из полностью одинаковой точки. Текущее состояние у них общее, но предполагаемая форма будущего различается. Поэтому генератор не конкурирует сам с собой, пытаясь каждый раз заново изобрести все возможные траектории. Он уточняет конкретный вариант, уже заданный прототипом.

Тот же состав входов получает блок неопределённости, поскольку её нельзя оценивать только по текущему рынку или только по форме прототипа. Роутер устроен проще: ему не нужна каждая точка горизонта, поэтому прототип усредняется по времени и объединяется с текущим состоянием. Генератор строит подробную траекторию, а роутер лишь оценивает совместимость сценария с текущим рынком.

После работы нейронных слоёв генератор выдаёт остаточную коррекцию, блок неопределённости — масштаб ожидаемой ошибки, а роутер — логиты, которые готовый слой CNeuronSoftMaxOCL преобразует в априорные вероятности. При повторном вызове кернела начинается сборка итоговых сценариев.

Это также упрощает дальнейшую интеграцию в существующую библиотеку. Мы используем готовый слой для нормализации вероятностей и оставляем новому кернелу роль адаптера между сценарными ветвями. Такой подход соответствует общей линии проекта: добавлять только те операции, которых действительно не хватает, а не переписывать уже проверенные блоки.

   log_pi[k] = log(pi[k] + 1.0e-6f);
   for(int v = 0; v < variables; v++)
    for(int h = 0; h < horizon; h++)
     {
      for(int d = 0; d < dimension; d++)
        {
         const int shift = ((k * variables + v) * horizon + h) * dimension + d;
         z[shift] = input[v * dimension + d] + prototypes[shift] + generator_output[shift];
        }
      const int shift = (k * variables + v) * horizon + h;
      u[shift] = clamp(confidence_output[shift] + 0.001f, 0.001f, 10.0f);
      log_u[shift] = log(u[shift] + 1.0e-6f);
     }
  }

Каждая траектория формируется как сумма текущего состояния, сценарного прототипа и коррекции генератора. Это принципиально: сеть не строит всё будущее с нуля, а адаптирует уже заданную геометрию сценария к текущему рынку. Такой остаточный режим делает задачу более структурированной и сохраняет различия между альтернативными вариантами будущего.

Одновременно вычисляется масштаб неопределённости распределения Лапласа. Чем он меньше, тем плотнее распределение вокруг прогнозной траектории и тем выше фактическая уверенность модели. Чем больше значение, тем шире допустимый диапазон отклонений. Для каждого сценария, последовательности и шага горизонта используется одно значение, общее для всех координат соответствующего латентного состояния.

На выходе первого кернела мы получаем набор из K сценариев. Каждый содержит собственную траекторию, оценку неопределённости и априорную вероятность. Но это пока только гипотезы. Во время обучения известна фактическая целевая траектория target, и второй кернел определяет, какие сценарии объясняют её лучше.

__kernel void ScenarioResponsibilities(__global const float *target,
                                       __global const float *z,
                                       __global const float *u,
                                       __global const float *pi,
                                       __global float *responsibilities,
                                       __global float *generator_gradient,
                                       __global float *router_gradient,
                                       __global float *confidence_gradient,
                                       const int scenarios,
                                       const int top_k,
                                       const int horizon,
                                       const int dimension,
                                       __global float *scores,
                                       __global const float *sparse,
                                       __global const float *indexes,
                                       const int phase,
                                       const int variables)
  {
   if(get_global_id(0) != 0 || variables <= 0 || scenarios <= 0 || top_k <= 0 || top_k > scenarios)
      return;
   if(phase == 0)
     {
      for(int k = 0; k < scenarios; k++)
        {
         float score = log(max(pi[k], 1.0e-12f));
         for(int v = 0; v < variables; v++)
          for(int h = 0; h < horizon; h++)
           {
            const float scale = clamp(u[(k * variables + v) * horizon + h], 1.0e-3f, 10.0f);
            for(int d = 0; d < dimension; d++)
              {
               const int shift = ((k * variables + v) * horizon + h) * dimension + d;
               const int target_shift = (v * horizon + h) * dimension + d;
               score -= fabs(target[target_shift] - z[shift]) / scale + log(2.0f * scale);
              }
           }
         scores[k] = score;
        }
      return;
     }

На первой фазе ScenarioResponsibilities для каждого сценария вычисляет балл: логарифм априорной вероятности дополняется логарифмическим правдоподобием распределения Лапласа. Чем ближе прогноз к фактической траектории и чем лучше откалибрована его неопределённость, тем выше итоговая оценка.

Лапласовская модель использует абсолютное отклонение, поэтому единичный сильный выброс влияет на обучение мягче, чем при квадратичной ошибке. Для финансовых рядов это полезно: рынок регулярно создаёт резкие движения и переходы между режимами волатильности. При этом большой масштаб неопределённости не даёт бесплатной страховки — логарифмический член штрафует чрезмерно широкое распределение.

После расчёта баллов выбираются только TopK наиболее подходящих сценариев. Сам отбор и нормализация весов выполняются вне кернела. На второй фазе все ответственности сначала обнуляются.

   for(int k = 0; k < scenarios; k++)
      responsibilities[k] = 0.0f;

Ненулевые значения получают только выбранные сценарии.

   for(int selected = 0; selected < top_k; selected++)
     {
      const int k = (int)indexes[selected];
      if(k >= 0 && k < scenarios)
         responsibilities[k] = sparse[selected];
     }

Так формируется разреженный вектор ответственности. Если бы каждая фактическая траектория обучала все сценарии одновременно, их прототипы постепенно двигались бы к одному среднему решению. Теперь обновляются только наиболее подходящие варианты, а остальные сохраняют возможность специализироваться на других типах будущего. TopK при этом не превращает обучение в жёсткий режим, где победитель получает всё: несколько близких сценариев могут оставаться активными одновременно.

Для рынка это особенно важно. Фактическое движение часто не совпадает идеально ни с одним заранее заданным вариантом. Оно может находиться между продолжением импульса и мягкой коррекцией или частично напоминать сразу несколько режимов. TopK позволяет не ломать сценарное пространство грубым выбором одного победителя, но при этом сохраняет разреженность обучения.

После формирования ответственностей кернел подготавливает градиенты трёх ветвей модели.

   for(int k = 0; k < scenarios; k++)
     {
      const float responsibility = responsibilities[k];
      router_gradient[k] = pi[k] - responsibility;
      for(int v = 0; v < variables; v++)
       for(int h = 0; h < horizon; h++)
        {
         const int confidence_shift = (k * variables + v) * horizon + h;
         const float scale = clamp(u[confidence_shift], 1.0e-3f, 10.0f);
         float absolute_sum = 0.0f;
         for(int d = 0; d < dimension; d++)
           {
            const int shift = ((k * variables + v) * horizon + h) * dimension + d;
            const int target_shift = (v * horizon + h) * dimension + d;
            const float error = z[shift] - target[target_shift];
            absolute_sum += fabs(error);
            generator_gradient[shift] = (responsibility > 0.0f ?
                                         (error > 0.0f ? 1.0f : (error < 0.0f ? -1.0f : 0.0f)) /
                                         scale : 0.0f);
           }
         confidence_gradient[confidence_shift] = (responsibility > 0.0f ?
                                                  ((float)dimension / scale -
                                                  absolute_sum / (scale * scale)) : 0.0f);
        }
     }
  }

Роутер повышает априорную вероятность сценариев, которые затем лучше объясняют фактическое будущее, и снижает вероятность неподходящих. Важно различать априорную вероятность и ответственность: роутер оценивает сценарий до знания будущего, тогда как ответственность вычисляется уже после того, как реальная траектория стала известна.

Для генератора численное значение responsibility используется как разреженная маска допуска. Нулевая ответственность полностью исключает сценарий из обучения на данной траектории; положительная допускает полный градиент ошибки. Это ограничивает взаимное влияние сценариев и не позволяет всем прогнозам понемногу подстраиваться под одну цель. Чем меньше заявленная неопределённость, тем сильнее сценарий отвечает за собственный промах.

Блок неопределённости также получает отдельный обучающий сигнал. Большая фактическая ошибка относительно текущего масштаба подталкивает модель увеличить допустимую неопределённость, а малая — уменьшить её. Поэтому блок учится не просто выдавать дополнительное число, а согласовывать заявленный диапазон ошибки с фактическим качеством прогноза.

В практическом смысле это означает, что модель должна различать точный план и широкий допуск. Если сценарий регулярно ошибается, но выдаёт малую неопределённость, он переоценивает свою надёжность. Если же он постоянно расширяет допустимый диапазон, он перестаёт быть полезным для торгового решения. Баланс между ошибкой и масштабом распределения делает сценарии более пригодными для последующего анализа Актером.

В результате два OpenCL-кернела создают первый вычислительный фундамент нашей сценарной модели. ScenarioForecastForward превращает текущее состояние и набор прототипов в несколько прогнозных траекторий, а ScenarioResponsibilities сравнивает их с фактическим будущим и формирует обучающие сигналы для генератора, роутера и блока неопределённости.


Заключение

В этой статье мы начали переход от единственного прогноза к пространству возможных рыночных сценариев. Во введении была обозначена проблема: одна траектория вынуждена сжимать несколько правдоподобных вариантов будущего и может превращать их в усреднённый прогноз, который плохо описывает реальные рыночные исходы.

В качестве архитектурной основы мы рассмотрели ORION. Его ключевой принцип состоит в разделении наблюдения, планирования и действия. Для нашей задачи это означает, что сценарный модуль сначала формирует несколько вариантов развития рынка, а Актер уже решает, что делать с учётом этих траекторий и текущего торгового контекста.

Практическую работу мы начали с двух OpenCL-кернелов. Первый формирует сценарные траектории, их априорные вероятности и оценки неопределённости. Второй сравнивает прогнозы с фактическим будущим, выбирает наиболее подходящие варианты и создаёт разреженный обучающий сигнал. Тем самым мы решаем центральную проблему статьи на уровне вычислительного фундамента: создаём условия для специализации сценариев и защищаем их от схлопывания в один усреднённый прогноз.

Поставленная во введении проблема уже получила практическое направление решения. Мы подготовили вычислительный механизм, который позволяет эти сценарии сформировать, оценить и обучать избирательно. Это ещё не полный торговый контур, но уже не единственный прогноз, замаскированный под несколько выходов.

Дальше предстоит организовать работу прототипов, объединить новые операции в полноценный нейронный слой, встроить его в CogDriver и передать всё пространство альтернативных траекторий Актеру. Но направление уже определено: вместо единственного ответа модель начинает формировать несколько правдоподобных будущих, сохраняя информацию, которую обычный усреднённый прогноз неизбежно теряет.


Ссылки


Программы, используемые в статье

# Имя Тип Описание
1 Study.mq5 Советник Советник офлайн-обучения моделей
2 StudyOnline.mq5 Советник Советник онлайн-обучения моделей
3 StudyStateEncoder.mq5 Советник Советник офлайн-обучения прогнозной модели
4 Test.mq5 Советник Советник для тестирования модели
5 Trajectory.mqh Библиотека класса Структура описания состояния системы и архитектуры моделей
6 NeuroNet.mqh Библиотека класса Библиотека классов для создания нейронной сети
7 NeuroNet.cl Библиотека Библиотека кода OpenCL-программы

Проект представлен на forge.mql5.io/dng.

Прикрепленные файлы |
MQL5.zip (3865.57 KB)
Создание пользовательских индикаторов в MQL5 (Часть 8): Интеграция объёма для углублённого анализа рыночного профиля (Market Profile) Создание пользовательских индикаторов в MQL5 (Часть 8): Интеграция объёма для углублённого анализа рыночного профиля (Market Profile)
В этой статье мы расширяем гибридный индикатор рыночного профиля Time Price Opportunity (TPO) в MQL5 за счёт интеграции данных объёма для расчёта точки контроля по объёму, области стоимости и средневзвешенной по объёму цены с настраиваемыми вариантами подсветки. Система вводит расширенные возможности, такие как определение начального баланса, линии продления ключевых уровней, режим split-профиля и альтернативные TPO-символы, например квадраты или круги, для улучшенного анализа графика на нескольких таймфреймах.
Оптимизация торговли на снятии ликвидности: Как различать снятие ликвидности и сдвиги рыночной структуры Оптимизация торговли на снятии ликвидности: Как различать снятие ликвидности и сдвиги рыночной структуры
Эта статья посвящена специализированному трендовому советнику, цель которого — подробно показать, как использовать торговые сетапы после снятий ликвидности. В ней рассматривается советник, специально разработанный для трейдеров, стремящихся оптимизировать применение рейдов и снятий ликвидности как критериев входа в рынок и принятия торговых решений. Также рассматривается, как правильно различать снятия ликвидности и сдвиги рыночной структуры, проверять и использовать каждый из этих сценариев при его возникновении и тем самым снижать потери, вызванные их смешением.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Встраивание торговой дисциплины в код (Часть 5): Контроль соблюдения риск-ограничений на уровне счёта в MQL5 Встраивание торговой дисциплины в код (Часть 5): Контроль соблюдения риск-ограничений на уровне счёта в MQL5
Мы представляем модуль контроля рисков на MQL5, который обеспечивает последовательное соблюдение правил риска на уровне счета. Он непрерывно сканирует позиции из любых источников, проверяет уровни стоп-лосса и тейк-профита, риск-экспозицию на основе эквити и целевое соотношение R:R, а также автоматически корректирует отклонения, устанавливая уровни или корректируя объем. В результате получается единый риск-профиль для ручных и автоматизированных сделок, с поддержкой визуальной обратной связи на графике и режимного управления.