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

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

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

Введение

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

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

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

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

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

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



Объект верхнего уровня

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

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

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

Однако интеграция EVA-Flow в качестве LTR-модели требует ряда уточнений. Ключевой вопрос возникает на границе между LTR и HTR модулями, где в исходной архитектуре ResFlow предполагается повторное использование внутренних представлений.

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

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

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

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

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

class CNeuronResFlow :  public CNeuronSpikeSuperKernelBlock
  {
protected:
   CNeuronPSSE          cPrepare;
   CNeuronEVAFlow       cLTR;
   CLayer               cContext;
   CLayer               cMFE;
   CNeuronBaseOCL       cUpsampleLTR;
   CNeuronBaseOCL       cMFEvsUpLTR;
   CNeuronResFlowHTR    cHTR;
   CNeuronBaseOCL       cUpdatedFlow;
   //---
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronResFlow(void) {};
                    ~CNeuronResFlow(void) {};
   //---
   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint dimension, uint hidden_dimension,
                          uint ltr_forecast, uint htr_points_to_segment,
                          uint ltr_layers, uint ltr_candidates,
                          ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int       Type(void) override const  {  return defNeuronResFlow;   }
   //--- 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;
  };

Первый этап обработки данных реализуется через объект cPrepare, экземпляр класса CNeuronPSSE. Здесь формируются нормализованные и предварительно обработанные признаки рынка, которые поступают в LTR-модель. Помимо стандартной подготовки данных, используется методика PSSE, что позволяет дополнительно стабилизировать входной сигнал и обеспечить его согласованность по масштабу и представлению для последующих вычислений. На этом этапе формируется база для дальнейшего построения контекста, необходимого для HTR.

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

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

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

Высокочастотный модуль cHTR уточняет остаточную динамику, корректируя локальные колебания рынка и реагируя на резкие изменения. При этом не разрушается глобальная траектория, заданная LTR.

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

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

bool CNeuronResFlow::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint dimension, uint hidden_dimension,
                          uint ltr_forecast, uint htr_points_to_segment,
                          uint ltr_layers, uint ltr_candidates,
                          ENUM_OPTIMIZATION optimization_type, uint batch)
  {
     {
      uint windows[] = {3, 5};
      uint steps[] = {1, 1};
      if(!CNeuronSpikeSuperKernelBlock::Init(numOutputs, myIndex, open_cl, hidden_dimension, dimension, windows,
                                      steps, ltr_forecast * htr_points_to_segment, 1, optimization_type, batch))
         ReturnFalse;
     }

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

После этого активируется cPrepare — модуль предварительной обработки и нормализации признаков с использованием PSSE. Он формирует основу, на которую будут опираться и контекст, и карты признаков движения.

   uint index = 0;
   if(!cPrepare.Init(0, index, OpenCL, 2 * htr_points_to_segment, dimension, hidden_dimension,
                                                                     1, optimization, iBatch))
      ReturnFalse;

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

//--- Context
   cContext.Clear();
   cContext.SetOpenCL(OpenCL);
   CNeuronBaseOCL* neuron = NULL;
   CNeuronSpikeSuperKernelBlock* block = NULL;
   CNeuronSpikeActivation* activ = NULL;
   CNeuronBatchNormOCL* norm = NULL;
   index++;
     {
      uint windows[] = {3, 5, 7};
      uint steps[] = {2, 2, 2};
      block = new CNeuronSpikeSuperKernelBlock();
      if(!block ||
         !block.Init(0, index, OpenCL, hidden_dimension, hidden_dimension, windows, steps,
                     (htr_points_to_segment + 3) / 4, 1, optimization, iBatch) ||
         !cContext.Add(block))
         DeleteObjAndFalse(block);
     }
   index++;
   activ = new CNeuronSpikeActivation();
   if(!activ ||
      !activ.Init(hidden_dimension, index, OpenCL, block.Neurons(), optimization, iBatch) ||
      !cContext.Add(activ))
      DeleteObjAndFalse(activ);
   index++;
   neuron = new CNeuronBaseOCL();
   if(!neuron ||
      !neuron.Init(0, index, OpenCL, hidden_dimension, optimization, iBatch) ||
      !cContext.Add(neuron))
      DeleteObjAndFalse(neuron);
   neuron.SetActivationFunction(None);
   index++;
   norm = new CNeuronBatchNormOCL();
   if(!norm ||
      !norm.Init(0, index, OpenCL, neuron.Neurons(), iBatch, optimization) ||
      !cContext.Add(norm))
      DeleteObjAndFalse(norm);
   norm.SetActivationFunction(None);

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

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

   index++;
   if(!cLTR.Init(0, index, OpenCL, ltr_forecast, cContext[-1].Neurons(), hidden_dimension,
                 ltr_layers, ltr_candidates, optimization, iBatch))
      ReturnFalse;

Этот подход обеспечивает, что LTR получает уже обработанный и структурированный сигнал, готовый для построения глобальной динамики.

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

   cMFE.Clear();
   cMFE.SetOpenCL(OpenCL);
   index++;
     {
      uint windows[] = {3, 5};
      uint steps[] = {1, 1};
      block = new CNeuronSpikeSuperKernelBlock();
      if(!block ||
         !block.Init(0, index, OpenCL, hidden_dimension, htr_points_to_segment * hidden_dimension,
                     windows, steps, ltr_forecast, 1, optimization, iBatch) ||
         !cMFE.Add(block))
         DeleteObjAndFalse(block);
     }

Для согласования временных разрешений и объединения потоков LTR с этими картами используются модули cUpsampleLTR и cMFEvsUpLTR. Они создают единое пространство признаков, в котором HTR может работать без необходимости повторного извлечения данных или зависеть от внутренних представлений LTR.

   index++;
   if(!cUpsampleLTR.Init(0, index, OpenCL, cLTR.Neurons()*htr_points_to_segment, optimization, iBatch))
      ReturnFalse;
   cUpsampleLTR.SetActivationFunction(None);
   index++;
   if(!cMFEvsUpLTR.Init(0, index, OpenCL, cUpsampleLTR.Neurons() + cMFE[-1].Neurons(), optimization, iBatch))
      ReturnFalse;
   cMFEvsUpLTR.SetActivationFunction(None);

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

   index++;
   if(!cHTR.Init(0, index, OpenCL, ltr_forecast * htr_points_to_segment, 2 * hidden_dimension, hidden_dimension,
                 hidden_dimension, hidden_dimension, optimization, iBatch))
      ReturnFalse;

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

   index++;
   if(!cUpdatedFlow.Init(0, index, OpenCL, cHTR.Neurons(), optimization, iBatch))
      ReturnFalse;
//---
   return true;
  }

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

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

bool CNeuronResFlow::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   if(!cPrepare.FeedForward(NeuronOCL))
      ReturnFalse;

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

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

   CNeuronBaseOCL* prev = cPrepare.AsObject();
   CNeuronBaseOCL*curr = NULL;
   for(int i = 0; i < cContext.Total(); i++)
     {
      curr = cContext[i];
      if(!curr ||
         !curr.FeedForward(prev))
         ReturnFalse;
      prev = curr;
     }

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

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

   if(!cLTR.FeedForward(prev))
      ReturnFalse;

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

   uint hidden_dimension = cLTR.GetWindow();
   uint ltr_forecat = cLTR.GetUnits();
   uint htr_points_to_segment = cUpsampleLTR.Neurons() / cLTR.Neurons();
   if(!LinearUpsample(cLTR.AsObject(), cUpsampleLTR.AsObject(), htr_points_to_segment,
                      ltr_forecat, hidden_dimension))
      ReturnFalse;

Следующим шагом формируются карты признаков движения путем преобразования выходы LTR в структурированные представления для HTR.

   prev = cLTR.AsObject();
   for(int i = 0; i < cMFE.Total(); i++)
     {
      curr = cMFE[i];
      if(!curr ||
         !curr.FeedForward(prev))
         ReturnFalse;
      prev = curr;
     }

После этого результаты LTR и MFE объединяются, создавая единое пространство признаков.

   if(!Concat(prev.getOutput(), cUpsampleLTR.getOutput(), cMFEvsUpLTR.getOutput(), hidden_dimension,
              hidden_dimension, ltr_forecat * htr_points_to_segment))
      ReturnFalse;

Высокочастотный модуль cHTR использует эти данные совместно с последним состоянием контекста для уточнения локальной динамики, корректируя быстрые колебания рынка без нарушения глобальной траектории LTR.

   if(!cHTR.FeedForward(cMFEvsUpLTR.AsObject(), cContext[-1].getOutput()))
      ReturnFalse;

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

   if(!SumAndNormilize(cUpsampleLTR.getOutput(), cHTR.getOutput(), cUpdatedFlow.getOutput(),
                                                     hidden_dimension, false, 0, 0, 0, 1) ||
      !SumVecMatrix(cPrepare.getOutput(), cUpdatedFlow.getOutput(), cUpdatedFlow.getOutput(),
                                                           hidden_dimension, 1, 0, 0, 0, 1))
      ReturnFalse;

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

   if(!CNeuronSpikeSuperKernelBlock::feedForward(cUpdatedFlow.AsObject()))
      ReturnFalse;
//---
   return true;
  }

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

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

bool CNeuronResFlow::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
  {
   if(!NeuronOCL)
      ReturnFalse;
//---
   if(!CNeuronSpikeSuperKernelBlock::calcInputGradients(cUpdatedFlow.AsObject()))
      ReturnFalse;

Алгоритм начинается с вычисления градиентов на уровне обновленного потока — cUpdatedFlow. Эти значения затем аккуратно распространяются обратно через HTR.

   if(!DeActivation(cHTR.getOutput(), cHTR.getGradient(), cUpdatedFlow.getGradient(), cHTR.Activation()))
      ReturnFalse;
   if(!cContext[-1] ||
      !cMFEvsUpLTR.CalcHiddenGradients(cHTR.AsObject(), cContext[-1].getOutput(),
                                       cContext[-1].getGradient(),
                                       (ENUM_ACTIVATION)cContext[-1].Activation()))
      ReturnFalse;

Далее градиенты проходят через объединённые карты признаков и upsample-блоки, разделяясь на составляющие.

   uint hidden_dimension = cLTR.GetWindow();
   uint ltr_forecat = cLTR.GetUnits();
   uint htr_points_to_segment = cUpsampleLTR.Neurons() / cLTR.Neurons();
//---
   if(!cMFE[-1] ||
      !DeConcat(cMFE[-1].getGradient(), cUpsampleLTR.getGradient(), cMFEvsUpLTR.getGradient(),
                hidden_dimension, hidden_dimension, ltr_forecat * htr_points_to_segment))
      ReturnFalse;
   for(int i = cMFE.Total() - 2; i >= 0; i--)
     {
      if(!cMFE[i] ||
         !cMFE[i].CalcHiddenGradients(cMFE[i + 1]))
         ReturnFalse;
     }
   if(!cLTR.CalcHiddenGradients(cMFE[0]))
      ReturnFalse;

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

Чтобы сохранить чистоту низкочастотного уровня, мы формируем высокочастотные целевые значения отдельно, исходя из чистого изменения потока, без смещения исходных данных.

   if(!SumAndNormilize(cUpsampleLTR.getOutput(), cHTR.getOutput(), cUpsampleLTR.getGradient(),
                       hidden_dimension, false, 0, 0, 0, 1) ||
      !SumAndNormilize(cUpsampleLTR.getGradient(), cUpdatedFlow.getGradient(), cUpsampleLTR.getGradient(),
                       hidden_dimension, false, 0, 0, 0, 1))
      ReturnFalse;

Далее на их основе строим отклонения линейной тенденции, которую прогнозирует LTR.

   float error = 0;
   if(!cUpsampleLTR.calcOutputGradients(cUpsampleLTR.getGradient(), error))
      ReturnFalse;

Эти отклонения проходят обратный upsample и формируют ошибку LTR.

   if(!LinearUpsampleGrad(cLTR.AsObject(), cUpsampleLTR.AsObject(), htr_points_to_segment,
                          ltr_forecat, hidden_dimension))
      ReturnFalse;
   Deactivation(cLTR);

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

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

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

   CNeuronBaseOCL* next = cLTR.AsObject();
   for(int i = cContext.Total() - 1; i >= 0; i--)
     {
      if(!cContext[i] ||
         !cContext[i].CalcHiddenGradients(next))
         ReturnFalse;
      next = cContext[i];
     }

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

   if(!cPrepare.CalcHiddenGradients(next))
      ReturnFalse;
   if(!NeuronOCL.CalcHiddenGradients(cPrepare.AsObject()))
      ReturnFalse;
//---
   return true;
  }

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

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



Тестирование

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

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

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

Эксперимент стартовал с офлайн-обучения на исторических данных EURUSD H1 с Января 2024 по Июнь 2025 года. Этот этап можно сравнить с тренировкой трейдера на демо-счёте. Рынок спокоен, ошибки не приводят к потерям, но именно здесь закладываются базовые навыки. Модель шаг за шагом осваивала рынок, выявляя повторяющиеся паттерны. Формируя внутреннее представление о том, как цена движется в разных условиях и как отдельные события влияют на общую динамику.

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

Затем последовал этап онлайн-тестирования в MetaTrader 5 на исторических данных с учетом реального рыночного шума. Теперь условия стали жёсткими. Резкие движения после новостей, провалы ликвидности, смена режимов рынка. Модель должна была адаптироваться на лету, корректировать локальные оценки, сохраняя накопленный опыт. И именно здесь проявляется сила ResFlow. Система сохраняет целостность прогнозов, плавно перестраивая внутренние представления даже при резких колебаниях цены.

Финальная проверка проводилась на полностью новых данных с Июля по Декабрь 2025 года. Мы сознательно отказались от подстройки параметров под рынок. Модель работала так, как вышла из этапов обучения. Это принципиально. Здесь проверяется не способность подогнать систему под прошлые данные, а умение видеть рынок в целом — переносить опыт на новые ситуации, сохранять устойчивость и делать прогнозы в условиях высокой неопределённости. Именно на этом этапе становится ясно, что архитектура действительно работает. Она выявляет тенденции, отделяет шум от значимых движений и создаёт прогноз, на который можно опираться при генерации реальных торговых решений.

Тестирование обученной стратегии показало впечатляющую картину баланса. Начальный депозит в 100USD за полгода вырос до 229.94USD, что даёт абсолютную доходность почти 130%. Это высокий результат даже для относительно короткого периода. Модель последовательно формирует устойчивый рост капитала.

Кривая Equity выглядит логично. Она растёт ступенчато, что свидетельствует о фиксации прибыли и правильном распределении риска. Но стоит отметить, что баланс далеко не всегда совпадает с Equity. Максимальная просадка по балансу составила 12.64%, тогда как Equity падала на 29%. А относительная просадка достигала 41%. Это значит, что сделки долго находятся в минусе — классическая ситуация, когда стратегия работает с удержанием позиции и внутрисделочными колебаниями. Простыми словами, модель иногда терпит урон, прежде чем закрепить прибыль, что важно учитывать при управлении лотом.

Вместе с тем, Recovery Factor равен 1.7. Это приемлемо, но не идеально для агрессивной стратегии. Каждая единица риска возвращается с небольшим запасом. Показатель Profit Factor2.41 говорит о том, что каждая убыточная единица покрытия компенсируется 2.4 единицами прибыли — это надёжный фундамент. Математическое ожидание сделки составляет почти 4USD.

Общий Win Rate75.76%, для коротких позиций даже выше — 86.67%. При этом средняя прибыль меньше средней потери (Avg Win 8.89, Avg Loss -11.54), но вероятность выигрыша значительно превышает вероятность убытка. Это даёт положительное ожидание на каждой сделке. Серии выигрышей могут достигать 8 подряд, а проигрышные — всего 2. Это говорит о редких, но кратковременных потерях.

Главные выводы: стратегия демонстрирует высокую доходность, устойчивый рост Equity и отличный Profit Factor. Но риски остаются заметными. Внутрисделочные просадки и максимальная Equity-просадка до 41% требуют осторожности. Система способна генерировать значительную прибыль, но требует жёсткого контроля риска.



Заключение

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

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

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


Ссылки


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

#ИмяТипОписание
1Study.mq5СоветникСоветник офлайн обучения моделей
2StudyOnline.mq5 Советник Советник онлайн обучения моделей
3Test.mq5СоветникСоветник для тестирования модели
4Trajectory.mqhБиблиотека классаСтруктура описания состояния системы и архитектуры моделей
5NeuroNet.mqhБиблиотека классаБиблиотека классов для создания нейронной сети
6NeuroNet.clБиблиотекаБиблиотека кода OpenCL-программы
Прикрепленные файлы |
MQL5.zip (3635.04 KB)
Переосмысливаем классические стратегии (Часть 14): Высоковероятные ситуации Переосмысливаем классические стратегии (Часть 14): Высоковероятные ситуации
В трейдерском сообществе хорошо известны торговые стратегии с высокой вероятностью успеха, но, к сожалению, они недостаточно четко определены. В этой статье мы попытаемся найти эмпирический и алгоритмический способы точного определения того, что представляет собой ситуация с высокой вероятностью успеха (high probability setup), а также выявить и использовать такие ситуации. Применяя деревья градиентного бустинга (Gradient Boosting Trees), мы продемонстрируем, как читатель может улучшить производительность произвольной торговой стратегии и более четко и понятно донести до компьютера точную задачу, которую необходимо выполнить.
Трейдинг с экономическим календарем MQL5 (Часть 7): Подготовка к тестированию стратегий с анализом новостей Трейдинг с экономическим календарем MQL5 (Часть 7): Подготовка к тестированию стратегий с анализом новостей
В этой статье мы подготовим нашу торговую систему на MQL5 для тестирования стратегий, используя данные экономического календаря в качестве ресурса для анализа вне реального времени. Мы реализуем загрузку и фильтрацию событий по времени, валюте и значимости, а затем проверим все в тестере стратегий. Так мы сможем тестировать на истории стратегии, работающие по экономическим новостям.
Создание торговой панели администратора на MQL5 (Часть X): Интерфейс из внешних ресурсов Создание торговой панели администратора на MQL5 (Часть X): Интерфейс из внешних ресурсов
Используем возможности MQL5 для работы с внешними ресурсами, в данном случае с изображениями в формате BMP, чтобы создать уникальный по стилю интерфейс главной страницы панели администратора торговых операций. В особенности рассмотрим упаковку множества файлов, включая изображения, звуки и многое другое, для упрощения дальнейшего их распространения. Реализуем функции для создания современного и визуально привлекательного интерфейса для нашей панели администратора, которую мы создаем с помощью советника New_Admin_Panel.
Знакомство с языком MQL5 (Часть 28): Освоение API и функции WebRequest в языке MQL5 (II) Знакомство с языком MQL5 (Часть 28): Освоение API и функции WebRequest в языке MQL5 (II)
В этой статье вы научитесь получать ценовые данные с внешних платформ с помощью API и функции WebRequest на языке MQL5. Вы узнаете, как структурируются URL, как форматируются ответы API, как преобразовать серверные данные в читаемые строки, а также как находить конкретные значения в ответах JSON и получать их оттуда.