preview
Нейросети в трейдинге: Потоковые модели с остаточной высокочастотной адаптацией (модуль HTR)

Нейросети в трейдинге: Потоковые модели с остаточной высокочастотной адаптацией (модуль HTR)

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

Введение

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

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

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

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

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

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

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

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

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

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

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


Модуль HTR

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

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

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

Каждая итерация начинается с потока F(j)n, сформированного модулем низкочастотной оценки. Важно подчеркнуть, что на этом этапе речь ещё не идёт о конечном результате или прогнозе в полном смысле слова. Это грубая рабочая оценка, находящаяся в процессе уточнения, которая передается в блок коррекции. Здесь над ней выполняется именно уточнение, а не пересчёт с нуля. Модуль коррекции в полной мере реализует классический Residual-подход: модель не ломает уже сформированную структуру, а аккуратно встраивает в неё необходимые поправки.

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

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

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

Результатом работы высокочастотного модуля на каждой итерации становится резидуальное уточнение ∆F(j)n. Оно добавляется к текущей оценке потока, сформированной LTR-модулем, и передаётся на следующий шаг. Без резких скачков и без попыток одномоментно исправить всё. Процесс носит последовательный и управляемый характер, что критически важно для устойчивости модели при работе с реальными рыночными данными.

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

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

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

class CNeuronResFlowHTR :  public   CNeuronMSRes
  {
protected:
   CLayer                  cContextProjection;
   CLayer                  cMFProjection;
   CNeuronBaseOCL          cContextVsMF;
   CNeuronSpikeConvGRU2D   cGRU;
   //---
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; }
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; }
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *second) override;
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; }
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput,
                                        CBufferFloat *SecondGradient,
                                        ENUM_ACTIVATION SecondActivation = None) override;

public:
                     CNeuronResFlowHTR(void) {};
                    ~CNeuronResFlowHTR(void) {};
   //---
   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint units, uint mf_dimension, uint context_size,
                          uint inside_dimension, uint chanels_out,
                          ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int       Type(void)   override const   {  return defNeuronResFlowHTR;   }
   //--- 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;
  };

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

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

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

Именно поэтому в рамках данного проекта мы сознательно вводим отдельные модули проекции, приводящие контекст и Motion-Features к сопоставимому внутреннему представлению. Контекстная часть реализована через отдельный блок cContextProjection. Его задача — привести глобальные контекстные признаки к рабочему внутреннему представлению, удобному для совместной обработки с локальной динамикой. Этот блок формирует тот самый стабильный фон, который задаёт рамки интерпретации высокочастотных отклонений.

Параллельно с этим используется проекция признаков движения cMFProjection. Здесь обрабатываются итеративно меняющиеся Motion-Features, отражающие локальные колебания и краткосрочные импульсы.

Сведение этих двух потоков выполняется специализированным узлом cContextVsMF. Это осмысленный этап согласования признаков. Здесь локальная динамика интерпретируется строго в рамках заданного контекста, что полностью соответствует идее Residual-уточнения. Быстрые движения не существуют сами по себе, они имеют смысл только относительно текущего состояния системы.

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

Метод инициализации объекта наглядно демонстрирует, насколько многомерной и поэтапной является структура HTR-модуля. Она не просто создаёт набор нейронных блоков — каждый слой и каждый компонент строится так, чтобы корректно отражать смысловые и временные зависимости, разделяя контекст, локальную динамику и рекуррентную память.

bool CNeuronResFlowHTR::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                             uint units, uint mf_dimension, uint context_size,
                             uint inside_dimension, uint chanels_out,
                             ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronMSRes::Init(numOutputs, myIndex, open_cl, units, chanels_out, 1,
                                                    optimization_type, batch))
      ReturnFalse;

Сначала управление передается одноименному методу родительского класса, что задаёт основу для всех последующих элементов.

Затем происходит подготовка проекций: cContextProjection и cMFProjection очищаются и связываются с общим OpenCL-контекстом для вычислений на GPU, что обеспечивает производительность при обработке больших потоков данных.

   cContextProjection.Clear();
   cMFProjection.Clear();
   cContextProjection.SetOpenCL(OpenCL);
   cMFProjection.SetOpenCL(OpenCL);

Далее формируется блок Context Projection. Здесь последовательно создаются базовые полносвязные нейроны, объект спайковой активации и слой нормализации.

   CNeuronBaseOCL*               neuron = NULL;
   CNeuronSpikeActivation*       activat = NULL;
   CNeuronBatchNormOCL*          norm = NULL;
   CNeuronSpikeSuperKernelBlock* block = NULL;
//--- Context Projection
   uint index = 0;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, context_size, optimization, iBatch) ||
      !cContextProjection.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(None);
   index++;
   activat = new CNeuronSpikeActivation();
   if(!activat ||
      !activat.Init(inside_dimension, index, OpenCL, neuron.Neurons(), optimization, iBatch) ||
      !cContextProjection.Add(activat))
      DeleteObjAndFalse(activat);
   index++;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, inside_dimension, optimization, iBatch) ||
      !cContextProjection.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(None);
   index++;
   norm = new CNeuronBatchNormOCL();
   if(!norm ||
      !norm.Init(0, index, OpenCL, neuron.Neurons(), iBatch, optimization) ||
      !cContextProjection.Add(norm))
      DeleteObjAndFalse(norm);
   norm.SetActivationFunction(None);
   index++;

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

Motion Feature Projection строится через последовательность блоков CNeuronSpikeSuperKernelBlock. Каждый блок берёт на вход исходные признаки движения или результаты предыдущего блока (chan_in обновляется на inside_dimension), применяя свёртки с разными окнами и шагами. Это формирует многомасштабное представление локальной динамики, где каждая итерация блока уточняет сигнал, сохраняя критичную информацию о быстрых колебаниях рынка.

//--- Motion Feature
   uint windows[] = {3, 5};
   uint steps[] = {1, 1};
   uint chan_in = mf_dimension;
   for(int i = 0; i < 3; i++)
     {
      block = new CNeuronSpikeSuperKernelBlock();
      if(!block ||
         !block.Init(0, index, OpenCL, chan_in, inside_dimension, windows, steps, units, 1, optimization, iBatch) ||
         !cMFProjection.Add(block))
         DeleteObjAndFalse(block);
      index++;
      chan_in = inside_dimension;
     }

После этого создаётся узел согласования cContextVsMF, который объединяет подготовленные контекстные и motion-признаки в единое внутреннее представление для дальнейшей работы GRU.

   if(!cContextVsMF.Init(0, index, OpenCL, block.Neurons(), optimization, iBatch))
      ReturnFalse;
   cContextVsMF.SetActivationFunction(None);

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

Наконец, инициализируется рекуррентный блок cGRU. Он получает на вход унифицированное представление потока, управляет временной зависимостью и формирует выходной поток HTR-модуля.

   index++;
   if(!cGRU.Init(0, index, OpenCL, units, inside_dimension, chanels_out, optimization, iBatch))
      ReturnFalse;
//---
   return true;
  }

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

Алгоритм прямого прохода, реализованный в методе feedForward, демонстрирует, как высокочастотный модуль аккуратно вписывается в общую архитектуру ResFlow, сочетая строгость residual-подхода с гибкостью обработки локальной динамики.

bool CNeuronResFlowHTR::feedForward(CNeuronBaseOCL *NeuronOCL,
                                    CBufferFloat *SecondInput)
  {
   CNeuronBaseOCL* prev = NeuronOCL;
   CNeuronBaseOCL* context = cContextProjection[0];
   CNeuronBaseOCL* mf = NULL;
//---
   if(!context.SetOutput(SecondInput, true))
      ReturnFalse;

На вход объект получает два потока информации. Основной NeuronOCL несёт текущую оценку потока и признаки движения. А дополнительный буфер SecondInput содержит признаки контекста. Именно с него начинается работа модуля — контекстные признаки передаются соответствующему слою cContextProjection, формируя стабильный фон, на котором будут уточняться высокочастотные колебания.

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

   for(int i = 0; i < cMFProjection.Total(); i++)
     {
      mf = cMFProjection[i];
      if(!mf || mf.FeedForward(prev))
         ReturnFalse;
      prev = mf;
     }

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

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

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

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

Когда оба потока — контекстный и признаков движения — сформированы, они объединяются в единое внутреннее представление.

   if(!SumVecMatrix(context.getOutput(), mf.getOutput(), cContextVsMF.getOutput(),
                                                context.Neurons(), 1, 0, 0, 0, 1))
      ReturnFalse;

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

Объединённый поток затем поступает в рекуррентный блок cGRU, который аккуратно накапливает информацию между итерациями.

   if(!cGRU.FeedForward(cContextVsMF.AsObject()))
      ReturnFalse;

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

Завершается прямой проход передачей выходного сигнала GRU в родительский residual-слой, что обеспечивает окончательную интеграцию высокочастотного уточнения.

   if(!CNeuronMSRes::feedForward(cGRU.AsObject()))
      ReturnFalse;
//---
   return true;
  }

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

После подробного разбора работы метода прямого прохода, возникает естественный вопрос: а как модель обучается, чтобы полученные уточнения были действительно точными и согласованными с общей траекторией потока? Именно здесь вступает в работу метод calcInputGradients, который реализует распределение градиентов через весь HTR-модуль. Именно он обеспечивает корректное распространение ошибки, позволяя модели адаптироваться и постепенно улучшать точность своих прогнозов.

bool CNeuronResFlowHTR::calcInputGradients(CNeuronBaseOCL *NeuronOCL,
                                           CBufferFloat *SecondInput,
                                           CBufferFloat *SecondGradient,
                                           ENUM_ACTIVATION SecondActivation = None)
  {
   if(!NeuronOCL || !SecondGradient)
      ReturnFalse;
   if(!cContextProjection[0] ||
      !cContextProjection[0].SetGradient(SecondGradient, true))
      ReturnFalse;
   cContextProjection[0].SetActivationFunction(SecondActivation);

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

Далее управление передается одноименному методу родительского класса, обеспечивая согласованное распределение ошибки до рекуррентного блок GRU.

   if(!CNeuronMSRes::calcInputGradients(cGRU.AsObject()))
      ReturnFalse;

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

   if(!cContextVsMF.CalcHiddenGradients(cGRU.AsObject()))
      ReturnFalse;
   CNeuronBaseOCL* context = cContextProjection[-1];
   CNeuronBaseOCL* mf = cMFProjection[-1];
   if(!context || !mf ||
      !SumVecMatrixGrad(context.getGradient(), mf.getGradient(), cContextVsMF.getGradient(),
                                                          context.Neurons(), 1, 0, 0, 0, 1))
      ReturnFalse;

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

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

   for(int i = cContextProjection.Total() - 2; i >= 0; i--)
     {
      context = cContextProjection[i];
      if(!context ||
         !context.CalcHiddenGradients(cContextProjection[i + 1]))
         ReturnFalse;
     }

Аналогично, элементы блока Motion-Features получают градиенты последовательно, корректируя свои внутренние параметры, но при этом не разрушая локальную динамику и не смешивая её с глобальной структурой контекста.

   for(int i = cMFProjection.Total() - 2; i >= 0; i--)
     {
      mf = cMFProjection[i];
      if(!mf ||
         !mf.CalcHiddenGradients(cMFProjection[i + 1]))
         ReturnFalse;
     }

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

   if(!NeuronOCL.CalcHiddenGradients(mf))
      ReturnFalse;
//---
   return true;
  }

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

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

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

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


Заключение

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

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

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

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


Ссылки


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

# Имя Тип Описание
1 Study.mq5 Советник Советник офлайн обучения моделей
2 StudyOnline.mq5 Советник Советник онлайн обучения моделей
3 Test.mq5 Советник Советник для тестирования модели
4 Trajectory.mqh Библиотека класса Структура описания состояния системы и архитектуры моделей
5 NeuroNet.mqh Библиотека класса Библиотека классов для создания нейронной сети
6 NeuroNet.cl Библиотека Библиотека кода OpenCL-программы
Прикрепленные файлы |
MQL5.zip (3610.73 KB)
Интеграция AI-модели в существующую торговую стратегию на MQL5 Интеграция AI-модели в существующую торговую стратегию на MQL5
Данная статья посвящена интеграции обученной модели искусственного интеллекта (например, модели обучения с подкреплением LSTM или прогностической модели на основе машинного обучения) в существующую торговую стратегию на MQL5.
Создание торговой панели администратора на MQL5 (Часть IX): Организация кода (V). Класс AnalyticsPanel Создание торговой панели администратора на MQL5 (Часть IX): Организация кода (V). Класс AnalyticsPanel
В этой статье мы рассмотрим, как получать рыночные данные в реальном времени и информацию о торговом счете, выполнять различные вычисления и отображать результаты на настраиваемой панели. Для достижения этой цели мы углубимся в разработку класса AnalyticsPanel, который будет включать в себя все эти функции, в том числе создание панелей. Эта работа является частью нашего продолжающегося расширения советника новой панели администратора (New Admin Panel EA), внедряющей расширенные функции с использованием принципов модульного проектирования и лучших практик организации кода.
Разработка инструментария для анализа движения цен (Часть 20): Внешние библиотеки (IV) — Correlation Pathfinder Разработка инструментария для анализа движения цен (Часть 20): Внешние библиотеки (IV) — Correlation Pathfinder
Correlation Pathfinder предлагает новый подход к пониманию динамики валютных пар в рамках серии инструментов для анализа ценового действия. Этот инструмент автоматизирует сбор и анализ данных, предоставляя информацию о взаимодействии таких валютных пар, как EURUSD и GBPUSD. Практическая информация в реальном времени поможет вам более эффективно управлять рисками и выявлять торговые возможности.
Улучшенная оптимизация сталкивающихся тел — Enhanced Colliding Bodies Optimization (ECBO) Улучшенная оптимизация сталкивающихся тел — Enhanced Colliding Bodies Optimization (ECBO)
В статье рассматривается алгоритм Colliding Bodies Optimization (CBO), основанный на физике одномерных столкновений тел. Базовая версия алгоритма не содержит настраиваемых параметров, что делает её простой. Поэтому за основу реализации была взята расширенная версия ECBO, дополненная памятью столкновений и механизмом кроссовера, что позволило алгоритму показать достойные результаты и занять место в рейтинговой таблице.