English Русский
preview
Mapas auto-organizáveis de Kohonen em um EA MQL5

Mapas auto-organizáveis de Kohonen em um EA MQL5

MetaTrader 5Experts |
44 1
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Introdução: em busca da ordem invisível

Imagine que você esteja olhando para o gráfico de um par de moedas. Milhares de velas, milhões de pontos de dados, um fluxo interminável de números. Em algum lugar desse caos existem padrões, regularidades e estruturas recorrentes. Mas o cérebro humano não consegue manter milhares de velas em mente ao mesmo tempo e identificar as relações entre elas. Precisamos de um mapa para esse caos. Precisamos de uma estrutura que mostre onde situações de mercado semelhantes se agrupam e onde começa algo fundamentalmente novo.

Foi exatamente para isso que, em 1982, o cientista finlandês Teuvo Kohonen criou os mapas auto-organizáveis, conhecidos como Self-Organizing Maps ou SOM. Não se trata apenas de mais uma rede neural. É uma forma de fazer o computador enxergar a estrutura invisível dos dados, encontrar ordem no caos e criar um mapa bidimensional de um espaço multidimensional. E o mais interessante é que essa tecnologia, criada há mais de quarenta anos para análise da fala, mostrou-se perfeitamente adequada à análise dos mercados financeiros.


O que são mapas auto-organizáveis: a geografia do caos do mercado

Vamos começar com uma analogia simples. Imagine que você seja um geógrafo encarregado de criar o mapa de uma região desconhecida. Você dispõe das coordenadas de milhares de pontos, além de medições de altitude, temperatura, umidade e muitos outros parâmetros para cada um deles. Como transformar esse conjunto de números em um mapa bidimensional compreensível, no qual lugares semelhantes fiquem próximos e lugares diferentes, distantes uns dos outros?

O mapa auto-organizável de Kohonen faz exatamente isso, mas com dados de mercado. Temos um espaço multidimensional de atributos, formado por preços, volumes, volatilidade, variações em diferentes períodos e indicadores técnicos. Cada vela do gráfico corresponde a um ponto nesse espaço multidimensional. A SOM pega todos esses pontos e os projeta sobre uma grade bidimensional de neurônios, preservando a topologia: situações de mercado semelhantes acabam associadas a neurônios vizinhos no mapa.

A mágica acontece durante o treinamento. A rede é formada por uma grade bidimensional de neurônios, por exemplo, vinte por vinte, totalizando quatrocentos neurônios. Cada neurônio possui um vetor de pesos com a mesma dimensionalidade dos dados de entrada. Quando apresentamos à rede um novo padrão de mercado, ela encontra o neurônio cujos pesos mais se aproximam desse padrão. Esse neurônio é chamado de Best Matching Unit, ou BMU. Em seguida acontece a parte mais interessante: não apenas a BMU atualiza seus pesos para se tornar ainda mais semelhante ao padrão de entrada, como os pesos dos neurônios vizinhos no mapa também são ajustados na mesma direção. Quanto maior a distância em relação à BMU, menor é a influência.

Depois do treinamento com milhares de situações de mercado, o mapa se auto-organiza. Os neurônios em um dos cantos do mapa podem passar a representar fortes tendências de alta; em outro, fortes movimentos de baixa; e, na região central, mercados laterais e períodos de incerteza. O mapa cria uma espécie de geografia dos estados de mercado, na qual a distância entre os neurônios reflete o grau de diferença entre os padrões.


Por que as SOM são ideais para trading: as vantagens da topologia

As redes neurais tradicionais usadas para classificação, como o perceptron multicamadas ou as redes convolucionais, funcionam como uma "caixa-preta". Você alimenta a rede com dados, ela produz uma previsão, mas o que acontece internamente permanece difícil de interpretar. Com as SOM é diferente. Elas oferecem visualização, compreensão e estrutura. Você pode observar o mapa e identificar em que região do espaço de padrões se encontra a situação atual do mercado. Também pode acompanhar como o mercado se desloca pelo mapa à medida que passa de um estado para outro.

Mais importante ainda, as SOM preservam a topologia. Se dois padrões de mercado forem semelhantes, eles serão associados a neurônios vizinhos. Isso significa que a rede não apenas classifica: ela também agrupa padrões em clusters e identifica fronteiras naturais entre diferentes tipos de comportamento do mercado. Trata-se de unsupervised learning, ou aprendizado não supervisionado. Não é necessário rotular previamente os dados em classes como "tendência de alta", "tendência de baixa" ou "mercado lateral". A própria rede encontra essas classes e determina as fronteiras entre elas.

As SOM também são robustas ao ruído. Os dados de mercado são ruidosos por natureza, com valores atípicos aleatórios, gaps, manipulações e picos provocados por notícias. Redes neurais convencionais podem se sobreajustar a esse ruído. Já as SOM, graças à atualização da vizinhança dos neurônios, atenuam o ruído por meio do efeito de média e destacam padrões mais estáveis.


Arquitetura da SOM em MQL5: criação do mapa neural

Vamos ver como o mapa auto-organizável é implementado no código do EA. Comecemos pelos parâmetros básicos:

#define SOM_WIDTH 20
#define SOM_HEIGHT 20
#define SOM_NEURONS (SOM_WIDTH * SOM_HEIGHT)

struct QuantumProcessor {
    matrix som_weights;           // SOM weights [SOM_NEURONS x input_dim]
    double learning_rate_som;
    double neighborhood_radius;
    
    void Init() {
        learning_rate_som = 0.1;
        neighborhood_radius = 5.0;
        som_weights = matrix::Zeros(SOM_NEURONS, FEATURES_COUNT);
        InitializeRandomMatrix(som_weights, -0.5, 0.5);
    }

Um mapa com vinte por vinte neurônios corresponde a quatrocentos pontos no espaço de classificação. Cada neurônio possui um vetor de pesos com dimensão FEATURES_COUNT, ou seja, quatrocentos atributos extraídos dos dados de mercado. A inicialização dos pesos com valores aleatórios entre menos 0,5 e mais 0,5 cria a diversidade inicial do mapa.

Os principais parâmetros de treinamento são a taxa de aprendizado de 0,1 e o raio de vizinhança de 5,0. O raio de vizinhança determina até que distância da Best Matching Unit se estende a influência durante a atualização dos pesos. Um raio maior no início do treinamento permite que o mapa estabeleça sua estrutura global. À medida que o treinamento avança, esse raio pode ser reduzido para realizar um ajuste mais fino.


Busca da Best Matching Unit: o núcleo do algoritmo

A operação mais importante em uma SOM é encontrar o neurônio mais semelhante ao padrão de entrada:

int FindBestMatchingUnit(const vector &_input) {
    int bmu = 0;
    double min_distance = DBL_MAX;
    
    for(int i = 0; i < SOM_NEURONS; i++) {
        vector neuron_weights = som_weights.Row(i);
        double distance = 0.0;
        
        for(ulong j = 0; j < MathMin(_input.Size(), neuron_weights.Size()); j++) {
            double diff = _input[j] - neuron_weights[j];
            distance += diff * diff;
        }
        
        if(distance < min_distance) {
            min_distance = distance;
            bmu = i;
        }
    }
    return bmu;
}

O algoritmo é simples e elegante. Percorremos todos os quatrocentos neurônios do mapa e, para cada um deles, calculamos a distância euclidiana entre os pesos do neurônio e o vetor de entrada. Usar a distância ao quadrado é mais rápido do que calcular a raiz quadrada e já basta para comparar os neurônios. O neurônio com a menor distância é escolhido como vencedor, ou seja, como BMU.

Essa operação tem complexidade linear em relação ao número de neurônios. Em um mapa de vinte por vinte com quatrocentos atributos, uma única busca pela BMU exige cento e sessenta mil operações de multiplicação e adição. Em processadores modernos, isso é executado em microssegundos. Um ponto importante é que essa operação é determinística: para uma mesma entrada, a mesma BMU será encontrada sempre que os pesos permanecerem inalterados.


Atualização dos pesos: a dança dos neurônios

Depois de encontrar a BMU, começa a parte mais interessante: a atualização dos pesos na vizinhança.

void UpdateSOMWeights(const vector &_input, int bmu) {
    int bmu_x = bmu % SOM_WIDTH;
    int bmu_y = bmu / SOM_WIDTH;
    
    for(int i = 0; i < SOM_NEURONS; i++) {
        int neuron_x = i % SOM_WIDTH;
        int neuron_y = i / SOM_WIDTH;
        
        double distance = MathSqrt((neuron_x - bmu_x) * (neuron_x - bmu_x) + 
                                 (neuron_y - bmu_y) * (neuron_y - bmu_y));
        
        if(distance <= neighborhood_radius) {
            double influence = MathExp(-(distance * distance) / 
                              (2.0 * neighborhood_radius * neighborhood_radius));
            
            for(ulong j = 0; j < MathMin(_input.Size(), som_weights.Cols()); j++) {
                som_weights[i][j] += learning_rate_som * influence * 
                                   (_input[j] - som_weights[i][j]);
            }
        }
    }
}

O código implementa a função clássica de vizinhança com kernel gaussiano. Primeiro, calculamos as coordenadas da BMU no mapa bidimensional: o resto da divisão do índice pela largura fornece a coordenada x, enquanto a divisão inteira pela largura fornece a coordenada y. Em seguida, para cada neurônio, calculamos a distância euclidiana até a BMU nas coordenadas do mapa, e não no espaço de atributos.

Se a distância for menor que o raio de vizinhança, o neurônio é afetado pela atualização. A intensidade dessa influência é determinada por uma função gaussiana, dada pela exponencial do negativo do quadrado da distância. No centro, isto é, na própria BMU, a influência é máxima e igual a um. Próximo ao limite do raio, ela cai quase a zero. Essa função suave produz uma topologia com transições graduais: os neurônios são atualizados proporcionalmente à sua proximidade em relação ao vencedor.

A regra final de aprendizado é a clássica regra delta. O novo peso é igual ao peso anterior mais a taxa de aprendizado multiplicada pela influência e pela diferença entre o valor de entrada e o peso atual. Essa regra desloca o vetor de pesos do neurônio em direção ao vetor de entrada. Quanto mais próximo o neurônio estiver da BMU, maior será esse deslocamento. Quanto mais distante, menor será.


Integração da SOM ao sistema de trading: efeitos quânticos

Uma particularidade desta implementação no EA é a integração da SOM a um "processador quântico", que acrescenta efeitos adicionais sobre a SOM básica.

matrix ApplyQuantumEffects(const matrix &input_data, const matrix &context_data) {
    matrix result = matrix::Zeros(input_data.Rows(), input_data.Cols());
    
    for(ulong i = 0; i < input_data.Rows(); i++) {
        vector input_row = input_data.Row(i);
        
        // Find the BMU for the current input
        int bmu = FindBestMatchingUnit(input_row);
        
        // Update the SOM weights
        UpdateSOMWeights(input_row, bmu);
        
        // Get the activation from the BMU
        vector bmu_weights = som_weights.Row(bmu);
        
        // Apply classical effects + SOM activation
        for(ulong j = 0; j < input_data.Cols(); j++) {
            double input_val = input_data[i][j];
            double context_val = (i < context_data.Rows() && j < context_data.Cols()) ? 
                                context_data[i][j] : 0.0;
            
            // SOM effect
            double som_factor = 1.0;
            if(j < bmu_weights.Size()) {
                som_factor += (bmu_weights[j] - input_val) * coherence * 0.1;
            }
            
            // Classical effects
            double resonance = 1.0 + resonance_strength * 
                             MathCos(input_val * context_val * M_PI);
            double interference = interference_amplitude * 
                                MathSin(input_val * context_val * 2.0 * M_PI);
            double coherent_factor = coherence + (1.0 - coherence) * 
                                   MathExp(-decoherence_rate * i);
            
            result[i][j] = input_val * resonance * coherent_factor * 
                         som_factor + interference;
        }
    }
    
    return result;
}

A expressão "efeitos quânticos" é, evidentemente, uma metáfora. Não há nenhum tipo de computação quântica real envolvido. A ideia, porém, é interessante: transformações adicionais são aplicadas à saída da SOM para simular ressonância, interferência e coerência. A SOM encontra padrões semelhantes e os agrupa, enquanto esses efeitos adicionais introduzem não linearidade e dependência do contexto.

O efeito da SOM calcula a diferença entre os pesos da BMU e os dados de entrada, multiplica essa diferença pelo parâmetro de coerência e o acrescenta ao coeficiente de base. Isso cria uma realimentação: se o padrão atual estiver distante do centro do cluster, representado pelos pesos da BMU, a saída será amplificada ou atenuada. A ressonância é modelada pelo cosseno do produto entre a entrada e o contexto. A interferência é acrescentada como um componente senoidal. Já o fator de coerência decai exponencialmente com o índice, simulando a perda de memória.


Treinamento com dados históricos: das barras aos padrões

O treinamento do EA começa durante sua inicialização.

void TrainSOMNetwork() {
    matrix training_data = matrix::Zeros(TrainingBars, FEATURES_COUNT);
    vector targets = vector::Zeros(TrainingBars);
    
    MqlRates rates[];
    ArraySetAsSeries(rates, true);
    
    if(CopyRates(Symbol(), Period(), 0, TrainingBars + 50, rates) < TrainingBars + 50) {
        Print("Failed to copy rates for training");
        return;
    }
    
    for(int i = 0; i < TrainingBars; i++) {
        vector features = vector::Zeros(FEATURES_COUNT);
        
        // Basic Features
        double price_change = (rates[i].close - rates[i].open) / rates[i].open;
        double volatility = 0.0;
        for(int j = i; j < i + 10 && j < ArraySize(rates); j++) {
            double change = (rates[j].close - rates[j].open) / rates[j].open;
            volatility += change * change;
        }
        volatility = MathSqrt(volatility / 10.0);
        
        double volume_ratio = (rates[i].tick_volume > 0) ? 
            MathLog(1.0 + rates[i].tick_volume / 1000.0) : 0.0;
        
        features[0] = MathMax(-1.0, MathMin(1.0, price_change * 100));
        features[1] = MathMax(0.0, MathMin(1.0, volatility * 100));
        features[2] = MathMax(0.0, MathMin(1.0, volume_ratio / 10.0));

Os três primeiros atributos são básicos. O primeiro é a variação do preço da barra atual, normalizada para o intervalo de menos um a mais um. O segundo é a volatilidade das últimas dez barras, calculada a partir do desvio-padrão das variações e normalizada entre zero e um. O terceiro é o volume em escala logarítmica, também normalizado.

Em seguida, são acrescentados atributos adicionais: variações de preço e amplitudes das vinte barras anteriores, formando uma janela temporal para analisar o histórico de curto prazo. No total, cada barra é representada por quatrocentos atributos. Trata-se de uma representação multidimensional do estado do mercado que a SOM aprenderá a agrupar em clusters.


Criação dos valores-alvo: previsão do futuro

Um ponto fundamental do treinamento é definir a variável-alvo. O que queremos prever?

// NEW TARGET: price change after N bars (default: 24)
if(i + TargetBarsLookahead < ArraySize(rates)) {
    double current_price = rates[i].close;
    double future_price = rates[i + TargetBarsLookahead].close;
    double price_change_percent = (current_price - future_price) / future_price * 100.0;
    
    // Define the target based on configurable thresholds
    if(price_change_percent > BullishThreshold) {        // Rise Exceeds the Threshold
        targets[i] = 0.8;
    }
    else if(price_change_percent < BearishThreshold) {   // Decline Exceeds the Threshold
        targets[i] = 0.2;
    }
    else {                                               // Sideways Market
        targets[i] = 0.5;
    }
}

O sistema analisa um número configurável de barras à frente, vinte e quatro por padrão, e calcula a variação percentual do preço. Se a alta superar o limiar definido, 0,5% por padrão, o valor-alvo será definido como 0,8, indicando um forte sinal de alta. Se a queda ultrapassar o limiar correspondente, menos 0,5% por padrão, o valor-alvo será 0,2, indicando um forte sinal de baixa. Todos os demais casos são classificados como mercado lateral, com valor-alvo de 0,5.

Essa classificação em três categorias estabelece objetivos de aprendizado bem definidos. A SOM agrupa, em uma região do mapa, as situações de mercado que antecedem movimentos de alta; em outra, as situações que precedem quedas; e, em uma terceira, os períodos de incerteza. Depois de ser treinado com milhares de exemplos, o mapa se torna uma ferramenta preditiva.


Processo de previsão: dos atributos ao sinal

Quando o EA recebe um novo tick, ele extrai os atributos e gera uma previsão:

double GetSOMPrediction(double &confidence) {
    vector feature_data = vector::Zeros(FEATURES_COUNT);
    
    MqlRates rates[];
    ArraySetAsSeries(rates, true);
    
    if(CopyRates(Symbol(), Period(), 0, 50, rates) < 50) {
        Print("Failed to copy rates");
        return -1;
    }
    
    // Populate the features
    double price_change = (rates[0].close - rates[1].close) / rates[1].close;
    double volatility = 0.0;
    for(int i = 0; i < 10; i++) {
        double change = (rates[i].close - rates[i].open) / rates[i].open;
        volatility += change * change;
    }
    volatility = MathSqrt(volatility / 10.0);
    
    double volume_ratio = (rates[0].tick_volume > 0) ? 
        MathLog(1.0 + rates[0].tick_volume / 1000.0) : 0.0;
    
    feature_data[0] = MathMax(-1.0, MathMin(1.0, price_change * 100));
    feature_data[1] = MathMax(0.0, MathMin(1.0, volatility * 100));
    feature_data[2] = MathMax(0.0, MathMin(1.0, volume_ratio / 10.0));
    
    return g_som_net.Predict(feature_data, confidence);
}

A extração dos atributos é idêntica à utilizada durante o treinamento: variação do preço, volatilidade, volume e valores históricos adicionais. O vetor de atributos é passado ao método Predict da rede neural, que percorre toda a arquitetura: a SOM encontra a BMU, os efeitos quânticos são aplicados, os dados passam pelos blocos Transformer e, ao final, é gerada uma previsão entre zero e um.

Um valor próximo de 0,8 indica que a situação atual do mercado se assemelha aos exemplos da amostra de treinamento que antecederam movimentos de alta. Um valor próximo de 0,2 sinaliza uma provável queda. Já um valor em torno de 0,5 indica incerteza: o mercado está lateralizado ou próximo de uma possível mudança de direção.


Processamento dos sinais e abertura de posições

A lógica das decisões de trading se baseia na previsão e no nível de confiança do modelo:

void ProcessSignals(double prediction, double confidence) {
    if(TimeCurrent() - g_last_signal_time < PeriodSeconds(Period())) return;
    
    int positions = CountPositions();
    
    if(confidence >= MinConfidence && prediction >= 0.6 && positions == 0) {
        if(OpenPosition(ORDER_TYPE_BUY)) {
            g_last_signal_time = TimeCurrent();
            Print("SOM BUY: Prediction=", DoubleToString(prediction*100,1), 
                  "%, Confidence=", DoubleToString(confidence*100,1), "%");
        }
    }
    else if(confidence >= MinConfidence && prediction <= 0.4 && positions == 0) {
        if(OpenPosition(ORDER_TYPE_SELL)) {
            g_last_signal_time = TimeCurrent();
            Print("SOM SELL: Prediction=", DoubleToString(prediction*100,1), 
                  "%, Confidence=", DoubleToString(confidence*100,1), "%");
        }
    }
}

O EA abre uma posição somente quando três condições são atendidas: a confiança do modelo está acima do limiar mínimo, 65% por padrão; a previsão é suficientemente forte, acima de 0,6 para compra ou abaixo de 0,4 para venda; e não há posições abertas. Essa lógica mais conservadora reduz a quantidade de entradas falsas.

O nível de confiança é calculado por um metamodelo que estima a confiabilidade da previsão atual com base na precisão histórica do modelo e nas características do padrão observado. Uma confiança baixa pode indicar que o padrão atual não se parece com nada presente na amostra de treinamento. Nesse caso, o modelo está diante de uma região desconhecida e é preferível não operar.


Treinamento contínuo: adaptação ao mercado

Os mercados mudam. Padrões que funcionavam há um ano podem deixar de ser relevantes. Por isso, o EA oferece treinamento contínuo:

input bool     ContinuousLearning = true; // Retrain periodically
input int      RetrainHours = 12;         // Retrain every N hours

void OnTick() {
    if(!g_net_initialized) return;
    if(!IsNewBar()) return;
    
    if(ContinuousLearning && ShouldRetrain()) {
        Print("Retraining SOM...");
        TrainSOMNetwork();
        g_last_retrain_time = TimeCurrent();
        Print("SOM retrained!");
    }

A cada doze horas, por padrão, em um intervalo que pode ser configurado, o EA atualiza o modelo com dados históricos recentes. O mapa SOM é reajustado para se adaptar às novas condições de mercado. Os padrões anteriores não são esquecidos por completo: os pesos dos neurônios são modificados gradualmente, preservando a estrutura já aprendida ao mesmo tempo que incorporam novas informações.

Esse mecanismo é fundamental para a estabilidade do sistema de trading no longo prazo. Um modelo estático, treinado uma única vez, inevitavelmente acaba perdendo desempenho. Já um modelo adaptativo, que continua aprendendo com dados recentes, permanece relevante.


Visualização do mapa SOM: enxergar o invisível

Uma das principais vantagens das SOM é a possibilidade de visualização. Depois do treinamento, é possível construir uma U-matrix (unified distance matrix), que mostra as distâncias entre neurônios vizinhos. As regiões escuras da U-matrix representam as fronteiras entre clusters, enquanto as regiões claras correspondem a áreas homogêneas com padrões semelhantes.

Também é possível colorir o mapa de acordo com os valores-alvo médios associados a cada neurônio. Neurônios vermelhos representam a região dos padrões de baixa, os verdes correspondem aos padrões de alta e os cinza, ao mercado lateral. Dessa forma, o mapa se torna uma ferramenta útil para o trader: basta observar a qual neurônio a situação atual foi associada para obter uma indicação imediata da direção mais provável do movimento. 

Na implementação do EA, a visualização é feita por meio da exportação de um mapa HTML interativo, um heatmap da SOM com tooltips ao passar o cursor e dimensionamento adaptativo. Trata-se de uma página web autônoma, gerada diretamente em MQL5, sem bibliotecas externas. Depois do treinamento, ou ao pressionar a tecla de atalho "H" no gráfico, o método ExportSOMHTML calcula a norma L2 dos pesos de cada neurônio, usada como medida da "força" ou da densidade estrutural do cluster, normaliza os valores para o intervalo [0..1] e grava o arquivo HTML no diretório comum do terminal (Common\Files\SOM_map.html).

O código de exportação é simples e eficiente:

bool ExportSOMHTML(const string filename = "SOM_map.html") {
    // Initialization Check
    if(input_quantum_proc.som_weights.Rows() != SOM_NEURONS) {
        Print("ExportSOMHTML: som_weights not initialized");
        return false;
    }
    
    // Calculation of L2 Norms for a Heat Map
    vector vals = vector::Zeros(SOM_NEURONS);
    double vmin = DBL_MAX, vmax = -DBL_MAX;
    for(int i = 0; i < SOM_NEURONS; i++) {
        double s = 0.0;
        for(ulong j = 0; j < input_quantum_proc.som_weights.Cols(); j++) {
            double w = input_quantum_proc.som_weights[i][j];
            s += w * w;
        }
        s = MathSqrt(s);
        vals[i] = s;
        if(s < vmin) vmin = s;
        if(s > vmax) vmax = s;
    }
    
    // Normalization and Saving the HTML
    double range = (vmax > vmin) ? (vmax - vmin) : 1.0;
    int h = FileOpen(filename, FILE_WRITE | FILE_TXT | FILE_COMMON, CP_UTF8);
    if(h == INVALID_HANDLE) {
        Print("ExportSOMHTML: cannot open file: ", filename);
        return false;
    }
    
    // Generating HTML with Canvas and JavaScript for Rendering
    // ... (complete HTML code with an HSL color palette ranging from blue to red, hover support, and resizing)
    
    FileClose(h);
    Print("SOM map exported to Common\\Files\\", filename);
    return true;
}

O arquivo pode ser aberto com um duplo clique no terminal MT5 ou em qualquer navegador. O mapa de 20×20 células usa uma escala que vai do azul "frio", correspondente a uma norma de pesos baixa e a clusters fracos ou vazios, até o vermelho "quente", associado a uma norma alta e a padrões densos e ativos. Ao passar o cursor sobre uma célula, são exibidas suas coordenadas (x, y) e a intensidade normalizada (0.0000–1.0000). O dimensionamento é adaptativo: em telas grandes, as células são maiores; em dispositivos móveis, ficam mais compactas.

Essa visualização é essencial para interpretar o modelo. Por exemplo, se a BMU atual estiver em uma região vermelha "quente", com norma elevada, isso indica um cluster forte de padrões, seja de alta ou de baixa. Se cair em uma região azul, o mercado estará em uma zona rara e incerta, na qual é preferível não operar.  



Comparação com outros métodos: onde as SOM se destacam

A análise técnica clássica trabalha com indicadores predefinidos, como RSI, MACD e Bandas de Bollinger. Esses indicadores foram criados por pessoas com base em hipóteses sobre o comportamento do mercado. A SOM não parte de nenhuma hipótese desse tipo. Ela aprende diretamente com os dados e encontra padrões que realmente funcionam, e não apenas aqueles que imaginamos que funcionem.

Redes neurais feedforward simples exigem dados rotulados: para cada exemplo, é necessário indicar a resposta correta. A SOM utiliza unsupervised learning, ou aprendizado não supervisionado. Ela também pode operar em modo supervisionado, como acontece em nosso EA, mas sua principal vantagem é a capacidade de identificar por conta própria a estrutura existente nos dados.

Redes neurais profundas, como LSTM, GRU e Transformers, exigem grandes volumes de dados e recursos computacionais consideráveis. A SOM é compacta, rápida e pode ser treinada mesmo com amostras relativamente pequenas. Um mapa com quatrocentos neurônios pode ser treinado em poucos minutos em um computador comum, enquanto cada previsão é gerada em milissegundos.

Random Forest e gradient boosting funcionam muito bem com dados tabulares, mas têm dificuldade para preservar a topologia. Eles constroem árvores de decisão que dividem o espaço de atributos em regiões retangulares. A SOM, por sua vez, cria um mapa com transições suaves, no qual padrões semelhantes ficam próximos uns dos outros, no qual padrões semelhantes ficam próximos uns dos outros. Essa propriedade é especialmente importante para dados financeiros, pois pequenas variações nos atributos não devem provocar mudanças bruscas nas previsões.


Limitações e problemas: teoria versus realidade

Como qualquer tecnologia, a SOM não é uma solução universal. O primeiro problema é o tamanho do mapa. Um mapa pequeno demais, por exemplo, com dez por dez neurônios, não consegue representar toda a complexidade dos padrões de mercado. Já um mapa excessivamente grande, como cem por cem, fica mais sujeito a sobreajuste e exige mais tempo de treinamento. O tamanho ideal precisa ser determinado experimentalmente.

O segundo problema é o número de épocas de treinamento. Com poucas épocas, o mapa pode não ter tempo suficiente para se organizar; com épocas demais, pode ocorrer sobreajuste. Em nosso EA, são utilizadas apenas três épocas em cada ciclo de treinamento contínuo, como um compromisso entre capacidade de adaptação e estabilidade.

O terceiro problema é a normalização dos atributos. A SOM é sensível à escala dos dados. Se um atributo variar de zero a cem e outro de zero a um, o primeiro terá uma influência muito maior no cálculo das distâncias. Por isso, todos os atributos precisam ser cuidadosamente normalizados para uma mesma faixa de valores.

O quarto problema é a dependência temporal. A SOM clássica não leva em consideração a ordem temporal dos dados: cada padrão é processado de forma independente. Para séries temporais financeiras, essa é uma limitação importante. Nosso EA atenua parcialmente esse problema ao acrescentar lags históricos ao conjunto de atributos e integrar a SOM a blocos Transformer capazes de processar sequências.


Próximos caminhos: como avançar

Os mapas auto-organizáveis são apenas o começo. Existem diversas extensões do algoritmo clássico de Kohonen que podem ser incorporadas ao EA. Um exemplo é o Growing Neural Gas, algoritmo que adiciona e remove neurônios dinamicamente durante o treinamento, ajustando automaticamente o tamanho do mapa à complexidade dos dados.

As Temporal Kohonen Maps acrescentam conexões temporais entre os neurônios, permitindo que o mapa represente não apenas padrões isolados, mas também sequências de padrões. Isso é fundamental para prever tendências de mercado, pois não importa apenas a situação atual, mas também a trajetória percorrida pelo mercado até chegar a ela.

As Hierarchical SOM utilizam vários níveis de mapas, nos quais o nível superior agrupa os neurônios do nível inferior em metaclusters. Dessa forma, é possível representar a estrutura do mercado em diferentes escalas temporais, desde oscilações de poucos minutos até tendências que se estendem por semanas.

A integração das SOM com outras técnicas de deep learning abre ainda mais possibilidades. É possível usar uma SOM como primeira camada de feature extraction antes de uma rede LSTM. Também é possível treinar ensembles de mapas SOM em diferentes timeframes e combinar suas previsões. Outra possibilidade é aplicar reinforcement learning sobre a SOM, fazendo com que um agente aprenda estratégias de trading a partir dos estados de mercado classificados pelo mapa.


Recomendações práticas: como usar o EA

Se você decidir testar ou utilizar o EA baseado em SOM, comece ajustando cuidadosamente os parâmetros de treinamento. O parâmetro TrainingBars determina quantas barras históricas serão usadas no treinamento: duas mil barras são o mínimo; quatro mil barras são preferíveis. TargetBarsLookahead define o horizonte de previsão. Em um gráfico de uma hora, vinte e quatro barras correspondem a uma previsão de um dia à frente.

Os limiares BullishThreshold e BearishThreshold são fundamentais. Valores muito baixos, como 0,1%, produzem muitos sinais fracos. Valores muito altos, como 2%, tornam os sinais raros. Os valores ideais dependem da volatilidade do instrumento e do timeframe.

O parâmetro MinConfidence filtra previsões pouco confiáveis. Um valor de 0,65 significa que o EA só irá operar quando a confiança do modelo estiver acima de 65%. Isso reduz o número de operações, mas tende a melhorar sua qualidade. Durante o backtest, observe a relação entre win rate e profit factor para diferentes valores desse parâmetro.

Ao operar em conta real, mantenha obrigatoriamente o treinamento contínuo ativado (ContinuousLearning = true). Os mercados evoluem, e um modelo estático rapidamente perde relevância. Com RetrainHours = 12, o modelo passa por uma nova etapa de treinamento com dados históricos recentes duas vezes ao dia, o que oferece um equilíbrio razoável entre adaptação e estabilidade.

Vejamos agora o teste do nosso sistema:

O gráfico não é exatamente bonito, mas vale lembrar que não houve qualquer otimização e os parâmetros foram escolhidos praticamente ao acaso. Mesmo assim, o índice de Sharpe ficou muito próximo de 4:


Conclusão: cartografia neural dos mercados financeiros

Os mapas auto-organizáveis de Kohonen são uma ferramenta elegante para analisar dados complexos e multidimensionais. Criados há mais de quarenta anos para reconhecimento da fala, encontraram aplicações em centenas de áreas, da bioinformática à sociologia. E, como se viu, também se adaptam muito bem à análise dos mercados financeiros.

O EA cujo código analisamos mostra uma das formas de aplicar SOM ao trading algorítmico. Não se trata de um sistema de trading pronto para uso, mas de uma plataforma de pesquisa que demonstra as possibilidades dessa tecnologia. A operação em mercado real exige trabalho adicional: testes com dados históricos, otimização de parâmetros, integração com um sistema de gestão de risco e preparo psicológico para enfrentar períodos de drawdown.

O mais importante, porém, é o conceito. A ideia de que o mercado pode ser cartografado, de que por trás do aparente caos das velas no gráfico existe uma estrutura organizada que pode ser identificada e aproveitada. A SOM é a ferramenta que permite construir esse mapa. Um mapa capaz de mostrar onde estamos no espaço dos estados de mercado e para onde provavelmente estamos nos movendo.

O código é aberto. A tecnologia está disponível. Resta aplicá-la com inteligência, paciência e a devida cautela. Os mercados não perdoam o excesso de confiança, mas recompensam quem sabe usar as ferramentas certas da maneira adequada. Talvez os mapas auto-organizáveis se tornem a sua ferramenta de navegação nesse oceano de dados financeiros.

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

Arquivos anexados |
SOMMAP_html.mqh (56.51 KB)
SOMMAP_Exp.mq5 (28.17 KB)
Últimos Comentários | Ir para discussão (1)
mma-meta
mma-meta | 2 nov. 2025 em 17:26
Yevgeniy, bom dia
onde posso ver e compilar os códigos-fonte completos?
É uma abordagem interessante, dá vontade de experimentar
Algoritmo de sistema artificial de circulação coronariana (Artificial Coronary Circulation System, ACCS) Algoritmo de sistema artificial de circulação coronariana (Artificial Coronary Circulation System, ACCS)
Algoritmo meta-heurístico que simula o crescimento das artérias coronárias do coração humano para resolver problemas de otimização. Utiliza os princípios da angiogênese (crescimento de novos vasos), da bifurcação (ramificação) e da poda de ramos fracos para buscar soluções ótimas em um espaço multidimensional. Os testes de sua eficiência em uma ampla variedade de problemas produziram resultados inesperados.
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)
Apresentamos o framework S3CE-Net e seus mecanismos SSAM e STFS, que processam com precisão eventos de spikes levando em conta a causalidade. O modelo é leve, opera em paralelo e é capaz de identificar relações complexas no tempo e no espaço.
Redes neurais em trading: abordagem semântica baseada em spikes para identificação espaço-temporal (Componentes principais) Redes neurais em trading: abordagem semântica baseada em spikes para identificação espaço-temporal (Componentes principais)
Neste artigo, analisamos em detalhes a integração do módulo SSAM ao bloco SEW-ResNeXt, mostrando como o framework S3CE-Net permite combinar de forma eficiente a atenção baseada em spikes com blocos residuais. Essa arquitetura proporciona um processamento preciso dos fluxos de dados temporais e espaciais, além de alta estabilidade durante o treinamento. A modularidade e a flexibilidade dos componentes facilitam a expansão do modelo e a reutilização de métodos já validados.
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.