preview
MQL5 Wizard Techniques you should know (Part 89): Using Bitwise Vectorization with Perceptron Classifiers

MQL5 Wizard Techniques you should know (Part 89): Using Bitwise Vectorization with Perceptron Classifiers

MetaTrader 5Trading systems |
648 0
Stephen Njuki
Stephen Njuki

Introduction

The entry logic for algorithms is usually a bottleneck with real-time trading systems: with every incoming tick or new bar, an Expert Advisor can do dozens of floating-point reads and loop iterations(up to 64 historical reads) to put together OHLC context, fill indicator buffers and prepare ML inputs. In quiet markets this cost can be acceptable; when having bursts of volume and tick activity it turns into latency that one can track, meaning - later order submission, worse fills, higher slippage. Our engineering goal therefore becomes simple: restructure the entry path so that a 64-bar context is read and evaluated almost instantly, without using expensive double arrays or matrix math while waiting on a decision.

To achieve this, we use CSignalBitwisePerceptron: a compact MQL5 Signal class that vectorizes 64 periods into one 64-bit ‘word’, applying a O(1) bitwise map gate giving us ultra-fast pattern matching and also using a lightweight perceptron gate (hardware-level dot-product over bits) as a contextual filter. This pairing keeps floating-point work low,provides a single tunable confidence parameter (m_threshold) for trade off frequency vs precision, and - per forward walk tests - has potential to reduce drawdown while keeping execution latency near zero.



Problem Statement

For some strategies, in that pursuit of zero-latency trading, their algorithmic entry logic can be a silent killer of performance. Typical Expert Advisors depend on indicator buffers and historical price arrays—such as moving averages or oscillators—to establish market entry. Under the hood, this entails collecting, buffering, and iterating through deep arrays of double-precision or floating-point data. When an algorithm requires analyzing the past 64 minutes of, say, M1 data in order to identify a setup, this regular logic can force the CPU to loop through 64 distinct index positions on every incoming price bar/tick.

During volatile market episodes when real and tick volume is very high, this repetitive array iteration can introduce significant computation bloat. The Expert Advisor is forced to waste more precious micro-cycles by merely reading the historical state of the market. This delays the actual trade execution and often guarantees unfavorable slippage.

Latency can worsen when machine-learning models are integrated into entry logic. Many EAs feed networks with uncompressed floating-point inputs (e.g., FP32 on GPUs) or raw decimal data on CPUs. In most instances, what would be suitable would be FP-16 for the GPUs and INT8 for CPUs. Processing 64 discrete float values through an AI’s input layer on a live tick does force the Expert Advisor to manage a large memory footprint while concurrently performing matrix multiplications.

This bottleneck is rarely a trading strategy on its own; rather, it is an inefficiency in data structuring. This can cause the system to choke on the amount of floating-point math required before producing a long/short decision. We make the case here that in order to properly get rid of compute latency, we would need to fundamentally reorganize how the machine interprets historical data.

We cannot keep relying on high-level loops as well as floating-point arrays. The solution is to avoid these structures and convert raw market data into machine-readable binary at the hardware level. By shifting from heavy double arrays to a bitwise vectorization, we give our neural network an ultra-lightweight, instantly accessible data format, effectively stripping the compute down to near zero.


The Code

To truly grasp how we achieve near-zero latency, we should examine the inner mechanics of our custom signal class. Unlike typical wizard classes derived from CExpertSignal that rely heavily on MA, MACD, or RSI buffers, our approach uses only raw price series. We set up a direct connection within the class constructor by overriding the default data series’ initialization:

m_used_series = USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_OPEN + USE_SERIES_CLOSE; 

In doing this, we tell the Expert Advisor to bypass intermediary indicator calculations and pull raw market data directly from memory. The real reduction in latency, though, occurs in how we process this data.

The ‘GetVectorizeState’ method:

The main constraint in standard algorithmic trading is array iteration. When an Expert Advisor wants to read the last 64 periods of market data, the common approach is often looping through an array of 64 double-precision floating-point numbers on every incoming tick. This method fundamentally replaces this inefficiency as follows:

//+------------------------------------------------------------------+
//| Bitwise Vectorization: Pack 64 periods into a uint64             |
//+------------------------------------------------------------------+
ulong CSignalBitwisePerceptron::GetVectorizedState(int start_index)
  {
   ulong state = 0;
//--- Loop through the last 64 bars.
//--- If Close > Open (Bullish), set the bit to 1. Else, leave as 0.
   for(int i = 0; i < 64; i++)
     {
      if(Close(start_index + i) > Open(start_index + i))
        {
         //--- Shift 1 by 'i' positions and perform bitwise OR
         state |= ((ulong)1 << i);
        }
     }
   return(state);
  }

Instead of keeping raw OHLC float values, the loop evaluates a basic binary condition for each bar. Did the close price rise across the bar? This evaluation reduces a complex candlestick into a pure binary state of the form 1 for bullish and 0 for bearish. On larger timeframes, this simplification could be meaningful since flat bars are less likely; however, on small timeframes, the blur between flat and bearish could be an issue.

We reduce latency by executing on the very next line the bitwise OR assignment operator:

state |= ((ulong)1 << i);

If a candlestick is bullish, the algorithm takes a binary 1 and shifts it to the left by i positions. This slots it into a specific memory bit within the state variable. Since state is declared as an unsigned 64-bit integer, it has exactly 64 available bits. In a single, rapid pass, 64 minutes of market history are condensed into one ‘machine word’.

The ‘PerceptronInference’ Method:

Once the market state is converted to a vector format, it should be evaluated by our neural network. This processing of machine learning models within an EA often necessitates heavy matrix multiplication libraries that can gobble up CPU threads. This method attempts to avoid this by running the mathematical dot product at the hardware level:

//+------------------------------------------------------------------+
//| Perceptron Inference: Hardware-level dot product calculation     |
//+------------------------------------------------------------------+
double CSignalBitwisePerceptron::PerceptronInference(ulong state)
  {
   double sum = m_bias;
//--- Iterate through the 64-bit integer
   for(int i = 0; i < 64; i++)
     {
      //--- Use bitwise AND to check if the i-th bit is set to 1
      if((state & ((ulong)1 << i)) != 0)
        {
         //--- If bit is 1, add the corresponding weight to the sum
         sum += m_weights[i];
        }
     }
   return(sum);
  }

The perceptron takes the packed 64-bit integer (state) and initializes sum with the network bias. To establish if a particular synaptic weight should be added to the sum, the method uses a bitwise AND mask:

(state & ((ulong)1 << i)) != 0;

This operation immediately checks the i-th bit of our packed/vector integer. If the bit is active (implying a bullish bar), the condition evaluates as true and a corresponding pre-trained weight is added to our total activation sum via:

sum += m_weights[i];

There are no complicated math libraries to invoke. It is pure, raw, CPU instruction execution. By keeping the data in binary format until the exact moment of inference, the perceptron can evaluate the composite combo of patterns through the 64-bar sequence with near-zero compute overhead.



Algorithm Vs Neural-Network

After compressing the historical data into a 64-bit integer, the EA decides whether to trade. Traditionally, MQL5 signal classes make this choice linearly - as a single-layer process. This can follow events such as checking if the RSI is above or below a static level. However, in order to get to high-frequency execution speeds to support latency-dependent strategies, a dual-layered verification architecture, as we had in the last article, is considered for this one as well. We thus rely on an algorithmic gate acting as a primary filter, and a neural network gate serving as the final discriminator.

Execution Flow:

The execution process starts the moment the MQL5 engine requests a market assessment. The first action taken by both the Long and Short conditions is to invoke the data structuring method discussed above.

ulong current_state = GetVectorizedState(idx);

At this moment, the Expert Advisor processes the whole 64-bar market context that is locked within the current_state variable. The system gets to pass this state through two unique gates.

Layer 1:

The first of these is the defense layer against bad trades. It is purely algorithmic and uses m_map as a lookup table of binary signatures of historically bullish/bearish price patterns. Rather than writing an if/else tree to verify whether the current market state is in line with our bullish/bearish states, we use an elegant bitwise operation:

if(!(m_map & (1 << current_state)))

The math mechanics of this give us a compute advantage. The algorithm takes the binary number 1 and shifts it to the left by the integer value of our current_state. Since current_state is a large 64-bit number, this bit shift operation effectively acts as an ultra-fast hash function that maps the current market structure to a particular unique bit position. The system, then, uses the bitwise AND operator (&) to compare this unique position against our optimized master ledger, m_map. If the NOT operator makes the condition true, the current 64-bar sequence matches a bullish (or bearish) pattern in m_map. Looking at the function that checks for short conditions, one can see that it's the inverse of the bullish. We acknowledge this match by assigning a 100% weight via:

result = m_pattern_0;

This validation process from checking a complex 64-bar structure against an optimized input pattern map runs in O(1) time. It hardly costs the CPU, thus acting as a high-speed algo-gate.

Layer 2:

Whereas the algorithm gate is fast by default, it can also be quite rigid. It looks for strict matches. Financial markets, however, tend to be more dynamic than static. m_map settings that work today may require minor adjustments to fit future market conditions. A rigid algorithmic gate is bound to discard these variations, thus missing out on potentially good setups. This is where our secondary neural network layer intervenes to introduce some potentially useful flexibility. After the map check, we run neural inference:

double activation = PerceptronInference(current_state);

This perceptron performs evaluations using the exact 64-bit word; instead of looking for a rigid hash match, we calculate the dot product of the bits that are active against its pre-trained synaptic weights. The neural network gate is also enforced by a key condition:

if(activation > m_threshold && m_threshold > 0.0)

With this line, the m_threshold input parameter serves as a dynamic confidence slider. When the activation sum goes past this threshold, the neural network validates the trade, confirming the present market state is a high-probability setup. Consequently, the result is assigned 100%, as it is when only the algorithm runs. If the result is already 100, we halve it before reassigning:

result /= 2;

 if(IS_PATTERN_USAGE(0))

     result = m_pattern_0;



Composite Combinations Vs Individual Patterns

It can be important to grasp what a neural network is seeing when deploying it in automated settings. Traditional Expert Advisor entry logic typically focuses on isolated, localized patterns of a candlestick which can include an engulfing bar, or a doji, etc. Arguably, this can be taken as a flawed microscopic view of the market.

By feeding the entire current_state vector into our network, we are not evaluating a single candlestick, but rather the goal is usually assessing a composite combination of patterns that in this case span the 64 price-bar window. The perceptron might recognize that while the final three minutes of price action are similar to standard bullish breakouts, the preceding 61 bars’ context is actually pointing to a liquidity trap.

The m_weights array enables us to assign varying degrees of importance to various historical periods within the analyzed context, which in our case is a 64-bar window. By adjusting the m_threshold, the developer directly controls how strict the network should be when processing data that is composite.

A higher threshold demands stronger math alignment of favorable historical contexts before allowing the entry. This in essence filters out the ‘B-Level’ setups, conserving capital only for the scenarios where a complete 64-bar context keeps up with the trained model’s optimal state.

Therefore, by layering these two gates within our custom signal class of CSignalBitwisePerceptron, we are on paper at least striving for the best of both worlds. To sum up, the algorithm’s m_map gives us lightning-quick, zero-latency pattern matching, while the perceptron m_threshold acts as a highly intelligent contextual discriminator, sieving out inevitable false positives gotten from raw speed.


Test Result Analysis

Next, we test the approach using a forward-walk analysis. To validate the architecture, we first determine profitable entry/exit thresholds. We then evaluate them using an out-of-sample forward-walk test. We are testing the EURUSD on the 4-hour timeframe from 2025.01.01 to 2026.05.01. The optimization period is the year 2025, with the forward walk being from 2026.01.01 to 2026.05.01.

We tested (1) the algorithm gate only and (2) the algorithm gate plus the neural gate. The testing environment was the same on both runs in order to isolate any potential impact of the neural network layer. Our first report is given below:

r1

In this first run, which is a forward-walk test of the Expert Advisor using only Gate 1, the algorithm, we disabled the network. By assigning the perceptron’s activation threshold a value of 0.0, our system defaulted entirely to the layer-1 algorithmic hash check, m_map. If the 64-bit sequence matches the map, then the trade would have been fired immediately without the neural network.

The results showcase the raw, unrestrained aggression of pure algorithmic pattern matching. The Expert Advisor executed a total of 11 trades, generating a net profit of USD 528.03 on a starting balance of USD 10,000. With a profit factor of 1.19. However, a deeper look at trade distribution reveals the rigidity of the algorithmic gate. All 11 executions were long trades with zero short opportunities identified, which is undesirable in forex over a 4-month window.

Also, while the raw profit generation was reasonably substantial, it came at a significant ‘risk cost’. Our test result equity drawdown was at 18.66% with a value of USD 2,379.77. That drawdown was almost six times the net profit. Therefore, while our algorithm was very fast at finding the exact pattern, it lacks some contextual awareness in avoiding setups that have technically matched the sequence but are in deteriorating conditions. Our second report is below:

r2

For the second forward walk, also post-optimization, we engaged the full architecture. By increasing m_threshold to a positive value, requiring the perceptron to evaluate the composite combination of our 64 price-bar sequence to reach a given weighted amount before allowing trades.

The statistical shift is immediate. Total executions dropped from 11 trades to 10. As a result, the raw net profit was USD 299.30, and the profit factor decreased slightly to 1.13. On the surface, while this may seem like a degradation, the risk-adjusted returns are what could define the difference, as opposed to raw profit.

By analyzing the execution log, we can see the difference the perceptron made. The neural gate actively filtered out two long trades that the raw algorithm blindly placed. This reduced potential losses by reducing potential losses. Furthermore, the network successfully spotted and executed a highly profitable short trade, in contrast to the algorithm that only placed long trades. Most importantly, by filtering out low-probability composite patterns, the perceptron successfully reduced the trade action volatility from 18.66% to 16.75%. The dollar value of this drawdown, though, is still significant.


The ML Trade-Off

The comparison becomes interesting because neither version of the system is universally better — they simply optimize for different things. The raw bit-pattern engine is more aggressive. It reacts to every valid occurrence of m_map , increasing trade frequency and producing slightly higher overall profit, but also exposing the account to larger drawdowns.

Adding the perceptron changes the role of the system. The neural layer does not generate new signals; instead, it filters existing ones by evaluating whether the current market structure resembles the historical conditions where the pattern previously performed well. This reduces the number of trades, but also removes many weaker setups that technically match the binary sequence while appearing in unstable market conditions.

The forward tests reflect this shift clearly. The pure algorithm traded more frequently and achieved slightly higher gross profit, while the hybrid version produced a smoother equity curve and reduced drawdown from 18.66% to 16.75% .

In practice, this is the real trade-off: maximizing exposure versus improving selectivity. The perceptron was never replacing the core algorithm — it was deciding when the algorithm should stay out of the market.


Conclusion

Writing afresh entry logic around a bitwise vectorization and a two-gate decision path has potentially given us a template one can drop into a CExpertSignal implementation. Concretely, this requires implementing: GetVectorizedState (with 64 bar in one ulong) and a gate-2 (activation > m_threshold). We use m_threshold to tune the precision/recall trade off and log both decision latency and economic metrics.

We have aggreagated the checkpoints:

  • functional parity - which ensures the 64-bit encoding maps the intended bar rules (mind flat bars on small timeframes),
  • performance - where we measure CPU/time per tick before and after vectorization,
  • economics - for a forward walk comparison of algorithm vs neural-network with out-of-sample trades on strategy tester report metrics.

Our results could mean a conceptual gain (‘near-zero latency’) could lead to verifiable engineering improvements that are tunable and replicatable.

name description
wz_89.mq5 wizard assembled Expert Advisor
SignalBitwisePerceptron.mqh Custom Signal Class used in Wizard Assembly

Attached files |
wz_89.mq5 (6.73 KB)
Features of Custom Indicators Creation Features of Custom Indicators Creation
Creation of Custom Indicators in the MetaTrader trading system has a number of features.
Building AI-Powered Trading Systems in MQL5 (Part 9): Creating an AI Signal Dispatcher Building AI-Powered Trading Systems in MQL5 (Part 9): Creating an AI Signal Dispatcher
We turn the MQL5 AI trading assistant into a dispatch-driven system that routes seven trading actions through a single central dispatcher. A line-based key-value protocol constrains AI output, while each action maps to market or pending orders and instrument-aware stop levels. A canvas-based UI with a custom prompt editor and pixel-accurate text fitting makes signals consistent, auditable, and ready to render on the chart
Features of Experts Advisors Features of Experts Advisors
Creation of expert advisors in the MetaTrader trading system has a number of features.
Beyond GARCH (Part I): Mandelbrot's MMAR versus Engle's GARCH Beyond GARCH (Part I): Mandelbrot's MMAR versus Engle's GARCH
This article starts the MMAR pipeline on EURUSD M5 data. We load market data via the MetaTrader5 Python API and run partition-function analysis with non-overlapping intervals to test for multifractal scaling. The result is an evidence-based decision on fractality, a prerequisite for building MMAR and for choosing whether to proceed beyond GARCH.