Русский Español Português
preview
Quantum Neural Network in MQL5 (Part I): Creating the Include File

Quantum Neural Network in MQL5 (Part I): Creating the Include File

MetaTrader 5Expert Advisors |
310 8
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Imagine a trader who never sleeps, never panics, and is able to analyze thousands of market patterns simultaneously. Moreover, imagine that this trader has the memory of an elephant, the intuition of a genius, and the ability to learn instantly. Sounds like science fiction? Welcome to the world of quantum neural networks in MQL5.

What we are creating today goes far beyond simple machine learning. It is a symbiosis of quantum mechanics and artificial intelligence, embodied in code that can run right in your MetaTrader 5. Our architecture does not just predict price movements - it understands the market at a level inaccessible to human consciousness. 


Revolution in understanding memory

The human brain operates with several types of memory simultaneously. When an experienced trader looks at a chart, they instantly recall similar situations from the past, analyze the current context, and form an intuitive understanding of what might happen next. This principle forms the basis of our ContextAnalyzer, a revolutionary component that recreates human intuition in digital form.

Our memory system operates on five levels, each with its own specialization. Short-term memory captures instantaneous market changes — every tick, every price movement. Medium-term memory accumulates information about hourly and daily trends. Long-term memory stores fundamental patterns that emerge over months and years.

But real magic starts with episodic memory. It is activated only when something really important happens - a sharp jump in volatility, unexpected news, a change in trend. These moments are imprinted with particular force, forming unique "memories" that the system will use to recognize similar situations in the future.

The architecture combines memory across different time horizons (from short-term to long-term) to adapt to market dynamics. The attention mechanism and transformers ensure the selection of key information and abstraction. The State Space Model is responsible for temporal dependencies, and the Context Analyzer integrates memory while taking volatility into account. A quantum processor amplifies signals and suppresses noise, and the MetaVerificationModel verifies the reliability of predictions. The entire architecture functions as a self-adjusting system with built-in critical evaluation.


Quantum mechanics in action

Classical neural networks process information linearly — data passes from input to output through a sequence of transformations. Our system works fundamentally differently. We apply the principles of quantum mechanics: superposition, interference and resonance.

When different levels of memory interact with each other, they create interference patterns — just as light waves can reinforce or cancel each other out. These interferences give rise to emergent properties that cannot be obtained by simply adding up the components.

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);

These formulas are not just mathematical calculations. They describe how different "layers of reality" in the market resonate with each other, creating complex harmonics that our system is able to recognize and use for forecasting.


Transformer as an architectural revolution

At the heart of modern AI is the attention mechanism — the model's ability to focus on truly important information while ignoring noise. Our UShapeTransformer takes this idea to the next level.

Imagine an orchestra conductor who can hear every instrument at the same time and understand how they interact with each other. The attention mechanism works in a similar way: it calculates the importance of each element of the input sequence relative to all other elements.

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));
        }
    }
}

The U-shaped architecture adds another layer of complexity. The information first passes through an encoder, which compresses and abstracts the input data, highlighting the most significant features. The decoder then reconstructs this information, but enriched with context and an understanding of deep connections.


Alchemy of code: Creating a digital brain

Foundation: Matrix structure
Any complex structure begins with a strong foundation. In our case, this is a Matrix structure - not just a container for numbers, but an intelligent system for managing multidimensional data.

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;
    }
}

It would seem to be a simple structure. But it is based on the philosophy of safety and reliability. Every access to data is checked, every operation is controlled. This is especially critical for financial systems, where one mistake can cost real money.

StateSpaceModel: Remembering the past, looking to the future
Markets have memory. What happened yesterday influences events today. What happens today determines the possibilities of tomorrow. StateSpaceModel embodies this fundamental truth in mathematical form.

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);
            }
        }
    }
}

The beauty of this model is in its simplicity and power. Three matrices determine how the system evolves over time. Matrix A describes the internal dynamics — how past states influence future ones. Matrix B defines how external influences (new data) change the state of the system. Matrix C shows how the internal state manifests itself in external observations.

ContextAnalyzer: Digital intuition
The most complex and innovative component of our system is ContextAnalyzer. This is where the real magic happens: transforming raw data into understanding.

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));

The system constantly analyzes the nature of incoming data. High volatility forces more attention to short-term memory. Complex patterns activate episodic and pattern memory. These are not hard and fast rules, but dynamic weights that adapt to the current market situation.

Now the most interesting thing happens - quantum interactions between different types of memory:

// 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);
    }
}

These are not mere mathematical operations. Each formula has a deep meaning. Resonance occurs when current data "synchronizes" with the accumulated context. Interference creates complex patterns of interaction between different time scales. Non-linear factors add adaptability allowing the system to respond to changing market conditions.

Training and adaptation system
True intelligence is not demonstrated by the ability to remember, but by the ability to learn and adapt. Our system constantly analyzes the importance of incoming information and updates its memory accordingly:

// 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);
}

The system works like a living organism. It does not just accumulate information - it understands what is important and what can be ignored. Important events are remembered for a long time, routine data is quickly forgotten. Patterns that repeat themselves become stronger. Random noise is filtered out.

MetaVerificationModel: The art of doubt
One of the main problems in machine learning is model overconfidence. The system can produce predictions with high "confidence" even when input data is inconsistent or insufficient. MetaVerificationModel solves this problem by adding a critical thinking layer:

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
    }
}

The meta model analyzes not only the initial data and forecast of the main model, but also the error history, current quality metrics, and market behavior patterns. It learns to recognize situations where the underlying model is prone to error, and accordingly reduces confidence in its predictions.

Memory balancing
One of the key aspects of efficient system operation is the correct configuration of the different types of memory. Each market has its own characteristics, and there are no universal settings.

For volatile markets such as cryptocurrencies, the influence of short-term and episodic memory should be increased. The system should quickly respond to sudden changes and remember extreme events. For more stable instruments, such as government bonds, more weight should be given to long-term and pattern memory.

// 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
}

Self-diagnosis system
An intelligent system should understand its own limitations. We implement self-diagnostic functions that monitor various aspects of the model's operation:

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
        }
    }
}



Quantum effects in action

The most intriguing part of our system is the quantum-inspired interactions between the different components. Let's look at how they work in practice.

Resonance occurs when incoming data is "tuned" to the same "frequency" as the stored memory. This creates a signal amplification effect - important patterns become more pronounced and noise is suppressed.

Interference works as a cross-checking system. When different memory types are matched together, it strengthens the overall signal. When they contradict each other, this creates "destructive interference" which causes the system to be more cautious in its predictions.

// 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
    }
}


Philosophy of artificial intelligence in trading

The creation of our quantum neural network raises profound questions about the nature of intelligence and the predictability of financial markets. Can a machine truly "understand" the market, or does it merely detect complex correlations in the data? We propose the third way: an architecture that goes beyond simply remembering patterns or finding correlations. Our system creates a multi-level representation of market reality, where each level is responsible for a unique aspect of perception and analysis.

  • Short-term memory captures instant changes in market participants' sentiment — every tick, every price fluctuation. It is like a sensitive radar that picks up momentary impulses.

  • Medium-term memory tracks trends and cycles that form on hourly and daily timeframes, identifying patterns in the development of market movements.

  • Long-term memory stores fundamental economic patterns that emerge over months and years, providing the system with strategic vision.

  • Episodic memory captures unique, critical events — sharp spikes in volatility, unexpected news, or trend changes. These "memories" allow the system to anticipate the repetition of similar scenarios.

  • Pattern memory acts like digital intuition, extracting deep structures that repeat across different time scales and market conditions.

Quantum effects — resonance, interference, and coherence — add a new level of complexity. They allow the system to perceive uncertainty not as an obstacle, but as a source of valuable information. Like quantum particles that exist in a superposition of states, our network is able to simultaneously consider multiple possible market scenarios, amplifying meaningful signals and suppressing noise. This turns uncertainty into a learning tool, allowing the system to adapt to the chaotic nature of markets.


The benefits of embedded MQL5 matrices: From bicycle to spaceship

Initially, our system relied on our own implementation of matrix operations, which was akin to reinventing the wheel. However, the MQL5 developers have done an outstanding job by providing built-in matrix and vector types, as well as the <matrix.mqh> library, which turned our "bicycle" into a high-performance spaceship. The use of native matrix operations allowed us to radically reduce the amount of code, improve its readability and performance.

Advantages of built-in MQL5 matrices:

  • High performance: Operations like matrix multiplication (MatMul, @ operator) use the processor's vector instructions, providing speedups several times faster than manual loops.

  • Reliability: Built-in types eliminate indexing errors and ensure numerical stability, which is critical for financial calculations, where any inaccuracy can lead to losses.

  • Brevity and clarity: The code has become closer to mathematical notation, which simplifies its development and maintenance. For example, instead of cumbersome loops for matrix multiplication, it is sufficient to write Q = input @ W_q.

  • Ready-made tools for machine learning: RandUniform, Exp, Sigmoid, ReLU and other functions allow us to focus on high-level logic rather than low-level calculations.

  • Optimized memory management: Built-in types minimize memory allocations, which is especially important when handling large volumes of market data in real time.

As an example, let's look at how the code changes using built-in types:

Before  After 
   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);
   }
   

The full optimized code can be found in the attached QuantumNeuralMQL.mqh. file

Knowing the capabilities of MQL5 turned out to be the key to creating complex neural networks. Instead of spending time writing our own implementations of basic operations, we can focus on developing innovative architectures like our ContextAnalyzer or QuantumProcessor. Studying MQL5 documentation (such as matrix operations) opens the door to the efficient implementation of mathematically complex algorithms, making the process of creating neural networks not only productive but also engaging.

Finally, we will use a small script to make sure the code works.

//+------------------------------------------------------------------+
//| 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();
}




Conclusion

The resulting system is not just an algorithm, but a self-learning structure capable of adapting and developing its own understanding of the market.

Key components:

  • Matrices - the mathematical basis
  • State Space Model — dynamics over time
  • Transformer — attention and generalization
  • Context Analyzer — multi-level insights
  • Meta Verification Model — validating conclusions

The main effect is achieved through the interaction of these modules. The second part of the article will cover examples of use, configuration, and optimization of the system in practice. The transition to new forms of AI in trading is just beginning.

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/18759

Last comments | Go to discussion (8)
[Deleted] | 10 Jul 2025 at 15:12

The script from the article only compiled correctly after I replaced the include file. Otherwise, the neural network doesn’t recognise it. It’s probably because I uploaded it to the experts’ section without reading the article to the end.

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

But then it’s still not clear what to test on :) Like homework – finish writing the bot?
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 11 Jul 2025 at 14:32
Maxim Dmitrievsky #:

The script from the article only compiled after I replaced the include file. Otherwise, the neural network doesn’t recognise it. Probably because I posted it in the experts’ section without reading the article to the end.


But then it’s still not clear what to test on :) Like, is the homework to finish writing the bot?

Hello, Maxim! I’ve just replaced the files – I’d mixed up the include files in the different versions of the article

As for the bot – there’ll be a simple bot on this neural network in the next part)

[Deleted] | 11 Jul 2025 at 15:22
Yevgeniy Koshtenko #:

Hello, Maxim! I’ve just replaced the files – I’d mixed up the include files in the different versions of the article

As for the bot – there’ll be a simple bot on this forum in the next part)

Cheers, nice one, let’s have a go :)

10748356
10748356 | 29 Jul 2025 at 15:17
The concept behind the article is brilliant and fascinating. I fully understood the quantum properties of the system, and it’s the first of its kind I’ve come across in the MQL5 community. Well done, and keep up the good work
Renat Akhtyamov
Renat Akhtyamov | 29 Jul 2025 at 17:53
Maxim Dmitrievsky #:

The script from the article only compiled after I replaced the include file. Otherwise, the neural network doesn’t recognise it. Probably because I posted it in the experts’ section without reading the article to the end.


But then it’s still not clear what to test on :) Like, is the homework to finish writing the bot?
Yevgeniy Koshtenko #:

Well, what’s wrong with that? It was transformers that really drove forward natural language processing technology back in the day. Compared to the RNNs that came before, this is definitely cooler. I think that in the future we’ll see a fusion of quantum computing and neural networks; the ring meta-neural network architecture is working brilliantly, where there are 12 copies of the model, as in the article, which, like a circle, boost each other’s results and learn from each other’s outputs, confidences and errors. Here’s a test without even any pre-training; it’s simply learning online...


A test on events from 2017?

Why not 2024 or 2025?

Custom Debugging and Profiling Tools for MQL5 Development (Part III): Regression Gates for Performance and Trading Rules Custom Debugging and Profiling Tools for MQL5 Development (Part III): Regression Gates for Performance and Trading Rules
This article adds a regression gate to the MQL5 debugging and profiling workflow. It keeps the Part II profiler, TestLite runner, and trading math helper as contracts, then compares current profiler evidence with an accepted baseline. The workflow also adds symbol-aware assertions, compact status files, and report tables so performance drift, missing tests, and broker-assumption problems are visible before a build is accepted.
MQL5 Wizard Techniques you should know (Part 94): Using Reservoir Sampling and Linear Regression in a Custom Trailing Stop Class MQL5 Wizard Techniques you should know (Part 94): Using Reservoir Sampling and Linear Regression in a Custom Trailing Stop Class
For this article we rotate to a custom MQL5 Wizard class implementation that explores Trailing Stops. Our custom class is ‘CTrailingReservoirLinReg’ that we derive by combining the Reservoir Sampling algorithm with a Linear Regression network. As has been the case throughout these series, this formulation is testable with MQL5 Wizard Assembled Expert Advisors that can be tuned with various entry signals and money management classes.
Neural Networks in Trading: Skill Hierarchy for Adaptive Agent Behavior (Final Part) Neural Networks in Trading: Skill Hierarchy for Adaptive Agent Behavior (Final Part)
The article discusses the practical implementation of the HiSSD framework in algorithmic trading tasks. It explains how the skill hierarchy and adaptive architecture can be used to build sustainable trading strategies.
Step-by-Step Implementation of a Local Stop Loss System in MQL5 Step-by-Step Implementation of a Local Stop Loss System in MQL5
This article shows how to build a local stop-loss system in an MQL5 Expert Advisor that keeps stop levels on the terminal side. It walks through the execution logic, event handlers, inputs, and an OOP design using CTrade, CPositionInfo, CHashMap/CHashSet, and chart objects. You will implement multi-position tracking, draggable stops, visual spacers and labels, plus cleanup and disconnection behavior to create a practical risk-control utility.