Нейросети в трейдинге: Возмущённые модели пространства состояний для анализа рыночной динамики (Окончание)
Введение
Финансовый рынок, как и любой сложный динамический объект, не прощает поверхностных моделей. Он многослоен, шумен, нелинеен и, что особенно важно, событийно насыщен. Именно события, а не усреднённые значения, формируют реальную динамику цены. И именно здесь классические методы анализа временных рядов, какими бы изящными они ни были, начинают скрипеть.
Именно здесь в поле зрения появляется работа "Perturbed State Space Feature Encoders for Optical Flow with Event Cameras". Формально она посвящена компьютерному зрению и обработке данных событийных камер, но если абстрагироваться от терминологии, становится очевидно: перед нами универсальный фреймворк обработки потоков изменений, а не статических наблюдений. И в этом смысле рынок и событийная камера удивительно похожи — оба генерируют не кадры, а импульсы. Оба требуют мгновенной реакции модели и оба наказывают за излишнее сглаживание.
Предложенный авторами фреймворк строится вокруг идеи возмущённого пространства состояний. В отличие от классических State-Space моделей, где динамика задаётся фиксированной матрицей перехода, здесь само пространство состояний становится живым, подвижным объектом. Его эволюция зависит не только от прошлого состояния, но и от локальных событий. Они вносят контролируемые возмущения в динамику. Это тонкое, но принципиальное отличие. Вместо того чтобы бороться с нестабильностью, авторы делают её дополнительным источником информации. Ровно так, как опытный трейдер читает рынок не по средним значениям, а по всплескам, провалам, сбоям и резким изменениям ритма.
Архитектурно фреймворк построен как последовательный энкодер пространства состояний, работающий с потоками событий. Каждый новый импульс обновляет состояние и деформирует его, создавая расширенное представление текущей динамики. В результате модель одновременно сохраняет долгосрочную память и остаётся чувствительной к краткосрочным изменениям. Этот баланс — редкий гость в нейросетевых архитектурах, обычно приходится выбирать: либо стабильность, либо чувствительность. P-SSE демонстрирует, что при грамотной организации динамики пространства состояний можно получить и то, и другое.
Особого внимания заслуживает то, как авторы фреймворка решают проблему масштабов. В классических рекуррентных моделях длинные зависимости либо теряются, либо приводят к численной нестабильности. Здесь же динамика разбита на последовательность управляемых переходов, каждый из которых вносит ограниченное возмущение. Это позволяет модели аккумулировать информацию на больших временных горизонтах без накопления ошибок. В терминах финансового рынка это означает способность видеть не только текущий импульс, но и контекст, в котором он возник — будь то фаза накопления, распределения или смены режима.
Не менее важно и то, что фреймворк сохраняет линейную вычислительную сложность по времени. Для событийных потоков это критично, и для финансовых тиков — тем более. Мы имеем дело с архитектурой, которая принципиально ориентирована на работу в реальном времени, без необходимости переобучения на каждом шаге и без тяжёлых окон агрегации. Это роднит её с теми подходами, которые мы постепенно выстраивали в предыдущих статьях: компактные, устойчивые, потоковые модели. Способные жить в торговом терминале, а не только в исследовательской среде.
Таким образом, фреймворк P-SSE задаёт не столько конкретную реализацию, сколько направление мышления. Она показывает, пространство состояний может быть не жёсткой конструкцией, а гибким носителем динамики. Возмущения — это не ошибка, а сигнал. Поток событий важнее усреднённого кадра. Устойчивость модели достигается не подавлением динамики, а её правильной организацией.
Важно подчеркнуть: мы не переносим механически архитектуру P-SSE в финансовый рынок. Мы не используем её в исходном виде. И не копируем компоненты буквально. Мы переносим принцип организации вычислений, логику работы с событиями и подход к динамике пространства состояний. Именно эти элементы оказываются универсальными.


В предыдущих статьях мы уже начали этот процесс. Шаг за шагом рассматривали, как возмущённая динамика может быть встроена в модели. Как формируется скрытое состояние, устойчивое к шуму, но чувствительное к импульсам. И данная статья, логически продолжает эту линию.
Объект верхнего уровня
Мы выполнили значительный объём работы, последовательно адаптируя подходы, предложенные в рамках фреймворка P-SSE, к задачам финансовых рынков. Этот путь оказался далеко не прямым. Каждое архитектурное решение приходилось переосмысливать с учётом событийной природы рыночных данных, жёстких требований к устойчивости и вычислительной эффективности. В предыдущей статье мы остановились на построении модуля E-TROF — Event-Triplet Optical Flow, который стал базовым инструментом локального анализа рыночной динамики.
В оригинальном фреймворке каждый модуль E-TROF анализирует один триплет последовательных состояний. Для расширения временного контекста используются три параллельных модуля с перекрывающимися окнами, что позволяет охватить пять последовательных состояний без увеличения глубины рекурсии. Такое решение хорошо подходит для офлайн-сценариев, где доступна вся последовательность данных и можно заранее сформировать окна анализа. Архитектура остаётся компактной, но при этом получает расширенный временной обзор за счёт перекрытия входных интервалов.
При переходе к онлайн-режиму, который является принципиальным для финансовых рынков, подобная организация вычислений перестаёт быть оптимальной — оток данных становится непрерывным, а любое дублирование вычислений мгновенно отражается на производительности. Именно поэтому в нашей реализации мы сознательно отказались от параллельных перекрывающихся окон. Мы используем один модуль E-TROF, который на каждом шаге анализирует последний доступный триплет состояний. Это позволяет сохранить строгую последовательность обработки и гарантировать постоянную вычислительную сложность на каждом шаге, независимо от глубины истории.
Расширение окна анализа достигается другим способом. Результаты работы E-TROF последовательно добавляются в стек, размер которого задаётся пользователем. Таким образом, временной контекст может быть расширен до произвольной глубины без роста вычислительной нагрузки. Каждый новый шаг требует обработки только одного триплета, а история накапливается уже в виде готовых локальных оценок.
Именно в этой точке архитектура естественным образом подводит нас к следующему этапу. Возникает необходимость перейти от набора локальных оценок к согласованной динамике пространства состояний, в которой каждое новое наблюдение аккуратно встраивается в общую траекторию.
Авторы фреймворка решают проблему несогласованности локальных оценок за счёт введения модуля E-MOP (Event-Motion Propagation). Этот модуль превращает набор независимых оценок E-TROF в связанную во времени динамическую систему. Авторы используют прогнозные оптические потоки, чтобы перенести состояния движения из предыдущего и следующего сегмента в текущий временной контекст. В результате формируется двунаправленная временная информация. Прошлое и будущее начинают влиять на текущее состояние, а не просто следовать за ним.
Ключевой момент здесь заключается в том, что E-MOP не расширяет входные данные, а расширяет динамику состояния. Временная глубина достигается за счёт итеративного обмена информацией между соседними сегментами.
В контексте нашей задачи это особенно важно. Мы уже пришли к архитектуре, в которой локальные оценки аккуратно накапливаются в стеке. Однако без механизма согласования этот стек остаётся пассивным хранилищем. Подход, предложенный в E-MOP, показывает, как превратить набор локальных фрагментов в единую согласованную динамику, не жертвуя чувствительностью к событиям и не увеличивая вычислительную сложность. Фактически авторы P-SSE демонстрируют, как локальные возмущения можно встроить в управляемую эволюцию состояния.
Именно эта идея — итеративное согласование локальных состояний через распространение движения — становится ключевой опорной точкой для следующего шага нашей адаптации.
Однако, в рамках данного проекта мы сознательно отказались от прямого воспроизведения модуля E-MOP в виде отдельного блока. Вместо этого его функциональность была перенесена непосредственно в объект верхнего уровня, что позволило сформировать иерархическую структуру объектов с более естественным распределением ответственности.
Такое решение продиктовано не стремлением упростить архитектуру, а наоборот, желанием сделать её более устойчивой и управляемой в условиях потоковой обработки данных. В онлайн-режиме согласование локальных состояний перестаёт быть отдельной операцией и превращается в неотъемлемую часть эволюции модели. Поэтому мы встроили механизмы распространения и уточнения состояния в основной управляющий объект, где уже сосредоточена логика последовательной обработки, хранения истории и перехода между временными шагами.
Класс CNeuronPSSEFlow представляет собой объект верхнего уровня, организующий работу всей адаптированной архитектуры P-SSE для финансовых потоков. По сути, это управляющий нейронный блок, который объединяет локальные вычисления, согласование состояния и формирование глобального представления динамики рынка. Он наследуется от CNeuronSpikeSuperKernelBlock, что обеспечивает стандартные интерфейсы, но при этом добавляет специализированные механизмы работы с потоковыми триплетами событий.
class CNeuronPSSEFlow : public CNeuronSpikeSuperKernelBlock { protected: CNeuronETROF cETROF; CNeuronSpikeSuperKernelBlock cLocal; CLayer cGlobal; CLayer cUpdateFlow; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronPSSEFlow(void) {}; ~CNeuronPSSEFlow(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint forecast, uint dimension, uint hidden_dimension, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { rturn defNeuronPSSEFlow; } //--- 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; };
На нижнем уровне класса размещён объект cETROF — реализация модуля E-TROF, отвечающего за локальный анализ триплетов состояний. Именно здесь формируются базовые оценки движения. Каждый триплет обрабатывается отдельно, а результаты аккуратно накапливаются в стеке для последующей интеграции. Благодаря такой структуре можно обеспечивать потоковую обработку без роста вычислительной сложности, сохраняя чувствительность к микрособытиям рынка.
Следующий компонент — cLocal, отвечающий за локальное согласование и фильтрацию результатов E-TROF. Он выполняет роль промежуточного слоя, в котором локальные оценки приводятся в сопоставимую форму и готовятся к объединению в глобальное пространство состояния. Этот блок можно рассматривать как миниатюрный центр обработки, способный учитывать соседние триплеты и обеспечивать начальное выравнивание динамики.
Здесь стоит обратить внимание на важный нюанс. В оригинальной реализации авторов обмен данными между перекрывающимися триплетами был рассчитан на относительно малое окно анализа — 5 последовательных состояний. Для задач компьютерного зрения это было достаточно, так как временная глубина ограничена и локальные паттерны хорошо описывают движение.
Для финансовых данных такой подход оказывается недостаточным. Рыночные события формируют длинные и сложные последовательности, а локальные триплеты не могут адекватно отразить глобальные тенденции и структуру динамики. В нашей реализации мы ожидаем, что стек локальных оценок будет значительно больше и будет хранить информацию о значительно более длинных последовательностях.
Именно поэтому после локальной агрегации мы вводим блок глобального смешивания — cGlobal. Его задача — выровнять и интегрировать потоки динамики по всей накопленной истории, создавая единое согласованное представление состояния рынка. Здесь локальные оценки из стека взаимодействуют друг с другом, корректируя и уточняя общую динамику. Такой подход обеспечивает согласованность потоков движения: позволяет учитывать более длинные временные зависимости и при этом сохраняет чувствительность к краткосрочным событиям.
Блок cUpdateFlow отвечает за обновление потоков движения на основе уже накопленных и согласованных данных.
Метод инициализации объекта играет ключевую роль, так как именно в нём задаются все параметры архитектуры, формируются и связываются все внутренние компоненты, а также настраиваются вычислительные ресурсы.
bool CNeuronPSSEFlow::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint forecast, uint dimension, uint hidden_dimension, ENUM_OPTIMIZATION optimization_type, uint batch) { uint windows[] = {3, 5}; uint steps[] = {1, 1}; if(!CNeuronSpikeSuperKernelBlock::Init(numOutputs, myIndex, open_cl, hidden_dimension, dimension, windows, steps, forecast, 1, optimization_type, batch)) ReturnFalse;
Инициализация начинается с верхнего уровня — вызова одноименного метода родительского класса, который задаёт основные параметры блока. Это обеспечивает основу для последующей последовательной иерархической сборки всех внутренних компонентов.
Далее инициализируется cETROF — модуль локального анализа триплетов. Ему передаются параметры размерности стека, исходных данных и скрытого состояния, а также указатель на OpenCL-контекст.
uint index = 0; if(!cETROF.Init(0, index, OpenCL, forecast, dimension, hidden_dimension, optimization, iBatch)) ReturnFalse;
После успешной инициализации cETROF готов выполнять последовательный анализ локальных триплетов, аккумулируя результаты в стек для дальнейшей интеграции.
Следующий шаг — инициализация cLocal, промежуточного блока, отвечающего за локальное согласование. Он получает на вход результаты cETROF.
index++; if(!cLocal.Init(0, index, OpenCL, hidden_dimension, hidden_dimension, windows, steps, forecast, 1, optimization, iBatch)) ReturnFalse;
Блок cGlobal строится несколько иначе. После очистки предыдущих состояний в cGlobal передается указатель на объект OpenCL.
index++; //--- cGlobal.Clear(); cGlobal.SetOpenCL(OpenCL); CNeuronBaseOCL* neuron = NULL; CNeuronSpikeGMA* gma = NULL; neuron = new CNeuronBaseOCL(); if(!neuron || !neuron.Init(0, index, OpenCL, 2 * hidden_dimension * forecast, optimization, iBatch) || !cGlobal.Add(neuron)) DeleteObjAndFalse(neuron); neuron.SetActivationFunction(None);
Далее создаются базовый нейронные объект, который аккумулирует результаты локального согласования и стек динамики триплетов. А за глобальное согласование отвечает объект CNeuronSpikeGMA.
index++; gma = new CNeuronSpikeGMA(); if(!gma || !gma.Init(0, index, OpenCL, hidden_dimension, forecast, 1, optimization, iBatch) || !cGlobal.Add(gma)) DeleteObjAndFalse(gma);
Каждый из этих объектов инициализируется с указанием размера скрытого состояния, после чего добавляется в cGlobal. Благодаря этому блок становится центром интеграции локальных оценок, формируя согласованное представление состояния рынка.
Затем инициализируется блок cUpdateFlow, отвечающий за обновление потоков на основе согласованных данных. Сначала очищается его предыдущий контент и задаётся OpenCL.
index++;
cUpdateFlow.Clear();
cUpdateFlow.SetOpenCL(OpenCL);
CNeuronSpikeSuperKernelBlock* sk_blok = NULL;
Далее создаются объект базового нейронного слоя CNeuronBaseOCL. На это раз он объединяет стек локальных оценок триплетов, их локальное и глобальное согласование. И дополняется результатами анализа динамического потока на предыдущем шаге.
neuron = new CNeuronBaseOCL(); if(!neuron || !neuron.Init(0, index, OpenCL, 4 * hidden_dimension * forecast, optimization, iBatch) || !cUpdateFlow.Add(neuron)) DeleteObjAndFalse(neuron); neuron.SetActivationFunction(None);
На основании этих данных блок CNeuronSpikeSuperKernelBlock формирует итоговый поток динамики.
index++; sk_blok = new CNeuronSpikeSuperKernelBlock(); if(!sk_blok || !sk_blok.Init(0, index, OpenCL, 4 * hidden_dimension, hidden_dimension, windows, steps, forecast, 1, optimization, iBatch) || !cUpdateFlow.Add(sk_blok)) DeleteObjAndFalse(sk_blok); if(!sk_blok.Clear()) ReturnFalse; //--- return true; }
Эти объекты получают соответствующие размеры скрытого состояния и окна анализа, после чего добавляются в cUpdateFlow. На этом уровне происходит интеграция всей истории и формирование согласованного обновления, готового к следующему шагу модели.
Вся последовательность инициализации обеспечивает, что каждый компонент — от локального анализа триплетов до глобального согласования и обновления потоков — получает корректные параметры и интегрируется в единую иерархическую архитектуру. Такой подход гарантирует, что CNeuronPSSEFlow сразу после инициализации готов к потоковой обработке финансовых данных, последовательной агрегации локальных оценок и формированию целостного динамического представления рынка.
Прямой поток данных через всю архитектуру объекта организован в методе feedForward. Здесь локальные оценки событий превращаются в согласованное глобальное представление динамики рынка. Алгоритм метода можно представить как последовательное путешествие информации через несколько уровней обработки, где каждый шаг трансформирует сырые рыночные данные в согласованное представление динамики.
bool CNeuronPSSEFlow::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!cETROF.FeedForward(NeuronOCL)) ReturnFalse;
Путешествие начинается с cETROF, где на каждом шаге анализируется последний триплет состояний. Представьте себе ситуацию, когда в течение нескольких тиков цена резко реагирует на новости — спред внезапно расширяется, объёмы торгов подскакивают, активность внутри тикового потока растёт. cETROF фиксирует эти микровзрывы, оценивая локальные импульсы движения. В отличие от простого фильтра, блок видит контекст соседних шагов и вычисляет локальный оптический поток движения — своего рода миниатюрный прогноз того, куда двигается рынок на микроуровне.
Следующий этап — cLocal, который выравнивает эти оценки. Если, например, два соседних триплета показывают противоположные направления (первый сигнализирует о резком росте, второй — о краткой коррекции), cLocal аккуратно сглаживает противоречие, сохраняя при этом значимость сильных движений.
if(!cLocal.FeedForward(cETROF.AsObject()))
ReturnFalse;
На этом уровне локальные импульсы уже начинают общаться. Сильные сигналы усиливаются, слабые — подавляются. В терминах рынка это можно представить как фильтр, который различает истинные всплески активности от случайного шума, обеспечивая надёжность локального анализа.
Далее информация поступает в cGlobal. Здесь начинается итеративная интеграция. На первой итерации формируется каркас глобального состояния. Выходы cETROF и cLocal конкатенируются.
CNeuronSpikeDepthWiseResidual* resid = cSKFlow[0]; uint hidden_dimension = resid.GetWindow(); uint units = cLocal.Neurons() / hidden_dimension; uint dimension = Neurons() / units; //--- CNeuronBaseOCL* prev = cGlobal[0]; CNeuronBaseOCL* curr = NULL; if(!prev || !Concat(cLocal.getOutput(), cETROF.getOutput(), prev.getOutput(), hidden_dimension, hidden_dimension, units)) ReturnFalse;
Здесь стоит обратить внимание на строгую последовательность конкатенации данных. Напомню, что следующим мы используем модуль GMA для глобального выравнивания динамики, который корректирует основной поток на основании согласованности контекста. В данном случае мы используем результаты локального согласования в качестве основного потока, а результаты работы E-TROF — в качестве контекста.
На последующих итерациях каждый элемент блока уточняет состояние, добавляя новые данные и выравнивая предыдущие оценки.
for(int i = 1; i < cGlobal.Total(); i++) { curr = cGlobal[i]; if(!curr || !curr.FeedForward(prev)) ReturnFalse; prev = curr; }
Рынок уже воспринимается как последовательность взаимосвязанных событий, где каждое движение имеет последствия для общего тренда.
Блок cUpdateFlow превращает эту согласованную глобальную информацию в обновлённый поток движения. Например, если после серии локальных всплесков начинается плавный тренд, cUpdateFlow корректирует направление потока, усиливая ключевые сигналы и подавляя случайные колебания.
curr = cUpdateFlow[0]; prev = cUpdateFlow[-1]; if(!prev || !curr || !Concat(cLocal.getOutput(), cETROF.getOutput(), cGlobal[-1].getOutput(), prev.getOutput(), curr.getOutput(), hidden_dimension, hidden_dimension, hidden_dimension, hidden_dimension, units)) ReturnFalse; prev = curr; for(int i = 1; i < cUpdateFlow.Total(); i++) { curr = cUpdateFlow[i]; if(!curr || !curr.FeedForward(prev)) ReturnFalse; prev = curr; }
Здесь каждая итерация выполняет объединение локальных оценок, глобального состояния и предыдущих выходов cUpdateFlow. В рамках цикла каждый объект слоя уточняет поток динамики, корректирует направление движения, усиливает значимые сигналы и подавляет шум. Благодаря такой последовательной обработке, каждый шаг cUpdateFlow становится точкой согласования всей накопленной информации, превращая стек локальных оценок в целостный динамический поток, готовый к прогнозированию и дальнейшей обработке.
Завершает процесс вызов одноименного метода родительского класса, в котором аккумулируется вся обработанная информация и формируется окончательный выход модуля.
if(!CNeuronSpikeSuperKernelBlock::feedForward(prev))
ReturnFalse;
Важно подчеркнуть, что на выходе модуля мы получаем именно прогноз динамики потока на заданный горизонт планирования — то есть изменение состояния рынка, а не само состояние. Динамика отражает направление и величину движения цены, объёмов и других рыночных характеристик, позволяя модели предвидеть будущие колебания.
Для того чтобы получить полноценное представление о текущей рыночной ситуации, необходимо объединить прогнозную динамику с последним доступным состоянием окружающей среды. В нашей реализации это достигается простым, но эффективным приёмом — прогнозный поток динамики суммируется с последним анализируемым состоянием.
if(!SumVecMatrix(NeuronOCL.getOutput(), Output, Output, dimension, 1, 0, 0, 0, 1)) ReturnFalse; //--- return true; }
Таким образом, итоговый выход модели отражает не только ожидаемые изменения, но и актуальное положение рынка на момент прогноза.
Этот подход обеспечивает два важных эффекта. Во-первых, сохраняется чувствительность к локальным событиям и новым входным данным. Во-вторых, создаётся согласованная картина рыночной ситуации, пригодная для принятия решений и последующего анализа. Иными словами, модель одновременно прогнозирует движение и формирует контекст, позволяя оценивать, где находится рынок и куда он, вероятнее всего, будет двигаться.
Правильная организация процесса прямого прохода является лишь частью успеха. Чтобы модель работала корректно и предсказуемо, необходимо обучить её, и ключевым этапом обучения становится распределение градиента ошибки через все уровни архитектуры. Метод calcInputGradients выполняет эту задачу, обеспечивая последовательное и согласованное распространение сигналов ошибки от выходного слоя к каждому внутреннему компоненту.
bool CNeuronPSSEFlow::calcInputGradients(CNeuronBaseOCL *NeuronOCL) { if(!NeuronOCL) ReturnFalse; //--- if(!CNeuronSpikeSuperKernelBlock::calcInputGradients(cUpdateFlow[-1])) ReturnFalse;
Процесс начинается с верхнего уровня — вызова одноименного метода родительского класса для передачи градиента ошибки последнему объекту cUpdateFlow. Здесь формируется первичная обратная волна градиента, отражающая ошибку прогноза динамики рынка. На практике это соответствует выявлению того, насколько текущий поток предсказанной динамики отклонился от реальных изменений цены, объёмов и других рыночных характеристик.
Далее метод последовательно обрабатывает все элементы блока cUpdateFlow в обратном порядке.
CNeuronBaseOCL* curr = NULL; for(int i = cUpdateFlow.Total() - 2; i >= 0; i--) { curr = cUpdateFlow[i]; if(!curr || !curr.CalcHiddenGradients(cUpdateFlow[i + 1])) ReturnFalse; }
Каждая итерация выполняет уточнение скрытых градиентов. Текущий элемент получает сигнал ошибки от следующего и корректирует внутренние веса. Таким образом, поток градиентов движется против потока прямого прохода, аккуратно учитывая вклад каждого элемента в итоговую ошибку. В терминах рынка это можно интерпретировать как обратную проверку: как каждая локальная корректировка потока движения повлияла на прогноз на заданном горизонте.
После этого начинается обработка cGlobal. Сначала выполняется операция DeConcat, которая разделяет накопленные градиенты и восстанавливает соответствие между локальными и глобальными состояниями.
CNeuronSpikeDepthWiseResidual* resid = cSKFlow[0]; uint hidden_dimension = resid.GetWindow(); uint units = cLocal.Neurons() / hidden_dimension; uint dimension = Neurons() / units; //--- curr = cGlobal[-1]; if(!curr || !DeConcat(cLocal.getPrevOutput(), cETROF.getPrevOutput(), curr.getGradient(), cUpdateFlow[0].getPrevOutput(), cUpdateFlow[0].getGradient(), hidden_dimension, hidden_dimension, hidden_dimension, hidden_dimension, units)) ReturnFalse; Deactivation(curr);
Затем каждый элемент cGlobal в обратном порядке корректирует свои скрытые состояния, распространяя градиенты к предыдущим объектам.
for(int i = cGlobal.Total() - 2; i >= 0; i--) { curr = cGlobal[i]; if(!curr || !curr.CalcHiddenGradients(cGlobal[i + 1])) ReturnFalse; }
На этом уровне модель выстраивает причинно-следственные связи между локальными событиями и глобальной динамикой, обеспечивая согласованность всей истории рынка.
Блоки cLocal и cETROF получают свои градиенты. cLocal суммирует сигналы ошибки, корректируя внутренние оценки локальной динамики.
if(!DeConcat(cLocal.getGradient(), cETROF.getGradient(), curr.getGradient(), hidden_dimension, hidden_dimension, units)) ReturnFalse; if(!SumAndNormilize(cLocal.getGradient(), cLocal.getPrevOutput(), cLocal.getGradient(), hidden_dimension, false, 0, 0, 0, 1)) ReturnFalse; if(!SumAndNormilize(cETROF.getGradient(), cETROF.getPrevOutput(), cETROF.getPrevOutput(), hidden_dimension, false, 0, 0, 0, 1)) ReturnFalse; Deactivation(cLocal);
А cETROF получает градиенты через объект cLocal, выполняя собственные уточнения.
if(!cETROF.CalcHiddenGradients(cLocal.AsObject())) ReturnFalse; if(cETROF.Activation() != None) if(!DeActivation(cETROF.getOutput(), cETROF.getPrevOutput(), cETROF.getPrevOutput(), cETROF.Activation())) ReturnFalse; if(!SumAndNormilize(cETROF.getGradient(), cETROF.getPrevOutput(), cETROF.getGradient(), hidden_dimension, false, 0, 0, 0, 1)) ReturnFalse;
Здесь учитывается активность нейронов, применяются функции деактивации при необходимости. Таким образом, локальные триплеты не просто получают сигнал ошибки, а корректируют свои оценки в контексте всей модели, связывая локальные события с глобальными последствиями.
Наконец, метод передает градиенты внешнему объекту NeuronOCL, завершив цикл обратного распространения.
if(!NeuronOCL.CalcHiddenGradients(cETROF.AsObject())) ReturnFalse; //--- return true; }
Важно подчеркнуть принципиальный момент. Градиент на объект исходных данных распространяется только по основной магистрали операций и не затрагивает линию обратных связей. Этот шаг является сознательным и продуманным. Модель не корректирует исходные рыночные данные, поскольку они представляют объективную реальность, независимую от её вычислительной структуры.
Каждая итерация метода — это точная и последовательная передача градиентов ошибки. Она гарантирует, что обучение модели учитывает локальные микрособытия и глобальные тенденции рынка.
В итоге calcInputGradients обеспечивает устойчивость и предсказуемость модели. Каждый локальный и глобальный компонент получает корректный сигнал ошибки. Веса корректируются пропорционально их влиянию на результат, а стек локальных оценок превращается в управляемый инструмент прогнозирования. Этот метод делает обучение модели непрерывным, последовательным и согласованным, что критически важно для потоковой обработки финансовых данных в реальном времени.
Тестирование
Мы подошли к важной границе. Работа по формированию собственного взгляда на идеи, предложенные авторами P-SSE, завершена. Архитектурные решения получили конкретную реализацию средствами MQL5 и превратились в рабочий инструмент. Следующий шаг — проверить, как этот инструмент ведёт себя в реальных торговых условиях, где рынок не прощает неопределённости.
Как и в предыдущих работах, мы строим торговую модель, способную самостоятельно анализировать рыночную ситуацию и принимать решения без жёстко заданных правил. Нас по-прежнему интересует не набор эвристик, а поведение системы в целом. Важно, что внедрение P-SSE не требует перестройки всей архитектуры. Мы не ломаем отлаженные компоненты и не усложняем их без необходимости — наоборот, интегрируем новые подходы точечно, чтобы повысить эффективность, сохранив стабильность.
Новый объект верхнего уровня CNeuronPSSEFlow заменяет лишь последний слой энкодера анализа окружающей среды. Именно здесь раскрывается сила P-SSE: локальные триплеты событий проходят обработку, формируя динамику, которая затем аккуратно интегрируется в глобальное представление рынка. Модель начинает видеть рыночную ситуацию иначе, при этом остальные компоненты системы продолжают работать без изменений.
Экспериментальная работа началась с офлайн-обучения на исторических данных EURUSD таймфрейм H1 за период с Января 2024 по Июнь 2025 года. В этом спокойном и контролируемом режиме модель постепенно осваивала рынок, словно исследователь на неизведанной территории. Она училась распознавать повторяющиеся паттерны: устойчивые коридоры цен, резкие импульсы объёмов в новостные часы, кратковременные всплески волатильности. Каждый триплет событий позволял модели формировать локальные оценки движения, которые затем аккумулировались в стек, создавая последовательное и согласованное представление динамики рынка. Постепенно формировалась целостная картина. Где начинается тренд? Где импульс утихает? Какие события повторяются и усиливаются с течением времени?
Следующий этап — тонкая онлайн-настройка в тестере стратегий MetaTrader 5. Здесь данные стали живыми. Рынок шумел, менял режимы поведения, демонстрировал резкие скачки цен после новостей или обрывов ликвидности, а модель, словно опытный трейдер, училась подстраиваться под эти колебания. Локальные импульсы корректировались, но накопленный опыт сохранялся.
Финальная проверка проводилась на полностью новых данных за период с Июля по Декабрь 2025 года. Все параметры модели оставались неизменными, что обеспечивало объективность оценки. Модель сталкивалась с непривычными рыночными сценариями. Здесь проверялось не только умение прогнозировать динамику, но и способность обобщать накопленный опыт, верно интерпретировать незнакомые ситуации и сохранять устойчивость вне обучающей выборки.


По результатам тестирования доходность составила 263%. При этом просадки оказались заметными — до 52% по Equity. Это отражает активный характер анализа микрособытий и подчёркивает, что модель реагирует на рынок чувствительно.
Статистика сделок демонстрирует устойчивость: 107 операций, почти поровну прибыльные и убыточные. Средний выигрыш 18.28USD против среднего убытка -13.66USD. Лонги работают лучше шортов, а серии убыточных сделок объясняют глубокие просадки — модель учится адаптироваться к рыночным шумам.
Кривая баланса показывает уверенный рост в начале теста, затем боковик и постепенный откат. Модель ясно реагирует на рыночные режимы: она уверенно зарабатывает на тренде, корректно оценивает локальные импульсы. Но по мере удаления от периода обучения эффективность постепенно снижается.
В целом модель подтвердила свою способность формировать согласованное представление рынка, связывать локальные события в глобальный поток и принимать решения на основе динамики. Стратегия требует доработки в части снижения просадок и адаптации под разные рыночные сценарии.
Заключение
Мы подошли к логическому завершению текущего этапа работы. Предложенные авторами P-SSE идеи были последовательно адаптированы к специфике финансовых рынков и полностью реализованы средствами MQL5. Архитектура модели, построенная вокруг объекта верхнего уровня CNeuronPSSEFlow, доказала свою работоспособность. Локальные оценки динамики рынка аккуратно интегрируются в согласованное представление состояния, а потоковая обработка триплетов событий позволяет сохранять высокую скорость и точность вычислений.
Тестирование на исторических данных показало, что модель способна эффективно выявлять повторяющиеся паттерны, отслеживать импульсы и корректно прогнозировать динамику потока на заданный горизонт планирования. При этом она сохраняет чувствительность к локальным событиям и не теряет информации о краткосрочных колебаниях, даже когда рынок демонстрирует резкие движения. В то же время наблюдается естественное снижение качества прогнозов по мере удаления от периода обучения, что подчёркивает важность регулярного обновления данных и адаптации под новые рыночные условия.
В результате мы получили рабочий инструмент, который формирует глубокое, согласованное понимание рыночной ситуации, соединяя локальные импульсы в глобальный поток событий.
Ссылки
- Perturbed State Space Feature Encoders for Optical Flow with Event Cameras
- SKFlow: Learning Optical Flow with Super Kernels
- Другие статьи серии
Программы, используемые в статье
| # | Имя | Тип | Описание |
|---|---|---|---|
| 1 | Study.mq5 | Советник | Советник офлайн обучения моделей |
| 2 | StudyOnline.mq5 | Советник | Советник онлайн обучения моделей |
| 3 | Test.mq5 | Советник | Советник для тестирования модели |
| 4 | Trajectory.mqh | Библиотека класса | Структура описания состояния системы и архитектуры моделей |
| 5 | NeuroNet.mqh | Библиотека класса | Библиотека классов для создания нейронной сети |
| 6 | NeuroNet.cl | Библиотека | Библиотека кода OpenCL-программы |
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Особенности написания Пользовательских Индикаторов
Эко-эволюционный алгоритм — Eco-inspired Evolutionary Algorithm (ECO)
Возможности Мастера MQL5, которые вам нужно знать (Часть 58): Обучение с подкреплением (DDPG) совместно с паттернами скользящей средней и стохастика
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования