preview
Нейросети в трейдинге: Многоагентная система с концептуальным подтверждением (FinCon)

Нейросети в трейдинге: Многоагентная система с концептуальным подтверждением (FinCon)

MetaTrader 5Торговые системы | 15 января 2025, 15:51
541 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Введение

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

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

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

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

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

Указанные вопросы решаются авторами работы "FinCon: A Synthesized LLM Multi-Agent System with Conceptual Verbal Reinforcement for Enhanced Financial Decision Making". В ней предложен фреймворк FinCon — это многоагентная система, разработанная специально для интеграции процессов торговли акциями и управления портфелем.

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

Авторы фреймворка FinCon предусматривают возможность его использования как для работы с одним финансовым активом, так и для комплексного управления портфелем активов. Это делает систему универсальной.

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

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


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

Архитектура FinCon имеет двухуровневую иерархию и включает два ключевых компонента: группу агентов «Менеджер-Аналитик» и систему «Контроля Рисков». Такая структура обеспечивает эффективную обработку информации, снижение вероятности возникновения ошибок, минимизацию затрат при принятии решений и глубокий анализ рыночных данных.

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

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

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

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

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

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

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

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

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

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

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

Многоуровневая структура делает FinCon эффективной и адаптивной системой. Авторская визуализация фреймворка представлена ниже.

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


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

После рассмотрения теоретических аспектов фреймворка FinCon, мы переходим к практической части нашей статьи, в которой реализуем  свое видение предложенных подходов средствами MQL5.

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

Подходы модернизации модуля памяти


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

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

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

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

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

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

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

Реализация нового модуля памяти


Предложенные подходы мы реализуем в рамках нового объекта CNeuronMemoryDistil, структура которого представлена ниже.

class CNeuronMemoryDistil  :  public CNeuronMemory
  {
protected:
   CNeuronBaseOCL       cConcatenated;
   CNeuronTransposeOCL  cTransposeConc;
   CNeuronConvOCL       cConvolution;
   CNeuronEmbeddingOCL  cDistilMemory;
   CNeuronRelativeCrossAttention cCrossAttention;
   //---
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronMemoryDistil(void) {};
                    ~CNeuronMemoryDistil(void) {};
   //---
   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint window, uint window_key, uint units_count,
                          uint heads, uint stack_size,
                          ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int       Type(void) override
 const   {  return defNeuronMemoryDistil; }
   //---
   virtual bool      Save(int const file_handle) override;
   virtual bool      Load(int const file_handle) override;
   //---
   virtual bool      WeightsUpdate(CNeuronBaseOCL *source, float tau) override;
   virtual void      SetOpenCL(COpenCLMy *obj) override;
   //---
   virtual bool      Clear(void) override;
  };

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

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

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

bool CNeuronMemoryDistil::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                               uint window, uint window_key, uint units_count,
                               uint heads, uint stack_size,
                               ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronRelativeCrossAttention::Init(numOutputs, myIndex, open_cl, window,
                                         window_key, units_count, heads, window,
                                       2 * stack_size, optimization_type, batch))
      return false;

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

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

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

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

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

   uint index = 0;
   if(!cLSTM.Init(0, index, OpenCL, iWindow, iUnits, optimization, iBatch))
      return false;
   index++;
   if(!cMamba.Init(0, index, OpenCL, iWindow, 2 * iWindow, iUnits, optimization,
                                                                        iBatch))
      return false;

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

   index++;
   if(!cConcatenated.Init(0, index, OpenCL, 2 * iWindow * iUnits, optimization,
                                                                       iBatch))
      return false;
   cConcatenated.SetActivationFunction(None);

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

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

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

   index++;
   if(!cTransposeConc.Init(0, index, OpenCL, iUnits, 2 * iWindow, optimization,
                                                                       iBatch))
      return false;

А затем сжимаем данные средствами сверточного слоя.

   index++;
   if(!cConvolution.Init(0, index, OpenCL, iUnits, iUnits, iWindowKey, iWindow,
                                                      1, optimization, iBatch))
      return false;
   cConvolution.SetActivationFunction(GELU);

Для хранения данных эпизодической памяти мы применяем слой эмбединга, который обеспечивает эффективную организацию стека памяти фиксированной длины, реализованного по принципу FIFO (First In, First Out).

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

   index++;
   uint windows[] = {iWindowKey * iWindow, iWindowKey * iWindow};
   if(!cDistilMemory.Init(0, index, OpenCL, iUnitsKV / 2, iWindow, windows))
      return false;

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

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

   index++;
   if(!cCrossAttention.Init(0, index, OpenCL, iWindow, iWindowKey, iUnits, iHeads,
                                       iWindow, 2 * iUnits, optimization, iBatch))
      return false;
//---
   return true;
  }

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

Следующим этапом мы переходим к построению метода прямого прохода нашего нового блока памяти в рамках метода feedForward.

bool CNeuronMemoryDistil::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   if(!cLSTM.FeedForward(NeuronOCL))
      return false;
   if(!cMamba.FeedForward(NeuronOCL))
      return false;

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

   if(!Concat(cLSTM.getOutput(), cMamba.getOutput(), cConcatenated.getOutput(),
                                                     iWindow, iWindow, iUnits))
      return false;
   if(!cTransposeConc.FeedForward(cConcatenated.AsObject()))
      return false;

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

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

   if(!cConvolution.FeedForward(cTransposeConc.AsObject()))
      return false;

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

   if(!cDistilMemory.FeedForward(cConvolution.AsObject()))
      return false;

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

   if(!cCrossAttention.FeedForward(NeuronOCL, cConcatenated.getOutput()))
      return false;

А затем обогатим информацию контекстом эпизодической памяти.

   return CNeuronRelativeCrossAttention::feedForward(cCrossAttention.AsObject(),
                                                     cDistilMemory.getOutput());
  }

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

За построением метода прямого прохода следует реализация алгоритмов обратного прохода. Как вы знаете, здесь предполагается построение двух методов:

  • распределения градиентов ошибки calcInputGradients;
  • обновления параметров модели updateInputWeights.

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

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

bool CNeuronMemoryDistil::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
  {
   if(!NeuronOCL)
      return false;

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

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

  if(!CNeuronRelativeCrossAttention::calcInputGradients(cCrossAttention.AsObject(),
                                                         cDistilMemory.getOutput(),
                                                       cDistilMemory.getGradient(),
                                      (ENUM_ACTIVATION)cDistilMemory.Activation()))
      return false;

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

   if(!cConvolution.calcHiddenGradients(cDistilMemory.AsObject()))
      return false;
   if(!cTransposeConc.calcHiddenGradients(cConvolution.AsObject()))
      return false;
   if(!cConcatenated.calcHiddenGradients(cTransposeConc.AsObject()))
      return false;

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

   if(!NeuronOCL.calcHiddenGradients(cCrossAttention.AsObject(),
                                     cConcatenated.getOutput(),
                                     cConcatenated.getPrevOutput(),
                                     (ENUM_ACTIVATION)cConcatenated.Activation()))
      return false;

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

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

   if(!SumAndNormilize(cConcatenated.getGradient(), cConcatenated.getPrevOutput(),
                       cConcatenated.getGradient(), iWindow, false, 0, 0, 0, 1) ||
      !DeConcat(cLSTM.getGradient(), cMamba.getGradient(), 
                cConcatenated.getGradient(), iWindow, iWindow, iUnits))
      return false;

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

   if(cLSTM.Activation() != None)
      if(!DeActivation(cLSTM.getOutput(), cLSTM.getGradient(), 
                       cLSTM.getGradient(), cLSTM.Activation()))
         return false;
   if(cMamba.Activation() != None)
      if(!DeActivation(cMamba.getOutput(), cMamba.getGradient(), 
                       cMamba.getGradient(), cMamba.Activation()))
         return false;

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

   CBufferFloat *temp = NeuronOCL.getGradient();
   if(!NeuronOCL.SetGradient(cConcatenated.getPrevOutput(), false) ||
      !NeuronOCL.calcHiddenGradients(cLSTM.AsObject()) ||
      !SumAndNormilize(temp, NeuronOCL.getGradient(), temp, iWindow,
                                                  false, 0, 0, 0, 1))
      return false;

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

   if(!NeuronOCL.calcHiddenGradients(cMamba.AsObject()) ||
      !SumAndNormilize(temp, NeuronOCL.getGradient(), temp, iWindow,
                                               false, 0, 0, 0, 1) ||
      !NeuronOCL.SetGradient(temp, false))
      return false;
//---
   return true;
  }

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

На этом мы завершаем рассмотрение методов модернизированного блока памяти CNeuronMemoryDistil. С полным кодом данного объекта и всех его методов вы можете самостоятельно ознакомиться во вложении.

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


Заключение

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

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


Ссылки


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

# Имя Тип Описание
1 Research.mq5 Советник Советник сбора примеров
2 ResearchRealORL.mq5
Советник
Советник сбора примеров методом Real-ORL
3 Study.mq5 Советник Советник обучения моделей
4 Test.mq5 Советник Советник для тестирования модели
5 Trajectory.mqh Библиотека класса Структура описания состояния системы и архитектуры моделей
6 NeuroNet.mqh Библиотека класса Библиотека классов для создания нейронной сети
7 NeuroNet.cl Библиотека Библиотека кода OpenCL-программы
Прикрепленные файлы |
MQL5.zip (2352.32 KB)
Использование JSON Data API в MQL-проектах Использование JSON Data API в MQL-проектах
Представьте, что вы можете использовать данные, которых нет в MetaTrader. Обычно вы получаете информацию только от индикаторов, основанных на анализе цен и техническом анализе. Теперь представьте, что у вас есть доступ к данным, которые выведут ваши торговые возможности на новый уровень. Вы можете значительно увеличить мощность платформы MetaTrader, если объедините её возможности с результатами работы других программ, методов макроанализа и ультрасовременных инструментов через API. В этой статье мы расскажем, как использовать API, и представим полезные и ценные API-сервисы.
Возможности Мастера MQL5, которые вам нужно знать (Часть 28): Сети GAN в контексте темпа обучения Возможности Мастера MQL5, которые вам нужно знать (Часть 28): Сети GAN в контексте темпа обучения
Темп обучения — это размер шага к цели обучения во многих алгоритмах машинного обучения. В статье мы изучим, какое влияние многочисленные форматы могут оказать на производительность генеративно-состязательной сети (Generative Adversarial Network, GAN) — разновидности нейронной сети, которую мы рассмотрели в одной из предыдущих статей.
Разработка системы репликации (Часть 58): Возвращаемся к работе над сервисом Разработка системы репликации (Часть 58): Возвращаемся к работе над сервисом
После перерыва в разработке и улучшении сервиса, используемого для репликации/моделирования, сегодня мы возобновляем над ним работу. Теперь, когда мы отказались от использования таких ресурсов, как глобальные переменные терминала, нам придется полностью реструктурировать некоторые его части. Не волнуйтесь, этот процесс будет подробно объяснен, чтобы каждый мог следить за разработкой нашего сервиса.
MetaTrader 5 на macOS MetaTrader 5 на macOS
Мы подготовили специальный установщик торговой платформы MetaTrader 5 для macOS. Это полноценный визард, позволяющий установить приложение как нативное. Он выполняет все необходимые действия: определяет вашу систему, скачивает и устанавливают последнюю версию Wine для нее, настраивает его, а затем устанавливает внутри него MetaTrader. Все происходит в автоматическом режиме, вам нужно лишь дождаться окончания установки, после чего вы можете сразу же приступать к полноценной работе с платформой.