Нейросети в трейдинге: Когнитивная инерция в анализе финансовых рынков (CogDriver)
Введение
Финансовый рынок редко наказывает трейдера за отсутствие сложной модели. Чаще он наказывает за отсутствие связной картины. Цена делает импульс — модель видит продолжение. Через несколько свечей появляется откат — модель уже видит разворот. Затем рынок возвращается к прежнему направлению — и решение снова меняется. Так проявляется одна из главных проблем нейросетевого анализа: модель хорошо реагирует на текущее состояние, но плохо удерживает смысл происходящего во времени. Она видит последнюю свечу, локальный паттерн, набор индикаторов и короткий фрагмент истории. Но ей часто не хватает внутренней устойчивости, которая помогает отличить рыночный шум от настоящей смены режима.
В автономном вождении дрожание решения может проявиться как непоследовательное перестроение между полосами. В трейдинге его аналог — частая смена торговой гипотезы. Модель открывает позицию, быстро теряет уверенность, закрывает её на шуме, а затем снова входит почти в том же направлении, но уже по худшей цене. Комиссии, спред и проскальзывание делают своё дело. Система вроде бы активно реагирует на рынок, но фактически сжигает капитал на собственных колебаниях.
Классический подход к временным рядам пытается решить эту проблему через историческое окно. Мы подаём модели последние N баров, добавляем индикаторы, объёмы, производные признаки, состояние счёта и параметры открытых позиций. Это правильный шаг. Но он не равен пониманию ситуации. Историческое окно показывает, что происходило. Оно не гарантирует, что модель сформировала устойчивую гипотезу о том, что происходит сейчас и почему выбранное ранее действие всё ещё имеет смысл.
Именно здесь появляется интерес к фреймворку CogDriver, представленному в работе "CogDriver: Integrating Cognitive Inertia for Temporally Coherent Planning in Autonomous Driving". Он был предложен для автономного вождения. Его задача — сохранить временно согласованное внутреннее представление. Автомобиль не должен каждый момент заново решать, куда он едет. Он должен удерживать намерение, проверять его на новых данных и менять план только при существенном изменении условий.
На финансовых рынках эта идея переносится почти естественно. Трейдер или торговый агент тоже не должен каждый бар начинать анализ с нуля. Он должен помнить, какая рыночная гипотеза была активна ранее, почему она возникла, какие признаки её поддерживали и какие начали разрушать. Новое состояние рынка должно не автоматически сбрасывать прежний план, а проверять его. Это уже не просто прогноз следующей цены. Это контроль непрерывности торгового рассуждения.
Когнитивная инерция в таком контексте не означает упрямство. Плохая инерция превращает модель в заложника идеи: купили — значит будем верить в рост до последнего. Нам нужна другая механика. Модель должна сохранять рабочую гипотезу, пока новые данные не дают достаточно оснований её изменить. Речь идёт не о слепой задержке реакции, а о фильтре смысловой устойчивости. Рыночный шум не должен каждый раз сбрасывать внутреннее состояние агента. Но смена режима должна распознаваться без опасного запаздывания.
Такой подход особенно важен для нейросетевых торговых систем. Нейросеть хорошо извлекает нелинейные зависимости и находит связи, которые трудно формализовать обычными правилами. Но эта сила имеет обратную сторону. Модель может оказаться слишком чувствительной к локальным изменениям. Она способна увидеть новый паттерн там, где рынок просто сделал технический откат. В результате торговая система получает не интеллект, а гиперактивность: на спокойном участке она выглядит уверенно, а на шумном начинает дёргаться.
Адаптация CogDriver к финансовым рынкам позволяет сместить акцент. Мы перестаём рассматривать торговое решение как мгновенную реакцию на текущий набор признаков. Вместо этого строим агента, который ведёт внутреннюю линию анализа. Он накапливает представления о рыночных состояниях, сопоставляет их с текущей ситуацией, оценивает устойчивость прежней гипотезы и только затем формирует действие. В такой логике сделка становится не одиночным ответом модели, а продолжением временно согласованного плана.
В автономном вождении базой служит окружающая 3D-сцена: положение объектов, траектории движения и намерение автомобиля. В финансовой адаптации роль сцены выполняет рыночное состояние. Это может быть: плотность распределения цены и объёма, структура волатильности, направленность импульса, положение относительно значимых диапазонов, динамика индикаторов, состояние позиции и риск‑профиль счёта. Рынок рассматривается не как одна линия цены, а как многомерная среда, в которой агент должен сохранять ориентацию.
Здесь важен принципиальный момент. Мы не переносим дорожную задачу на рынок буквально. У финансового рынка нет полос движения, светофоров и физических препятствий. Но у него есть свои аналоги. Тренд не является дорогой, но задаёт предпочтительное направление. Диапазон не является перекрестком, но требует осторожности. Резкий всплеск волатильности не является внезапным пешеходом, но меняет допустимый риск. Ложный пробой не является встречным автомобилем, но способен разрушить прежний сценарий. Поэтому нам нужна не копия автомобильной архитектуры, а перенос идеи временно устойчивого рассуждения.
Практическая цель такой адаптации — снизить дрожание торговых решений. Если модель видит рынок только через текущий срез, она легко переоценивает последнее движение. Если модель сохраняет когнитивную инерцию, она сравнивает новый фрагмент с накопленным контекстом. Она не обязана менять позицию только потому, что последняя свеча оказалась против открытого направления. Но она должна заметить, если противоречия стали системными. Именно на этой границе часто отделяется рабочая торговая система от красивого, но бесполезного генератора сигналов.
В рамках данного проекта мы будем рассматривать CogDriver как основу для построения более устойчивого рыночного агента. Его задача — не угадать каждый следующий тик. Такая постановка слишком хрупкая. Более интересная цель — сформировать внутреннее состояние, которое связывает прошлые наблюдения, текущую рыночную конфигурацию и будущую торговую гипотезу. Модель должна не только отвечать на вопрос что делать сейчас, но и понимать, насколько это действие согласуется с предыдущим анализом.
Алгоритм фреймворка CogDriver
При адаптации CogDriver к финансовым рынкам важно не потерять его центральную идею. Это не очередной энкодер временного ряда и не обычный механизм памяти, куда складываются прошлые признаки. Фреймворк строит агента, который сохраняет устойчивое внутреннее состояние и не превращает каждое новое наблюдение в полный пересмотр предыдущего решения. Авторы называют это когнитивной инерцией. В исходной работе проблема описывается через Decision Jitter: VLM/VLA-агенты работают с изолированными снимками среды, теряют временную связность и хуже выполняют сложные многошаговые планы.
Для финансовых рынков это знакомая практическая проблема. Модель получает новый бар, видит локальный откат и меняет прогноз. Через несколько баров рынок возвращается к прежнему импульсу, и модель снова меняет мнение. В отчёте Strategy Tester это проявляется как лишние сделки, преждевременные выходы, развороты на шуме и рост издержек. Ожидали гибкость. Получили нервную систему без устойчивой логики.
CogDriver предлагает другую логику. Агент должен не просто воспринимать текущую сцену, а вести непрерывную внутреннюю линию рассуждения. В автономном вождении такая линия связывает прошлые наблюдения, текущее положение объектов, состояние автомобиля и будущую траекторию. В трейдинге аналогичная линия должна связывать прошлые рыночные состояния, текущую конфигурацию цены и объёма, состояние позиции, риск и вероятный торговый план.
В авторской архитектуре CogDriver состоит из двух крупных блоков. Первый — CogDriver-Data. Это набор данных с временно связными нарративными аннотациями. Они описывают не только текущее действие, но и причинную историю: почему агент сохраняет прежнее намерение, какие факторы его поддерживают и какие факторы могут привести к изменению плана. Авторы подчеркивают, что такие аннотации дают обучающий сигнал для временной динамики и Persistent Intent — устойчивого намерения.
Второй блок — CogDriver-Agent. Это модель, которая преобразует поток наблюдений в компактные пространственно-временные токены, поддерживает динамическое состояние мира через Temporal Coherence Module и использует это состояние для генерации согласованного плана. В исходной работе токены проецируются в пространство замороженной VLM-модели, где смешиваются с историей и инструкциями, а легкие обучаемые адаптеры направляют модель к формированию траектории.
При переносе на финансовые рынки мы не будем буквально воспроизводить VLM-часть. Языковой планировщик не является обязательным компонентом торгового робота. Но нам нужен его функциональный аналог. В нашей архитектуре эту роль будет выполнять Actor–Critic. Actor формирует торговое действие. Critic оценивает качество состояния и перспективу выбранного действия. А Temporal Coherence Module становится связующим механизмом между рыночным восприятием, памятью и торговым решением.
Рабочий алгоритм можно представить как последовательность преобразований. На каждом шаге времени t агент получает рыночное наблюдение Xt. Это не одна свеча, а многомерное описание рынка: OHLC, объёмы, волатильность, производные признаки, индикаторы, состояние позиции и параметры риска. Для нашей задачи особенно важен формат MarketStateDensity. Это рыночный аналог BEV-представления: плотностная карта текущей ситуации, где цена, диапазоны, объёмы, локальные экстремумы, импульс и волатильность собраны в единую структуру.
Один MarketStateDensity-снимок показывает текущее состояние рынка. Стек таких снимков показывает, как рынок пришел к этому состоянию. Последний бар сам по себе часто обманчив. На фоне накопленного стека он уже получает контекст: может быть частью коррекции, кульминации импульса, выхода из диапазона или ложного пробоя. Поэтому первым входом будущего CogDriver будет стек состояний: St = {Dt-k+1, ..., Dt}. Здесь Dt — текущая карта MarketStateDensity, а k — глубина стека.
Этот стек выполняет роль короткой рабочей памяти восприятия. Но CogDriver идёт дальше. Помимо локального стека, ему нужна Sparse Temporal Memory — разреженная временная память для поддержания стабильного внутреннего состояния. В рыночной адаптации она не должна хранить все свечи подряд. Это дорого и бессмысленно: финансовый ряд содержит слишком много однотипного шума. В памяти должны оставаться только значимые эпизоды: начало импульса, пробой диапазона, возврат к уровню, резкое расширение волатильности, формирование экстремума, смена режима, вход в позицию или критическое изменение риска. Такая память становится не календарной, а событийной.
На шаге t у модели есть три ключевых источника информации:
- текущие признаки рынка Zt, полученные энкодером из MarketStateDensity-стека;
- исторические запросы памяти Mt-1, сохраненные на предыдущих шагах;
- контекст движения Ct.
В автономном вождении контекстом выступает ego-motion, то есть собственное движение автомобиля. В рынке прямого аналога автомобиля нет. Но есть рыночное смещение системы координат: изменение цены, волатильности, диапазона, трендового наклона, ликвидности и состояния позиции.
Поэтому в финансовой версии Ct можно сформировать из нормированного изменения цены, текущей и исторической волатильности, наклона локального тренда, ширины диапазона, положения цены относительно недавних экстремумов, направления открытой позиции, текущей загрузки риска и времени удержания позиции. Это не просто дополнительные признаки. Это параметры, которые показывают, как старые состояния нужно перенести в текущую рыночную систему координат.
Первый вычислительный этап CogDriver — Propagation, перенос исторического состояния к текущему моменту. В авторской TCM исторические 3D-запросы геометрически переносятся в текущую систему координат с учетом ego-motion. Так модель получает физически осмысленную начальную оценку перед последующей обработкой признаков.
На рынке мы выполняем аналогичный перенос, но уже не в геометрическом, а в ценовом и волатильностном пространстве. Историческое состояние, сохраненное при одной цене и одном масштабе волатильности, нельзя напрямую сравнивать с текущим состоянием. Его нужно нормализовать: ценовые уровни пересчитать относительно текущей цены, амплитуды движения — относительно текущего ATR или другой оценки волатильности, временную составляющую — через коэффициент затухания. Тогда старая карта не лежит в памяти как музейный экспонат. Она становится рабочим ориентиром.
Практически здесь мы готовим буфер памяти к сравнению с текущим состоянием. Старые состояния приводятся к новым координатам. Без этого модель будет сравнивать несравнимое: тренд на спокойном рынке с импульсом после новости, узкий диапазон с фазой расширенной волатильности, локальный откат с полноценной сменой режима.
Второй этап — Motion-Conditioned State Refinement. В исходной работе одной геометрической коррекции недостаточно, поэтому авторы используют Motion-Aware Normalization. Условные аффинные коэффициенты зависят от контекста движения и модулируют позиционные эмбеддинги и признаки памяти. Это позволяет усилить релевантные признаки и ослабить те, которые стали ненадежными.
В рыночной версии этот блок становится одним из главных механизмов когнитивной инерции. Мы не просто переносим память. Мы уточняем её значимость с учетом текущего режима. Если рынок остается в трендовой фазе, память о предыдущих импульсах усиливается. Если рынок входит в боковик, трендовые состояния получают меньший вес. Если волатильность резко выросла, старая спокойная структура уже не должна управлять решением с прежней силой.
Третий этап — State Reconciliation, согласование памяти и текущего восприятия. В авторской TCM уточненные Memory Queries объединяются с Current Queries. Затем Self-Attention взвешивает исторические убеждения против новых наблюдений, обновляет состояние и подавляет ложные или избыточные детекции. После этого Cross-Attention снова привязывает согласованное состояние к текущим визуальным признакам.
Для финансового агента это центральный момент. Модель получает две силы. Первая — инерция памяти: прежняя гипотеза, прежний план, прежняя структура рынка. Вторая — новое свидетельство: свежая свеча, новый импульс, новый объём, новая волатильность. Self-Attention между текущими и историческими запросами отвечает на вопрос, что сейчас важнее: сохранить прежнюю линию или пересобрать картину. Память не заменяет рынок. Но и текущая свеча не стирает память автоматически. Между ними возникает механизм согласования.
Далее необходимо обновить Sparse Temporal Memory. Без этого фреймворк быстро превратится в обычный Transformer по окну истории. После получения согласованного состояния Ot модель должна решить, какие элементы стоит сохранить. Не каждое состояние имеет право попасть в память. Если сохранять всё, память станет шумной. Если сохранять слишком мало, модель снова станет реактивной.
Для отбора можно использовать три оценки:
- Novelty, новизна состояния относительно уже сохраненной памяти;
- Relevance, полезность состояния для текущего или будущего торгового решения;
- Stability, устойчивость гипотезы после появления нового состояния.
Состояния с высокой новизной и высокой релевантностью добавляются в память. Устаревшие состояния или эпизоды, потерявшие связь с текущим режимом, удаляются либо получают малый вес. Память должна оставаться ограниченной по размеру. Иначе получится красивая архитектура, которая плохо живет в реальном терминале.
После обновления памяти согласованное состояние Ot передается в планировщик. В исходном CogDriver таким планировщиком выступает VLM-ядро с адаптерами, которое генерирует траекторию. Авторы отдельно подчеркивают переход от реактивного поведения Stimulus-Response к агенту, который строит устойчивую стратегию на основе внутренней модели мира.
В нашей версии планировщиком будет Actor–Critic. Это важная замена. Мы не пытаемся заставить торгового робота рассуждать текстом. Мы переносим сам принцип когнитивной связности в числовую торговую архитектуру.
Отдельно нужно сказать об обучении такой архитектуры. CogDriver не сводится к одной функции потерь. В исходной работе обучение включает несколько задач: восприятие, структурное понимание сцены и авторегрессионную языковую часть. Также используется Spatiotemporal Knowledge Distillation, чтобы явно поддерживать согласованность решений.
В финансовой адаптации нужна похожая многокомпонентная логика, но без лишней привязки к языковой модели. Базовая функция потерь может включать прогнозную ошибку по будущим рыночным состояниям, ошибку оценки действия, ошибку Critic и отдельный штраф за лишнее дрожание решений. Но этот штраф нельзя делать слепым. Модель не должна сохранять Buy только потому, что раньше уже выбрала Buy. Инерция должна ослабевать при признаках смены режима.
Поэтому полезно ввести вес согласованности wt. Он высокий, когда рынок остается в том же режиме, и низкий, когда появляются признаки реального изменения: пробой диапазона, всплеск волатильности, смена направленности, разрушение структуры позиции. Тогда штраф временной несогласованности работает не как запрет на изменение решения, а как контролируемое сопротивление шуму. Если рынок стабилен, модель получает штраф за резкую смену мнения. Если рынок действительно изменился, wt уменьшается, и модель получает право быстро перестроиться.
Именно здесь когнитивная инерция отличается от обычного сглаживания. Сглаживание просто замедляет реакцию. Когнитивная инерция удерживает гипотезу, пока она подтверждается рынком. Первое может убить торговую систему на развороте. Второе должно помочь ей не дёргаться на шуме и при этом выйти из старого сценария, когда рынок действительно сменил режим.
В итоге алгоритм CogDriver в рыночной адаптации можно свести к одной рабочей идее: каждый новый бар не должен начинать анализ с чистого листа. Он должен проверять уже существующую гипотезу.

Реализация средствами MQL5
Переход от идеи к коду в этом проекте нельзя реализовать одним небольшим классом. CogDriver в исходной постановке — это не отдельный слой нейронной сети, а целый контур обработки состояния, памяти, согласования и принятия решения. В финансовой адаптации объём работ также велик. Нам предстоит:
- построить представление рыночной сцены,
- организовать стек состояний,
- добавить разреженную временную память,
- реализовать перенос исторических состояний к текущему масштабу рынка,
- связать всё это с механизмом внимания и Actor–Critic.
Поэтому в этой статье мы не будем пытаться собрать весь фреймворк сразу. Такой подход был бы красивым на схеме, но тяжелым для понимания и неудобным для воспроизведения. Разумнее идти классическим инженерным путем: сначала подготовить фундамент, затем постепенно наращивать на нем рабочие модули.
В качестве фундамента будущей реализации мы сосредоточимся на организации рыночного состояния и его накоплении во времени. Именно здесь начинается финансовый аналог CogDriver. Модель не может проявить когнитивную инерцию, если у неё нет устойчивого представления о прошлом. Она не может согласовать текущий бар с прежней гипотезой, если прежняя гипотеза нигде явно не хранится. Поэтому первым практическим шагом становится структура, которая принимает рыночные данные, преобразует их в плотностное состояние и сохраняет последовательность таких состояний в стек.
Для первого практического шага создадим класс CNeuronCogDriverData. Его задача — реализовать нижний слой будущего фреймворка. Мы пока не собираем полный CogDriver-Agent: у нас ещё нет Temporal Coherence Module, полноценной Sparse Temporal Memory и блока принятия торгового решения. На этом этапе нужен базовый модуль, который принимает рыночные признаки, приводит их к стабильному формату, накапливает состояния во времени и подготавливает данные для последующего согласования памяти с текущим рынком.
class CNeuronCogDriverData : public CNeuronSpikeConvBlock { protected: uint iWindow; uint iVariables; uint iStateStackSize; uint iQuantStackSize; uint iQuantiles; float fRange; CNeuronBatchNormOCL cNorm; CNeuronAddToStack cStateStack; CNeuronUncAD_MSD cMSD; CNeuronConvOCL cAffine; CNeuronAddToStack cQuantStack; CNeuronBaseOCL cPrevQuantStack; //--- virtual bool AffineStack(void); virtual bool AffineStackGradient(void); virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronCogDriverData(void) : iWindow(0), iVariables(0), iStateStackSize(0), iQuantStackSize(0), iQuantiles(0), fRange(0) {}; ~CNeuronCogDriverData(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint variables, uint state_stack_size, uint quant_stack_size, uint quantiles, float range, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronCogDriverData; } //--- 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; };
Класс наследуется от CNeuronSpikeConvBlock. Это позволяет сразу встроить его в существующую нейросетевую инфраструктуру. Объект получает стандартные методы прямого прохода, обратного распространения ошибки и обновления весов. Мы не создаем внешний препроцессор, живущий отдельно от сети. Подготовка CogDriver-данных становится частью вычислительного графа. Значит, через неё можно проводить градиент ошибки, обновлять обучаемые параметры и сохранять состояние вместе с остальной моделью.
Метод инициализации показывает архитектуру блока лучше любой схемы. В нем видны входные ограничения, расчет внутренних размерностей и последовательная сборка вычислительного конвейера.
bool CNeuronCogDriverData::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint variables, uint state_stack_size, uint quant_stack_size, uint quantiles, float range, ENUM_OPTIMIZATION optimization_type, uint batch) { if(window == 0 || variables == 0 || state_stack_size < (10 * quantiles) || quant_stack_size < 2 || quantiles == 0 || range <= 0) ReturnFalse; uint bins = 2 * quantiles + 1; uint quant_dimension = window * bins; uint quant_features = quant_dimension * variables; if(!CNeuronSpikeConvBlock::Init(numOutputs, myIndex, open_cl, quant_stack_size, quant_stack_size, 1, 1, quant_features, optimization_type, batch)) ReturnFalse;
В начале метода выполняется проверка параметров. Мы сразу отсекаем конфигурации, при которых блок не сможет построить осмысленное рыночное состояние. Размер окна window и число переменных variables не могут быть нулевыми: без них нет входной сцены. Количество квантилей quantiles должно быть положительным, а диапазон range — задавать ненулевую область построения плотностной карты. Также контролируется глубина стека исходных состояний. Она должна быть не меньше 10 * quantiles. Это ограничение защищает MarketStateDensity от слишком бедной истории. Если наблюдений мало, квантильная структура получается случайной, и модель видит не рыночную плотность, а шум.
Параметр quant_stack_size также проверяется отдельно. Он должен быть не меньше двух. Это минимальное условие для хранения последовательности плотностных состояний. Один снимок рынка ещё не даёт временной динамики. Два снимка уже позволяют увидеть изменение. Для CogDriver это принципиально: мы строим не статический индикатор, а основу будущей когнитивной инерции.
После проверки параметров рассчитывается количество интервалов плотностной карты. Мы задаем симметричную структуру вокруг центрального состояния. Если quantiles определяет количество уровней в одну сторону от центра, то общее число интервалов включает левую область, центральную область и правую область. Для рынка это удобно: можно описывать не только абсолютное положение признака, но и его отклонение относительно центральной зоны. В результате плотностная карта получает простую и устойчивую геометрию.
Далее определяется размерность одного квантильного представления. Параметр quant_dimension объединяет временное окно и квантильные интервалы. Затем эта размерность умножается на количество переменных. В итоге quant_features задаёт полный размер одного плотностного состояния рынка. Именно такой вектор будет передаваться дальше по вычислительному графу и накапливаться в стеке плотностных состояний.
Затем вызывается инициализация родительского класса. На этом этапе мы задаем внешнюю форму блока. Выход CNeuronCogDriverData будет связан не с одним рыночным снимком, а со стеком плотностных представлений. Поэтому в базовый класс передается quant_stack_size и размер одного состояния quant_features. На выходе используется свертка, поэтому следующий модуль получает карту, уже учитывающую локальную динамику, а не сырые свечи.
После успешной базовой инициализации сохраняются основные параметры объекта.
iWindow = window; iVariables = variables; iStateStackSize = state_stack_size; iQuantStackSize = quant_stack_size; iQuantiles = quantiles; fRange = range;
Эти значения понадобятся в прямом и обратном проходах. Здесь фиксируется конфигурация входной сцены, глубина памяти восприятия, разрешение плотностной карты и диапазон построения распределения. Параметры задаются один раз при инициализации, после чего все внутренние буферы и слои работают в согласованной размерности.
Первым внутренним блоком инициализируется нормализация.
if(!cNorm.Init(0, 0, OpenCL, window * variables, iBatch, optimization)) ReturnFalse; cNorm.SetActivationFunction(None);
Его задача — привести данные к сопоставимому масштабу до попадания в стек. Для финансовых рядов это обязательный этап. Цена, волатильность и объёмы постоянно меняют амплитуду. Если складывать в память ненормированные состояния, модель будет сравнивать разные рыночные режимы так, будто они записаны в одной шкале. Это прямой путь к ложным соответствиям.
Функция активации для нормализации отключается. Нам не нужно вносить нелинейное искажение на этом шаге. Блок должен стабилизировать распределение признаков, а не менять их смысловую структуру.
Следующим создается стек исходных рыночных состояний.
if(!cStateStack.Init(0, 1, OpenCL, state_stack_size, window, variables, optimization, iBatch)) ReturnFalse;
Его задача — накапливать нормализованные состояния рынка. Здесь формируется первая рабочая память восприятия. Последний рыночный фрагмент больше не живет отдельно. Он помещается в последовательность предыдущих состояний. Благодаря этому будущая модель сможет анализировать не только текущий срез, но и путь, которым рынок пришел к нему.
Далее инициализируется блок cMSD.
if(!cMSD.Init(0, 2, OpenCL, window, state_stack_size, variables, quantiles, range, optimization, iBatch)) ReturnFalse;
Этот блок строит MarketStateDensity. Здесь обычный временной ряд превращается в плотностное представление рыночной сцены. Мы переходим от линейной последовательности значений к карте распределения состояний. В логике нашего проекта MarketStateDensity выполняет роль рыночного аналога BEV-представления: модель должна видеть не одну свечу, а структуру ситуации, концентрацию движения, распределение отклонений и устойчивость локального режима.
После построения плотностной карты добавляется обучаемое аффинное преобразование.
if(!cAffine.Init(0, 3, OpenCL, window, window, 2, 1, variables, optimization, iBatch)) ReturnFalse; cAffine.SetActivationFunction(None);
Оно готовит основу для будущего согласования исторических состояний с текущим рынком. В полном CogDriver нам понадобится механизм Align, который переносит память в актуальную рыночную систему координат. На первом этапе мы ещё не строим весь этот контур, но уже вводим обучаемый слой для коррекции представления стека. Его задача — не классифицировать состояние и не формировать торговый сигнал, а выполнить линейную адаптацию признаков, сохранив их числовую природу. Поэтому функция активации отключается.
Следующим инициализируется стек квантильных представлений.
if(!cQuantStack.Init(0, 4, OpenCL, quant_stack_size, 1, quant_features, optimization, iBatch)) ReturnFalse;
cQuantStack хранит уже не исходные нормализованные признаки, а плотностные MarketStateDensity-состояния. Это второй уровень памяти. cStateStack нужен для построения текущей карты рынка, а cQuantStack — для накопления последовательности таких карт. Первый стек помогает построить один осмысленный снимок рынка. Второй показывает, как такие снимки меняются во времени.
Последним создается буфер предыдущего квантильного стека.
if(!cPrevQuantStack.Init(0, 5, OpenCL, quant_stack_size * quant_features, optimization, iBatch)) ReturnFalse; cPrevQuantStack.SetActivationFunction(None); //--- return true; }
cPrevQuantStack резервирует буфер под предыдущее состояние плотностного стека. В задачах с памятью это не служебная мелочь. Для последовательного блока важно иметь доступ к состоянию до очередного обновления стека. При обратном проходе такой буфер также помогает корректно распространить градиент через операцию накопления. Без явного хранения предыдущего состояния последовательная часть быстро становится непрозрачной для обучения.
После инициализации внутренних компонентов можно перейти к прямому проходу класса. Если метод инициализации показывает архитектуру блока, то прямой проход показывает движение данных внутри этой архитектуры. Здесь видно, как сырой рыночный вход превращается в подготовленное плотностное представление, пригодное для дальнейшего использования в CogDriver.
bool CNeuronCogDriverData::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!NeuronOCL || NeuronOCL.Neurons() < int(iWindow * iVariables)) ReturnFalse; if(!cNorm.FeedForward(NeuronOCL)) ReturnFalse;
В начале метода выполняется проверка входного объекта данных. Указатель NeuronOCL должен быть корректным, а количество нейронов во входном слое не может быть меньше iWindow * iVariables. Это минимальный размер текущего рыночного наблюдения. Если входной буфер короче ожидаемого, дальнейшие операции теряют смысл: мы не сможем построить рыночное состояние из неполного набора признаков.
Далее входные данные передаются в блок нормализации. Текущий рыночный фрагмент приводится к устойчивому масштабу. Для финансовых данных это не косметика, а обязательная часть вычислительного контура. Цена, объём и волатильность живут в разных диапазонах, и эти диапазоны меняются от режима к режиму. Без нормализации модель будет сравнивать не структуру рынка, а абсолютные числовые масштабы. В таком виде память быстро начнет ошибаться: спокойный тренд и резкий импульс окажутся несопоставимыми не по смыслу, а по амплитуде.
После нормализации новое состояние добавляется в стек исходных рыночных состояний.
if(!cStateStack.FeedForward(cNorm.AsObject()))
ReturnFalse;
Здесь формируется локальная рабочая память восприятия. Каждый новый нормализованный фрагмент не заменяет предыдущий, а добавляется в последовательность. Старые элементы постепенно вытесняются по мере заполнения стека. В результате модель получает не одиночный снимок рынка, а короткую историю развития текущей ситуации. Именно на этом уровне появляется первый технический контур будущей когнитивной инерции: текущий бар рассматривается на фоне недавней динамики.
Затем накопленный стек передается в блок MarketStateDensity.
if(!cMSD.FeedForward(cStateStack.AsObject()))
ReturnFalse;
cMSD преобразует последовательность нормализованных состояний в плотностное представление рынка. Мы перестаём работать с обычной линейной историей признаков и получаем карту состояния. В ней можно отразить распределение значений, концентрацию движения, отклонения от центральной зоны и структуру локального режима. Агент должен видеть не только последнюю реакцию цены, но и форму рыночной сцены, которая к этой реакции привела.
Следующий вызов может показаться неожиданным. Аффинный блок получает не весь стек, а текущее нормализованное состояние. Это сделано осознанно: актуальный рыночный фрагмент используется как источник параметров коррекции. Модель сначала оценивает текущее состояние рынка, а затем на его основе подготавливает преобразование, которое будет применено к плотностной карте.
if(!cAffine.FeedForward(cNorm.AsObject()))
ReturnFalse;
В будущей архитектуре этот принцип станет основой Align-механизма: прошлые и накопленные состояния должны рассматриваться с учетом текущего масштаба и текущего режима.
После расчета аффинных параметров вызывается вспомогательный метод AffineStack. В нем аффинная коррекция применяется к подготовленному представлению.
if(!AffineStack())
ReturnFalse;
Такой шаг нужен, чтобы плотностная карта не оставалась статическим описанием истории. Она должна быть согласована с текущим рыночным контекстом. Если рынок ускорился, изменил волатильность или сместился относительно прежнего диапазона, накопленная структура должна получить поправку. В противном случае память будет хранить правильные значения в неправильной системе координат.
Далее скорректированное плотностное представление добавляется в стек квантильных состояний.
if(!cQuantStack.FeedForward(cMSD.AsObject()))
ReturnFalse;
На этом этапе появляется второй уровень временной памяти. cStateStack хранит нормализованные исходные состояния, необходимые для построения текущей MarketStateDensity-карты. cQuantStack хранит уже сами плотностные представления. Первый стек отвечает на вопрос как менялись признаки. Второй — на вопрос как менялась сама рыночная сцена.
Финальным шагом прямого прохода становится вызов родительского класса.
if(!CNeuronSpikeConvBlock::feedForward(cQuantStack.AsObject())) ReturnFalse; //--- return true; }
Здесь стек плотностных состояний передается в базовый сверточный блок. Поэтому наружу CNeuronCogDriverData отдает уже не простой набор MarketStateDensity-карт, а обработанное представление с учетом локальной динамики. cQuantStack накапливает последовательность, а базовый SpikeConvBlock извлекает из неё признаки более высокого уровня. Следующий модуль сети получает не сырые свечи, не нормализованный вход и даже не отдельную карту рынка, а компактное представление динамики рыночных состояний.
Такой прямой проход ещё не реализует полный механизм когнитивной инерции. Но он уже готовит правильные данные. Модель перестает смотреть на рынок через одиночный фрагмент. Она получает нормализованную, накопленную и скорректированную последовательность плотностных состояний.
Текущий этап может выглядеть скромно, но он принципиален. Мы не начинаем с эффектной головы модели. Мы начинаем с нижнего слоя, без которого вся последующая логика будет стоять на зыбком основании. CNeuronCogDriverData формирует рабочую память восприятия. Именно с него начинается практическая адаптация CogDriver к анализу финансовых рынков.
Заключение
В этой статье мы начали адаптацию CogDriver к задачам анализа финансовых рынков. Исходная идея фреймворка пришла из области автономного вождения, но сама проблема хорошо знакома трейдингу. Модель не должна каждый раз реагировать на новый рыночный фрагмент как на отдельное событие. Ей нужно удерживать линию анализа, сопоставлять новое состояние с прежней гипотезой и менять решение только тогда, когда рынок действительно даёт для этого основания.
В финансовых рядах это особенно важно. Последняя свеча часто выглядит убедительно, но без контекста легко превращается в ловушку. Поэтому когнитивная инерция здесь выступает как защита от дрожания решений. Она помогает модели не метаться между сигналами, а сохранять рабочее представление рынка до тех пор, пока оно подтверждается данными.
Практическую часть мы сознательно начали не с торгового агента и не с блока принятия решений. Полный CogDriver требует большого объёма работы: потребуется реализовать временное согласование, событийную память, механизм переноса исторических состояний, блоки внимания и связку с Actor–Critic. Поэтому в первой статье был заложен фундамент будущей архитектуры — класс CNeuronCogDriverData. Он нормализует входные признаки, накапливает рыночные состояния, строит MarketStateDensity и формирует стек плотностных представлений. Это нижний слой системы, без которого дальнейшая когнитивная логика будет висеть в воздухе.
На первый взгляд такой шаг может показаться служебным. Но именно здесь начинается главное отличие будущего фреймворка от обычной модели временного ряда. Мы начинаем формировать рыночную сцену, накопленную во времени. Следующие модули будут работать уже не с одиночным баром, а с подготовленным представлением динамики состояний. В следующих статьях мы продолжим эту линию.
Ссылки
- CogDriver: Integrating Cognitive Inertia for Temporally Coherent Planning in Autonomous Driving
- Другие статьи серии
Программы, используемые в статье
| # | Имя | Тип | Описание |
|---|---|---|---|
| 1 | Study.mq5 | Советник | Советник офлайн-обучения моделей |
| 2 | StudyOnline.mq5 | Советник | Советник онлайн-обучения моделей |
| 3 | Test.mq5 | Советник | Советник для тестирования модели |
| 4 | Trajectory.mqh | Библиотека класса | Структура описания состояния системы и архитектуры моделей |
| 5 | NeuroNet.mqh | Библиотека класса | Библиотека классов для создания нейронной сети |
| 6 | NeuroNet.cl | Библиотека | Библиотека кода OpenCL-программы |
Проект представлен на forge.mql5.io/dng.
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Особенности написания Пользовательских Индикаторов
От начального до среднего уровня: FileSave и FileLoad
Рыночные секреты Ларри Уильямса (Часть 5): Автоматизация стратегии волатильного пробоя на MQL5
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования