Русский
preview
Redes neurais em trading: Abordagem semântica baseada em spikes para identificação espaço-temporal (S3CE-Net)

Redes neurais em trading: Abordagem semântica baseada em spikes para identificação espaço-temporal (S3CE-Net)

MetaTrader 5Sistemas de negociação |
50 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Introdução

No mundo financeiro atual, o mercado há muito deixou de ser um lugar onde se negociam apenas ativos. Nele, negociam-se informação, tempo e atenção. A velocidade de reação torna-se uma nova moeda, enquanto a capacidade de extrair padrões de um fluxo contínuo de dados passa a ser a principal vantagem. A cada segundo, milhões de cotações, ordens e notícias formam um oceano turbulento de eventos, no qual acaso e regularidade se entrelaçam de tal forma que, por vezes, a fronteira entre ambos desaparece. Esse fluxo não possui limites bem definidos: não é discreto nem síncrono e, por isso, exige modelos capazes de perceber não apenas a sequência, mas também a estrutura das mudanças, as relações e as tensões presentes nos dados.

Os métodos tradicionais de análise de séries temporais financeiras, sejam modelos estatísticos clássicos, redes recorrentes ou mesmo transformers de grande porte, enfrentam diversas limitações. Muitas vezes são lentos demais, sofrem sobreajuste ou perdem o contexto ao tentar capturar apenas dependências superficiais. O problema se torna ainda mais evidente em dados esparsos e assíncronos: eventos importantes ocorrem raramente, mas são justamente eles que determinam a dinâmica do mercado. Nesses casos, cada tick, cada pico de volume e cada desequilíbrio anômalo entre oferta e demanda passam a representar eventos, impulsos raros, porém extremamente relevantes, dos quais depende a estrutura do movimento subsequente dos preços.

O mercado pode ser comparado a um gigantesco fluxo neuromórfico. Ele se manifesta por picos de atividade, respostas breves a estímulos externos e oscilações internas. Assim como o sistema nervoso, reage a estímulos transmitindo sinais por uma rede complexa de interconexões. E, se o encararmos precisamente como um sistema de eventos, fica evidente que as abordagens clássicas baseadas em amostragem temporal uniforme não refletem a verdadeira natureza do que ocorre. É por isso que, nos últimos anos, pesquisadores vêm recorrendo a arquiteturas inspiradas em redes neurais de spikes e na abordagem neuromórfica de análise de dados.

É nesse contexto que surge o framework S3CE-Net (Spike-guided Spatiotemporal Semantic Coupling and Expansion Network), arquitetura apresentada no trabalho "S3CE-Net: Spike-guided Spatiotemporal Semantic Coupling and Expansion Network for Long Sequence Event Re-Identification". Esse modelo foi proposto para a tarefa de reidentificação de eventos em sequências longas (long-sequence event re-identification) em fluxos de dados obtidos por sensores neuromórficos. Esses sensores registram apenas mudanças, como variações abruptas de luminosidade e sinais assíncronos que surgem somente quando algo de fato acontece. O S3CE-Net modela conjuntamente as dependências espaciais e temporais, reforçando sinais informativos e suprimindo ruído, ao mesmo tempo que mantém alta eficiência computacional.

A ideia central consiste não apenas em analisar os eventos ao longo do tempo, mas também em captar as relações entre os canais espaciais, isto é, em termos figurativos, entre diferentes regiões do campo de visão. No contexto financeiro, isso pode ser interpretado como relações entre diferentes ativos, níveis de liquidez ou componentes da estrutura de mercado. Quando um setor do mercado começa a se mover enquanto outro fica para trás ou se antecipa, surge uma correlação espaço-temporal, uma espécie de ressonância. É justamente esse tipo de relação que o mecanismo de atenção do S3CE-Net procura captar: o Spike-guided Spatiotemporal Attention Mechanism (SSAM). Esse mecanismo avalia a relevância do evento atual e atribui a ele um peso considerando o contexto histórico, sem recorrer a informações futuras, algo fundamental para qualquer modelo de previsão.

Outra inovação do framework é a Spatiotemporal Feature Sampling Strategy (STFS). Durante o treinamento, ela permite que o modelo trabalhe com subconjuntos de atributos espaço-temporais, evitando o sobreajuste a fragmentos fixos dos dados. Em termos simples, a estratégia ensina o modelo a identificar padrões gerais em vez de memorizar combinações específicas de sinais. No contexto financeiro, isso é especialmente relevante: o mercado não se prende a padrões fixos, muda constantemente, e qualquer memorização tende a degradar os resultados. A STFS proporciona essa flexibilidade, forçando o modelo a se adaptar e a desenvolver a capacidade de perceber a dinâmica, em vez de se prender a configurações estáticas.

Se transportarmos mentalmente a arquitetura do S3CE-Net para o universo do trading, podemos compará-la a um sistema que escuta o mercado da mesma forma que o nervo auditivo percebe o som: sem registrar cada nota isoladamente, mas destacando transições, contrastes, intensidade e ritmo. Um modelo assim poderia reconhecer microeventos, como picos de volume, surgimento de grandes ordens e breves valores anômalos de volatilidade. Ao mesmo tempo, não se limitaria a registrar a ocorrência do evento, mas compreenderia sua importância no contexto de outros ativos e de picos anteriores, como um maestro que não escuta apenas um violino isolado, mas toda a partitura.

Os mercados financeiros há muito necessitam de abordagens desse tipo. A transição de modelos estáticos para sistemas capazes de interpretar de forma significativa sequências de eventos não representa apenas uma evolução, mas uma necessidade. Quanto mais rápido o mercado se move, maior é a importância da capacidade de reação e mais relevante se torna a aptidão do modelo para extrair significado de dados esparsos. O S3CE-Net se destaca por combinar a leveza das redes neurais de spikes com o poder expressivo dos mecanismos de atenção, sem sacrificar velocidade nem eficiência energética. São justamente essas características que o tornam conceitualmente alinhado às necessidades dos modelos financeiros, sobretudo daqueles que operam em tempo real ou em timeframes baixos.

Além disso, a própria filosofia do S3CE-Net, de reforçar o que é relevante e descartar o que é supérfluo, está em sintonia com os desafios do trading. O mercado está repleto de sinais falsos, ruído e coincidências aleatórias. E a verdadeira arte da análise consiste em identificar o que realmente importa.


Algoritmo S3CE-Net

O framework S3CE-Net é construído em torno de uma ideia central: relacionar a dinâmica dos impulsos de spikes aos padrões espaço-temporais do fluxo de dados, criando um modelo capaz não apenas de registrar a ocorrência dos eventos, mas também de estabelecer relações significativas entre eles. Se uma rede neural clássica se assemelha a uma câmera que captura imagens em intervalos regulares e com frequência constante, o S3CE-Net está mais próximo do sistema auditivo: ele percebe apenas aquilo que realmente aconteceu, reagindo à mudança, à transição e ao contraste. É justamente aí que reside a principal força dos modelos de spikes: eles operam no nível dos impulsos, eventos individuais que, em conjunto, formam uma representação completa.

O S3CE-Net é alimentado com uma sequência de tensores de eventos formada a partir de um fluxo assíncrono. Cada spike registrado pelo sensor é descrito pelas coordenadas (x, y), pela marca de tempo t e pela polaridade p, que indica a direção da mudança, ou seja, aumento ou redução da luminosidade. Dessa forma, o fluxo de eventos pode ser representado como um conjunto de dados em quatro dimensões: tempo, duas dimensões espaciais e polaridade. Para conferir uma estrutura regular a esse fluxo, os eventos assíncronos são agrupados em uma sequência de janelas temporais fixas, uma espécie de pequenos recortes do ambiente, cada um contendo dois canais: mudanças positivas e negativas. O conjunto desses tensores forma a estrutura XₑRT×2×W×H, em que T representa o número de passos temporais e W×H, a resolução espacial da cena.

Essa abordagem resolve dois problemas ao mesmo tempo. Primeiro, transforma o fluxo irregular de spikes em uma representação adequada ao processamento convolucional, permitindo utilizar métodos consolidados de extração de atributos. Segundo, preserva as características essenciais dos dados baseados em eventos: esparsidade, assincronia e direcionalidade. Enquanto um vídeo convencional registra continuamente tudo o que ocorre, aqui a rede recebe apenas os pulsos, os pontos de mudança que concentram a informação relevante. No contexto financeiro, o equivalente não seria cada valor de preço, mas apenas seus movimentos bruscos, valores anômalos de volume e picos de liquidez, justamente os momentos em que o mercado desperta.

A estrutura central do modelo é a SEW-ResNet, um framework residual de spikes leve e menos suscetível ao desaparecimento do gradiente. Seu componente básico é o Spike-Element-Wise Residual Block. Em essência, trata-se do bloco fundamental da rede, combinando duas ideias: processamento energeticamente eficiente de eventos e propagação estável do sinal ao longo das camadas da arquitetura. Cada bloco recebe um fluxo de spikes, acumula seu potencial nos neurônios e propaga o impulso transformado para a frente, somando-o ao sinal original segundo o princípio do aprendizado residual.

A ResNet clássica foi criada para lidar com o problema do desaparecimento do gradiente em redes convolucionais profundas. No universo dos spikes, o desafio é semelhante, mas ocorre em um cenário no qual os sinais têm natureza orientada a eventos e são regidos por limiares de ativação. A SEW-ResNet resolve esse problema de forma eficiente ao implementar a conexão residual por meio de operações elemento a elemento. Isso permite propagar as informações sem distorções, preservando a forma dos impulsos e a estabilidade do potencial.

Essa arquitetura atua como um extrator fundamental de atributos espaço-temporais. Nas primeiras camadas, captura estruturas locais, como formas, contornos e transições de luminosidade ou, na analogia com o mercado, micropadrões no fluxo de negociações e cotações. Nas camadas mais profundas, agrega essas estruturas em composições temporais e espaciais, reconhecendo configurações persistentes de atividade e padrões na distribuição dos impulsos. Em outras palavras, a SEW-ResNet transforma uma sequência bruta e caótica de eventos em uma hierarquia de atributos, na qual cada nível sucessivo depende menos de coordenadas específicas e passa a refletir cada vez mais a estrutura semântica do que está acontecendo.

Essa representação em múltiplos níveis desempenha um papel decisivo. Ela fornece a base sobre a qual podem ser construídos mecanismos de ordem superior, voltados à interação semântica e à atenção contextual. Afinal, para que o modelo consiga interpretar os eventos de forma significativa, primeiro precisa aprender a reconhecer suas formas e seus ritmos. É exatamente isso que a SEW-ResNet proporciona: uma base enxuta, porém expressiva, na qual os impulsos se transformam em padrões de atividade.

No entanto, apesar da eficiência energética e da capacidade natural das SNNs de processar dados em fluxo, a estrutura da SEW-ResNet, por si só, não resolve o principal problema: a fragmentação e a natureza discreta da semântica dos eventos. Fluxos de eventos, sejam sinais de uma câmera neuromórfica ou ticks de preços no mercado, são altamente fragmentados. Cada evento carrega informações locais, mas não estabelece, por si só, uma relação com o contexto. Como resultado, o modelo pode perceber picos isolados de atividade sem compreender seu significado ao longo do tempo e do espaço.

É justamente nesse ponto que surge a necessidade de um mecanismo capaz de conectar impulsos de spikes isolados em uma sequência dinâmica coerente. É aqui que entra o Spike-guided Spatiotemporal Attention Mechanism (SSAM), funcionando como uma espécie de ponte entre fragmentos isolados da percepção. Esse módulo incorpora um mecanismo de atenção ao modelo, estabelecendo relações associativas entre eventos no espaço e no tempo. Em essência, o SSAM transforma a SEW-ResNet de um simples interpretador rápido de eventos em um sistema capaz de contextualizá-los, identificando padrões relevantes e dependências contextuais no fluxo de dados.

A ideia parte do princípio de que o mundo real nunca é estático. Os eventos estão intrinsecamente ligados uns aos outros e formam um tecido temporal contínuo. No entanto, a maioria dos modelos, mesmo os mais sofisticados, trata os dados como quadros isolados e desprovidos de contexto. O SSAM busca justamente preencher essa lacuna, promovendo o acoplamento semântico entre diferentes momentos e transformando uma percepção discreta em uma interpretação contínua.

A principal dificuldade no processamento de dados baseados em eventos está justamente em sua fragmentação. Cada evento, seja um fóton registrado por um sensor ou um tick de preço que representa uma alteração na cotação, existe apenas por um instante e não carrega consigo o passado. Sem contexto, esse sinal tem utilidade muito limitada. É por isso que os sistemas clássicos recorrem a mecanismos de armazenamento em buffer, cálculo de médias ou agregação convolucional. No entanto, todos eles acabam, em certa medida, suavizando a realidade e reduzindo a capacidade do modelo de perceber detalhes sutis. O SSAM aborda o problema de outra forma: em vez de suavizar o fluxo, conecta os eventos por seu significado, estabelecendo relações associativas entre diferentes estados temporais.

Essas relações são construídas por meio do Spike-Guided Spatiotemporal Attention, orientado pelos próprios impulsos de spikes. Diferentemente dos modelos clássicos de atenção, nos quais cada estado pode interagir com todos os demais, o SSAM segue um princípio rigoroso de causalidade: um evento no instante atual pode se apoiar apenas em eventos que já ocorreram, sem recorrer a informações futuras. Esse princípio aproxima a arquitetura do funcionamento dos sistemas vivos, nos quais a percepção sempre ocorre com uma fração de atraso e as decisões são tomadas com base na experiência acumulada, e não no conhecimento do futuro.

Transpondo essa ideia para os mercados financeiros, o SSAM funciona como um analista que enxerga o movimento dos preços como uma sequência de impulsos inter-relacionados. Cada novo tick não é apenas um número, mas a continuação de uma história cujo contexto já foi armazenado e interpretado. O analista não conhece os preços futuros, mas consegue perceber uma direção provável porque já estabeleceu relações associativas entre os movimentos passados e o movimento atual. O mesmo ocorre no SSAM: cada estado atual resulta da integração de todos os estados anteriores, e não de uma simples reação aos dados de entrada do momento.

Tecnicamente, o mecanismo implementa esse conceito por meio da tríade Q, K e V, consultas, chaves e valores gerados por camadas SNN independentes. Esses parâmetros funcionam como uma espécie de coordenadas de atenção, por meio das quais o modelo determina quais partes do passado são mais relevantes para o instante atual. Para cada passo temporal, é construída uma matriz de atenção A específica, na qual as relações entre o instante atual t e todos os estados anteriores t't são calculadas segundo a lógica dos spikes, por meio de um produto suavizado e normalizado.

Um detalhe particularmente importante é o viés treinável de posição relativa B, que representa as dependências espaciais entre os elementos de cada quadro. Nas redes clássicas, essa informação muitas vezes se perde durante as convoluções, mas no SSAM ela é preservada e refinada, permitindo considerar não apenas as relações temporais, mas também a topologia espacial dos dados. Em séries temporais financeiras, isso pode ser interpretado como a capacidade do modelo de identificar correlações não apenas entre diferentes instantes, mas também entre diferentes regiões do mercado, como zonas de liquidez, clusters de volume e a estrutura das ordens.

Matematicamente, a atenção no SSAM é implementada com uma matriz triangular superior de pesos:

Essa construção simples, mas fundamental, transforma o fluxo de spikes em um grafo causal de dependências temporais. Cada novo evento atualiza o estado interno do modelo, incorporando a ele o contexto semântico do passado. Dessa forma, a rede passa, por assim dizer, a refletir sobre sua própria experiência, formando algo semelhante a um traço cognitivo.

Após a normalização, a representação resultante O é encaminhada para a próxima etapa de processamento, na qual é concatenada para formar a saída final Y = [O; O; …; O]. Nesse conjunto, cada elemento já carrega não apenas informações locais, mas também a marca de todo o histórico anterior, como um trader que, ao observar a última vela, consegue perceber toda a tendência precedente.

Assim, o SSAM torna-se para o S3CE-Net aquilo que a experiência representa para um analista: a capacidade de perceber relações que não são visíveis no instante presente. Ele confere fluidez semântica ao modelo, mantendo uma coerência perceptiva estável entre suas camadas. Com isso, o modelo consegue interpretar e compreender o significado das estruturas temporais.

Se o SSAM pode ser comparado a um olhar atento, capaz de distinguir significado ao longo do tempo, a Spatiotemporal Feature Sampling Strategy (STFS) se aproxima mais da capacidade de observar uma situação sob diferentes perspectivas sem perder a visão do conjunto. Esse mecanismo ensina o modelo a perceber não apenas os detalhes, mas também o contexto que se estende além da percepção local. Em essência, a STFS atua em um metanível de percepção e combate um dos principais problemas das redes neurais profundas: a tendência de se prender a padrões semânticos locais e perder a noção da estrutura global.

Esse tipo de visão em túnel não é exclusivo dos sistemas artificiais. Também pode ser observado nos mercados financeiros, quando um participante, ao se concentrar em um movimento curto dos preços, perde de vista a tendência de longo prazo. É justamente esse efeito que a STFS procura reduzir. Ela treina o modelo para interpretar os dados simultaneamente em várias escalas: local, sublocal e global, formando uma percepção robusta e multicamada da dinâmica.

Do ponto de vista técnico, a STFS baseia-se na divisão do campo de atributos espaço-temporais em subconjuntos: subsequências temporais e sub-regiões espaciais. Essa divisão não tem como objetivo simplificar os dados, mas forçar o modelo a generalizar. Como a rede encontra diferentes combinações de fragmentos a cada iteração, ela é levada a buscar significado não na configuração específica do mapa de atributos, mas nas características invariantes que permanecem presentes independentemente da forma como os dados são divididos. É assim que se desenvolve artificialmente a capacidade de percepção generalizada.

Formalmente, a estratégia opera sobre o mapa de atributos profundos Y, no qual são executados, em sequência, três procedimentos inter-relacionados:

  • seleção de subsequências no tempo,
  • seleção de sub-regiões no espaço,
  • formação de um descritor semântico global.
Essa análise em três níveis lembra o comportamento de um analista experiente que, ao observar o mercado, alterna entre três modos de raciocínio: avaliação local da dinâmica atual, análise da estrutura em diferentes janelas temporais e síntese da visão geral da tendência.

No primeiro nível, a STFS seleciona aleatoriamente uma parte dos passos temporais T ⊂ {1, 2, …, T}, formando uma espécie de recorte do fluxo completo de eventos. Para cada instante selecionado, calcula-se a média espacial do mapa de atributos, que é convertida em um vetor compacto V = Avg(Y[t,:,:,:]). O conjunto desses vetores Y = {V tT} representa a essência das subsequências temporais: em vez de preservar todo o fluxo, mantém seus principais pontos de referência semânticos.

Esse procedimento proporciona ao modelo uma experiência singular. A rede aprende a não depender da continuidade dos dados, mas a compreender sua essência mesmo a partir de fragmentos selecionados. É semelhante à capacidade de um trader experiente de identificar a direção do mercado observando apenas algumas velas características: sem conhecer todo o percurso, mas percebendo sua estrutura.

No segundo nível, a STFS divide o mapa de atributos Y em quatro regiões espaciais: superior esquerda, superior direita, inferior esquerda e inferior direita. Para cada uma delas, é calculada a média (Avg), com o objetivo de destacar as características mais estáveis da respectiva região. Essa abordagem pode ser interpretada como a formação de representações perceptivas locais, nas quais cada parte da cena (ou da estrutura de mercado) é analisada separadamente e, em seguida, integrada a um sistema de coordenadas unificado.

A seleção aleatória dos limites das sub-regiões (W, H) acrescenta um componente estocástico, algo especialmente valioso durante o treinamento. O modelo deixa de depender de posições fixas dos objetos e aprende a reconhecer significado em diferentes configurações. No contexto financeiro, isso se assemelha ao modo como um analista acompanha o comportamento de segmentos específicos do mercado sem perder de vista as relações entre eles.

No terceiro e mais importante nível, a STFS reconstrói a representação espaço-temporal Y e extrai dela um descritor global Y = Avg(Y[:,:,:,:]). Trata-se de uma forma condensada de toda a informação acumulada, uma espécie de núcleo intelectual da experiência do modelo. Ele carrega não os detalhes, mas o significado, a essência da percepção acumulada a partir de inúmeras observações individuais.

É nessa etapa que se consolida a capacidade final do modelo de formar uma interpretação semântica. Na análise financeira, isso equivale ao momento em que diversos sinais locais, ruídos e movimentos convergem para uma compreensão única do estado do mercado. O modelo deixa de perceber picos isolados de preços e passa a captar a dinâmica geral do mercado, como uma espécie de melodia dos dados em constante transformação.

Para aumentar a estabilidade do treinamento, a STFS utiliza uma função de perda combinada: triplet loss e cross-entropy loss com label smoothing, reunidas em uma única expressão final. A primeira parte ensina o modelo a distinguir estados semanticamente próximos daqueles mais distantes, em uma analogia com a percepção humana de contraste, enquanto a segunda estabiliza a confiança da classificação, evitando decisões excessivamente categóricas.

Durante os testes, utiliza-se apenas o vetor global Y, reforçando a ideia de que uma representação única e amplamente generalizada é suficiente para classificar ou comparar estados com precisão. Em termos de modelos financeiros, isso equivale a um indicador final: um valor conciso, mas informativo, que sintetiza toda a análise multidimensional dos eventos anteriores.

A STFS completa a arquitetura do S3CE-Net, transformando-a em um sistema de percepção em múltiplos níveis. Se a SEW-ResNet estabelece um fluxo estável de informações e o SSAM confere atenção e memória à rede, a STFS ensina o modelo a reconhecer o todo a partir das partes e a sintetizar significado com base em fragmentos. Essa é a forma mais avançada de percepção computacional: compreender padrões no tempo e no espaço.

Aplicada aos mercados financeiros, essa abordagem abre caminho para a criação de modelos de redes neurais capazes de prever variações de preço e identificar aspectos semânticos ocultos do comportamento do mercado: mudanças nas fases da tendência, surgimento de sinergias entre ativos e formação de novos padrões de liquidez. Nesse sentido, o S3CE-Net com o módulo STFS torna-se uma ferramenta de compreensão, um sistema capaz de identificar estrutura onde outros enxergam apenas um fluxo de dados.

A visualização do framework S3CE-Net elaborada pelo autor é apresentada abaixo.

Visualização do framework S3CE-Net elaborada pelo autor


Implementação em MQL5

Depois de analisarmos em detalhes os aspectos teóricos do framework S3CE-Net, é hora de passar à parte prática e mostrar como essas ideias podem ser implementadas em MQL5. Vale lembrar que, em trabalhos anteriores, já estudamos a arquitetura SEW-ResNet, que aqui serve como uma base sólida. Implementamos as abordagens propostas integrando-as à ResNeXt, o que nos permitiu construir uma plataforma flexível e capaz de processar de forma estável fluxos temporais complexos.

Agora podemos usar esses desenvolvimentos como base e acrescentar os módulos SSAM e STFS, para que o modelo não apenas registre os eventos, mas também aprenda a perceber as relações entre eles no tempo e no espaço. No contexto dos mercados financeiros, isso se assemelha à experiência de um trader profissional: não basta observar velas isoladas ou ticks de preço, é importante perceber seu ritmo, compreender como o passado molda o presente e como os eventos atuais afetam a dinâmica do mercado. É justamente isso que os módulos SSAM e STFS acrescentam, transformando o S3CE-Net de uma simples ferramenta de análise em um sistema capaz de perceber o contexto e compreender mais profundamente a estrutura dos dados.

Começaremos pela construção do módulo de atenção espaço-temporal SSAM. Logo de início, chama atenção a semelhança do algoritmo proposto com o Self-Attention causal. No entanto, ele é complementado por elementos da arquitetura de spikes, o que lhe confere uma dinâmica própria e a capacidade de considerar eventos discretos ao longo do tempo. Essa característica exige alterações correspondentes nos algoritmos que desenvolvemos anteriormente, para que a integração do SSAM seja feita corretamente e o modelo consiga captar de forma eficiente tanto as dependências espaciais quanto as temporais presentes nos dados.

Para formar as consultas (Q), chaves (K) e valores (V), utilizaremos os algoritmos já existentes de camadas convolucionais em conjunto com ativações de spikes. O próprio algoritmo de atenção será implementado em OpenCL, permitindo paralelizar os cálculos de forma eficiente e acelerar significativamente o processamento das relações espaço-temporais. Essa abordagem combina as vantagens das redes de spikes com a computação paralela de alto desempenho, proporcionando simultaneamente precisão e velocidade ao módulo SSAM.

A implementação do módulo SSAM é baseada no kernel OpenCL SpikeMHAttention do programa, que permite paralelizar completamente os cálculos entre todos os tokens espaço-temporais e as cabeças de atenção. Os dados de entrada consistem em um tensor QKV combinado, formado por consultas, chaves e valores, além do viés diagonal diag_bias, que garante o tratamento correto da relação de cada token consigo mesmo durante o cálculo dos pesos de atenção.

__kernel void SpikeMHAttention(__global const float *qkv,
                               __global const float *diag_bias,
                               __global float *scores,
                               __global float *out,
                               const int dimension,
                               const int mask_future
                              )
  {
//--- init
   const int q_id = get_global_id(0);
   const int k_id = get_local_id(1);
   const int h_id = get_global_id(2);
   const int total_q = get_global_size(0);
   const int total_heads = get_global_size(2);
//---
   __local float temp[LOCAL_ARRAY_SIZE];

Cada cálculo começa pela determinação dos índices global e local da cabeça de atenção e do token atuais. Em seguida, são calculados os deslocamentos necessários para acessar os componentes correspondentes de Q, K e V na representação linearizada do tensor.

//--- Shifts
   const int shift_q = RCtoFlat(h_id, 0, total_heads, dimension, 3 * q_id);
   const int shift_k = RCtoFlat(h_id, 0, total_heads, dimension, 3 * k_id + 1);
   const int shift_v = RCtoFlat(h_id, 0, total_heads, dimension, 3 * k_id + 2);
   const int shift_s = RCtoFlat(h_id, k_id, total_heads, total_q, q_id);
   const int shift_out = RCtoFlat(h_id, 0, total_heads, dimension, q_id);

A parte principal do algoritmo consiste no cálculo do produto escalar entre Q e K para formar a matriz de atenção. Nesse processo, o princípio de causalidade é respeitado: se o sinalizador mask_future estiver ativado, a consulta atual não considerará chaves futuras. Isso está totalmente de acordo com o conceito do SSAM e impede o uso de informações do futuro.

//--- Score
   float score = 0;
   if(mask_future == 0 || q_id <= k_id)
     {
      for(int d = 0; d < dimension; d++)
        {
         float q = IsNaNOrInf(qkv[shift_q + d], 0);
         if(q == 0)
            continue;
         float k = IsNaNOrInf(qkv[shift_k + d], 0);
         if(k == 0)
            continue;
         score += q * k;
        }
     }
   else
      score = MIN_VALUE;

É importante observar que trabalhamos com uma representação de spikes das chaves e consultas, na qual há grande probabilidade de obter valores nulos. Para reduzir operações desnecessárias e aumentar a eficiência, antes de executar as operações matemáticas verificamos os valores obtidos dos buffers globais. Os cálculos são realizados apenas para os componentes diferentes de zero. Essa abordagem permite otimizar significativamente a execução do kernel sem comprometer a correção dos cálculos nem a precisão da distribuição dos pesos de atenção.

Em seguida, se a consulta atual corresponder à chave (q_id == k_id, elemento da diagonal), o viés diagonal treinável armazenado em diag_bias é adicionado ao score.

   if(q_id == k_id)
      score += IsNaNOrInf(diag_bias[q_id], 0);

Depois disso, os pesos de atenção são normalizados por meio da função LocalSoftMax.

//--- norm score
   score = LocalSoftMax(score, 1, temp);
   scores[shift_s] = score;

Vale destacar que essa normalização é realizada dentro do grupo de trabalho correspondente a uma consulta Q específica. Ou seja, o SoftMax não é aplicado de uma só vez a toda a matriz de atenção, mas localmente a todas as chaves K associadas àquela consulta e à respectiva cabeça de atenção. Isso garante uma distribuição correta dos pesos de atenção para cada consulta e, ao mesmo tempo, mantém um alto grau de paralelismo nos cálculos executados em OpenCL.

Na etapa final, é formado o tensor de saída out. Cada vetor de valores V é multiplicado pelo respectivo peso de atenção e acumulado por meio da função LocalSum.

//--- out
   for(int d = 0; d < dimension; d++)
     {
      float val = 0;
      if(score > 0)
        {
         float v = IsNaNOrInf(qkv[shift_v + d], 0);
         if(v != 0)
            val = v * score;
        }
      val = LocalSum(val, 1, temp);
      if(k == 0)
         out[shift_out + d] = val;
     }
  }

Com isso, obtém-se uma representação ponderada correta para cada token, combinando informações provenientes de todas as posições temporais e espaciais relevantes.

O kernel apresentado implementa todo o mecanismo de Spatiotemporal Attention em baixo nível e com alto desempenho, aproveitando os recursos do OpenCL para paralelizar os cálculos entre tokens, cabeças de atenção e coordenadas espaço-temporais. Em termos financeiros, isso se assemelha ao trabalho de um analista experiente que avalia simultaneamente as relações entre diversos atributos temporais e locais, atribuindo a cada um deles um peso de importância de acordo com o contexto e a experiência acumulada.

Para treinar o modelo corretamente, não basta executar os cálculos da propagação para frente do mecanismo de atenção. Também é necessário distribuir os erros da propagação reversa entre todos os componentes envolvidos, levando em conta a contribuição de cada um para o resultado final. Essa funcionalidade é implementada pelo kernel SpikeMHAttentionGrad, que permite calcular de forma simultânea e consistente os gradientes de Q, K, V e do viés diagonal diag_bias.

__kernel void SpikeMHAttentionGrad(__global const float *qkv,
                                   __global float *qkv_gr,
                                   __global const float *diag_bias,
                                   __global float *diag_bias_gr,
                                   __global const float *scores,
                                   __global const float *gradients,
                                   const int dimension,
                                   const int mask_future
                                  )
  {
//--- init
   const int global_id = get_global_id(0);
   const int local_id = get_local_id(1);
   const int h_id = get_global_id(2);
   const int total_global = get_global_size(0);
   const int total_local = get_local_size(1);
   const int total_heads = get_global_size(2);
//---
   __local float temp[LOCAL_ARRAY_SIZE];

O kernel inicia sua execução determinando os índices globais e locais. Para armazenar as somas intermediárias e calcular corretamente o gradiente da função SoftMax, é criado um array local que permite a interação eficiente entre os work-items dentro de um mesmo grupo de trabalho.

Primeiro, são calculados os gradientes dos valores V, pois eles influenciam diretamente a representação de saída do módulo. Durante a propagação para frente, cada valor V contribui para todos os elementos do tensor resultante por meio do respectivo peso de atenção. Isso significa que, ao calcular o gradiente do erro para um elemento específico de V, multiplicamos o gradiente no nível do tensor de saída pelo mesmo peso de atenção, refletindo com precisão a contribuição desse valor V para o resultado final.

//--- Value Gradient global_id -> v_id, local_id -> q_id
     {
      //--- Shifts
      const int shift_v = RCtoFlat(h_id, 0, total_heads, dimension, 3 * global_id + 2);
      const int shift_s = RCtoFlat(h_id, glodal_id, total_heads, total_q, local_id);
      const int shift_out = RCtoFlat(h_id, 0, total_heads, dimension, local_id);
      for(int d = 0; d < dimension; d++)
        {
         float grad = 0;
         if(mask_future == 0 || local_id <= global_id)
           {
            float score = IsNaNOrInf(scores[shift_s], 0);
            if(score > 0)
               grad = IsNaNOrInf(score * gradients[shift_out + d], 0);
           }
         grad = LocalSum(grad, 1, temp);
         if(local_id == 0)
            qkv_gr[shift_v + d] = grad;
        }
     }

Ao mesmo tempo, levamos em conta a causalidade do algoritmo. Ela permite determinar analiticamente quais elementos da sequência resultante não foram influenciados e excluí-los imediatamente dos cálculos, evitando operações matemáticas desnecessárias e acessos custosos à memória global.

Em seguida, todos os gradientes parciais são acumulados por meio de soma local, e o valor resultante é gravado no elemento correspondente do buffer global qkv_gr. Dessa forma, cada componente de V recebe um sinal de erro correto e proporcional à sua contribuição para o resultado, garantindo um treinamento preciso e consistente do modelo.

Depois, é a vez das consultas Q. Para elas, primeiro calculamos o gradiente dos pesos de atenção como o produto dos respectivos vetores de valores V pelos gradientes da saída. Em seguida, aplicamos localmente a função de gradiente do SoftMax, ajustando a distribuição dos sinais de acordo com a normalização.

//--- Query Gradient global_id -> q_id, local_id -> k_id/v_id
     {
      //--- Shifts
      const int shift_q = RCtoFlat(h_id, 0, total_heads, dimension, 3 * global_id);
      const int shift_k = RCtoFlat(h_id, 0, total_heads, dimension, 3 * local_id + 1);
      const int shift_v = RCtoFlat(h_id, 0, total_heads, dimension, 3 * local_id + 2);
      const int shift_s = RCtoFlat(h_id, local_id, total_heads, total_q, global_id);
      const int shift_out = RCtoFlat(h_id, 0, total_heads, dimension, global_id);
      //--- 1. Score grad
      float grad_s = 0;
      if(mask_future == 0 || global_id <= local_id)
         for(int d = 0; d < dimension; d++)
           {
            float val = IsNaNOrInf(qkv[shift_v + d], 0);
            if(val == 0)
               continue;
            grad_s += IsNaNOrInf(qkv[shift_v + d] * out_gr[shift_out + d], 0);
           }
      //--- 2. SoftMax grad
      grad_s = LocalSoftMaxGrad(scores[shift_s], grad_s, 1, temp);
      if(global_id == local_id)
         diag_bias_gr[gloval_id] = grad_s;

Por fim, o gradiente de Q é formado pela combinação do gradiente de score com as chaves K, permitindo que cada componente da consulta receba um sinal de erro ponderado. Os elementos diagonais diag_bias recebem um gradiente próprio, levando em conta seu papel no reforço da influência de cada token sobre si mesmo.

      //--- 3. Query grad
      for(int d = 0; d < dimension; d++)
        {
         float grad = 0;
         if(mask_future == 0 || global_id <= local_id)
           {
            float key = IsNaNOrInf(qkv[shift_k + d], 0);
            if(key != 0)
               grad = key * grad_s;
           }
         grad = LocalSum(grad, 1, temp);
         if(local_id == 0)
            qkv_gr[shift_q + d] = grad;
        }
     }

Nesse processo, respeitamos rigorosamente a causalidade, que é um dos princípios fundamentais do SSAM: o modelo não recorre a informações futuras, pois a máscara correspondente já é aplicada durante a propagação para frente. Isso exige cuidado durante a propagação reversa, uma vez que a derivada do SoftMax pode retornar um gradiente diferente de zero mesmo para valores nulos, criando potencialmente um sinal de erro para elementos pertencentes a passos temporais futuros. Em um processamento temporal real, esses sinais não devem existir, pois violariam o princípio da causalidade. Para preservar a correção do treinamento e evitar cálculos desnecessários, verificamos os valores das chaves e consultas antes das operações matemáticas e excluímos do cálculo todos os componentes futuros.

Além disso, levamos em conta a natureza baseada em spikes dos dados analisados, nos quais uma parcela significativa pode assumir valores nulos. Por isso, primeiro verificamos os dados recebidos e executamos as operações matemáticas apenas para os elementos diferentes de zero. Isso permite não apenas reduzir a carga computacional, mas também distribuir os gradientes com precisão apenas entre os spikes efetivamente presentes.

Na etapa seguinte, são calculados os gradientes das chaves K. Para cada chave, acumula-se a contribuição de todas as consultas Q, levando em conta sua interação com os respectivos valores V por meio dos pesos de atenção.

//--- Key Gradient global_id -> k_id, local_id -> score_id/v_id/dimension
     {
      //--- Shifts
      const int shift_k = RCtoFlat(h_id, 0, total_heads, dimension, 3 * global_id + 1);
      const int shift_v = RCtoFlat(h_id, 0, total_heads, dimension, 3 * local_id + 2);
      const int shift_out = RCtoFlat(h_id, 0, total_heads, dimension, local_id);
      float grad = 0;
      for(int q_id = 0; q_id < total_q; q_id++)
        {
         //--- 1. Score grad local_id -> score_id/v_id
         float grad_s = 0;
         const int shift_s = RCtoFlat(h_id, local_id, total_heads, total_q, q_id);
         int shift_q = RCtoFlat(h_id, 0, total_heads, dimension, 3 * q_id);
         if(mask_future == 0 || q_id <= local_id)
            for(int d = 0; d < dimension; d++)
              {
               float val = IsNaNOrInf(qkv[shift_v + d], 0);
               if(val == 0)
                  continue;
               grad_s += IsNaNOrInf(val * out_gr[shift_q + d], 0);
              }
         //--- 2. SoftMax grad
         grad_s = LocalSoftMaxGrad(scores[shift_s], grad_s, 1, temp);
         BarrierLoc;
         if(global_id == local_id)
            temp[0] = grad_s;
         BarrierLoc;
         grad_s = temp[0];
         //--- 3. Key grad local_id -> dimension
         if(local_id < dimension)
           {
            float query = IsNaNOrInf(qkv[shift_q + local_id], 0);
            if(query != 0)
               grad += IsNaNOrInf(query * grad_s, 0);
           }
        }
      if(local_id < dimension)
         qkv_gr[shift_k + local_id] = IsNaNOrInf(grad, 0);
     }
  }

A máscara causal garante que os tokens futuros não influenciem o cálculo atual, enquanto os gradientes são acumulados e gravados em qkv_gr. Essa abordagem permite distribuir corretamente os erros e atualizar simultaneamente todos os parâmetros do SSAM, preservando a consistência e a precisão do treinamento.

Como resultado, o kernel SpikeMHAttentionGrad implementa por completo o mecanismo de propagação reversa do erro para o SSAM, garantindo a atualização consistente de Q, K, V e dos vieses diagonais. No contexto dos mercados financeiros, isso pode ser comparado a um processo em que cada erro de previsão é cuidadosamente distribuído entre todos os fatores que contribuíram para o resultado, permitindo que o sistema aprenda gradualmente a avaliar corretamente as relações entre os eventos e a prever a dinâmica do mercado com alta precisão.

Hoje avançamos bastante, e chegou o momento de fazer uma breve pausa. Vamos deixar as ideias amadurecerem para que as informações apresentadas possam ser assimiladas e reavaliadas. No próximo artigo, continuaremos a implementação das abordagens do framework S3CE-Net em MQL5, avançando passo a passo rumo à integração completa de todos os módulos e à sua validação na prática.


Conclusão

Neste artigo, conhecemos o framework S3CE-Net e seus principais mecanismos: o SSAM espaço-temporal e a estratégia de amostragem STFS. O modelo trabalha com eventos de spikes e respeita rigorosamente a causalidade, o que permite identificar com precisão padrões relevantes e considerar corretamente a dinâmica das séries temporais sem recorrer a informações futuras.

O S3CE-Net combina uma arquitetura leve, alto grau de paralelização e capacidade de identificar relações temporais e espaciais complexas. Para os mercados financeiros, isso significa reagir rapidamente aos sinais e tomar decisões com precisão em meio a um enorme fluxo de dados ruidosos.

A implementação em MQL5 abrirá caminho para testar o modelo em cenários reais de trading. O S3CE-Net mostra como métodos modernos de processamento de eventos esparsos podem se transformar em uma ferramenta poderosa para análise e previsão de mercado. Estamos apenas começando a explorar o potencial do framework e, no próximo artigo, continuaremos sua implementação prática.


Referências


Programas usados no artigo

# Nome Tipo Descrição
1 Study.mq5 Expert Advisor EA de treinamento offline de modelos
2 StudyOnline.mq5 Expert Advisor EA de treinamento online de modelos
3 Test.mq5 Expert Advisor EA para teste do modelo
4 Trajectory.mqh Biblioteca de classes Estrutura de descrição do estado do sistema e da arquitetura dos modelos
5 NeuroNet.mqh Biblioteca de classes Biblioteca de classes para criação de rede neural
6 NeuroNet.cl Biblioteca Biblioteca de código do programa OpenCL

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/19928

Arquivos anexados |
MQL5.zip (3190.82 KB)
Caminhe em novos trilhos: Personalize indicadores no MQL5 Caminhe em novos trilhos: Personalize indicadores no MQL5
Vou agora listar todas as possibilidades novas e recursos do novo terminal e linguagem. Elas são várias, e algumas novidades valem a discussão em um artigo separado. Além disso, não há códigos aqui escritos com programação orientada ao objeto, é um tópico muito importante para ser simplesmente mencionado em um contexto como vantagens adicionais para os desenvolvedores. Neste artigo vamos considerar os indicadores, sua estrutura, desenho, tipos e seus detalhes de programação em comparação com o MQL4. Espero que este artigo seja útil tanto para desenvolvedores iniciantes quanto para experientes, talvez alguns deles encontrem algo novo.
Desenvolvemos um gerenciador de terminais (Parte 2): Execução de várias instâncias Desenvolvemos um gerenciador de terminais (Parte 2): Execução de várias instâncias
Passamos a usar várias instâncias do terminal no servidor, criando um painel de controle simples para iniciá-las e encerrá-las. Agora chegou a hora de ampliar a funcionalidade e avançar para as próximas etapas, implementando recursos mais complexos, como o gerenciamento de várias instâncias, o armazenamento de estado, a integração com a API do MetaTrader 5 e uma interface web com informações completas sobre os terminais.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Redes neurais em trading: Treinamento de modelos spiking profundos (Conclusão) Redes neurais em trading: Treinamento de modelos spiking profundos (Conclusão)
Neste artigo, apresentamos uma implementação prática do framework SEW ResNet em MQL5, com ênfase em sua aplicação ao trading. O Bottleneck duplo permite analisar simultaneamente fluxos unitários e dependências entre canais, sem perda de gradientes durante o treinamento. Ativações spiking com limiares adaptativos e gates aumentam a robustez ao ruído e a sensibilidade a novas configurações do mercado. O texto apresenta detalhes da implementação e os resultados dos testes.