preview
Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Основные компоненты)

Нейросети в трейдинге: Гибридные модели прогнозирования с управляемой смесью распределений (Основные компоненты)

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

Введение

Финансовый рынок — среда изменчивая и местами коварная. Сегодня он демонстрирует чистый импульсный тренд, завтра — вязнет в боковой фазе, а послезавтра — устраивает резкий выброс, который ломает статистику последних недель. Классические модели анализа последовательностей, будь то LSTM или более современные вариации, устроены по принципу непрерывного прогнозирования — им не свойственно сомневаться. Они всегда выдают число, всегда формируют сигнал. И в этом их сила — и их слабость.

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

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

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

Механизм Confidence-Gating реализован как классификатор, который определяет, достаточно ли текущая ситуация соответствует одному из архетипов. Если мера уверенности превышает установленный порог, соответствующий специализированный модуль активируется. Если нет — система остаётся в базовом режиме. Либо архетип включён, либо нет. Третьего состояния не предусмотрено.

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

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

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

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

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



Проработка создания архетипов

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

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

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

На этапе прогнозирования в оригинальной архитектуре применяется Soft-Assignment. Каждому архетипу присваивается вероятность соответствия текущему эмбеддингу. При этом для оценки уверенности используется Hard-Assignment — ориентация на ближайший архетип. Именно он служит базой для расчёта Confidence и принятия решения о том, активировать ли специализированный режим. Когда архетип активирован, его блок генерирует прогноз, опираясь на накопленную статистику поведения в рамках данного кластера.

С теоретической точки зрения конструкция выглядит стройной. Однако при переносе в прикладную торговую среду возникает ряд существенных вопросов. Во-первых, сама процедура кластеризации эмбеддингов требует значительных вычислительных ресурсов и аккуратной предварительной обработки данных. Пространство скрытых состояний высокоразмерно, и K-means в нём далеко не всегда ведёт себя стабильно. Число кластеров приходится подбирать эмпирически, а сами центроиды могут смещаться при изменении рыночной структуры.

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

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

В предыдущей статье мы уже упоминали работу "Tail-Aware Density Forecasting of Locally Explosive Time Series: A Neural Network Approach" и напрямую связали её идеи с подходами Lattice. В рамках данного проекта мы идем дальше и включаем Tail-Aware Density Forecasting в качестве отдельного элемента для моделирования плотности распределения будущих значений с учетом тяжёлых хвостов и локально экстремальных событий.

Важный момент практической реализации заключается в том, что Tail-Aware блоки работают как специализированные эксперты внутри смеси архетипов. Здесь важно подчеркнуть, что Tail-Aware моделирование функционирует как смесь экспертов, формирующая адаптивные распределения будущих значений. По сути, аналог множества архетипов. Каждый эксперт генерирует свой прогнозный спектр, учитывая особенности хвостов и локальные экстремумы. Результат комбинируется во взвешенное распределение. При этом этот механизм сам по себе не имеет встроенного Confidence-Gating, который в Lattice отвечает за бинарное включение или исключение архетипа из прогноза на основе уверенности в распознавании режима.

Следовательно, перед нами стоит задача аккуратно скоординировать работу двух систем. Tail-Aware обеспечивает богатую и гибкую модель распределения внутри каждого эксперта, а Lattice через Confidence-Gating решает, какие архетипы следует активировать в текущий момент. Синхронизация этих блоков требует выверенной логики: необходимо, чтобы распределения генерировались только для тех архетипов, которые признаны релевантными механизмом уверенности.

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

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

И наконец, на основе этих взвешенных параметров формируется единый прогноз взвешенного распределения. Такой подход позволяет резко сократить количество ненужных вычислений, сохранив при этом точность и адаптивность модели. Мы сохраняем контекстную гибкость Tail-Aware прогнозирования, одновременно удерживая строгую дисциплину Lattice через механизм Confidence-Gating. В итоге модель остаётся быстрой, управляемой и практично применимой в торговых системах с высокой частотой обновления данных.



Построение объекта Tail-Aware прогнозирования

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

class CNeuronConfGateTailAwareMoE   :  public CNeuronBaseOCL
  {
protected:
   CLayer            cConfidenceGating;
   CLayer            cScore;
   CParams           cTailAwareMoE;
   CLayer            cCGScore;
   CNeuronAddToStack cCGStack;
   CNeuronAddToStack cScoreStack;
   CNeuronBaseOCL    cDensity;
   //---
   virtual bool      MixExpertsPredict(void);
   virtual bool      MixExpertsPredictGrad(void);
   //---
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronConfGateTailAwareMoE(void) {};
                    ~CNeuronConfGateTailAwareMoE(void) {};
   //---
   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint dimension, uint units,
                          uint forecast, uint experts,
                          ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int       Type(void) override const  {  return defNeuronConfGateTailAwareMoE;   }
   //--- methods for working with files
   virtual bool      Save(int const file_handle) override;
   virtual bool      Load(int const file_handle) override;
   //---
   virtual void      SetOpenCL(COpenCLMy *obj)   override;
   virtual void      TrainMode(bool flag) override;
   //---
   virtual bool      WeightsUpdate(CNeuronBaseOCL *source, float tau) override;
   virtual bool      Clear(void) override;
   virtual void      SetActivationFunction(ENUM_ACTIVATION value) override { };
  };

Внутри объекта Confidence-Gating организован блоком cConfidenceGating, который активирует архетипы, релевантные в текущий момент, а модуль cScore отвечает за оценку релевантности отдельных экспертов. Tail-Aware блок, представленный объектом cTailAwareMoE, обеспечивает изучение параметров распределений для каждого эксперта.

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

bool CNeuronConfGateTailAwareMoE::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                                       uint dimension, uint units, uint forecast, uint experts,
                                       ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, dimension * forecast, optimization_type, batch))
      ReturnFalse;
   activation = None;

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

Далее очищаются внутренние динамические массивы cConfidenceGating,cScore и cCGScore. После чего они связываются с общим OpenCL-контекстом. Это обеспечивает полное GPU-ускорение, позволяя обрабатывать одновременно множество экспертов и длинные горизонты прогнозирования без падения производительности.

   cConfidenceGating.Clear();
   cScore.Clear();
   cCGScore.Clear();
   cConfidenceGating.SetOpenCL(OpenCL);
   cScore.SetOpenCL(OpenCL);
   cCGScore.SetOpenCL(OpenCL);

Tail-Aware блок представлен в виде объекта обучаемых параметров cTailAwareMoE и инициализируется с учётом числа экспертов, размерности параметров распределения и горизонта прогнозирования.

   uint index = 0;
   if(!cTailAwareMoE.Init(0, index, OpenCL, dimension * forecast * 4 * experts, optimization, iBatch))
      ReturnFalse;
   cTailAwareMoE.SetActivationFunction(None);

Здесь важно уточнить, что генерация распределений в Tail-Aware блоке выполнена максимально просто. Мы не создаём адаптивные распределения, подстраивающиеся под каждый конкретный фрагмент анализируемых данных. Наследуя логику архетипов, модель просто запоминает параметры распределений в процессе обучения. Это значит, что сами распределения статичны для каждого архетипа и не меняются динамически на основе текущего рынка.

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

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

   uint windows[] = {7, 5, 3};
   uint steps[] = {2, 2, 2};
   CNeuronSpikeSuperKernelBlock* conv = NULL;
   CNeuronBaseOCL* neuron = NULL;
   CNeuronBatchNormOCL* norm = NULL;
   CNeuronSoftMaxOCL* softmax = NULL;
   CNeuronSpikeActivation* spike = NULL;
//--- Score
   index++;
   conv = CNeuronSpikeSuperKernelBlock();
   if(!conv ||
      !conv.Init(experts, index, OpenCL, dimension, (dimension + 1) / 2, windows,
                                        steps, units, 1, optimization, iBatch) ||
      !cScore.Add(conv))
      DeleteObjAndFalse(conv);

Затем полносвязный нейронный слой с активацией SoftPlus аккумулирует информацию и сжимает размерность данных до числа используемых экспертов.

   index++;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, experts, optimization, iBatch) ||
      !cScore.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(SoftPlus);

А слой SoftMax превращает оценки экспертов в вероятности, позволяя системе понять, какой эксперт в текущий момент более значим.

   index++;
   softmax = new CNeuronSoftMaxOCL();
   if(!softmax ||
      !softmax.Init(0, index, OpenCL, neuron.Neurons(), optimization, iBatch) ||
      !cScore.Add(softmax))
      DeleteObjAndFalse(softmax);
   softmax.SetHeads(1);

Результаты аккумулируются в cScoreStack. В процессе обучения мы используем Diversity-Loss, который стимулирует модель формировать текущий прогноз максимально отличным от всех предыдущих. Это ключевой момент. Система не зацикливается на одном наборе экспертов, а постоянно ищет новые комбинации. Благодаря такому подходу модель изучает разнообразие возможных сценариев, расширяя спектр прогнозов и повышая адаптивность, вместо того чтобы ограничиваться повторяющимися паттернами использования одних и тех же экспертов.

   index++;
   if(!cScoreStack.Init(0, index, OpenCL, iBatch, neuron.Neurons(), 1, optimization, iBatch))
      ReturnFalse;

Модуль Confidence-Gating решает другую задачу. Здесь система отвечает на вопрос "достаточно ли уверена модель, чтобы активировать данный архетип?"

Архитектура аналогична Score. Сначала конволюционные блоки выделяют локальные особенности, затем нейроны с SoftPlus обрабатывают эти данные, а BatchNorm стабилизируют и нормализуют сигналы.

//--- Confidence-Gating
   index++;
   conv = CNeuronSpikeSuperKernelBlock();
   if(!conv ||
      !conv.Init(experts, index, OpenCL, dimension, (dimension + 1) / 2,
                      windows, steps, units, 1, optimization, iBatch) ||
      !cConfidenceGating.Add(conv))
      DeleteObjAndFalse(conv);
   index++;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, experts, optimization, iBatch) ||
      !cConfidenceGating.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(SoftPlus);
   index++;
   norm = new CNeuronBatchNormOCL();
   if(!norm ||
      !norm.Init(0, index, OpenCL, neuron.Neurons(), iBatch, optimization) ||
      !cConfidenceGating.Add(norm))
      DeleteObjAndFalse(norm);
   norm.SetActivationFunction(SoftPlus);

За создание бинарной маски отвечает слой спайковой активации. А чтобы исключить отрицательные результаты мы используем SoftPlus активацию на выходе слоя пакетной нормализации.

   index++;
   spike = new CNeuronSpikeActivation();
   if(!spike ||
      !spike.Init(0, index, OpenCL, neuron.Neurons(), optimization, iBatch) ||
      !cConfidenceGating.Add(spike))
      DeleteObjAndFalse(spike);

Итоговые оценки аккумулируются в cCGStack. Он по сути выполняет ту же роль аналогичную cScoreStack, но в другом контексте.

   index++;
   if(!cCGStack.Init(0, index, OpenCL, iBatch, neuron.Neurons(), 1, optimization, iBatch))
      ReturnFalse;

Блок Confidence-Gating Score (cCGScore) интегрирует оценки релевантности и уверенности, превращая их в окончательные веса для активных экспертов.

//--- Confidence-Gating Score
   index++;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, experts, optimization, iBatch) ||
      !cCGScore.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(None);
   index++;
   softmax = new CNeuronSoftMaxOCL();
   if(!softmax ||
      !softmax.Init(0, index, OpenCL, neuron.Neurons(), optimization, iBatch) ||
      !cCGScore.Add(softmax))
      DeleteObjAndFalse(softmax);

Только после этого корректные параметры распределения комбинируются в единый прогноз плотности через cDensity.

   index++;
   if(!cDensity.Init(0, index, OpenCL, 4 * Neurons(), optimization, iBatch))
      ReturnFalse;
   cDensity.SetActivationFunction(None);
//---
   return true;
  }

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

Продолжая описание работы модуля, стоит обратить внимание на реализацию алгоритма прямого прохода в методе feedForward. Здесь полностью прослеживается логика взаимодействия всех компонентов: Score, Confidence-Gating, Tail-Aware экспертов и итоговой генерации распределения.

bool CNeuronConfGateTailAwareMoE::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   CNeuronBaseOCL* prev = NeuronOCL;
   CNeuronBaseOCL* curr = NULL;
//--- Score
   for(int i = 0; i < cScore.Total(); i++)
     {
      curr = cScore[i];
      if(!curr ||
         !curr.FeedForward(prev))
         ReturnFalse;
      prev = curr;
     }

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

Далее активируется Confidence-Gating. Алгоритм повторяет ту же последовательность обработки, но теперь с целью бинарной оценки: какие архетипы можно включать, а какие — игнорировать.

//--- Confidence-Gating
   prev = NeuronOCL;
   for(int i = 0; i < cConfidenceGating.Total(); i++)
     {
      curr = cConfidenceGating[i];
      if(!curr ||
         !curr.FeedForward(prev))
         ReturnFalse;
      prev = curr;
     }

Следующий шаг — Confidence-Gating Score. Здесь оценки релевантности из Score комбинируются с бинарными сигналами Confidence-Gating через поэлементное умножение (ElementMult).

//--- Confidence-Gating Score
   prev = cCGScore[0];
   if(!prev ||
      !ElementMult(cConfidenceGating[-1].getOutput(), cScore[-1].getOutput(), prev.getOutput()))
      ReturnFalse;

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

   for(int i = 1; i < cCGScore.Total(); i++)
     {
      curr = cCGScore[i];
      if(!curr ||
         !curr.FeedForward(prev))
         ReturnFalse;
      prev = curr;
     }

Наконец, активируется смесь экспертов Tail-Aware. В режиме обучения блок обновляет параметры распределений для каждого эксперта.

//--- Density
   if(bTrain)
      if(!cTailAwareMoE.FeedForward())
         ReturnFalse;

Затем результат перемножается на оценку релевантности активных экспертов через MatMul. Результат операции — взвешенное распределение передаётся в слой cDensity.

   if(!MatMul(prev.getOutput(), cTailAwareMoE.getOutput(), cDensity.getOutput(),
              1, prev.Neurons(), cDensity.Neurons(), 1, false))
      ReturnFalse;

Итоговые значения проходят через метод MixExpertsPredict, который формирует окончательный прогноз с учётом финального распределения.

   if(MixExpertsPredict())
      ReturnFalse;
//---
   return true;
  }

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

Однако генерация прогноза с использованием случайного распределения по определению будет далека от желаемого результата. Перед практическим применением модели необходимо провести её обучение, где ключевую роль играет процесс обратного распространения градиента ошибки, реализованный в методе calcInputGradients. Этот метод обеспечивает корректную настройку всех параметров системы, от Tail-Aware экспертов до механизмов Score и Confidence-Gating, позволяя модели постепенно приближаться к адекватному прогнозу.

bool CNeuronConfGateTailAwareMoE::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
  {
   if(!NeuronOCL)
      ReturnFalse;
//---
   if(!MixExpertsPredictGrad())
      ReturnFalse;

Процесс начинается с вызова метода MixExpertsPredictGrad, который формирует градиенты для Tail-Aware блока, учитывая текущие прогнозы и параметры распределений экспертов.

Затем градиенты распространяются по цепочке Confidence-Gating Score. Полученные выше значения сначала распределяются между оценками релевантности активных экспертов и выученными распределениями.

//--- Confidence-Gating Score
   CNeuronBaseOCL* next = NULL;
   CNeuronBaseOCL* curr = cCGScore[-1];
   if(!curr ||
      !MatMulGrad(curr.getOutput(), curr.getGradient(),
                  cTailAwareMoE.getOutput(), cTailAwareMoE.getGradient(),
                  cDensity.getGradient(), 1, curr.Neurons(), cDensity.Neurons(), 1, false))
      ReturnFalse;

После чего градиенты аккуратно распределяются по всем компонентам блока cCGScore, начиная с последнего и двигаясь к первому.

   next = curr;
   for(int i = cCGScore.Total() - 2; i >= 0; i--)
     {
      curr = cCGScore[i];
      if(!curr ||
         !curr.CalcHiddenGradients(next))
         ReturnFalse;
      next = curr;
     }

Следующий этап — обратное распространение по блокам Confidence-Gating и Score. Здесь через обратную операцию поэлементного умножения градиенты, с учётом корректировки на функции активации, распределяются между оценками релевантности экспертов и соответствующими бинарными уровнями уверенности.

   next = cConfidenceGating[-1];
   curr = cScore[-1];
   if(!next || !curr ||
      !!ElementMultGrad(next.getOutput(), next.getGradient(),
                        curr.getOutput(), curr.getGradient(),
                        cCGScore[0].getGradient(), next.Activation(), curr.Activation()))
      ReturnFalse;

Важный компонент — Diversity-Loss. Он стимулирует модель генерировать разнообразные комбинации экспертов вместо того, чтобы зацикливаться на одном наборе. Стек cCGStack аккумулирует последние композиции и используется для расчёта потерь на разнообразие.

//--- Confidence-Gating
   if(!cCGStack.FeedForward(next) ||
      !DiversityLoss(cCGStack.AsObject(), cCGStack.GetStackSize(), next.Neurons(), false))
      ReturnFalse;
   if(next.Activation() != None)
      if(!DeActivation(next.getOutput(), cCGStack.getGradient(), cCGStack.getGradient(), next.Activation()))
         ReturnFalse;

Это позволяет системе исследовать широкий спектр сценариев и избегать шаблонного поведения.

Градиенты основной магистрали прогнозирования бинарных уровней уверенности и разнообразия сценариев суммируются.

   if(!SumAndNormilize(next.getGradient(), cCGStack.getGradient(), next.getGradient(), 1, false, 0, 0, 0, 1))
      ReturnFalse;

А затем проходят через все компоненты блока в обратном порядке.

   for(int i = cConfidenceGating.Total() - 2; i >= 0; i--)
     {
      curr = cConfidenceGating[i];
      if(!curr ||
         !curr.CalcHiddenGradients(next))
         ReturnFalse;
      next = curr;
     }

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

Аналогичный путь проходят и градиенты магистрали оценки релевантности экспертов Score, что обеспечивает стабильность и согласованность обновлений.

//--- Score
   next = cScore[-1];
   if(!cScoreStack.FeedForward(next) ||
      !DiversityLoss(cScoreStack.AsObject(), cScoreStack.GetStackSize(), next.Neurons(), false))
      ReturnFalse;
   if(next.Activation() != None)
      if(!DeActivation(next.getOutput(), cScoreStack.getGradient(), cScoreStack.getGradient(), next.Activation()))
         ReturnFalse;
   if(!SumAndNormilize(next.getGradient(), cScoreStack.getGradient(), next.getGradient(), 1, false, 0, 0, 0, 1))
      ReturnFalse;
   for(int i = cScore.Total() - 2; i >= 0; i--)
     {
      curr = cScore[i];
      if(!curr ||
         !curr.CalcHiddenGradients(next))
         ReturnFalse;
      next = curr;
     }

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

   if(!NeuronOCL.CalcHiddenGradients(next))
      ReturnFalse;
   CBufferFloat* temp = NeuronOCL.getGradient();
   if(!NeuronOCL.SetGradient(NeuronOCL.getPrevOutput(), false) ||
      !NeuronOCL.CalcHiddenGradients(cConfidenceGating[0]) ||
      !SumAndNormilize(temp, NeuronOCL.getGradient(), temp, 1, false, 0, 0, 0, 1) ||
      !NeuronOCL.SetGradient(temp, false))
      ReturnFalse;
//---
   return true;
  }

Этот многоступенчатый алгоритм обеспечивает точное распределение ошибки по всей системе, позволяя Tail-Aware блокам формировать прогнозы, Score выбирать релевантных экспертов, а Confidence-Gating фильтровать их по уровню уверенности.

В результате обучение становится органичным процессом. Каждый компонент системы получает сигнал для корректировки. А механизм Diversity-Loss гарантирует, что модель исследует максимально разнообразные комбинации экспертов. Это ключевой момент. Без такой координации прогностическая мощь модели была бы ограничена случайными распределениями и повторяющимися паттернами активации. А с ней система постепенно учится давать адаптивные, контекстно-ориентированные прогнозы даже в сложной и шумной динамике финансового рынка.

Таким образом, модуль CNeuronConfGateTailAwareMoE становится живым сердцем всей архитектуры. Он координирует работу Confidence-Gating и смеси экспертов, формирует контекстно-адаптивные распределения и обеспечивает обучение параметров в реальном времени. Этот подход позволяет резко сократить лишние вычисления, сохраняет точность прогнозов и делает систему устойчивой к шуму и вариативности рынка, превращая абстрактные идеи Lattice и Tail-Aware моделирования в практический инструмент для алгоритмической торговли.



Заключение

В данной статье представлена практическая реализация модуля адаптивного прогнозирования, который объединяет концепции Lattice и Tail-Aware моделирования в единую, слаженно работающую систему для анализа финансовых временных рядов. Особенность подхода заключается в том, что модель адаптивно выбирает наиболее релевантные сценарии поведения рынка. Механизм Confidence-Gating решает, какие архетипы активны в текущий момент, а блок Score оценивает их значимость и формирует взвешенные параметры. На этой основе Tail-Aware блок генерирует распределения будущих значений, учитывая тяжёлые хвосты и локальные экстремумы, что позволяет системе прогнозировать редкие, но критически важные события. Такой синтез создаёт баланс между гибкостью прогнозов и контролем над неопределённостью, превращая абстрактные концепции в практический инструмент, способный работать с шумными и непредсказуемыми рыночными данными.

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

Не менее важным является стимулирование разнообразия прогнозов. С помощью стеков cScoreStack и cCGStack и механизма Diversity-Loss модель избегает зацикливания на одних и тех же комбинациях экспертов. Каждый новый прогноз формируется с учётом максимального разнообразия относительно предыдущих. Это позволяет исследовать широкий спектр сценариев и выявлять нетривиальные комбинации экспертов, повышая устойчивость системы к рыночному шуму.

Кроме того, архитектура остаётся модульной и легко расширяемой. Можно добавлять новые эксперты, менять горизонт прогнозирования или корректировать Tail-Aware блок, не нарушая согласованность всей системы. В итоге мы получаем инструмент, который сочетает адаптивность и управляемость, превращая концепции Lattice и Tail-Aware моделирования из теоретической идеи в полноценный рабочий механизм, готовый к применению в реальных условиях финансового рынка.

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


Ссылки


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

#ИмяТипОписание
1Study.mq5СоветникСоветник офлайн обучения моделей
2StudyOnline.mq5 Советник Советник онлайн обучения моделей
3Test.mq5СоветникСоветник для тестирования модели
4Trajectory.mqhБиблиотека классаСтруктура описания состояния системы и архитектуры моделей
5NeuroNet.mqhБиблиотека классаБиблиотека классов для создания нейронной сети
6NeuroNet.clБиблиотекаБиблиотека кода OpenCL-программы
Прикрепленные файлы |
MQL5.zip (3637.81 KB)
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Создание и форвардное тестирование автономного LLM агента для трейдинга с SEAL Создание и форвардное тестирование автономного LLM агента для трейдинга с SEAL
Гибридная архитектура на базе Llama 3.2 и SEAL тестируется на восьми валютных парах (M15) с форвардной изоляцией данных и контролем утечки информации. Методология объединяет adversarial self-play, curriculum learning и балансировку классов для стабильного обучения. Эксперименты подтверждают разрыв между точностью прогноза и реальной доходностью, что дает читателю практические ориентиры по проверке стратегий и корректной оценке их обобщающей способности.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Возможности Мастера MQL5, которые вам нужно знать (Часть 61): Использование паттернов ADX и CCI с обучением с учителем Возможности Мастера MQL5, которые вам нужно знать (Часть 61): Использование паттернов ADX и CCI с обучением с учителем
Осцилляторы ADX и CCI — это индикаторы следования за трендом и импульса, которые можно использовать в паре при разработке советника. Мы рассмотрим, как их можно систематизировать, используя все 3 основных режима машинного обучения. Созданные с помощью Мастера советники позволяют нам оценить паттерны, представленные этими двумя индикаторами. Начнем с рассмотрения того, как к этим паттернам можно применить обучение с учителем.