Русский Português
preview
Quantum Neural Network in MQL5 (Part III): A Virtual Quantum Processor Based on Qubits

Quantum Neural Network in MQL5 (Part III): A Virtual Quantum Processor Based on Qubits

MetaTrader 5Expert Advisors |
148 4
Yevgeniy Koshtenko
Yevgeniy Koshtenko

In the second part of our research, we developed a system that uses mathematical analogues of quantum effects: resonance (cosine), interference (sine), decoherence (exponential). However, this remained only an imitation. Formally, it looked elegant, but in essence it was not quantum.

Over time, it became clear that the model is elegant, but it does not capture the essence of quantum processing — superposition, entanglement, and the irreversibility of measurements. We operated with functions, not principles.

Classical approaches remain limited:

  • LSTM achieves up to 58% accuracy
  • Transformers are vulnerable to noise
  • ARIMA has lost its relevance
  • Models are unstable due to overfitting

A key breakthrough is the transition to virtual qubits

In the second version, a full-fledged quantum processor is used instead of analogues: 3 qubits, an 8-dimensional state space, gates and measurements. The architecture has been revised: now every operation obeys the laws of quantum mechanics - unitarity, normalization, behavior during measurements.


Quantum processor architecture

Each qubit is represented as a complex vector in a two-dimensional Hilbert space.

struct ComplexVector {
    double real[STATE_DIM];
    double imag[STATE_DIM]; 
    int size;
    
    void Initialize(int dim) {
        size = dim;
        for(int i = 0; i < dim; i++) {
            real[i] = (i == 0) ? 1.0 : 0.0;  // Initial state |000⟩
            imag[i] = 0.0;
        }
    }
    
    double GetProbability(int index) {
        return real[index] * real[index] + imag[index] * imag[index];
    }
    
    void Normalize() {
        double norm = 0.0;
        for(int i = 0; i < size; i++) {
            norm += real[i] * real[i] + imag[i] * imag[i];
        }
        
        norm = MathSqrt(norm);
        if(norm > MATRIX_EPSILON) {
            for(int i = 0; i < size; i++) {
                real[i] /= norm;
                imag[i] /= norm;
            }
        }
    }
};

This code implements a basic structure for storing a quantum state. Unlike classical bits, quantum states have complex amplitudes that can interfere with each other. The GetProbability function calculates the probability of measuring a system in a given state according to the Born rule.

The peculiarity of the implementation is that we work not with individual qubits, but with the complete quantum state of the entire system. This is critical for properly modeling entanglement and quantum correlations. Each state in our 8-dimensional space corresponds to a specific combination of three qubits: |000⟩, |001⟩, |010⟩, |011⟩, |100⟩, |101⟩, |110⟩, |111⟩.


Quantum gates: From theory to practice

Rotation gates implement unitary transformations, allowing the qubit state to be smoothly rotated on the Bloch sphere:

static void CreateRotationGate(int qubit, double angle, ComplexMatrix &gate) {
    gate.Initialize(STATE_DIM);
    double cos_half = MathCos(angle / 2.0);
    double sin_half = MathSin(angle / 2.0);
    
    for(int i = 0; i < STATE_DIM; i++) {
        for(int j = 0; j < STATE_DIM; j++) {
            gate.real[i][j] = 0.0;
            gate.imag[i][j] = 0.0;
            
            int bit_i = (i >> qubit) & 1;
            int bit_j = (j >> qubit) & 1;
            int other_bits_i = i & ~(1 << qubit);
            int other_bits_j = j & ~(1 << qubit);
            
            if(other_bits_i == other_bits_j) {
                if(bit_i == 0 && bit_j == 0) gate.real[i][j] = cos_half;
                else if(bit_i == 0 && bit_j == 1) gate.imag[i][j] = -sin_half;
                else if(bit_i == 1 && bit_j == 0) gate.imag[i][j] = -sin_half;
                else if(bit_i == 1 && bit_j == 1) gate.real[i][j] = cos_half;
            }
        }
    }
}

This code constructs a rotation gate matrix acting on a specific qubit. The rotation angle is directly related to market data - the stronger the price movement, the greater the rotation angle. This creates a direct link between market dynamics and the quantum state of the system.

The algorithm uses bitwise operations to determine which matrix elements need to be filled. For each pair of states |i⟩ and |j⟩, we check whether the rotation of a particular qubit affects the transition between them. If all other qubits are in the same state, then the rotation acts only on the target qubit.

Controlled phase gates create quantum entanglement between qubits:

static void CreateCPhaseGate(int control_qubit, int target_qubit, double phase, ComplexMatrix &gate) {
    gate.Initialize(STATE_DIM);
    
    for(int i = 0; i < STATE_DIM; i++) {
        int control_bit = (i >> control_qubit) & 1;
        int target_bit = (i >> target_qubit) & 1;
        
        if(control_bit == 1 && target_bit == 1) {
            gate.real[i][i] = MathCos(phase);
            gate.imag[i][i] = MathSin(phase);
        }
    }
}

The phase φ depends on the correlations between market features. When two market factors are highly correlated (e.g. price and volume), the corresponding qubits become entangled. This allows the system to take into account complex relationships in the data.

The controlled-phase gate operates only when both qubits are in the |1⟩ state. In this case, it adds the e^(iφ) phase factor to the corresponding state amplitude. This does not change the probabilities of measuring individual qubits, but creates quantum correlations between them.

Hadamard gates put qubits into superposition states:

static void CreateHadamardGate(int qubit, ComplexMatrix &gate) {
    gate.Initialize(STATE_DIM);
    double inv_sqrt2 = 1.0 / MathSqrt(2.0);
    
    for(int i = 0; i < STATE_DIM; i++) {
        for(int j = 0; j < STATE_DIM; j++) {
            // ... Hadamard matrix construction code
            if(bit_i == 0 && bit_j == 0) gate.real[i][j] = inv_sqrt2;
            else if(bit_i == 0 && bit_j == 1) gate.real[i][j] = inv_sqrt2;
            else if(bit_i == 1 && bit_j == 0) gate.real[i][j] = inv_sqrt2;
            else if(bit_i == 1 && bit_j == 1) gate.real[i][j] = -inv_sqrt2;
        }
    }
}

The Hadamard gate creates a uniform superposition of |0⟩ and |1⟩ states. In a trading context, this means that the system can simultaneously consider both bullish and bearish market scenarios before the final "measurement" (the trading decision) is made.


Dynamic construction of quantum circuits

The key innovation is building a quantum circuit dynamically based on incoming market data. Each market feature influences the parameters of the quantum gates, creating a unique quantum processing path for each market situation.

void BuildQuantumCircuit(const vector &features) {
    num_gates = 0;
    quantum_state.Initialize(STATE_DIM);
    
    // Rotation gates based on market features
    for(int qubit = 0; qubit < NUM_QUBITS && num_gates < MAX_GATES; qubit++) {
        if(qubit < features.Size()) {
            double angle = features[qubit] * M_PI / 2.0;
            CMatrixOps::CreateRotationGate(qubit, angle, circuit_gates[num_gates]);
            num_gates++;
        }
    }
    
    // Entangling gates between pairs of qubits
    for(int i = 0; i < NUM_QUBITS - 1 && num_gates < MAX_GATES; i++) {
        for(int j = i + 1; j < NUM_QUBITS && num_gates < MAX_GATES; j++) {
            double correlation = CalculateFeatureCorrelation(features[i], features[j]);
            double phase = correlation * features[i] * features[j] * M_PI * entanglement_factor;
            
            if(MathAbs(phase) > MIN_PHASE_THRESHOLD) {
                CMatrixOps::CreateCPhaseGate(i, j, phase, circuit_gates[num_gates]);
                num_gates++;
            }
        }
    }
    
    // Adaptive superposition gates
    double market_uncertainty = CalculateMarketUncertainty(features);
    for(int qubit = 0; qubit < NUM_QUBITS && num_gates < MAX_GATES; qubit++) {
        double superposition_probability = coherence * market_uncertainty;
        if(GetRandomDouble() < superposition_probability) {
            CMatrixOps::CreateHadamardGate(qubit, circuit_gates[num_gates]);
            num_gates++;
        }
    }
}

This algorithm shows how market data directly determines the architecture of a quantum circuit. Unlike static neural networks, our system adapts its internal structure to each market situation. High correlation between features creates more entangled states, and market uncertainty increases the likelihood of superposition operations.

The unique feature of our approach is that we do not simply apply a fixed sequence of gates. Instead, the structure is built adaptively: if the correlation between features is weak, the corresponding entanglement gates are not created. If market uncertainty is low, superposition gates are rarely used. This allows the system to save computing resources and focus on the most relevant quantum effects.


Quantum evolution and decoherence

After constructing the circuit, the system proceeds to quantum evolution — successive application of unitary operators to the initial state |000⟩:

void ExecuteQuantumCircuit() {
    // Initialize the state
    double state[STATE_DIM];
    ArrayInitialize(state, 0.0);
    state[0] = 1.0;  // Initial state |000⟩
    
    // Apply each gate in the circuit
    for(int gate_idx = 0; gate_idx < num_gates; gate_idx++) {
        ApplyGateToState(state, gate_idx);
    }
    
    // Normalize the state
    double norm = 0.0;
    for(int i = 0; i < STATE_DIM; i++) {
        norm += state[i] * state[i];
    }
    
    norm = MathSqrt(norm);
    if(norm > MATRIX_EPSILON) {
        for(int i = 0; i < STATE_DIM; i++) {
            quantum_state.real[i] = state[i] / norm;
            quantum_state.imag[i] = 0.0;
        }
    }
}

The order, in which the operators are applied, is critically important as quantum gates do not commute. This means that the sequence of market events affects the final state of the system, just as in real markets the data arrival order affects prices.


Simulating market decoherence

In real financial systems, quantum effects exist in a "noisy" environment. The constant flow of news, the emotional reactions of participants, and macroeconomic events create decoherence:

void ApplyEnvironmentalDecoherence(ComplexVector &state, int evolution_step) {
    // Adaptive assessment of market noise
    double market_volatility = CalculateRecentVolatility();
    double information_flow = CalculateInformationIntensity();
    double decoherence_strength = base_decoherence_rate * 
                                 (1.0 + 0.5 * market_volatility + 0.3 * information_flow);
    
    // Phase decoherence (loss of quantum interference)
    for(int i = 0; i < STATE_DIM; i++) {
        if(state.GetProbability(i) > DECOHERENCE_THRESHOLD) {
            double phase_noise = GenerateGaussianNoise(0.0, decoherence_strength);
            
            // Rotation in the complex plane
            double cos_phase = MathCos(phase_noise);
            double sin_phase = MathSin(phase_noise);
            
            double new_real = state.real[i] * cos_phase - state.imag[i] * sin_phase;
            double new_imag = state.real[i] * sin_phase + state.imag[i] * cos_phase;
            
            state.real[i] = new_real;
            state.imag[i] = new_imag;
        }
    }
    
    state.Normalize();
}

This code models realistic decoherence, where the intensity depends on market conditions. During calm periods, quantum effects persist longer, while during market turmoil the system quickly switches to classical behavior.

Decoherence is not just a technical artifact, but an important component of the model. It reflects the fact that financial markets cannot maintain quantum coherence indefinitely. New information, trader decisions, and changes in sentiment all act as "measurements" that disrupt quantum superpositions.


Quantum measurements and information extraction

Extracting information from a quantum state requires specialized measurement protocols:

vector MeasureQuantumState() {
    vector measurements = vector::Zeros(NUM_QUBITS);
    
    // Compute the probability of measuring each qubit
    for(int qubit = 0; qubit < NUM_QUBITS; qubit++) {
        double prob_1 = 0.0;
        
        for(int i = 0; i < STATE_DIM; i++) {
            if((i >> qubit) & 1) {  // If the qubit is in state |1⟩
                prob_1 += quantum_state.GetProbability(i);
            }
        }
        
        measurements[qubit] = prob_1;  // Probability to measure |1⟩
    }
    
    return measurements;
}

Z measurements represent classical trading signals — the probability of a price rise or fall. X measurements reveal superposition effects, showing moments of maximum market uncertainty. Two-qubit correlations reveal hidden relationships between various market factors.

An important feature of our implementation is that we conduct non-destructive measurements. Unlike real quantum systems, where measurement collapses the wave function, we extract statistical information without disturbing the quantum state. This allows for multiple measurements to be made and rich information to be obtained about the system.


Hybrid architecture: The best of both worlds

The key achievement is an elegant integration of quantum processing with classical methods. The quantum processor complements and enhances classical analysis:

double Predict(const vector &input_features, double &confidence, bool is_training = false) {
    // Apply the quantum processor to the input data
    matrix input_matrix(1, input_features.Size());
    input_matrix.Row(input_features, 0);
    
    // Create a base context for the quantum processor
    matrix basic_context = matrix::Zeros(1, input_features.Size());
    for(ulong i = 0; i < input_features.Size(); i++) {
        basic_context[0][i] = MathSin(input_features[i] * M_PI / 4.0);
    }
    
    // Apply quantum effects
    matrix quantum_enhanced_input = input_quantum_proc.ApplyQuantumEffects(input_matrix, basic_context);
    vector quantum_features = quantum_enhanced_input.Row(0);
    
    // Market state classification with quantum-enhanced data
    double price_change = quantum_features[0];
    double volatility = quantum_features[1];
    double volume_ratio = quantum_features[2];
    int state = markov_chain.ClassifyMarketState(price_change, volatility, volume_ratio);

    // Get state embedding
    matrix state_embedding = markov_chain.Forward(state);
    
    // Further processing via classical components...
    matrix ssm_output = ssm.ProcessSequence(quantum_input_matrix);
    matrix contextualized = context_analyzer.ProcessWithContext(combined);
    
    // Transformer layers with quantum attention
    matrix hidden = contextualized;
    for(int i = 0; i < TRANSFORMER_LAYERS; i++) {
        hidden = transformer_layers[i].Forward(hidden, is_training);
    }
    
    // Final forecast
    double prediction = Sigmoid(output_result[0][0] + output_bias[0]);
    confidence = meta_model.Forward(quantum_features, prediction, error_metrics);
    
    return prediction;
}

This code shows how quantum processing is integrated into the overall pipeline. The raw data is first passed through a quantum processor, which reveals hidden correlations and creates an enriched representation. The quantum-enhanced data is then processed by the classical system components.

An important detail of the architecture is that we are not replacing classical methods with quantum ones, but creating a symbiosis. The quantum processor acts as a "preprocessor" that enriches the input data with additional information about hidden correlations and nonlinear dependencies. Classical components then use this enriched information to make more accurate decisions.

The integration of quantum effects into the attention mechanisms of transformers deserves special attention:

matrix Forward(const matrix &input_data, bool is_training) {
    last_input_data = input_data;
    matrix Q = input_data.MatMul(W_q);
    matrix K = input_data.MatMul(W_k);
    matrix V = input_data.MatMul(W_v);
    
    // Apply dropout in training mode
    if (is_training) {
        Q = ApplyDropoutMask(Q, dropout_mask_q, 1.0 / (1.0 - DROPOUT_RATE));
        K = ApplyDropoutMask(K, dropout_mask_k, 1.0 / (1.0 - DROPOUT_RATE));
        V = ApplyDropoutMask(V, dropout_mask_v, 1.0 / (1.0 - DROPOUT_RATE));
    }
    
    // KEY INNOVATION: Quantum processing of Query and Key
    Q = quantum_proc.ApplyQuantumEffects(Q, input_data);
    K = quantum_proc.ApplyQuantumEffects(K, input_data);
    
    // Calculate attention scores with quantum correlations
    matrix scores = Q.MatMul(K.Transpose()) / MathSqrt((double)d_model);
    
    // Use softmax to obtain attention weights
    matrix scores_softmax = matrix::Zeros(scores.Rows(), scores.Cols());
    for(ulong i = 0; i < scores.Rows(); i++) {
        vector row = scores.Row(i);
        double max_val = row.Max();
        for(ulong j = 0; j < row.Size(); j++)
            row[j] = MathExp(row[j] - max_val);
        double sum = row.Sum();
        if (sum == 0.0) sum = 1e-9;
        row = row / sum;
        scores_softmax.Row(row, i);
    }
    
    matrix attention_output = scores_softmax.MatMul(V);
    return attention_output.MatMul(W_o);
}

Quantum processing of Query and Key matrices allows the attention mechanism to take into account not only linear relationships between features, but also their quantum correlations. This is particularly efficient for identifying weak signals in noisy financial data.

The entire system was implemented as a trading EA for MetaTrader 5, written entirely in MQL5 without any external dependencies. The architecture includes the following key components:

struct QuantumContextAnalyzer {
    matrix short_memory, medium_memory, long_memory, episodic_memory, pattern_memory;
    
    matrix ProcessWithContext(const matrix &input_data) {
        // Adaptive weighting of memory types
        double input_volatility = CalculateVolatility(input_data);
        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);
        
        // Apply quantum effects to contextual information
        matrix quantum_result = quantum_proc.ApplyQuantumEffects(input_matrix, context_matrix);
        
        return quantum_result;
    }
};

The system dynamically selects the most relevant memory type depending on market conditions. During periods of high volatility, short-term memory receives more weight, while in calm times, long-term memory receives more weight.

double Forward(const vector &original_features, double prediction, const vector &error_metrics) {
    vector meta_input = vector::Zeros(original_features.Size() + 1 + error_metrics.Size());
    
    // Combine the original features, forecast, and error metrics
    for(ulong i = 0; i < original_features.Size(); i++)
        meta_input[i] = original_features[i];
    meta_input[original_features.Size()] = prediction;
    for(ulong i = 0; i < error_metrics.Size(); i++)
        meta_input[original_features.Size() + 1 + i] = error_metrics[i];
    
    // Confidence prediction via a two-layer network
    matrix hidden = input_matrix.MatMul(meta_weights);
    for(ulong i = 0; i < hidden.Cols(); i++) 
        hidden[0][i] = Tanh(hidden[0][i] + meta_bias[i]);
    
    matrix output_result = hidden.MatMul(output_weights);
    return Sigmoid(output_result[0][0] + output_bias_meta[0]);
}

The meta-model analyzes not only the current forecast, but also the system error history, adaptively assessing confidence in each specific case.

Particular attention was paid to integration with the risk management system for working with prop companies. Modern proprietary firms have strict requirements for maximum drawdowns, daily loss limits, and profit targets.


Live trading results: Theory meets reality

The most important test of any trading system is its results under real market conditions. For 2024-2025, the quantum system showed:

Financial results:

  • Annual return: +13.3%
  • Maximum drawdown: 2.39%
  • Win rate: 87%
  • Sharpe ratio: 2.48
  • Average holding time: 4.2 hours

System adaptability: What is especially important is that the system has demonstrated stable results in various market conditions. During periods of high volatility, it automatically reduced position sizes and became more conservative. On the contrary, during calm periods, it behaved more aggressively, using quantum effects to search for weak but stable signals.

Despite the impressive results, the system has not yet achieved all of its goals:

Current limitations:

  • The Sharpe ratio of 2.48 is still below the target of 3.5+
  • The computational complexity of a quantum simulator requires significant resources
  • Hyperparameter tuning remains challenging
  • The system requires careful calibration for each trading instrument



Conclusion

The quantum future opens a new world in algorithmic trading. The transition to virtual qubits delivered a significant advantage over classical methods, improving predictions and results. Our system, based on the principles of quantum mechanics, naturally copes with market uncertainty and complex correlations, which remains a challenge for classical models. The creation of the first full-fledged quantum simulator, adaptive architecture, and integration of quantum and classical methods in a hybrid system highlight our achievements.

In the future, we will focus on optimizing the system and achieving a target Sharpe ratio above 3.5, developing the quantum trading ecosystem. The full implementation is available as a trading EA for MetaTrader 5, ready for real-time use.

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

Last comments | Go to discussion (4)
Anatoli Kazharski
Anatoli Kazharski | 1 Aug 2025 at 11:11

@Yevgeniy Koshtenko

There is a duplicate PropRiskManagerLoss.mqh file in the archive:

It appears that the file HybridQuantumNeuralV3.mqh is missing, preventing QuantumProp_EA_Lite.mq5 from compiling without errors.

Yevgeniy Koshtenko
Yevgeniy Koshtenko | 1 Aug 2025 at 12:05
Anatoli Kazharski #:

@Yevgeniy Koshtenko

There is a duplicate PropRiskManagerLoss.mqh file in the archive:

It appears that the file HybridQuantumNeuralV3.mqh is missing, preventing QuantumProp_EA_Lite.mq5 from compiling without errors.

Thank you very much! I’ve just spotted it myself and have sent it for review with the correct file)

Sergei Goncharov
Sergei Goncharov | 2 Aug 2025 at 09:20

Yevgeniy, this looks like a really good, professional product. We’ll test it and provide feedback. Could you tell me, is there any way to get this training model to use a GPU for training, as is the case with the LSTM model in Python, for example? Perhaps you’ve already looked into this, so as not to waste time. If not, we can think about it together, as hardware performance is important in this model – and rightly so. A high-quality model with in-depth analysis simply has to be demanding on the hardware.

sindicato
sindicato | 11 Sep 2025 at 14:31

Good morning.

I haven’t been able to replicate the test described in the article, or even produce a similar graph.

Could you please let us know the parameters and the symbol?

Thank you.

Features of Custom Indicators Creation Features of Custom Indicators Creation
Creation of Custom Indicators in the MetaTrader trading system has a number of features.
MQL5 Wizard Techniques you should know (Part 98): Using an Unscented Kalman Filter and a Capsule Network in a Custom Signal Class MQL5 Wizard Techniques you should know (Part 98): Using an Unscented Kalman Filter and a Capsule Network in a Custom Signal Class
This article presents 'CSignalUKFCapsNet', as a custom class coded in MQL5. This class is meant to be used with the MQL5 Wizard when assembling an Expert Advisor and when selected in the Wizard it defines the Expert Advisor's entry signals. In building this custom class, we brought together the algorithm Unscented Kalman Filter and the Capsule Neural Network. Our algorithm is showcased with four operation modes, and the coding of this as a custom class for the MQL5 Wizard, allows testing with various Trailing Stop methods and Money Management systems.
Features of Experts Advisors Features of Experts Advisors
Creation of expert advisors in the MetaTrader trading system has a number of features.
Encoding Candlestick Patterns (Part 3): Frequency Analysis for Single Candlestick Type Structure Encoding Candlestick Patterns (Part 3): Frequency Analysis for Single Candlestick Type Structure
This article introduces a frequency-analysis framework for encoded candlestick patterns in MQL5. By transforming candlesticks into alphabetic symbols, historical price action can be analyzed as a statistical sequence rather than a visual chart. Using GBPUSD and Gold across multiple timeframes, the study examines the occurrence frequency of individual candlestick types, identifies dominant market structures, and reveals the symmetry between bullish and bearish price movements. The results establish a quantitative foundation for pattern discovery and prepare the way for analyzing multi-candlestick sequences and their predictive potential in algorithmic trading systems.