Нейросети в трейдинге: Асинхронная обработка событий в потоковых моделях (Основные компоненты)
Введение
Когда мы говорим о моделировании финансовых рынков, мы почти всегда начинаем с формы, а не с сути. Свечи, бары, таймфреймы, окна наблюдений — всё это выглядит как нечто естественное, почти данное нам изначально. Но если отбросить привычку, станет ясно, что рынок не мыслит интервалами: он не знает, когда заканчивается минута или час, и не делает пауз между событиями, чтобы нам было удобнее считать индикаторы. Рынок — это поток. Непрерывный, асинхронный, неравномерный. Иногда он течёт спокойно, иногда срывается в бурный водоворот, но никогда не останавливается. Именно это фундаментальное несоответствие между природой рынка и тем, как мы его измеряем, годами ограничивало эффективность даже самых сложных алгоритмических моделей.
Классический кадровый подход (анализ дискретных слепков рынка) неизбежно приводит к запаздыванию. Модель всегда видит уже свершившееся. Она реагирует на то, что рынок успел прожить, а не на то, что рождается в текущий момент. И чем быстрее рынок, тем сильнее это отставание. Можно уменьшать таймфрейм, можно ускорять расчёты, можно добавлять всё более сложные архитектуры, но фундаментальная проблема остаётся — мы по-прежнему работаем с нарезанным прошлым, а не с живым настоящим. Именно здесь возникает потребность в архитектуре, которая мыслит так же, как движется рынок, — непрерывно, событийно, без искусственных границ.
Фреймворк EVA-Flow родился не в финансах, а в компьютерном зрении. Там эта проблема проявляется ещё нагляднее: событийные камеры не формируют кадры, они фиксируют изменения в момент их возникновения. Любая попытка превратить этот поток в последовательность изображений тут же убивает главное преимущество — мгновенную реакцию. Поэтому авторы EVA-Flow пошли другим путём — они построили архитектуру, в которой поток данных остаётся потоком на всём протяжении вычислений. Никаких кадров, никаких окон, никакой принудительной синхронизации, только эволюция состояния, которая обновляется при каждом новом событии. И именно эта идея оказалась удивительно созвучной финансовым рынкам.
Если рассматривать рынок как событийный сенсор, аналогия становится почти очевидной. Тик, сделка, изменение стакана, всплеск объёма — всё это события, возникающие в нерегулярные моменты времени и несущие информацию о факте изменения. В этом смысле рынок гораздо ближе к событийной камере, чем к видеопотоку. И значит, модель, построенная для работы с такими данными, может быть перенесена в финансовый контекст не метафорически, а буквально, с минимальными концептуальными потерями.
Архитектура EVA-Flow принципиально отличается от привычных нейросетевых моделей временных рядов. Она не стремится сразу дать точный ответ. Напротив, она допускает, что первое приближение может быть грубым, неточным, даже шумным. Но зато оно появляется мгновенно. Дальше начинается процесс внутреннего уточнения, где модель шаг за шагом перерабатывает своё собственное состояние, уточняя направление, скорость и характер движения. Это похоже на то, как опытный аналитик сначала чувствует импульс рынка, а уже затем, по мере поступления новых данных, корректирует своё понимание, убирая шум и выделяя структуру. В EVA-Flow этот процесс формализован и встроен в саму архитектуру, а не вынесен во внешнюю логику.
Вход в модель начинается не с формирования фиксированного тензора, а с накопления событий в Unified Voxel Grid — особом представлении, которое можно воспринимать как временную ткань. Каждое событие не просто добавляется в ячейку, а влияет на локальное состояние потока, изменяя его плотность и направление. В отличие от классических воксельных сеток, где время дискретизируется жёстко, здесь оно остаётся мягким: обновляется и перетекает вместе с данными. Именно этот слой делает возможной обработку данных в режиме anytime — модель может начать вычисления в любой момент, не дожидаясь заполнения всего объёма.
Далее в работу вступает базовый энкодер, который не пытается сразу извлечь точное движение, а формирует первичное представление локальной динамики. Это намеренно грубая оценка, своего рода набросок, но она появляется практически мгновенно. Здесь проявляется классическая инженерная мудрость: сначала быстрое приближение, затем уточнение. Такой подход резко контрастирует с традиционными моделями, которые долго думают и выдают результат только в конце прохода. В EVA-Flow вычисление начинается сразу и не останавливается.
Центральным элементом архитектуры является каскад модулей Spatiotemporal Motion Refinement (SMR). Каждый из них получает на вход текущее состояние потока и результат предыдущей оценки, после чего уточняет движение с учётом новых событий и накопленного контекста. Эти модули работают как последовательные линзы, через которые модель всё точнее видит структуру движения. Важно, что они не просто корректируют численные значения, а изменяют само состояние внутреннего представления, делая его всё более устойчивым к шуму и случайным всплескам. В финансовом контексте это особенно ценно. Рынок шумен по природе, и способность модели постепенно успокаивать поток, не теряя чувствительности к реальным изменениям, становится решающим преимуществом.
Между этими стадиями активно используется механизм варпинга — внутреннего переноса состояния вдоль предполагаемой траектории движения. Это позволяет модели согласовывать прошлые и текущие оценки без явного хранения истории. Проще говоря, EVA-Flow не запоминает рынок, он его продолжает. Каждое новое состояние логически вытекает из предыдущего, а не пересчитывается заново. С архитектурной точки зрения это означает резкое снижение вычислительных затрат и рост устойчивости при длинных последовательностях событий.
Отдельного внимания заслуживает функция потерь, встроенная в архитектуру не как внешняя проверка, а как часть внутренней логики. Rectified Flow Warp Loss не требует истинного движения. Она оценивает, насколько согласованно развивается поток при переносе состояния вперёд и назад. Если модель сама себе противоречит, ошибка возрастает. Если эволюция состояния стабильна, обучение продолжается в этом направлении. Для финансовых данных это принципиально важно, потому что рынок не предоставляет эталона, но отлично наказывает за внутреннюю несогласованность.
В результате архитектура EVA-Flow превращается в замкнутую систему, где данные, состояние, обновление и обучение образуют единый контур. Нет жёстких этапов, но есть непрерывный процесс, который может быть прерван, продолжен или ускорен в любой момент. Именно это делает модель пригодной для работы в реальном времени.

SMR-модуль
Сердцем всей архитектуры EVA-Flow является модуль Spatiotemporal Motion Recurrent (SMR). Именно в этом узле сходятся пространственная и временная логика. Именно здесь идея движения как процесса перестаёт быть абстракцией и превращается в вычислимую реальность. Все остальные компоненты фреймворка, по сути, существуют для того, чтобы этот модуль мог работать устойчиво, непрерывно и точно, не теряя связи с живым потоком событий.
Авторы EVA-Flow подошли к задаче движения предельно прагматично. Они не стали пытаться угадать движение сразу и целиком, как это делают многие классические архитектуры. Вместо этого они выстроили иерархическую систему постепенного уточнения, где каждая новая оценка не заменяет предыдущую, а аккуратно корректирует её. В архитектуре EVA-Flow используется стек SMR-блоков, проходящих от грубого представления к более точному — от общего направления к деталям. Такое движение сверху вниз по пирамиде признаков напоминает работу опытного аналитика: сначала он видит общий импульс рынка, затем структуру движения, и только потом — нюансы и локальные колебания.
Пространственная составляющая SMR построена именно на принципе Coarse-to-Fine. На грубых уровнях пирамиды модель работает с обобщёнными признаками. Здесь шум подавлен, а движение читается крупными мазками. На этом этапе формируется первичное понимание направления и масштаба изменения. Эти оценки затем передаются на более высокое разрешение, где они служат направляющей для уточнения. Важно, что на каждом уровне происходит не пересчёт, а корректировка. Ошибка не накапливается скачками. Она постепенно выдавливается из системы. Для финансовых данных, где шум часто превышает сигнал, это архитектурное решение особенно ценно. Модель не реагирует на каждую случайную тень, а движется по инерции реального импульса.
Но пространственное уточнение — лишь половина истории. Вторая, не менее важная ось работы SMR — временная. И здесь появляется ConvGRU. Рынок, как и физическое движение, обладает инерцией, памятью, ритмом. Он не прыгает хаотично из состояния в состояние, даже когда кажется, что всё рушится. ConvGRU в SMR играет роль внутреннего механизма памяти, который аккуратно удерживает накопленную информацию о движении и решает, что стоит сохранить или можно забыть. Его гейты работают как фильтры здравого смысла — пропускают устойчивые изменения и подавляют случайные всплески. В результате модель не просто реагирует на события, а формирует непрерывную временную траекторию состояния.
Внутри каждого SMR-блока процесс организован как повторяющийся цикл. Текущее приближение движения сначала переносится вперёд с помощью операции Warp — это важный момент, потому что модель буквально «продолжает» своё собственное движение, а не смотрит на рынок заново. Затем обновлённое представление объединяется с признаками текущего уровня пирамиды и состоянием памяти ConvGRU. Этот объединённый тензор проходит через рекуррентный блок, где формируется новое скрытое состояние, уже учитывающее пространственный контекст и временную историю. После этого специальная голова FlowHead извлекает поправку к движению, которая добавляется к предыдущей оценке. Таким образом, движение уточняется маленькими, аккуратными шагами. И так — снова и снова, пока поток событий продолжается.
Для финансовых рынков эта логика переносится почти напрямую. Пространственная иерархия соответствует различным масштабам рыночного движения — от глобального тренда до локальных колебаний. Временная рекуррентность отвечает за сохранение контекста. За то самое ощущение рынка, которое опытный трейдер описывает как чтение ленты. Warp-операция становится аналогом инерционного переноса ожиданий. Рынок редко разворачивается мгновенно, и модель, которая учитывает это, получает принципиальное преимущество, а итеративные остаточные обновления позволяют корректировать прогноз без ломки всей структуры состояния.
В практической реализации фреймворка вся абстрактная логика SMR-модуля должна быть сведена к конкретному, управляемому и расширяемому объекту. Именно поэтому в рамках проекта модуль Spatiotemporal Motion Recurrent оформляется как самостоятельный нейронный объект, встроенный в общую иерархию EVA-Flow. Класс CNeuronSpikeSMR становится тем самым узлом, где сходятся пространственное уточнение, временная рекуррентность и потоковая логика обновления состояния. Архитектурно это полноценный вычислительный организм, живущий по тем же законам, что и описанный в оригинальной статье SMR-модуль.
class CNeuronSpikeSMR : public CNeuronMSRes { protected: CNeuronSpikeConvBlock cUpsampleFlow; CNeuronBaseOCL cConcat; CNeuronSpikeConvGRU2D cConvGRU; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; } virtual bool feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; } virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL, CBufferFloat *second) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override { ReturnFalse; } virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput, CBufferFloat *SecondGradient, ENUM_ACTIVATION SecondActivation = None) override; public: CNeuronSpikeSMR(void) {}; ~CNeuronSpikeSMR(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint units, uint window, uint second_window, uint window_out, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronSpikeSMR; } //--- 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 bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual void TrainMode(bool flag) override; virtual bool Clear(void) override; };
В данной реализации наследование от CNeuronMSRes выполняет конкретную и инженерно честную роль — роль FlowHead. То есть того самого блока, который извлекает поправку к потоку из скрытого состояния SMR. Это принципиальный момент, потому что в оригинальной формуле именно FlowHead является точкой выхода каждого рекуррентного шага.
Внутреннее устройство класса почти буквально повторяет структуру SMR, описанную авторами. Объект cUpsampleFlow отвечает за перенос оценки движения между уровнями иерархии. Грубая оценка поднимается на более высокий уровень разрешения и становится отправной точкой для уточнения. В финансовой интерпретации это выглядит как перенос глобального импульса на локальный масштаб, где он начинает обрастать деталями, но не теряет направления.
Следующий элемент — cConcat. Он выполняет операцию объединения. Строго контролируемый этап сборки контекста, где текущий перенос движения, пространственные признаки и временная память соединяются в единый поток.
Сердцем модуля остаётся cConvGRU. Этот объект отвечает за временную рекуррентность и аккуратное распространение состояния через последовательность событий. Его роль в SMR трудно переоценить. Именно он обеспечивает устойчивость модели при длинных потоках данных, подавляя случайные флуктуации и сохраняя инерцию движения.
Метод инициализации объекта — это не техническая формальность, а точка, где архитектура EVA-Flow буквально материализуется в вычислительной геометрии модуля. Именно здесь идея SMR перестаёт быть схемой из статьи и превращается в конкретную конфигурацию потоков и связей, с которыми будет работать OpenCL-ядро.
bool CNeuronSpikeSMR::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint units, uint window, uint second_window, uint window_out, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronMSRes::Init(numOutputs, myIndex, open_cl, units, window_out, 1, optimization_type, batch)) ReturnFalse;
Вызов одноименного метода родительского класса сразу задаёт правильный контекст. Поскольку базовый класс в этой реализации выполняет роль FlowHead, мы начинаем именно с инициализации выходного преобразования. Архитектурно это означает: прежде чем строить память и динамику, мы заранее определяем форму движения, которое SMR сможет порождать.
Дальше начинается сборка внутреннего контура SMR. Инициализация cUpsampleFlow — первый осмысленный шаг после FlowHead. Этот блок подготавливает поток предыдущего уровня пирамиды к работе на текущем масштабе.
uint index = 0; if(!cUpsampleFlow.Init(0, index, OpenCL, window, window, window_out, units, 1, optimization, iBatch)) ReturnFalse;
Обратите внимание на параметры инициализации данного блока. Здесь чётко читается логика Coarse-To-Fine — входное окно, выходное окно и число каналов движения связаны напрямую. Это и есть реализация конкретного вычислительного узла, который будет реально переносить движение между масштабами.
Следом идёт cConcat. И вот здесь архитектура становится особенно наглядной. Размер входа объекта прямо говорит об объединении двух потоков информации: текущие пространственные признаки и рекуррентное состояние, пришедшее по временной оси.
index++; if(!cConcat.Init(0, index, OpenCL, (window + second_window)*units, optimization, iBatch)) ReturnFalse; cConcat.SetActivationFunction(None);
И наконец, cConvGRU. Его инициализация завершает замкнутый контур SMR. Параметры инициализации показывают, что рекуррентный блок работает уже с объединённым пространственно-временным представлением, а не с отдельными потоками.
index++; if(!cConvGRU.Init(0, index, OpenCL, units, (window + second_window), window_out, optimization, iBatch)) ReturnFalse; //--- return true; }
Именно здесь происходит главное — формирование скрытого состояния Hij, которое несёт в себе память движения, инерцию рынка и накопленную структуру. Всё, что было собрано и согласовано ранее, здесь превращается в устойчивую динамику.
Метод прямого прохода — это принципиальная точка входа рекуррентной логики. Здесь модуль получает два источника информации одновременно: основной поток признаков текущего уровня и дополнительное состояние, пришедшее с соседнего уровня пирамиды.
bool CNeuronSpikeSMR::feedForward(CNeuronBaseOCL *NeuronOCL, CBufferFloat *SecondInput) { if(!NeuronOCL || !SecondInput) ReturnFalse; if(!cUpsampleFlow.FeedForward(NeuronOCL)) ReturnFalse;
Первый шаг реализует перенос предыдущей оценки движения на текущий масштаб. С инженерной точки зрения здесь происходит важная вещь. Модель не пересматривает движение заново, она продолжает его. Поток как бы протягивается вперёд, сохраняя инерцию и направление. Для финансового рынка это критично: цена почти всегда движется по инерции, и архитектура, которая учитывает это на уровне вычислений, автоматически получает преимущество.
Далее код явно вычисляет размеры окон и каналов. Этот фрагмент выглядит техническим, но по сути он задаёт геометрию рекуррентного шага. Мы точно знаем, сколько пространства занимает перенесённый поток, и сколько — временное состояние.
uint window_flow = cUpsampleFlow.GetWindow(); uint units = GetUnits(); uint second_window = cConvGRU.GetChanelsIn() - window_flow; if(SecondInput.Total() < int(second_window * units)) ReturnFalse; if(!Concat(NeuronOCL.getOutput(), SecondInput, cConcat.getOutput(), window_flow, second_window, units)) ReturnFalse;
Операция конкатенации — ключевой момент метода. Именно здесь сходятся два мира: пространство и время. Текущие признаки и рекуррентное состояние сшиваются в единый тензор без активации, без интерпретации, без фильтрации. Это чистая сборка контекста.
Затем в работу вступает ConvGRU. Это тот самый момент, где временная рекуррентность перестаёт быть формулой и становится памятью.
if(!cConvGRU.FeedForward(cConcat.AsObject()))
ReturnFalse;
ConvGRU принимает собранный контекст и обновляет скрытое состояние, решая, что сохранить, ослабить или усилить. В финансовой интерпретации это похоже на внутренний фильтр модели. Шум подавляется, устойчивое движение усиливается, а случайные всплески не проходят дальше. Именно здесь формируется скрытое состояние, которое делает EVA-Flow живой потоковой системой.
Следующий шаг — вызов одноименного метода родительского класса — превращает скрытое состояние в поправку к потоку. Здесь родительский класс, выполняющий роль FlowHead, извлекает из внутренней динамики конкретное численное обновление.
if(!CNeuronMSRes::feedForward(cConvGRU.AsObject()))
ReturnFalse;
Важно, что SMR сам не знает, как выглядит поток — он только формирует динамику. А FlowHead аккуратно переводит эту динамику в движение.
И наконец, замыкает цикл добавление полученной поправки к перенесенному потоку.
if(!SumAndNormilize(cUpsampleFlow.getOutput(), Output, Output, GetWindow(), false, 0, 0, 0, 1)) ReturnFalse; //--- return true; }
Цикл замкнулся. Рекуррентный шаг завершён. Модель готова принять следующее событие.
Если теперь взглянуть на метод целиком, становится видно, что это один полный временной шаг SMR, реализованный без упрощений и компромиссов. Здесь нет магии, нет скрытых перескоков — каждый элемент формулы имеет своё отражение в коде, и всё это выполняется в одном проходе, синхронно, без ожиданий и без внешней синхронизации.
Модуль инициализации потока
Следующий модуль, который мы сегодня реализуем, отсутствует в авторской реализации EVA-Flow. Однако его необходимость вытекает напрямую из понимания логики работы модели применительно к финансовым рынкам. В исходной области применения (компьютерном зрении) инициализация потока нулевыми значениями — обычная практика. Робот или камера стартует в состоянии покоя: на первом кадре движения объекта почти нет, изменения минимальны и вызваны лишь внешними факторами. Модель начинает наблюдать, фиксировать и корректировать свои оценки, ошибка на начальных этапах остаётся крайне низкой, а поток постепенно прогревается по мере накопления событий.
На финансовых рынках такой подход оказывается неприемлемым. Рынок не ждет, пока модель прогреется. Пока SMR шагает по нулевым начальным состояниям, цена уже движется, формируя серию событий, которые модель должна уловить и интерпретировать. Каждое новое событие несёт информацию о направлении, скорости и характере движения, и если игнорировать это, модель начинает отставать. В терминах рекуррентного шага это означает, что на первых итерациях ещё не содержится никакой реальной информации, а ConvGRU формирует скрытое состояние почти наугад, лишь опираясь на заранее заданные параметры и прошлые нулевые значения. В реальном времени такой подход приводит к ошибкам, которые накапливаются быстрее, чем модель успевает их исправить.
Следовательно, для работы с рынком необходима особая логика прогрева. Более того, мы не можем позволить себе ждать, пока модель прогреется. Рынок движется без остановки, и каждый тик — это потерянная возможность. Да и как же понять, когда модель готова к реальной работе?
Ответ прост. Мы перестаем полагаться на естественный прогрев и пытаемся сформировать стартовое состояние заранее. Идея заключается в том, чтобы выучить начальное состояние, с которого SMR сможет сразу действовать эффективно.
Но тут сталкиваемся с очевидной проблемой — рынок не стационарен. Нет одного универсального начального состояния, которое подошло бы для всех ситуаций. Любой подход с фиксированной инициализацией обречен на ошибку. Поэтому мы идем дальше — обучаем несколько кандидатов начального состояния, каждый из которых отражает возможное положение рынка в начале работы модели.
Далее включается классификатор анализируемого состояния системы. Он смотрит на реальные входные данные и оценивает, какой кандидат наиболее соответствует текущей рыночной ситуации. Более того, мы признаем, что практически никогда не встречается две полностью идентичные конфигурации рынка. Поэтому мы не выбираем один кандидат строго, а взвешиваем их по оценке классификатора, формируя комбинированное начальное состояние. Такой подход позволяет SMR стартовать не с нуля, а с максимально приближенной к текущему моменту конфигурации, сразу учитывая динамику рынка и минимизируя первоначальное отставание.
Эта стратегия делает прогрев не периодом ожидания, а активным, управляемым процессом, который позволяет модели сразу быть в потоке, готовой корректировать движение цены и сопровождать рынок на самых первых шагах своей работы. Это принципиальный шаг в адаптации EVA-Flow для реальных финансовых потоков, где нет права на промедление.
Для практической реализации идеи адаптивного прогрева мы формируем отдельный объект — CNeuronInitialFlow. Его задача — активно выбирать и комбинировать кандидатов на начальные состояния в зависимости от текущей ситуации на рынке. Архитектурно этот объект становится первым звеном в цепочке стека SMR-блоков, подготавливая поток так, чтобы модель могла сразу работать.
class CNeuronInitialFlow : public CNeuronBaseOCL { protected: CParams cCandidates; CLayer cScores; CNeuronAddToStack cStack; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronInitialFlow(void) {}; ~CNeuronInitialFlow(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint units, uint window_out, uint candidates, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronInitialFlow; } //--- methods for working with files virtual bool Save(int const file_handle) override; virtual bool Load(int const file_handle) override; //--- virtual bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual bool Clear(void) override; //--- virtual void SetOpenCL(COpenCLMy *obj) override; virtual void TrainMode(bool flag) override; //--- virtual void SetActivationFunction(ENUM_ACTIVATION value) override { }; };
Внутри класса выделены три ключевых элемента.
- cCandidates хранит набор обученных кандидатов на стартовое состояние. Каждый кандидат отражает одну из возможных конфигураций рынка на начальном этапе работы модели.
- cScores реализует классификатор текущего состояния: он оценивает, насколько текущая рыночная ситуация соответствует каждому из кандидатов.
- cStack формирует стек последних оценок рыночного состояния. Он аккуратно хранит историю последних комбинаций, что обеспечивает разнообразие оценок и устойчивость обучения, не вмешиваясь в реальную работу потока.
Метод инициализации задаёт внутреннюю структуру объекта. Вначале мы передаем управление родительскому классу, который формирует все унаследованные интерфейсы.
bool CNeuronInitialFlow::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint units, uint window_out, uint candidates, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, units * window_out, optimization_type, batch)) ReturnFalse; activation = None;
Активация при этом отключается, чтобы результаты оставались чистыми и не подвергались искажению.
Следующий шаг — инициализация блока cCandidates. Он создаёт массив обучаемых кандидатов начальных состояний, объединяя их в один тензор.
uint index = 0; if(!cCandidates.Init(0, index, OpenCL, units * window_out * candidates, optimization, iBatch)) ReturnFalse; cCandidates.SetActivationFunction(None); CBufferFloat* temp = cCandidates.getWeightsParams(); if(!temp || !temp.Fill(0)) ReturnFalse; index++;
Каждый кандидат имеет свою область в памяти, которая будет использоваться для формирования стартового состояния, а веса инициализируются нулями. Это даёт модели чистую отправную точку, с которой можно начинать обучение, и гарантирует, что никакой кандидат не доминирует на старте.
После этого создаётся блок cScores, отвечающий за классификацию текущего состояния рынка. Для этого в блок добавляются два слоя глубинной свёртки (CNeuronSpikeDepthWiseConv), которые последовательно сокращают выходное окно и формируют признаки для SoftMax.
cScores.Clear(); cScores.SetOpenCL(OpenCL); CNeuronSpikeDepthWiseConv* dw_conv = NULL; CNeuronSoftMaxOCL* softmax = NULL; uint window_in = window; for(int i = 0; i < 2; i++) { dw_conv = new CNeuronSpikeDepthWiseConv(); if(!dw_conv || !dw_conv.Init(0, index, OpenCL, window_in, candidates, 3, 1, units, 1, optimization, iBatch) || !cScores.Add(dw_conv)) DeleteObjAndFalse(dw_conv); index++; window_in = candidates; }
Слой Softmax превращает эти признаки в вероятности, которые используются для взвешивания кандидатов при формировании начального состояния.
softmax = new CNeuronSoftMaxOCL(); if(!softmax || !softmax.Init(0, index, OpenCL, units * candidates, optimization, iBatch) || !cScores.Add(softmax)) DeleteObjAndFalse(softmax); index++;
Такое построение обеспечивает плавное и информативное преобразование входных данных в оценки соответствия кандидатов текущей рыночной ситуации.
Наконец, инициализируется cStack.
if(!cStack.Init(0, index, OpenCL, stack_size, softmax.Neurons(), 1, optimization, iBatch)) ReturnFalse; //--- return true; }
Его задача — обеспечивать разнообразие оценок. Стек сохраняет предыдущие оценки и используется для применения Diversity Loss, чтобы каждая новая оценка рынка была максимально удаленной от всех предыдущих. Таким образом, cStack стимулирует классификатор вырабатывать широкий спектр информативных оценок, повышая обучаемость и устойчивость модели.
В итоге метод инициализации выстраивает внутреннюю архитектуру класса, обеспечивая возможность корректной работы классификатора, хранение кандидатов и управление разнообразием оценок. Архитектурно это полностью соответствует философии EVA-Flow: мы заранее формируем пространство, в котором скрытое состояние может адаптироваться к рынку мгновенно, без задержек, и с учётом высокой динамики финансовых потоков.
Метод прямого прохода является сердцем класса. Именно здесь происходит полный цикл обработки, который позволяет модели сразу стартовать в рыночном потоке с максимально информативным начальным состоянием.
bool CNeuronInitialFlow::feedForward(CNeuronBaseOCL *NeuronOCL) { if(bTrain) if(!cCandidates.FeedForward()) ReturnFalse;
Сначала, если включён режим обучения, выполняется прямой проход через cCandidates. Это обеспечивает актуальность обучаемых кандидатов, гарантируя, что они отражают всю накопленную динамику рынка и готовы участвовать в формировании стартового состояния.
Далее последовательно обрабатываются слои классификатора cScores.
CNeuronBaseOCL* prev = NeuronOCL; CNeuronBaseOCL* curr = NULL; for(int i = 0; i < cScores.Total(); i++) { curr = cScores[i]; if(!curr || !curr.FeedForward(prev)) ReturnFalse; prev = curr; }
Каждый слой глубинной свёртки и финальный SoftMax преобразуют входное состояние в оценку соответствия каждого кандидата текущему рыночному контексту. Важно, что каждый слой опирается на выход предыдущего, формируя постепенное, устойчивое и информативное представление состояния рынка. Это не просто классификация. Это построение вероятностного распределения, которое отражает, насколько каждый кандидат способен догнать текущий рынок.
На выходе SoftMax превращает признаки в вероятности, которые затем используются для взвешивания кандидатов. Здесь происходит ключевая операция матричного умножения. Выход кандидатов комбинируется с оценками SoftMax, формируя итоговое начальное состояние в виде линейной комбинации.
CNeuronSoftMaxOCL* softmax = prev; uint units = softmax.Heads(); uint candidates = softmax.Neurons() / units; uint dimension = Neurons() / units; if(!MatMul(cCandidates.getOutput(), softmax.getOutput(), Output, dimension, candidates, 1, units, true)) ReturnFalse; //--- return true; }
Благодаря этому SMR получает готовое стартовое состояние, уже согласованное с текущим рыночным импульсом, без необходимости догонять рынок с нуля.
Таким образом, метод прямого прохода превращает идею обучаемых кандидатов и динамического выбора начального состояния в живую, вычислительно реализованную стратегию. Каждая итерация учитывает как накопленное знание о возможных начальных состояниях, так и текущую конфигурацию рынка, что позволяет модели стартовать мгновенно и минимизировать отставание.
Заключение
Фреймворк EVA-Flow представляет собой продуманную архитектуру, сочетающую пространственно-временную рекуррентную обработку с адаптивной инициализацией состояния. Центральный элемент — SMR-модуль — обеспечивает формирование скрытых состояний, аккуратно соединяя информацию о предыдущих временных шагах с текущими признаками. Это создаёт основу для точного и стабильного анализа динамики.
Предложенный механизм выбора и комбинирования кандидатов начального состояния позволит модели мгновенно работать в потоке рыночных данных, снижая потенциальные стартовые ошибки и повышая адаптивность к изменяющимся условиям. Такой подход формирует богатую и разнообразную структуру для обучения, обеспечивая устойчивую работу модели в самых разных сценариях.
Архитектурные решения EVA-Flow делают его гибкой и многообещающей платформой для дальнейшего исследования и применения в задачах анализа и прогнозирования сложных динамических процессов.
Ссылки
Программы, используемые в статье
| # | Имя | Тип | Описание |
|---|---|---|---|
| 1 | Study.mq5 | Советник | Советник офлайн обучения моделей |
| 2 | StudyOnline.mq5 | Советник | Советник онлайн обучения моделей |
| 3 | Test.mq5 | Советник | Советник для тестирования модели |
| 4 | Trajectory.mqh | Библиотека класса | Структура описания состояния системы и архитектуры моделей |
| 5 | NeuroNet.mqh | Библиотека класса | Библиотека классов для создания нейронной сети |
| 6 | NeuroNet.cl | Библиотека | Библиотека кода OpenCL-программы |
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Особенности написания Пользовательских Индикаторов
Алгоритм сверчков — Cricket Algorithm (CA)
Нейросети в трейдинге: Асинхронная обработка событий в потоковых моделях (EVA-Flow)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования