preview
Нейросети в трейдинге: Когнитивная инерция в анализе финансовых рынков (Окончание)

Нейросети в трейдинге: Когнитивная инерция в анализе финансовых рынков (Окончание)

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

Введение

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

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

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

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

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

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

Во второй статье мы добавили модуль временной согласованности. Его задача — хранить прошлые состояния не как простой архив, а как рабочую память. На рынке последний бар не всегда важнее того, что было несколько шагов назад. Иногда свежий бар является шумом, а более старый участок точнее описывает текущий режим. Поэтому появился RankTCM: он сопоставляет текущий запрос с накопленными состояниями и выбирает наиболее релевантный контекст.

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

Этой задаче была посвящена третья статья. В ней мы добавили модуль прогнозирования — Forecast Head. Его роль шире обычной головы прогноза цены. Мы не пытаемся заменить торговую логику прямым предсказанием будущего Close. Цена остаётся шумной величиной, а прямое прогнозирование одного значения часто ведёт либо к запаздывающему сглаживанию, либо к чрезмерной реакции на выбросы.

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

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

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

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

Общая архитектура модели CogDriver для анализа финансовых рынков


Архитектурная логика модели

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

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

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

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

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

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

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

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

Общая логика выглядит так:

  1. Прогнозный блок строит сценарий рынка.
  2. Торговый блок формирует сценарии поведения.
  3. Внутренний механизм MPI выбирает релевантный сценарий, уточняет план и сглаживает изменения.
  4. Финальный блок превращает план в конкретное действие.

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

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

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


Построение и обучение моделей

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

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

Построение моделей выполняется функцией CreateStateDescriptions. Она принимает на вход два массива описаний: первый используется для StateEncoder, второй — для ForecastDecoder. При необходимости объекты создаются внутри функции.

bool CreateStateDescriptions(CArrayObj *&encoder,
                             CArrayObj *&decoder
                            )
  {
//---
   CLayerDescription *descr;
//---
   if(!encoder)
     {
      encoder = new CArrayObj();
      if(!encoder)
         return false;
     }
   if(!decoder)
     {
      decoder = new CArrayObj();
      if(!decoder)
         return false;
     }

Далее начинается формирование StateEncoder. Первый слой принимает последовательность исторических рыночных признаков. Размер входа определяется произведением HistoryBars и BarDescr: глубина истории умножается на количество признаков одного бара.

//--- State Encoder
   encoder.Clear();
//--- Input layer
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronBaseOCL;
   uint prev_count = descr.count = HistoryBars * BarDescr;
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);

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

//--- layer 1
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronBatchNormOCL;
   descr.count = prev_count;
   descr.batch = 1e4;
   descr.activation = None;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);

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

//--- layer 2
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronDropoutOCL;
   descr.count = prev_count;
   descr.probability = 0.1f;
   descr.batch = BatchSize;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);

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

//--- layer 3
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronCogDriverData;
   descr.window = BarDescr;
   descr.count = HistoryBars;
     {
      uint temp[] = {StackSize, StackSize, Quantiles};
      if(ArrayCopy(descr.units, temp, 0, 0, temp.Size()) < int(temp.Size()))
         ReturnFalse;
     }
   descr.probability = 1.0f;
   descr.activation = None;
   descr.batch = BatchSize;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);

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

//--- layer 4
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronCogDriverRankTCM;
   descr.window = BarDescr * (2 * Quantiles + 1);
   descr.count = EmbeddingSize;
   descr.variables = HistoryBars;
     {
      uint temp[] = {StackSize, NHeads};
      if(ArrayCopy(descr.units, temp, 0, 0, temp.Size()) < int(temp.Size()))
         ReturnFalse;
     }
   descr.activation = None;
   descr.batch = BatchSize;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);

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

//--- layer 5
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronCogDriverForecastHead;
   descr.window = EmbeddingSize;
   descr.count = NForecast;
   descr.variables = HistoryBars;
     {
      uint temp[] = {Blocks, NHeads};
      if(ArrayCopy(descr.units, temp, 0, 0, temp.Size()) < int(temp.Size()))
         ReturnFalse;
     }
   descr.activation = None;
   descr.batch = BatchSize;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);
   iStateRawForecastLayer = 5;

Ссылка на этот слой сохраняется в переменной iStateRawForecastLayer. Именно его выход используется для обучения через ForecastDecoder. Это чистое латентное представление прогноза: без оценки уверенности и без преобразования для торговой части модели.

Следующий слой формирует торговое представление прогноза.

//--- layer 6
   if(!(descr = new CLayerDescription()))
      DeleteObjAndFalse(descr);
   descr.type = defNeuronCogDriverForecastToken;
   descr.window = EmbeddingSize;
   descr.count = NForecast;
   descr.activation = None;
   descr.batch = BatchSize;
   descr.optimization = ADAM;
   if(!encoder.Add(descr))
      DeleteObjAndFalse(descr);
   iStateTokenLayer = 6;

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

После StateEncoder строится ForecastDecoder. Он получает полный raw-прогноз Forecast Head. В него не передаются ни ожидаемая ошибка, ни RoPE-преобразование торгового токена. Это сохраняет чистую проверку: достаточно ли информации в латентном прогнозе, чтобы восстановить будущие рыночные данные.

Проще говоря, ForecastDecoder — проверяющий модуль. StateEncoder строит гипотезу о будущем, а Decoder переводит её в прогноз привычных рыночных признаков: цен, диапазонов, объёмов и других характеристик. Если восстановление получается точным, значит модель действительно уловила структуру рынка. Если нет — её внутренняя картина пока ненадёжна.

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

         if(!CreateBuffers(posit, GetPointer(bStateE), GetPointer(bTime), GetPointer(bTarget)))
           {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            break;
           }

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

         //--- State Encoder
         if(!StateEncoder.feedForward((CBufferFloat*)GetPointer(bStateE), 1, false, (CBufferFloat*)NULL))
           {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            break;
           }

Затем этот сценарий передаётся в ForecastDecoder. Он разворачивает латентный прогноз обратно в пространство рыночных признаков.

         if(!ForecastDecoder.feedForward((CNet*)GetPointer(StateEncoder), StateRawForecastLayer, (CBufferFloat*)NULL))
           {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            break;
           }

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

         if(!ForecastDecoder.backProp(GetPointer(bTarget), (CBufferFloat*)NULL, (CBufferFloat*)NULL))
           {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            break;
           }

После этого градиент возвращается в StateEncoder через слой чистого прогноза. Обучается не только Decoder, а вся цепочка: Forecast Head, RankTCM, CogDriverData и предыдущие слои. Модель постепенно учится формировать такое внутреннее представление рынка, которое действительно помогает восстановить будущее.

         if(!StateEncoder.backPropGradient((CBufferFloat*)NULL, (CBufferFloat*)NULL, StateRawForecastLayer, true))
           {
            PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
            Stop = true;
            break;
           }

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

Таким образом, StudyStateEncoder работает как self-supervised-система с прикладным торговым акцентом. Модель не просто учится угадывать направление. Она строит сценарий развития рынка и одновременно оценивает, насколько этот сценарий заслуживает внимания. После обучения StateEncoder фиксируется и становится источником структурированного рыночного контекста для торговых моделей.

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


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

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

Работа с моделью организована в три этапа. Сначала выполняется офлайн-обучение прогнозной модели на исторических данных EURUSD H1 за 2024–2025 годы. На этом этапе StateEncoder учится строить внутреннее представление рынка, связывать текущее состояние с памятью и формировать прогнозный план. ForecastDecoder восстанавливает из этого плана будущие рыночные данные и проверяет качество латентного представления.

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

На третьем этапе обучение переносится в тестер стратегий MetaTrader 5 и продолжается в онлайн-режиме на том же историческом участке. Здесь рынок движется последовательно. Каждое новое состояние зависит от предыдущих решений, открытых позиций и накопленного результата. Именно в такой среде особенно важна когнитивная инерция: модель должна реагировать на существенные изменения, но не менять поведение из-за каждого локального колебания.

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

При начальном депозите 1 000 USD модель получила чистую прибыль 685,72 USD, увеличив капитал примерно на 68,6%. Максимальная просадка по балансу составила 17,15%, по средствам — 18,74%. Фактор восстановления достиг 1,80, коэффициент Шарпа — 2,35.

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

За период тестирования модель совершила 1 289 сделок: 841 короткую и 448 длинных. Доля прибыльных сделок составила 46,86%, но средняя прибыльная сделка достигла 8,25 USD против среднего убытка 6,28 USD. Это позволило сохранить положительное математическое ожидание 0,53 USD на сделку и получить Profit Factor 1,16.

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


Заключение

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

Ключевым архитектурным решением стало разделение ролей между прогнозом и торговым поведением. Forecast Head формирует сценарий будущего состояния рынка и оценивает ожидаемую ошибку каждого шага. Actor использует весь прогнозный план вместе с текущим состоянием позиции и риском. MomAD MPI сглаживает изменения поведения, а Critic оценивает действия в контексте того же прогноза и его качества.

Обучение было разделено на несколько этапов. Сначала StateEncoder учился строить и проверять прогнозное представление через ForecastDecoder. Затем зафиксированный прогнозный контур использовался для обучения Actor и Critic. На завершающем этапе модель проходила адаптацию в последовательной среде тестера стратегий MetaTrader 5.

Тестирование на новых данных за первые пять месяцев 2026 года подтвердило практический потенциал подхода. При начальном депозите 1 000 USD модель получила чистую прибыль 685,72 USD при максимальной просадке по средствам 18,74%. Двухлетняя обучающая выборка позволила сохранить уверенную положительную динамику примерно четыре месяца за пределами обучения.

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


Ссылки


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

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

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

Прикрепленные файлы |
MQL5.zip (3853 KB)
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Неопределённость как модель (Часть 7): Стохастические регрессоры Неопределённость как модель (Часть 7): Стохастические регрессоры
Материал — практическое руководство по множественной регрессии со стохастическими факторами в алготрейдинге с акцентом на эндогенность. Показаны EDA/CDA-приёмы, тест Дарбина—Ву—Хаусмана и двухэтапный МНК для получения состоятельных коэффициентов. Все расчёты реализованы в MQL5 и проверены на внутридневной волатильности EURUSD. Читатель получит рабочий конвейер для выявления эндогенности и корректной спецификации моделей.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Алгоритм бактериальной эволюции — Bacterial Evolutionary Algorithm (BEA) Алгоритм бактериальной эволюции — Bacterial Evolutionary Algorithm (BEA)
Статья посвящена бактериальному эволюционному алгоритму Нава — Фурухаси (BEA) и его двум ключевым операторам: посегментной бактериальной мутации для локальной оптимизации и горизонтальному переносу генов для обмена удачными фрагментами решений. Мы реализуем BEA в каркасе C_AO как конечный автомат под фиксированный бюджет оценок, тестируем на Hilly, Forest и Megacity и поясняем терминологическую развилку с моделью Нумаоки.