English Русский Español
preview
Rede neural quântica em MQL5 (Parte I): Criando um arquivo de inclusão

Rede neural quântica em MQL5 (Parte I): Criando um arquivo de inclusão

MetaTrader 5Experts |
203 8
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Imagine um trader que nunca dorme, nunca entra em pânico e é capaz de analisar simultaneamente milhares de padrões de mercado. Mais do que isso, imagine que esse trader tem memória de elefante, intuição de gênio e capacidade de aprender instantaneamente. Parece ficção científica? Bem-vindo ao mundo das redes neurais quânticas em MQL5.

O que estamos criando hoje vai muito além do aprendizado de máquina convencional. É uma simbiose entre mecânica quântica e inteligência artificial, materializada em código, que pode funcionar diretamente no seu MetaTrader 5. Nossa arquitetura não apenas prevê os movimentos de preço, ela entende o mercado em um nível inacessível à consciência humana. 


Revolução na compreensão da memória

O cérebro humano opera com vários tipos de memória ao mesmo tempo. Quando um trader experiente olha para um gráfico, ele imediatamente se lembra de situações parecidas do passado, analisa o contexto atual e compreende de forma intuitiva o que pode acontecer em seguida. Foi exatamente esse princípio que serviu de base para o nosso ContextAnalyzer, um componente revolucionário que recria a intuição humana em formato digital.

Nosso sistema de memória funciona em cinco níveis, cada um com sua própria especialização. A memória de curto prazo registra as mudanças instantâneas do mercado, cada tick, cada movimento de preço. A memória de médio prazo acumula informações sobre tendências horárias e diárias. A memória de longo prazo armazena padrões fundamentais que se manifestam ao longo de meses e anos.

Mas a verdadeira mágica começa com a memória episódica. Ela é ativada apenas quando acontece algo realmente importante, como um salto brusco na volatilidade, uma notícia inesperada ou uma mudança de tendência. Esses momentos ficam gravados com força especial, formando "memórias" únicas, que o sistema usará para reconhecer situações semelhantes no futuro.

A arquitetura combina memórias de diferentes horizontes temporais, do curto ao longo prazo, para se adaptar à dinâmica do mercado. O mecanismo de atenção e os transformadores garantem o destaque das informações-chave e a abstração. O State Space Model é responsável pelas dependências temporais, e o Context Analyzer integra a memória levando em conta a volatilidade. O processador quântico amplifica os sinais e suprime o ruído, enquanto o MetaVerificationModel verifica se as previsões são confiáveis. Tudo funciona como um sistema autoajustável com pensamento crítico.


Mecânica quântica em ação

As redes neurais clássicas processam informações de forma linear: os dados passam da entrada até a saída por uma sequência de transformações. Nosso sistema funciona de maneira fundamentalmente diferente. Aplicamos princípios da mecânica quântica, como superposição, interferência e ressonância.

Quando os diferentes níveis de memória interagem entre si, eles criam padrões de interferência, exatamente como as ondas de luz podem se amplificar ou se suprimir mutuamente. Essas interferências geram propriedades emergentes que não podem ser obtidas pela simples soma dos componentes.

double resonance_factor = 1.0 + 0.5 * MathCos(input_val * linear_context * M_PI);
double interference = 0.3 * MathSin(short_context * medium_context * 2.0 * M_PI) +
                     0.2 * MathCos(long_context * episodic_context * M_PI) +
                     0.1 * MathSin(pattern_context * input_val * 3.0 * M_PI);

Essas fórmulas não são apenas desenvolvimentos matemáticos. Elas descrevem como diferentes "camadas da realidade" do mercado entram em ressonância entre si, criando ondas harmônicas complexas que nosso sistema é capaz de reconhecer e usar para previsão.


O transformer como uma revolução arquitetural

Na base da IA moderna está o mecanismo de atenção, a capacidade do modelo de focar na informação realmente importante, ignorando o ruído. Nosso UShapeTransformer leva essa ideia ao máximo.

Imagine um maestro de orquestra que ouve simultaneamente cada instrumento e entende como eles interagem entre si. O mecanismo de atenção funciona de forma parecida, ele calcula o grau de importância de cada elemento da sequência de entrada em relação a todos os demais elementos.

void Forward(Matrix &input_matrix, Matrix &output_matrix)
{
    // Create matrices of queries, keys, and values
    MatrixMultiply(input_matrix, W_q, Q);
    MatrixMultiply(input_matrix, W_k, K);
    MatrixMultiply(input_matrix, W_v, V);
    
    // Calculate attention weights
    for(int i = 0; i < seq_len; i++)
    {
        for(int j = 0; j < seq_len; j++)
        {
            double dot_product = 0.0;
            for(int k = 0; k < d_model; k++)
                dot_product += Q.Get(i, k) * K.Get(j, k);
            attention_weights.Set(i, j, dot_product / MathSqrt(d_model));
        }
    }
}

A arquitetura em U acrescenta mais um nível de complexidade. A informação primeiro passa pelo encoder, que comprime e abstrai os dados de entrada, destacando as características mais relevantes. Depois, o decoder reconstrói essa informação, mas agora enriquecida com contexto e compreensão das conexões profundas.


Alquimia do código: criando um cérebro digital

Fundamento: estrutura Matrix
Toda construção complexa começa com uma base sólida. No nosso caso, essa base é a estrutura Matrix, não apenas um contêiner para números, mas um sistema inteligente de gerenciamento de dados multidimensionais.

struct Matrix
{
    double data[];
    int rows, cols;

    void Init(int r, int c)
    {
        rows = r;
        cols = c;
        ArrayResize(data, r * c);
        ArrayInitialize(data, 0.0);
    }

    double Get(int r, int c)
    {
        if(r < 0 || r >= rows || c < 0 || c >= cols) return 0.0;
        return data[r * cols + c];
    }

    void Set(int r, int c, double val)
    {
        if(r < 0 || r >= rows || c < 0 || c >= cols) return;
        data[r * cols + c] = val;
    }

    void Random(double range = 0.5)
    {
        for(int i = 0; i < ArraySize(data); i++)
            data[i] = (MathRand() / 32767.0 - 0.5) * 2.0 * range;
    }
}

À primeira vista, parece uma estrutura simples. Mas nela está embutida uma filosofia de segurança e confiabilidade. Cada acesso aos dados é verificado, cada operação é controlada. Isso é especialmente crítico em sistemas financeiros, onde um único erro pode custar dinheiro real.

StateSpaceModel: memória do passado, olhar para o futuro
Os mercados têm memória. O que aconteceu ontem influencia os eventos de hoje. O que acontece hoje define as possibilidades de amanhã. O StateSpaceModel materializa essa verdade fundamental em forma matemática.

struct StateSpaceModel
{
    Matrix A, B, C;  // State, input, and output matrices
    Matrix state;    // Current state of the system
    int input_size, state_size;

    void ProcessSequence(Matrix &_input, Matrix &output)
    {
        output.Init(_input.rows, _input.cols);
        
        for(int t = 0; t < _input.rows; t++)
        {
            // Extract the current input vector
            Matrix input_row;
            input_row.Init(1, _input.cols);
            for(int j = 0; j < _input.cols; j++)
                input_row.Set(0, j, _input.Get(t, j));

            // Update internal state
            Matrix new_state;
            new_state.Init(1, state_size);
            
            // state = A * state + B * input
            for(int i = 0; i < state_size; i++)
            {
                double sum = 0.0;
                for(int k = 0; k < state_size; k++)
                    sum += A.Get(i, k) * state.Get(0, k);
                
                for(int k = 0; k < _input.cols; k++)
                    sum += B.Get(k, i) * input_row.Get(0, k);
                    
                new_state.Set(0, i, sum);
            }
            
            state = new_state;

            // Calculate output: output = C * state
            for(int j = 0; j < _input.cols; j++)
            {
                double sum = 0.0;
                for(int k = 0; k < state_size; k++)
                    sum += C.Get(k, j) * state.Get(0, k);
                output.Set(t, j, sum);
            }
        }
    }
}

A beleza desse modelo está na sua simplicidade e potência. Três matrizes determinam como o sistema evolui ao longo do tempo. A matriz A descreve a dinâmica interna, como os estados passados influenciam os futuros. A matriz B define como os impactos externos (novos dados) alteram o estado do sistema. A matriz C mostra como o estado interno se manifesta nas observações externas.

ContextAnalyzer: intuição digital
O componente mais complexo e inovador do nosso sistema é o ContextAnalyzer . É aqui que acontece a verdadeira mágica: a transformação de dados brutos em compreensão.

void ProcessWithContext(Matrix &_input, Matrix &output)
{
    output.Init(_input.rows, _input.cols);

    static Matrix short_term_memory, medium_term_memory, long_term_memory;
    static Matrix episodic_memory, pattern_memory;
    static bool memory_initialized = false;
    static int sequence_counter = 0;
    static double importance_buffer[100];
    static int buffer_index = 0;

    if(!memory_initialized)
    {
        short_term_memory.Init(5, context_size);
        medium_term_memory.Init(50, context_size);
        long_term_memory.Init(10, context_size);
        episodic_memory.Init(20, context_size);
        pattern_memory.Init(15, context_size);
        
        // Initialize all memory types
        ArrayInitialize(short_term_memory.data, 0.0);
        ArrayInitialize(medium_term_memory.data, 0.0);
        ArrayInitialize(long_term_memory.data, 0.0);
        ArrayInitialize(episodic_memory.data, 0.0);
        ArrayInitialize(pattern_memory.data, 0.0);
        ArrayInitialize(importance_buffer, 0.0);
        
        memory_initialized = true;
    }

    sequence_counter++;

    // Analyze input data characteristics
    double input_volatility = 0.0;
    double input_magnitude = 0.0;
    double input_complexity = 0.0;

    // Calculate volatility, magnitude, and complexity
    for(int i = 0; i < _input.rows; i++)
    {
        double row_sum = 0.0, row_variance = 0.0;
        for(int j = 0; j < _input.cols; j++)
        {
            double val = _input.Get(i, j);
            row_sum += val;
            input_magnitude += MathAbs(val);
        }

        double row_mean = row_sum / _input.cols;
        for(int j = 0; j < _input.cols; j++)
        {
            double val = _input.Get(i, j);
            row_variance += (val - row_mean) * (val - row_mean);
        }

        input_volatility += MathSqrt(row_variance / _input.cols);

        // Evaluate complexity through change analysis
        for(int j = 1; j < _input.cols; j++)
        {
            if(MathAbs(_input.Get(i, j) - _input.Get(i, j-1)) > 0.1)
                input_complexity += 1.0;
        }
    }

    input_volatility /= _input.rows;
    input_magnitude /= (_input.rows * _input.cols);
    input_complexity /= (_input.rows * (_input.cols - 1));

O sistema analisa constantemente a natureza dos dados recebidos. Alta volatilidade faz com que a atenção se volte mais para a memória de curto prazo. Padrões complexos ativam a memória episódica e a memória de padrões. Não se trata de regras rígidas, mas de pesos dinâmicos que se adaptam à situação atual do mercado.

Em seguida, acontece o mais interessante, as interações quânticas entre os diferentes tipos de memória:

// Dynamic calculation of weights for different memory types
double short_weight = 0.4 + 0.4 * input_volatility;
double medium_weight = 0.3 + 0.2 * (1.0 - input_volatility);
double long_weight = 0.2 + 0.3 * (1.0 - input_volatility);
double episodic_weight = 0.1 + 0.3 * input_complexity;
double pattern_weight = 0.15 + 0.25 * input_complexity;

// Normalize weights
double total_weight = short_weight + medium_weight + long_weight + episodic_weight + pattern_weight;
short_weight /= total_weight;
medium_weight /= total_weight;
long_weight /= total_weight;
episodic_weight /= total_weight;
pattern_weight /= total_weight;

for(int i = 0; i < _input.rows; i++)
{
    for(int j = 0; j < _input.cols; j++)
    {
        double input_val = _input.Get(i, j);
        double context_idx = j % context_size;

        // Extract context from different memory types
        double short_context = short_term_memory.Get(sequence_counter % 5, context_idx);
        double medium_context = medium_term_memory.Get(sequence_counter % 50, context_idx);
        double long_context = long_term_memory.Get(sequence_counter % 10, context_idx);
        double episodic_context = episodic_memory.Get(sequence_counter % 20, context_idx);
        double pattern_context = pattern_memory.Get(sequence_counter % 15, context_idx);

        // Linear combination of contexts
        double linear_context = short_weight * short_context +
                               medium_weight * medium_context +
                               long_weight * long_context +
                               episodic_weight * episodic_context +
                               pattern_weight * pattern_context;

        // Quantum effects: resonance and interference
        double resonance_factor = 1.0 + 0.5 * MathCos(input_val * linear_context * M_PI);
        double interference = 0.3 * MathSin(short_context * medium_context * 2.0 * M_PI) +
                             0.2 * MathCos(long_context * episodic_context * M_PI) +
                             0.1 * MathSin(pattern_context * input_val * 3.0 * M_PI);

        double nonlinear_factor = 1.0 + input_volatility * MathSin(linear_context * 2.0 * M_PI);

        // Integrate all effects
        double integrated_context = linear_context * resonance_factor * nonlinear_factor + interference;

        // Determine the strength of contextual influence
        double context_strength = 0.4 + 0.3 * input_complexity;
        double final_output = (1.0 - context_strength) * input_val + context_strength * integrated_context;

        output.Set(i, j, final_output);
    }
}

Não se trata apenas de operações matemáticas. Cada fórmula tem um significado profundo. A ressonância surge quando os dados atuais se "sincronizam" com o contexto acumulado. A interferência cria padrões complexos de interação entre diferentes escalas temporais. Os fatores não lineares acrescentam adaptabilidade, permitindo que o sistema reaja às mudanças nas condições de mercado.

Sistema de aprendizado e adaptação
A verdadeira inteligência se manifesta não na capacidade de memorizar, mas na capacidade de aprender e se adaptar. Nosso sistema analisa constantemente a importância das informações recebidas e, com base nisso, atualiza sua memória:

// Evaluate the importance of current data
double importance = input_volatility + input_complexity + MathAbs(input_val);
importance_buffer[buffer_index] = importance;
buffer_index = (buffer_index + 1) % 100;

double avg_importance = 0.0;
for(int k = 0; k < 100; k++) avg_importance += importance_buffer[k];
avg_importance /= 100.0;

// Adaptive learning rate
double learning_rate = (importance > avg_importance) ? 0.3 : 0.05;

// Update different memory types at different speeds
double new_short = short_context * (1.0 - 0.4) + final_output * 0.4;
short_term_memory.Set(sequence_counter % 5, context_idx, new_short);

double new_medium = medium_context * (1.0 - 0.1) + final_output * 0.1;
medium_term_memory.Set(sequence_counter % 50, context_idx, new_medium);

double new_long = long_context * (1.0 - 0.02) + final_output * 0.02;
long_term_memory.Set(sequence_counter % 10, context_idx, new_long);

// Episodic memory is activated only for important events
if(importance > avg_importance * 1.5)
{
    double new_episodic = episodic_context * 0.7 + final_output * 0.3;
    episodic_memory.Set(sequence_counter % 20, context_idx, new_episodic);
}

// Pattern memory is updated when correlations are detected
double pattern_correlation = input_val * linear_context;
if(MathAbs(pattern_correlation) > 0.1)
{
    double pattern_update = pattern_correlation * learning_rate;
    double new_pattern = pattern_context * 0.9 + pattern_update * 0.1;
    pattern_memory.Set(sequence_counter % 15, context_idx, new_pattern);
}

O sistema funciona como um organismo vivo. Ele não apenas acumula informações, ele entende o que é importante e o que pode ser ignorado. Eventos importantes são lembrados por muito tempo, dados rotineiros são esquecidos rapidamente. Os padrões que se repetem são reforçados. O ruído aleatório é filtrado.

MetaVerificationModel: a arte da dúvida
Um dos principais problemas do aprendizado de máquina é o excesso de confiança dos modelos. O sistema pode gerar previsões com alta "confiança", mesmo quando os dados de entrada são contraditórios ou insuficientes. O MetaVerificationModel resolve esse problema ao adicionar uma camada de pensamento crítico:

struct MetaVerificationModel
{
    Matrix meta_weights;
    Matrix meta_output_weights;

    void Init()
    {
        int meta_input_size = FEATURES_COUNT + 1 + 3; // features + forecast + metrics
        meta_weights.Init(meta_input_size, 16);
        meta_weights.Random(0.3);
        meta_output_weights.Init(16, 1);
        meta_output_weights.Random(0.5);
    }

    double Forward(double &original_features[], double first_model_prediction, double &error_metrics[])
    {
        // Forming the meta input
        double meta_input[];
        int total_input_size = ArraySize(original_features) + 1 + ArraySize(error_metrics);
        ArrayResize(meta_input, total_input_size);

        // Copy the original features
        for(int i = 0; i < ArraySize(original_features); i++)
            meta_input[i] = original_features[i];

        // Add the main model forecast
        meta_input[ArraySize(original_features)] = first_model_prediction;

        // Add error metrics
        for(int i = 0; i < ArraySize(error_metrics); i++)
            meta_input[ArraySize(original_features) + 1 + i] = error_metrics[i];

        // Forward propagation through the hidden layer
        double hidden[];
        ArrayResize(hidden, 16);

        for(int i = 0; i < 16; i++)
        {
            double sum = 0.0;
            for(int j = 0; j < ArraySize(meta_input) && j < meta_weights.cols; j++)
                sum += meta_input[j] * meta_weights.Get(j, i);
            hidden[i] = Tanh(sum);
        }

        // Calculate the final output
        double output = 0.0;
        for(int i = 0; i < 16; i++)
            output += hidden[i] * meta_output_weights.Get(i, 0);

        return Sigmoid(output); // Return confidence from 0 to 1
    }
}

O meta-modelo analisa não apenas os dados brutos e a previsão do modelo principal, mas também o histórico de erros, as métricas atuais de qualidade e os padrões de comportamento do mercado. Ele aprende a reconhecer situações em que o modelo principal tende a errar e, com isso, reduz a confiança em suas previsões.

Balanceamento da memória
Um dos aspectos centrais para o funcionamento eficiente do sistema é a configuração correta dos diferentes tipos de memória. Cada mercado tem suas próprias características, e não existem configurações universais.

Para mercados voláteis, como as criptomoedas, deve-se aumentar a influência da memória de curto prazo e da memória episódica. O sistema precisa reagir rapidamente a mudanças bruscas e memorizar eventos extremos. Para instrumentos mais estáveis, como títulos públicos, convém dar mais peso à memória de longo prazo e à memória de padrões.

// Adaptive adjustment of memory weights depending on the instrument
void AdaptMemoryWeights(string symbol)
{
    if(StringFind(symbol, "BTC") >= 0 || StringFind(symbol, "ETH") >= 0)
    {
        // Settings for cryptocurrencies
        short_term_base_weight = 0.5;
        episodic_base_weight = 0.25;
        long_term_base_weight = 0.1;
    }
    else if(StringFind(symbol, "USD") >= 0)
    {
        // Forex settings
        short_term_base_weight = 0.35;
        medium_term_base_weight = 0.35;
        long_term_base_weight = 0.2;
    }
    // And so on for different types of assets
}

Sistema de autodiagnóstico
Um sistema inteligente precisa entender suas próprias limitações. Implementamos funções de autodiagnóstico que monitoram diferentes aspectos do funcionamento do modelo:

void RunDiagnostics()
{
    static int diagnostic_counter = 0;
    diagnostic_counter++;
    
    if(diagnostic_counter % 1000 == 0) // every thousand ticks
    {
        // Entropy analysis in different types of memory
        double short_entropy = context_analyzer.CalculateMemoryEntropy(short_term_memory);
        double long_entropy = context_analyzer.CalculateMemoryEntropy(long_term_memory);
        double pattern_entropy = context_analyzer.CalculateMemoryEntropy(pattern_memory);
        
        // If short-term memory is too chaotic and long-term memory is too stable
        if(short_entropy > 2.5 && long_entropy < 0.5)
        {
            Print("DIAGNOSIS: Memory imbalance detected. Increasing connectivity.");
            // Increase interaction between memory types
            interference_strength += 0.1;
        }
        
        // If the system becomes too conservative
        if(pattern_entropy < 0.3)
        {
            Print("DIAGNOSIS: The system is too conservative. Adding exploratory noise.");
            exploration_noise += 0.05;
        }
        
        // Analyze forecast quality
        double recent_accuracy = prediction_history.GetRecentAccuracy(50);
        if(recent_accuracy < 0.4)
        {
            Print("DIAGNOSIS: Low accuracy of forecasts. Activating retraining mode.");
            learning_rate_multiplier = 1.5;
            confidence_threshold += 0.1; // Raise the bar for confidence
        }
    }
}



Efeitos quânticos em ação

A parte mais intrigante do nosso sistema são as interações inspiradas na mecânica quântica entre os diferentes componentes. Vamos ver como elas funcionam na prática.

A ressonância surge quando os dados de entrada estão "ajustados" à mesma "frequência" da memória acumulada. Isso cria um efeito de amplificação do sinal, padrões importantes ficam mais evidentes, e o ruído é suprimido.

A interferência funciona como um sistema de verificações cruzadas. Quando os diferentes tipos de memória estão alinhados entre si, isso reforça o sinal geral. Quando entram em contradição, isso cria uma "interferência destrutiva", que leva o sistema a ser mais cauteloso em suas previsões.

// Example of analysis of quantum effects
void AnalyzeQuantumEffects(double input_val, double linear_context)
{
    double resonance = MathCos(input_val * linear_context * M_PI);
    
    if(MathAbs(resonance) > 0.8)
    {
        if(resonance > 0)
            Print("QUANTUM EFFECT: Strong constructive resonance detected");
        else
            Print("QUANTUM EFFECT: Strong destructive resonance detected");
    }
    
    // Analyze interference patterns
    double interference_pattern = AnalyzeInterferencePattern();
    if(MathAbs(interference_pattern) > threshold)
    {
        Print("QUANTUM EFFECT: Complex interference pattern detected");
        // The market may be in a transitional state
    }
}


Filosofia da inteligência artificial no trading

A criação da nossa rede neural quântica levanta questões profundas sobre a natureza da inteligência e a previsibilidade dos mercados financeiros. Uma máquina pode realmente "entender" o mercado ou ela apenas identifica correlações complexas nos dados? Propomos um terceiro caminho: uma arquitetura que vai além da simples memorização de padrões ou da busca por correlações. Nosso sistema forma uma representação em múltiplos níveis da realidade do mercado, em que cada nível responde por um aspecto único de percepção e análise.

  • A memória de curto prazo registra mudanças instantâneas no sentimento dos participantes do mercado, cada tick, cada oscilação de preço. Ela se assemelha a um radar sensível, capaz de captar impulsos momentâneos.

  • A memória de médio prazo acompanha tendências e ciclos que se formam em timeframes horários e diários, identificando padrões na evolução dos movimentos do mercado.

  • A memória de longo prazo armazena padrões econômicos fundamentais que se manifestam ao longo de meses e anos, dando ao sistema uma visão estratégica.

  • A memória episódica registra eventos únicos e críticos, saltos bruscos de volatilidade, notícias inesperadas ou mudanças de tendência. Essas "memórias" permitem que o sistema antecipe a repetição de cenários semelhantes.

  • A memória de padrões atua como uma intuição digital, extraindo estruturas profundas que se repetem em diferentes escalas de tempo e em diferentes condições de mercado.

Os efeitos quânticos — ressonância, interferência e coerência — acrescentam um novo nível de complexidade. Eles permitem que o sistema trate a incerteza não como um obstáculo, mas como uma fonte de informação valiosa. Assim como partículas quânticas, que existem em superposição de estados, nossa rede é capaz de considerar simultaneamente vários cenários possíveis de mercado, amplificando sinais relevantes e suprimindo o ruído. Isso transforma a incerteza em uma ferramenta de conhecimento, permitindo que o sistema se adapte à natureza caótica dos mercados.


Vantagens das matrizes nativas do MQL5: da bicicleta à nave espacial

Inicialmente, nosso sistema se baseava em uma implementação própria de operações matriciais, algo parecido com reinventar a roda. No entanto, os desenvolvedores do MQL5 fizeram um trabalho excepcional ao fornecer os tipos nativos matrix e vector, além da biblioteca <matrix.mqh>, que transformaram nossa "bicicleta" em uma nave espacial de alto desempenho. O uso de operações matriciais nativas permitiu reduzir radicalmente o volume de código, aumentar sua clareza e melhorar a performance.

Vantagens das matrizes nativas do MQL5:

  • Alta performance: operações como multiplicação de matrizes (MatMul, operador @) usam instruções vetoriais do processador, garantindo aceleração de várias vezes em comparação com loops manuais.

  • Confiabilidade: os tipos nativos eliminam erros de indexação e garantem estabilidade numérica, algo crítico em cálculos financeiros, em que qualquer imprecisão pode levar a perdas.

  • Concisão e clareza: o código ficou mais próximo da notação matemática, o que facilita seu desenvolvimento e manutenção. Por exemplo, em vez de loops extensos para multiplicar matrizes, basta escrever Q = input @ W_q.

  • Ferramentas prontas para aprendizado de máquina: funções como RandUniform, Exp, Sigmoid, ReLU e outras permitem focar na lógica de alto nível, e não em cálculos de baixo nível.

  • Gerenciamento de memória otimizado: os tipos nativos minimizam alocações de memória, o que é especialmente importante ao processar grandes volumes de dados de mercado em tempo real.

Como exemplo, vamos ver como o código muda com o uso dos tipos nativos:

Era  Ficou 
   void Forward(Matrix &input_matrix, Matrix &output_matrix)
   {
      int seq_len = input_matrix.rows;
      
      Matrix Q, K, V;
      Q.Init(seq_len, d_model);
      K.Init(seq_len, d_model);
      V.Init(seq_len, d_model);

      // Simple matrix multiplication Q = input * W_q
      for(int i = 0; i < seq_len; i++)
      {
         for(int j = 0; j < d_model; j++)
         {
            double q_sum = 0.0, k_sum = 0.0, v_sum = 0.0;
            for(int k = 0; k < d_model; k++)
            {
               double input_val = input_matrix.Get(i, k);
               q_sum += input_val * W_q.Get(k, j);
               k_sum += input_val * W_k.Get(k, j);
               v_sum += input_val * W_v.Get(k, j);
            }
            Q.Set(i, j, q_sum);
            K.Set(i, j, k_sum);
            V.Set(i, j, v_sum);
         }
      }

      // Calculate attention weights
      Matrix attention_weights;
      attention_weights.Init(seq_len, seq_len);

      for(int i = 0; i < seq_len; i++)
      {
         double max_score = -DBL_MAX;
         
         // Calculate scores
         for(int j = 0; j < seq_len; j++)
         {
            double score = 0.0;
            for(int k = 0; k < d_model; k++)
               score += Q.Get(i, k) * K.Get(j, k);
            
            score /= MathSqrt(d_model);
            attention_weights.Set(i, j, score);
            if(score > max_score) max_score = score;
         }

         // Softmax
         double sum_exp = 0.0;
         for(int j = 0; j < seq_len; j++)
         {
            double exp_val = MathExp(attention_weights.Get(i, j) - max_score);
            attention_weights.Set(i, j, exp_val);
            sum_exp += exp_val;
         }

         if(sum_exp > 0)
         {
            for(int j = 0; j < seq_len; j++)
               attention_weights.Set(i, j, attention_weights.Get(i, j) / sum_exp);
         }
      }

      // Apply weights to values
      output_matrix.Init(seq_len, d_model);
      for(int i = 0; i < seq_len; i++)
      {
         for(int j = 0; j < d_model; j++)
         {
            double sum = 0.0;
            for(int k = 0; k < seq_len; k++)
               sum += attention_weights.Get(i, k) * V.Get(k, j);
            output_matrix.Set(i, j, sum);
         }
      }
   }

   matrix Forward(const matrix &input_data)
   {
      // Calculate Q, K, V
      matrix Q = input_data.MatMul(W_q);
      matrix K = input_data.MatMul(W_k);
      matrix V = input_data.MatMul(W_v);
      
      // Apply quantum effects
      Q = quantum_proc.ApplyQuantumEffects(Q, input_data);
      K = quantum_proc.ApplyQuantumEffects(K, input_data);
      
      // Calculate attention weights
      matrix scores = Q.MatMul(K.Transpose()) / MathSqrt((double)d_model);
      
      // Softmax across rows
      for(ulong i = 0; i < scores.Rows(); i++)
      {
         vector row = scores.Row(i);
         
         // Find the maximum value for numerical stability
         double max_val = row.Max();
         
         // Subtract the maximum and apply the exponential element-wise
         for(ulong j = 0; j < row.Size(); j++)
         {
            row[j] = MathExp(row[j] - max_val);
         }
         
         // Normalize (divide by the sum)
         double sum = row.Sum();
         row = row / sum;
         
         // Write back to the matrix
         scores.Row(row, i);
      }
      
      // Apply to values and output projection
      matrix attention_output = scores.MatMul(V);
      return attention_output.MatMul(W_o);
   }
   

O código completo otimizado pode ser visto no arquivo anexado QuantumNeuralMQL.mqh.

Conhecer os recursos do MQL5 acabou sendo a chave para criar redes neurais complexas. Em vez de gastar tempo escrevendo implementações próprias para operações básicas, podemos focar no desenvolvimento de arquiteturas inovadoras, como o nosso ContextAnalyzer ou o QuantumProcessor. Estudar a documentação do MQL5, por exemplo, sobre matrix operations, abre caminho para implementar com eficiência algoritmos matematicamente complexos, tornando o processo de criação de redes neurais não apenas produtivo, mas também envolvente.

Por fim, usamos um pequeno script para garantir que o código funciona.

//+------------------------------------------------------------------+
//| Usage example                                                    |
//+------------------------------------------------------------------+
// Using in EA:
SimpleQuantumNeural neural_net;

int OnInit()
{
   neural_net.Init();
   return INIT_SUCCEEDED;
}

void OnTick()
{
   double features[];
   if(MarketDataCollector::CollectSimpleFeatures(_Symbol, PERIOD_H1, 10, features))
   {
      double prediction[];
      neural_net.Forward(features, prediction);
      
      if(ArraySize(prediction) > 0)
      {
         double signal = prediction[0];
         Comment("Quantum signal: ", DoubleToString(signal, 4));
         
         if(signal > 0.6)
         {
            // Buy
         }
         else if(signal < 0.4)
         {
            // Sell
         }
      }
   }
   
   // Diagnostics
   static int counter = 0;
   counter++;
   if(counter % 100 == 0)
      neural_net.PrintDiagnostics();
}




Conclusão

O sistema criado não é apenas um algoritmo, mas uma estrutura autoaprendente, capaz de se adaptar e formar sua própria compreensão do mercado.

Componentes principais:

  • Matrizes, a base matemática
  • State Space Model, dinâmica no tempo
  • Transformer, atenção e generalização
  • Context Analyzer, compreensão em múltiplos níveis
  • Meta Verification Model, verificação das conclusões

O principal efeito é alcançado pela interação entre esses módulos. Na segunda parte do artigo, serão apresentados exemplos de uso, configuração e otimização do sistema na prática. A transição para novas formas de IA no trading está apenas começando.

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

Últimos Comentários | Ir para discussão (8)
[Excluído] | 10 jul. 2025 em 15:12

O script do artigo foi compilado somente dessa forma, após a substituição do includnik. Caso contrário, ele não vê a rede neural. Provavelmente porque eu o coloquei na seção Expert Advisors sem ler o artigo até o fim.

//#include <Shtenco_SimpleQuantumNeural.mqh>
#include  <QuantumNeuralMQL.mqh>

mas ainda não está claro o que testar :) como lição de casa - terminar de escrever o bot?
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 11 jul. 2025 em 14:32
Maxim Dmitrievsky #:

O script do artigo foi compilado somente dessa forma, após a substituição do includnik. Caso contrário, ele não vê a rede neural. Provavelmente porque eu o coloquei na seção Expert Advisors sem ler o artigo até o fim.


mas ainda não está claro o que testar :) como lição de casa - terminar de escrever o bot?

Oi Maxim, substituí os arquivos agora - misturei as inclusões em diferentes versões do artigo

Quanto ao bot - na próxima parte, terei um bot simples sobre esse NS).

[Excluído] | 11 jul. 2025 em 15:22
Yevgeniy Koshtenko #:

Olá Maxim, substituí os arquivos agora - misturei as inclusões em diferentes versões do artigo

Sobre o bot - haverá um bot simples sobre esse NS no próximo artigo).

Bom dia, vamos dar uma olhada nele :)

10748356
10748356 | 29 jul. 2025 em 15:17
O conceito do artigo é incrível e interessante. Compreendi totalmente as propriedades quânticas do sistema e esse é o primeiro cérebro que encontrei na comunidade mql5. Ótimo, e vá em frente
Renat Akhtyamov
Renat Akhtyamov | 29 jul. 2025 em 17:53
Maxim Dmitrievsky #:

O script do artigo foi compilado somente dessa forma, após a substituição do includnik. Caso contrário, ele não vê a rede neural. Provavelmente porque eu o coloquei na seção Expert Advisors sem ler o artigo até o fim.


mas ainda não está claro o que testar :) como lição de casa - terminar de escrever o bot?
Yevgeniy Koshtenko #:

Bem, o que há de errado? Foram os Transformers que, em sua época, avançaram poderosamente as tecnologias de processamento de linguagem natural. Em comparação com os RNNs que vieram antes, esse é realmente mais legal. Acho que, no futuro, veremos uma síntese de computação quântica e redes neurais, a arquitetura de rede neural em anel, em que há 12 cópias do modelo, como no artigo, que, em uma rodada como a de bousting, melhoram os resultados uns dos outros e aprendem com os resultados, a confiança e os erros uns dos outros, está indo muito bem. Aqui está um teste, mesmo sem pré-treinamento, é apenas aprendizado on-line.....


Um teste sobre histórias de 2017?

Por que não 24/25 anos?

Redes neurais em trading: Previsão probabilística de séries temporais (Conclusão) Redes neurais em trading: Previsão probabilística de séries temporais (Conclusão)
Apresentamos a você o framework K²VAE e uma variante de como integrar as abordagens propostas a um sistema de trading. Você verá como a abordagem híbrida Koopman-Kalman-VAE ajuda a construir modelos adaptativos e interpretáveis. Ao final do artigo, veremos os resultados práticos obtidos com as soluções implementadas.
Redes neurais em trading: Previsão probabilística de séries temporais (Codificador) Redes neurais em trading: Previsão probabilística de séries temporais (Codificador)
Apresentamos uma nova abordagem que combina métodos clássicos e redes neurais modernas para a análise de séries temporais. O artigo descreve detalhadamente a arquitetura e os princípios de funcionamento do modelo K²VAE.
Otimização extrema — Extremal Optimization (EO) Otimização extrema — Extremal Optimization (EO)
Neste artigo, é analisado o algoritmo Extremal Optimization (EO), um método de otimização inspirado no modelo de criticidade auto-organizada de Bak-Sneppen, no qual a evolução ocorre por meio da eliminação dos piores componentes do sistema. A versão populacional modificada do algoritmo se afasta dos princípios teóricos em favor da eficiência prática, o que leva à criação de poderosas ferramentas computacionais.
Do básico ao intermediário: Recursos Do básico ao intermediário: Recursos
Neste artigo você será apresentado a um conceito que pode ser de extrema utilidade em muitos casos. Facilitando em muito o compartilhamento de suas aplicações e projetos. Apesar de não ser um conceito muito simples de ser totalmente explicando em um único artigo. O que será explicado e exposto aqui, já nos irá permitir fazer diversas coisas no futuro. Inclusive algumas que de outra maneira não seriam possíveis de serem feitas. Justamente por que este artigo ainda não havia sido publicado, para que você, pudesse ter um material de apoio e uma base inicial de estudo.