preview
Нейросети в трейдинге: Адаптация прогноза при смене рыночного режима (OMPB)

Нейросети в трейдинге: Адаптация прогноза при смене рыночного режима (OMPB)

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

Введение

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

Изменяется волатильность. Меняется длительность направленных движений и глубина коррекций. Связи между ценой, объёмом и другими признаками могут усиливаться или ослабевать. Иногда меняется само распределение входных данных. Такой случай называют Covariate Shift. В других ситуациях привычное состояние рынка начинает приводить к другому будущему результату. Это уже Concept Shift. На рынке оба эффекта могут возникать одновременно.

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

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

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

Один из вариантов такого решения предложен в работе Model-Agnostic Online Certificate-Driven Calibration for Time Series Forecasting Under Distribution Shift. Авторы представили OMPB — модельно-независимый фреймворк онлайн-калибровки прогнозов. Он рассчитан на временные ряды с последовательной зависимостью и смещением распределения. Базовая прогнозная модель остаётся фиксированной. Адаптируется только небольшой байесовский корректирующий модуль.

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

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

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


Архитектура OMPB

Авторы OMPB начинают с уже обученной модели временного ряда. В момент t она получает окно наблюдений Xt и строит базовый прогноз Zt=f(W, Xt). Параметры W после исходного обучения фиксируются. Во время калибровки они не обновляются. OMPB можно подключить к разным прогнозным архитектурам. В работе авторы проверяют подход на свёрточных моделях, моделях внимания и прогнозных моделях на основе языковой архитектуры. Для фреймворка важен сам прогноз Zt, а не внутреннее устройство базовой сети.

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

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

Параметры корректирующей головы представлены вероятностно. Вместо одного набора весов рассматривается апостериорное распределение Q. Для гауссовского варианта его параметры можно представить через среднее и дисперсию. Из Q можно получить несколько допустимых реализаций параметров. Каждая реализация строит собственный вариант корректированного прогноза yt. Эти варианты не нужны для случайной торговли. Они нужны для оценки поведения апостериорного распределения. Если все допустимые варианты дают близкие результаты, реакция корректирующего модуля устойчива. Если прогнозы расходятся, неопределённость адаптации растёт.

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

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

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

Степень такого расхождения авторы оценивают по разбросу прогнозов. Обозначим оценку на исходной области как DS(Q), а на целевой как DT(Q). Временной член Mismatch отражает различие их поведения. Это не обычное расстояние между двумя наборами цен. OMPB оценивает изменение реакции модели. Такая оценка дополняет обычный контроль ATR или диапазона бара. Рост волатильности виден и без нейросети. Сложнее заметить ситуацию, когда знакомые признаки сохраняют обычные значения, но их связь с будущим движением меняется. Расхождение прогнозов разных реализаций Q помогает обнаружить такой случай.

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

Следующий контроль связан со сложностью апостериорного распределения. В PAC-Bayes подходе она измеряется через KL-дивергенцию между апостериорным и априорным распределениями. Априорное распределение P задаёт исходное состояние корректирующей модели. Чем дальше Q уходит от P, тем более существенная коррекция требуется для объяснения новых данных. Небольшое изменение рынка не должно требовать радикального изменения параметров.

В онлайн-калибровке авторы также используют штраф за сдвиг апостериорного распределения. Он ограничивает изменение Qt относительно предыдущего состояния Qt-1. Такой штраф не даёт одному новому наблюдению резко перестроить корректирующий модуль. Сдвиг может накапливаться постепенно, если новый режим подтверждается следующими данными.

Эти компоненты входят в PAC-Bayes сертификат. Авторы исходят из стандартной идеи Domain Adaptation. Риск на целевой области связывается с риском на исходной области, расхождением между областями и сложностью выбранного распределения параметров.

Для обычных PAC-Bayes границ часто требуется независимая выборка и достаточно стабильное распределение. Финансовый ряд этим условиям не соответствует. Соседние наблюдения связаны во времени. Волатильность имеет инерцию. Ошибки модели тоже могут образовывать серии. Кроме того, само распределение меняется по мере движения рынка.

OMPB использует вместо стандартной концентрации мартингальную концентрацию. Полученная оценка учитывает масштаб потерь и предсказуемую изменчивость последовательности. За счёт этого авторы получают конечновыборочный сертификат при временной зависимости и смещении распределения. Именно этот механизм дал название Online Martingale PAC-Bayes.

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

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

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

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

Сначала оценивается качество модели на знакомом рынке. Затем проверяется её поведение на свежих данных и цена требуемой коррекции. Если новый режим подтверждается, байесовская голова получает основание для обновления. Если оснований мало, затвор сохраняет базовый прогноз.

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

Весь процесс выполняется причинно. Сначала модель строит прогноз. Затем становится известен фактический результат. Только после этого разрешается обновление, которое повлияет на следующий прогноз. Авторы называют эту схему Predict-Then-Update. Целевая оценка Mismatch также строится по окнам, которые были доступны до соответствующего прогноза.

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

В OMPB базовая модель отвечает за прогноз временного ряда, а байесовский блок — за его ограниченную коррекцию. Исходная область удерживает связь с уже изученным режимом. Целевая область показывает текущее состояние. Расхождение между ними определяет необходимость адаптации. PAC-Bayes компонент ограничивает её сложность. Затвор управляет фактическим влиянием поправки.

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

В нашей модели место корректирующего блока будет отличаться от оригинальной схемы. OMPB будет работать не с конечным прогнозом цены. Мы разместим его внутри энкодера состояния окружающей среды. Корректироваться будет латентное представление рынка. ScenarioForecast, Actor, Critics и D2Skill сохранят существующую структуру. Такое решение переносит принцип OMPB в текущую архитектуру и не требует перестраивать последующие блоки.


Реализация

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

В нашей архитектуре OMPB на вход нового слоя поступит набор латентных векторов рынка. Каждый вектор обрабатывается собственным линейным преобразованием. Отличие от обычного полносвязного слоя связано с параметрами. Вместо одного значения каждого веса мы храним параметры гауссовского апостериорного распределения.

В байесовском слое веса и смещения рассматриваются как гауссовские случайные величины. Для вычислений в буферах cWeights и cBias последовательно хранятся параметры этих распределений. Сначала записывается среднее значение µ, затем логарифм дисперсии. Для хранения используется существующий объект CParams. Отдельные контейнеры для среднего и разброса не требуются.

Объявление класса выглядит следующим образом.

class CNeuronBayesianLinearOCL : public CNeuronBaseOCL
  {
protected:
   uint              iVariables, iInputs, iOutputs, iSamples, iSampleState;
   float             m_fKLDMult;

   CParams           cWeights, cBias;
   CNeuronBaseOCL    cPosterior, cSampleWeights, cSampleBias, cSampleOutput;
   CNeuronBaseOCL    cInputGradient, cPosteriorGradient;
   CVAE              cMeanSampler;
   CArrayObj         cRandomSamplers;

   virtual bool      CreateTemporary(void);
   virtual bool      BuildPosterior(void);
   virtual uint      NextSampleRandom(void);
   virtual bool      SetSample(CVAE *sampler);
   virtual bool      Affine(CNeuronBaseOCL *NeuronOCL, CVAE *sampler, CNeuronBaseOCL *result);
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronBayesianLinearOCL(void);
                    ~CNeuronBayesianLinearOCL(void);

   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint variables,
                          uint inputs, uint outputs, uint samples, ENUM_OPTIMIZATION optimization_type,
                          uint batch);

   virtual void      SetKLDMult(float value);
   virtual float     KLDMult(void) const { return(m_fKLDMult); }
   virtual uint      Variables(void) const { return(iVariables); }
   virtual uint      Inputs(void) const { return(iInputs); }
   virtual uint      Outputs(void) const { return(iOutputs); }
   virtual uint      Samples(void) const { return(iSamples); }

   virtual bool      Save(const int file_handle) override;
   virtual bool      Load(const int 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      AppendParameterFingerprint(ulong &fingerprint) override;
   virtual CLayerDescription *GetLayerInfo(void) override;
   virtual int       Type(void) const override { return(defNeuronBayesianLinearOCL); }
  };

Размеры слоя задают четыре величины. Поле iVariables содержит число независимо обрабатываемых векторов. iInputs задаёт размер входа одного вектора. iOutputs определяет размер результата. Поле iSamples хранит число случайных реализаций апостериорного распределения, которые потребуются при обучении.

Обозначим эти размеры через V, Din, Dout и K. В байесовском слое каждый параметр представлен средним и логарифмом дисперсии.

Объекты cWeights и cBias хранят и обновляют параметры распределения. cPosterior собирает их в рабочее представление. Буферы cSampleWeights, cSampleBias и cSampleOutput используются при работе с отдельной реализацией. cInputGradient и cPosteriorGradient накапливают градиенты.

Для получения параметров используются два режима семплирования. Объект cMeanSampler возвращает среднее апостериорного распределения. Массив cRandomSamplers содержит K случайных семплеров. Такое разделение связано с будущим режимом работы OMPB. Основной выход сети должен оставаться детерминированным. Случайные реализации нужны только при обучении. По ним мы позднее рассчитаем расхождение между исходными и текущими состояниями рынка.

Поле m_fKLDMult задаёт вес KL-составляющей при обучении. Его можно изменить методом SetKLDMult и прочитать через KLDMult. Вес KL хранится в базовом слое. Верхний объект OMPB сможет менять силу ограничения без изменения внутренней структуры байесовского преобразования.

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

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

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

Инициализация слоя выполняется методом Init.

bool CNeuronBayesianLinearOCL::Init(uint no,uint mi,COpenCLMy *oc,uint v,uint in,
                                    uint out,uint k,ENUM_OPTIMIZATION opt,uint batch)
  {
   if(!v || !in || !out || !k ||
      !CNeuronBaseOCL::Init(no, mi, oc, v*out, opt, batch))
      ReturnFalse;

   iVariables = v;
   iInputs = in;
   iOutputs = out;
   iSamples = k;
   iSampleState = 1;
   bSamplesGradientReady = false;
   bSamplesPrepared = false;
   activation =None;
   uint w=v * in * out, b = v * out;

   if(!cWeights.Init(0, 0, OpenCL, 2 * w, opt, iBatch) ||
      !cBias.Init(0, 0, OpenCL, 2 * b, opt, iBatch) ||
      !cWeights.getWeightsParams().Fill(0.0f) ||
      !cBias.getWeightsParams().Fill(0.0f) ||
      !cWeights.FeedForward()||
      !cBias.FeedForward()||
      !CreateTemporary())
      ReturnFalse;
   return(true);
  }

Сначала метод проверяет основные размеры. После этого вызывается одноимённый метод родительского класса. Размер собственного выхода равен V×Dout. Функция активации отключается, поскольку новый объект выполняет линейное преобразование.

Затем рассчитываются размеры обычного набора весов и смещений. Объекты cWeights и cBias получают вдвое больше элементов. Начальные значения заполняются нулями. Для средних это означает отсутствие направленной коррекции. Нулевой логарифм дисперсии задаёт исходный масштаб распределения. После создания параметров метод CreateTemporary формирует временные GPU-буферы и семплеры.

Прямой проход реализован в методе feedForward.

bool CNeuronBayesianLinearOCL::feedForward(CNeuronBaseOCL *n)
  {
   if(!n || n.Neurons() != int(iVariables * iInputs) || !BuildPosterior())
      ReturnFalse;

   CVAE *mean = GetPointer(cMeanSampler);
   if(!mean || 
      !mean.FeedForward(cPosterior.AsObject()) ||
      !Affine(n,mean,GetPointer(this)))
      ReturnFalse;

   if(!bTrain)
     {
      bSamplesPrepared = false;
      return(true);
     }
//--- Stochastic states are retained exclusively for regularizers. The CNet output is always mean.
   for(uint i = 0; i < iSamples; i++)
     {
      CVAE *sample = cRandomSamplers.At(i);
      if(!sample || !SetSample(sample) || 
         !sample.FeedForward(cPosterior.AsObject()))
         ReturnFalse;
     }
   bSamplesGradientReady = false;
   bSamplesPrepared = true;

   return(true);
  }

Метод сначала проверяет размер входа. Он должен содержать V×Din элементов. Затем BuildPosterior собирает параметры весов и смещений в единое апостериорное представление.

Первым всегда выполняется cMeanSampler. Он получает среднее распределения. Метод Affine применяет эти параметры к входным данным и записывает результат непосредственно в выход CNeuronBayesianLinearOCL. Следующему слою сети передаётся только детерминированное значение.

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

В режиме обучения выполняется ещё один цикл. Каждый объект из cRandomSamplers получает собственное случайное состояние. Затем семплер строит очередную реализацию апостериорного распределения. Основной выход сети при этом не меняется. Случайные состояния сохраняются для последующих регуляризаторов.

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

После подготовки выборок устанавливается bSamplesPrepared. Одновременно сбрасывается bSamplesGradientReady. Объект готов к расчёту дополнительных потерь и обратному проходу.

Для обучения недостаточно передать назад градиент от среднего выхода. Параметры апостериорного распределения участвуют и в случайных реализациях. Их вклады должны быть собраны в одном буфере. Позднее к нему будет добавлен KL-градиент. При этом KL учитывается один раз за обновление. Его вес не должен увеличиваться вместе с числом K.

Градиент основной вычислительной ветви обрабатывается методом calcInputGradients.

bool CNeuronBayesianLinearOCL::calcInputGradients(CNeuronBaseOCL *n)
  {
   if(!bTrain)
      return(true);
   uint w = iVariables * iInputs * iOutputs;
   uint b = iVariables * iOutputs;
   uint p = w + b;
   if(!n || !n.getGradient().Fill(0.0f) ||
      (!bSamplesGradientReady && !cPosteriorGradient.getGradient().Fill(0.0f)))
      ReturnFalse;
   CVAE *mean = GetPointer(cMeanSampler);
   if(!mean ||
      !DeConcat(cSampleWeights.getOutput(), cSampleBias.getOutput(), mean.getOutput(), w, b, 1) ||
      !cSampleOutput.getGradient().Fill(Gradient) ||
      !SumVecMatrixGrad(cSampleBias.getGradient(), cSampleOutput.getGradient(),
                        cSampleOutput.getGradient(), iOutputs,iVariables) ||
      !MatMulGrad(n.getOutput(),cInputGradient.getGradient(), cSampleWeights.getOutput(), cSampleWeights.getGradient(),
                  cSampleOutput.getGradient(),1, iInputs, iOutputs, iVariables, true) ||
      !SumAndNormalize(cInputGradient.getGradient(), n.getGradient(), n.getGradient(), iInputs,
                       false, 0, 0, 0, 1.0f) ||
      !Concat(cSampleWeights.getGradient(), cSampleBias.getGradient(), mean.getGradient(), w, b, 1) ||
      !cPosterior.CalcHiddenGradients(mean) ||
      !SumAndNormalize(cPosterior.getGradient(), cPosteriorGradient.getGradient(),
                       cPosteriorGradient.getGradient(), p, false, 0, 0, 0, 1.0f) ||
      !DeConcat(cWeights.getGradient(),cBias.getGradient(), cPosteriorGradient.getGradient(), w, b, 2))
      ReturnFalse;
   bSamplesGradientReady = false;
   Deactivation(n);

   return(true);
  }

В рабочем режиме градиенты не нужны. Метод сразу завершает работу. При обучении сначала рассчитываются размеры w, b и общий размер одного набора параметров.

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

Далее берётся cMeanSampler. Метод DeConcat разделяет его выход на средние веса и смещения. После этого SumVecMatrixGrad формирует градиент смещения, а MatMulGrad вычисляет градиенты входа и матрицы весов.

Градиент входа передаётся предыдущему слою через SumAndNormalize. Так основная ветвь сети получает обычный обратный сигнал от детерминированного прогноза.

Градиенты весов и смещений объединяются методом Concat. Затем cPosterior.CalcHiddenGradients проводит их через механизм семплирования к параметрам распределения. В результате обучаются параметры распределения.

После накопления градиент снова разделяется между cWeights и cBias. Флаг bSamplesGradientReady сбрасывается. Следующий проход начнёт формирование нового набора вкладов.

Сервисные методы класса сохраняют тот же принцип. TrainMode управляет созданием случайных реализаций. В рабочем режиме остаётся только средний проход. Save и Load сохраняют конфигурацию и обучаемые параметры. WeightsUpdate поддерживает перенос состояния между совместимыми слоями. AppendParameterFingerprint добавляет параметры Bayesian Linear в контрольную подпись модели. Эта подпись позднее поможет убедиться, что при калибровке изменяется только разрешённая часть сети.

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


Заключение

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

Мы рассмотрели оригинальную архитектуру фреймворка. OMPB связывает риск на исходной области, временное расхождение с целевой областью и сложность апостериорного распределения. Мартингальная PAC-Bayes оценка учитывает последовательную зависимость временного ряда. Причинная схема Predict-Then-Update не допускает использования будущего результата до момента прогноза. Для финансовых данных это особенно важно, поскольку любая утечка будущей информации делает исторический результат бесполезным для реальной торговли.

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

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


Ссылки


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

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

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

Прикрепленные файлы |
MQL5.zip (4055.01 KB)
Алгоритм оптимизации на основе приспособленности — Fitness Dependent Optimizer (FDO) Алгоритм оптимизации на основе приспособленности — Fitness Dependent Optimizer (FDO)
Разбираем FDO — алгоритм, вдохновлённый роением пчёл, но интересный не пчёлами. Формулы просты, но направление шага фиксирует агента на луче к глобально лучшему, сводя поиск к одной степени свободы. Мы воспроизводим канонику, сопоставляем результат с равномерным случайным перебором на том же бюджете вычислений и устраняем дефект минимальной правкой. Прилагаются готовая реализация на MQL5, полный протокол тестов и методика нуль‑модели для оценки пользы итераций.
Пайплайны Codex: от Python к MQL5 для выбора индикаторов — анализ ETF FXI за несколько кварталов Пайплайны Codex: от Python к MQL5 для выбора индикаторов — анализ ETF FXI за несколько кварталов
Мы продолжаем рассматривать возможности использования MetaTrader за пределами «зоны комфорта» форекс-трейдинга, обратив внимание на ещё один торгуемый актив — ETF FXI. В отличие от предыдущей статьи, где мы попытались охватить «слишком много», углубившись не только в выбор индикаторов, но и в рассмотрение комбинаций индикаторных паттернов, в этой статье мы сделаем небольшой шаг назад и сосредоточимся в большей степени на выборе индикаторов. Наш конечный продукт в данном случае задуман как своего рода пайплайн, который может помочь рекомендовать индикаторы для различных активов при наличии достаточного объема их ценовой истории.
Моделирование рынка: В единстве — сила (I) Моделирование рынка: В единстве — сила (I)
Мы подходим к финишной прямой. Разработка системы репликации/моделирования почти завершена. Конечно, нам ещё предстоит доделать кое-что, но по сравнению со всем, что мы уже сделали, реализовать оставшееся будет несложно. Однако всё, что будет показано в этой статье, необходимо как следует усвоить и понять. Поэтому я желаю вам приятного чтения и, прежде всего, получить удовольствие от этого последнего этапа пути.
Моделирование рынка: Position View (XX) Моделирование рынка: Position View (XX)
В этой статье мы рассмотрим, как изменить код индикатора позиции, чтобы создать своего рода тень, которая позволит нам увидеть, где в данный момент находится цена, всё ещё актуальная на торговом сервере. Этот механизм призван облегчить планирование операций, в ходе которых мы перемещаем уровни стоп-лосса или тейк-профита. Добавление этой функции, то есть ценовых теней, может показаться чрезвычайно сложной задачей. В этой статье я покажу, что реализовать это можно очень просто и на практике.