MQL5 Wizard Techniques you should know (Part 91): Using Skip Lists and a Hopfield Network in a Custom Trailing Class
Introduction
In the last article, in MQL5-Wizard Techniques, we constructed a robust capital proportioning framework that used the Fenwick Trees as well as a 1-D CNN. Optimizing position size in tandem with volatility is an important aspect to trading but so is guarding profits in live markets. If traders use standard linear trailing stops they could be susceptible to the latency gap. In flash events, which tend to happen more frequently these days and in less predictable periods, price action is seldom contiguous.
In our last article, we coded a custom class that uses a Bloom filter for membership testing. Here, we explore an alternative approach. For this article we are using a probabilistic ‘leap’ over price gaps in order to cater for slippage voids. Also while we used an RNN as the second gate to set the new stop level by tracking sequential memory, some strategies can benefit from a model that is tailored to track holistic market stability instead and that is what we delve into for our neural network.
Therefore, in expanding our toolkit for the MQL5 Wizard series, this article explores a new approach. We will test a skip list for probabilistic gap-jumping as our algorithm, and pair this with a Hopfield network for associative memory in order to filter market noise, as a second check.
The Problem
So, let’s start this take on guarding profits with a trailing stop by unpacking some of the underlying mechanics. When an Expert Advisor manages an open position, our standard CExpertTrailing processes the stop-loss linearly. This in principle is done by checking the current tick, comparing it against the prior stop (if there is one) and then makes a sequential adjustment. In a ‘vacuum’, this works perfectly. However, in triangular arbitrage—especially when each pair uses a complex neural network—computational efficiency becomes critical.
Iterating through an array that is linear in order to identify the next valid trailing node on every new bar can bring microscopic and yet compounding latency. When one’s EA has dozens of volatile forex pairs concurrently this O(n) time complexity can be a performance bottleneck. Our take here though, is that Latency is only a symptom of a much larger issue: price-gap vulnerability.
Financial markets do not operate in perfect states all the time. The flow is not contiguous. These can be expected during macroeconomic news releases, or when there are rollover periods or unexpected institutional liquidations; so that liquidity evaporates. In these situations price does not tick neatly from 1.0500 to 1.0501; it vanishes from 1.0500 before aggressively reappearing at 1.0450! Standard linear trailing algorithms can muddle through this, but they are not equipped to handle non-contiguous price gaps. The thesis here is that because they search sequentially, a price jump over their predefined step threshold, can break their math logic. The EA is simply forced to execute the stop at the next available quote and this can force the trader to absorb significant slippage, since the code cannot ‘jump’ the void.
Compounding this structural weakness is also the issue of market noise. Traditional trailing stops are purely reactive and tend to suffer from a lack of ‘memory’. These stops often base their execution wholeheartedly on the most recent localized delta in price. If an asset is amidst a solid uptrend, a momentary retracement - like some sharp bear price bar from a localized block order - will immediately trigger a tight linear stop. These algorithms tend to blindly interpret this noise as a trend reversal and can shake a trader out of a decently profitable position, before the macro trend resumes. Given that the linear stop does not have associative memory, it is not well-equipped to contextualize the current price action over a broader, stable pattern. It tends to be terrible at separating structural breakdown from temporary whipsaw.
Thus, it is these failures - computational latency, large slippage in price gaps, and premature exits - that represent the core problems algorithmic traders need to tackle. In order to graduate from theoretical back tests into live-market profitability, we need to abandon the linear paradigm. In this article, we argue for a trailing algorithm that performs probabilistic, non-sequential searches to navigate price gaps. We also back it with a neural filter that recognizes stable long-term trends.
Skip Lists
In order to solve issues of latency and price-gap vulnerabilities common with linear stops, it can be helpful to look outside traditional financial math by borrowing concepts from computer science. For this we picked the skip list. This is a probabilistic data structure that was pioneered in 1989. Originally designed as a simplification of balanced-trees, the skip list inherently layers many linked lists on top of one another.
The bottom layer would contain all data points in the set. Subsequent layers above this then act as an ‘express-lane’ by containing an increasingly sparse and randomized subset of the layer beneath it. Within a standard linear array - that is the approach MT5 takes by default when evaluating an array - searching for correct exit points over a 50 point gap, for example, necessitates the algorithm to iterate in sequence. This, as mentioned above, represents O(n) complexity and can be a massive computational waste during critical market moments.
A skip list, however, begins its search at the highest and most sparse layer of the structure. It also leaps over large amounts of the dataset until it overshoots its target. When it does, it drops to a more granular layer, fine-tuning its search thus achieving O(log n) complexity. With these operations, how could they translate into an MQL5 risk management tool? In order to answer this, we need to redefine what we think of when considering price-action.
In our model, the base layer of the skip list represents the raw contiguous MT5 tick data. Every node in the list, is a micro-price point. The higher layers stand for the ‘volatility tiers’. When a high-impact news event hits the newswires, price does not just move, it teleports. If an Expert Advisor uses a regular trailing stop its logic gets trapped in the base layer, while trying to compute suitable exit prices within a liquidity void where no actual trading is taking place. By implementing a skip list algorithm our Expert Advisor can dynamically shift its search into a higher volatility tier. This is done by elegantly ‘skipping’ over empty, non-contiguous price gaps, bypassing the latency traps and immediately anchoring the trailing stop to the next valid cluster of available market liquidity.
The prime benefits of this approach could lie in its probabilistic nature. Unlike a rigid ‘step’ that moves by a fixed, hard-coded parameter, like to move the stops by X amount of points, our skip lists determine their ‘express-lanes’ from randomized probability. In our implementation of ‘SkipSearchProbabilistic’ (as well as three alternative execution modes) the algorithm dynamically rolls dice to establish how many levels it should skip on any given iteration. Of the three proposed modes the randomized approach could be suitable in certain market situations. Why?
Because currency markets can be non-deterministic. When grappling with volatility regimes, they can be very chaotic and always shifting. A rigid math step can - and often does - fall out of sync with the market’s rhythm. A probability-based algorithm that is helping with search, could be better placed to ‘organically’ adapt to such environments. Such an algorithm generates wider, faster, trailing jumps in violent market expansions while also generating conservative steps in times of consolidation. By discarding the flawed assumption that price moves continuously, the skip list algorithm is able to give us some ‘math-protection’ against flash crashes by systematically hunting for the safest structural anchor point, locking in profits.
Hopfield Networks and Associative Memory
In the last article on dynamic position sizing where we developed a custom money management class, we also used a 1-D Convolutional Neural Network. The aim of that setup was inherently predictive: extract hidden features from historical price data in order to forecast the optimal capital allocation in the upcoming trade. However, when managing a position that is already open, forecasting should take a back seat to recognizing the present state. Once capital is deployed, we can no longer try to speculate on the future; rather we have an open position that demands we first survive the present.
We need to continuously establish if the current price action is a structural trend continuation or localized market noise. In this particular case therefore a predictive CNN would not be appropriate, instead we could look at a Hopfield network. Introduced in 1982, it is a single-layer recurrent artificial neural network that works as a content-addressable, or associative system of memory. Human memory can be highly associative. If one views a photograph that is heavily blurred or partially obscured, his brain can instantly fill in the data that is missing by linking the visual fragments with a clear memory of the subject.
This network does this for mathematical sequences. When presented with a distorted, noisy, or incomplete input pattern, the network iteratively updates its neuron states until it converges to a stored state. Within the context of algorithmic risk management, this ability to associate can be a super-power. Financial markets are often noisy. A strong, macro bullish trend can often print sharp erratic bearish price-bars due to minor liquidity grabs or institutional block order execution. In these situations a linear trailing stop can react blindly to this noise by tightening its stop levels and thus shaking out a trader just before the macro trend resumes.
By integrating the Hopfield network, we provide the Expert Advisor with a ‘neural filter’. This network takes the messy, localized state of the market and makes associations between it and the broader momentum. It mathematically asks: ‘Despite these recent moves, does the overall structure still resemble a stable market or an intact trend’? The math engine driving this associative convergence is the network’s Energy Function, E, that we define as:

Where:
- Wij represents the connection weights between the neurons
- S is the binary state (Up or Down momentum) of the neurons.
Physically, in thermodynamics, systems naturally seek the state of least energy. The Hopfield network thus tries to imitate this principle. As the network processes rolling price momentum, its energy levels do fluctuate. When the network spots a stable, familiar market pattern, its energy function minimizes, thus settling into a deep ‘basin of attraction’. Conversely, when the market changes into whipsawing or ‘unpredictable-chaos’, the network will not converge on a recognized stored memory and therefore its energy state will spike.
In our custom trailing class, the energy function becomes the ultimate gatekeeper—a mathematical veto system. We do not use the network to compute the next price stop level but rather we rely on the probability-based skip list for that spatial calculation. Rather, prior to the skip list being allowed to run its jump move and then halt, the command needs to pass through the Hopfield filter. For this, we set up a ‘HopThreshold’ parameter. If the network’s calculated energy sits below this threshold, it confirms structural stability, and the trailing stops level can be adjusted accordingly. However, if the energy level exceeds the threshold—indicating a chaotic whipsaw or noise - the network vetoes the action. When this happens, the trailing stop is held in place, because we do not want to react to this noise until the ‘algorithmic storm’ passes and the network stabilizes.
MQL5 Implementation
Moving from theory to practice in the form of usable MQL5 code is always our aim within these articles, and so we try to structure this logic to integrate it with the ‘CExpertTrailing’ base class. This allows our algorithm to be assembled into an Expert Advisor via the MQL5 Wizard.
Initialization:
We start by declaring the Wizard macros. This is important in order for the Wizard assembly engine to parse out the input parameters: ‘SkipLevels’, ‘SkipMode’, and ‘UseHopfield’. These parameters are necessary for dictating the maximum ‘height’ of the probability jumps, selecting the algorithm for iteration, and setting the energy veto limit, respectively.
We establish the Hopfield memory matrix as follows:
//+------------------------------------------------------------------+ //| Initialization: Set up Hopfield Weights | //+------------------------------------------------------------------+ bool CTrailingSkipHopfield::InitIndicators(CIndicators *indicators) { if(!CExpertTrailing::InitIndicators(indicators)) return false; //--- Initialize Hopfield Weights with a basic stable memory pattern ArrayInitialize(m_state, 1.0); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { if(i == j) m_weights[i][j] = 0.0; // No self-connections else m_weights[i][j] = 0.5; // Simple associative pull } } return true; }
In the initialization function above a 3-neuron state array is initialized to the value 1.0 which assumes a bullish baseline memory. The weight matrix ‘m_weights’ is filled with ‘0.5’ for all cross-connections. In a true Hopfield network, a neuron cannot connect to itself thus the ‘0.0’ population of the diagonal (where i == j) is performed. This symmetrical weights matrix gives us the associative ‘gravity’ that should move our rolling price momentum into a state that is stable.
Hopfield Logic:
Before the skip list is made to work out a stop-loss price, the Expert Advisor should do an update of the Hopfield network with the latest market state. The MQL5 function for this is listed here://+------------------------------------------------------------------+ //| Hopfield Update: Shift states based on price momentum | //+------------------------------------------------------------------+ void CTrailingSkipHopfield::UpdateHopfield(double price) { if(m_last_price == 0.0) { m_last_price = price; return; } //--- Determine input momentum: 1.0 (Up) or -1.0 (Down) double input_state = (price >= m_last_price) ? 1.0 : -1.0; m_last_price = price; //--- Shift state array (rolling window) m_state[2] = m_state[1]; m_state[1] = m_state[0]; m_state[0] = input_state; }
This function acts as a rolling window of momentum. We compare the current ‘price’ to ‘m_last_price’. If the market ticked upwards, the input state is ‘1.0’; if it was down it is ‘-1.0’. Following this, we perform a shift in the ‘m_state’ array by pushing the oldest memory out and slotting the new momentum state into ‘m_state[0]’. With this done, we now have to determine if the new state is stable, and we determine this by calling the function below:
//+------------------------------------------------------------------+ //| Hopfield Energy Calculation | //+------------------------------------------------------------------+ double CTrailingSkipHopfield::GetHopfieldEnergy() { double energy = 0.0; //--- E = -0.5 * sum(W_ij * S_i * S_j) for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { energy += m_weights[i][j] * m_state[i] * m_state[j]; } } return -0.5 * energy; }What we do in this function is a literal translation of:

We introduced and covered this formula above. If the rolling momentum does match the structural weights of the network, the resulting ‘energy’ will be highly negative (i.e. stable). However, if the momentum is erratic - rapidly flipping between ‘+1.0’ and ‘-1.0’, due to market noise - the energy output spikes toward zero or positive territory.
Skip-List Modes:
Once the Hopfield network allows execution, the Expert Advisor evaluates the price by using one of four distinct skip list iterations that are mapped via a ‘switch’ statement that is controlled by parameter ‘m_skip_mode’.//+------------------------------------------------------------------+ //| Skip List Mode 1: Deterministic Linear Search (Base Level) | //+------------------------------------------------------------------+ double CTrailingSkipHopfield::SkipSearchLinear(double price) { //--- Evaluates price linearly without jumping gaps return price; }
This is our baseline. It imitates standard trailing logic by processing the precise localized price while avoiding jumping gaps. It is compute-heavy O(n) when used iteratively especially in multi-symbol settings. This therefore serves as a primary benchmark to prove the efficiency of the higher modes.
Next we have the skip search mode that is implemented as follows:
//+------------------------------------------------------------------+ //| Skip List Mode 2: Gap Search (Jumps fixed levels) | //+------------------------------------------------------------------+ double CTrailingSkipHopfield::SkipSearchGap(double price) { //--- Subtracts a fixed gap buffer based on defined skip levels double gap_buffer = (m_skip_levels * 2) * m_symbol.Point(); return price - gap_buffer; }
With this mode, we introduce a rudimentary bypass. By utilizing a fixed multiplier against the ‘m_skip_levels’, the algorithm intentionally ‘skips’ a static block of price points. This then prevents the stop-loss from anchoring in minor slippage zones that are known but are not dynamic. Our next mode is probabilistic search:
//+------------------------------------------------------------------+ //| Skip List Mode 3: Probabilistic Search (Coin flip skips) | //+------------------------------------------------------------------+ double CTrailingSkipHopfield::SkipSearchProbabilistic(double price) { //--- Simulates standard Skip List probability (typically P=0.5) int current_level = 1; while(current_level < m_skip_levels && (MathRand() % 2 == 0)) { current_level++; } double prob_buffer = current_level * 5 * m_symbol.Point(); return price - prob_buffer; }
This function runs at O(log n) for the skip list. We use ‘MathRand()%2 == 0’ to simulate a 50/50 coin flip. If the flip is heads, this algorithm dynamically promotes the search to a higher volatility tier with this getting repeated up to the ‘m_skip_levels’ input parameter cap. The trailing buffer is then scaled based on the final ‘current_level’. This allows the stop-loss to organically jump more, as a compensation, in cases where the market is very volatile. Our final mode is the hybrid approach that we implement as follows:
//+------------------------------------------------------------------+ //| Skip List Mode 4: Hybrid Search (Max gap bypass) | //+------------------------------------------------------------------+ double CTrailingSkipHopfield::SkipSearchHybrid(double price) { //--- Forces search to the highest skip level immediately for high volatility double max_buffer = (m_skip_levels * 10) * m_symbol.Point(); return price - max_buffer; }
This mode could work in extreme macroeconomic news releases since it forces the algorithm straight to the top of the apex tier. It assumes maximum gap vulnerability and applies the widest possible node jump in order to ensure the position isn’t stopped out by flash-crash slippage. We bring this all together in long and short conditions as follows:
//+------------------------------------------------------------------+ //| Check Long: Skip List -> Hopfield -> Execution | //+------------------------------------------------------------------+ bool CTrailingSkipHopfield::CheckTrailingStopLong(CPositionInfo *position, double &sl, double &tp) { if(position == NULL) return false; double price = m_symbol.Bid(); //--- 1. Neural Network Filter (Hopfield) if(m_use_hopfield) { UpdateHopfield(price); //--- If energy is higher than threshold, pattern is unstable; do not trail if(GetHopfieldEnergy() > m_hop_threshold) return false; } //--- 2. Skip List Algorithm (Select Mode) double base_price = price; switch(m_skip_mode) { case 1: base_price = SkipSearchLinear(price); break; case 2: base_price = SkipSearchGap(price); break; case 3: base_price = SkipSearchProbabilistic(price); break; case 4: base_price = SkipSearchHybrid(price); break; default: base_price = SkipSearchLinear(price); break; } //--- 3. Trailing Execution double new_sl = base_price - (m_symbol.StopsLevel() * m_symbol.Point()); double current_sl = position.StopLoss(); if(new_sl > current_sl || current_sl == 0.0) { sl = NormalizeDouble(new_sl, m_symbol.Digits()); return true; } return false; } //+------------------------------------------------------------------+ //| Check Short: Skip List -> Hopfield -> Execution | //+------------------------------------------------------------------+ bool CTrailingSkipHopfield::CheckTrailingStopShort(CPositionInfo *position, double &sl, double &tp) { if(position == NULL) return false; double price = m_symbol.Ask(); //--- 1. Neural Network Filter (Hopfield) if(m_use_hopfield) { UpdateHopfield(price); if(GetHopfieldEnergy() > m_hop_threshold) return false; } //--- 2. Skip List Algorithm (Select Mode) double base_price = price; switch(m_skip_mode) { case 1: base_price = SkipSearchLinear(price); break; case 2: base_price = SkipSearchGap(price); break; case 3: base_price = SkipSearchProbabilistic(price); break; case 4: base_price = SkipSearchHybrid(price); break; default: base_price = SkipSearchLinear(price); break; } //--- 3. Trailing Execution double new_sl = base_price + (m_symbol.StopsLevel() * m_symbol.Point()); double current_sl = position.StopLoss(); if(new_sl < current_sl || current_sl == 0.0) { sl = NormalizeDouble(new_sl, m_symbol.Digits()); return true; } return false; }
With these two functions, the neural veto is active. If 'm use hopfield' is true, the Expert Advisor calculates the energy. If it exceeds 'm hop threshold', the function returns false. This result would mean the market is too noisy to take any recent price gyrations as warranting a stop-loss adjustment. If on the other hand the energy is stable, the function proceeds to the ‘switch’ statement to run the selected skip list mode and work out the new stop loss (‘new_sl’). This is set relative to the symbol’s ‘StopsLevel()’ and it effectively modifies the position. By bringing together these two computer science methods of an algorithm and neural network one can say we have transitioned from reactive linear trailing stops to a balanced, proactive defense mechanism.
Performance Analysis
To validate the advantages of 'CTrailingSkipHopfield', we ran rigorous backtests in the Strategy Tester. We performed our tests with the pair GBP JPY with optimization for the year 2025, and forward run from 2026.01.01 to 2026.05.01. Besides establishing the overall efficacy of the trailing class in safeguarding position profits, we need to get a sense of how much the Skip algorithm is influential in this synergy versus the Hopfield network. Thus, we perform two tests with the first run being with only the probabilistic skip list algorithm while the second run tests the fully integrated hybrid system with the Hopfield network serving as the neural gatekeeper. The first run results are given below:

In the first run, post-optimization, we had disabled the neural network by having the parameter ‘m_use_hopfield’ as false in order to isolate the performance of our baseline algorithm logic. We attach the input parameters for this forward-walk run as 'r1.set'. In these attached input values we can see that the closing threshold, ‘Signal_ThresholdClose’, was set to a relatively high value of 57, and we had a wide deviation threshold as well for the Envelopes' indicator of 0.485. Arguably, one can say this was a necessary concession given that we had the neural network noise filter absent; the EA therefore required a wider breathing room for its entry signal in order to avoid being chopped by the entry signal.
The first forward-walk results do show a reasonable structural advantage over standard linear trailing stops. By having the stops gap dynamically shifted to higher volatility tiers where we optimized to have ‘m_skip_mode’ as 3 the Expert Advisor was able to successfully navigate macroeconomic price gaps. During fast-moving flash events where price gaps are significant, in the instances where linear stops would have been easily triggered, it can be said that our algorithm elegantly bypassed these ‘empty spaces’. This spatial defense gave us a net profit of $1,586.39 while maintaining a reasonable drawdown of 18.63%. However, by only partly following our thesis in the problem statement, it can be argued that without associative memory, the algorithm remained reactive for the most part. It was still susceptible to localized chop, or occasionally trailing too aggressively leading to premature position exits.
On the second post-optimization forward run, we had introduced the neural network:

As expected in this second post-optimization forward stint, we engaged a hybrid system where the parameter ‘m_use_hopfield’ was assigned ‘true’. With the neural gatekeeper engaged, we were configured to run more aggressive entry parameters. If we look at the attached inputs for the second run in the file ‘r2.set’, we can see that we significantly lowered the closing threshold ‘Signal_ThresholdClose’ from 57 in the first run to 13. Also, we tightened the ‘Signal_Envelopes_Deviation’ input parameter from 0.485 to just 0.100.
The rationale is that because the Hopfield network is continuously evaluating the associative energy of the price momentum, the Expert Advisor no longer has to rely on artificially wide adjusted technical indicators, to survive market noise. Whenever the markets get chaotic, the energy function (E) would spike above the ‘HopThreshold’, and the network would essentially veto any trailing actions. The impact of this is striking. Whereas our overall profit declined, the equity drawdown collapsed to just 6.79%. In fact in the first run, the 18% drawdown was for a value $2,376.88 which was almost twice the netted profit of $1,500. By contrast, we now have a drawdown amount of just $820 which is less than one third of our eventual net profit.
Takeaways (Summary)
For traders who are keen on automating their strategies by deploying these algorithms in live settings a number of tech nuances need to be handled:
-
Tuning the Associative Gatekeeper: The ‘HopThreshold’ is a very sensitive parameter, and it is highly asset-dependent. A volatile currency cross such as the GBP JPY that we tested with in this case, is bound to generate a lot of baseline associative ‘energy’ in a regular trend when compared to a slower pair like EUR CHF. One should therefore optimize this parameter to work well with the intended trade asset.
-
The Deterministic Backtesting Trap: When coding algorithms that use probability such as the skip list one should not rely on MQL5’s ‘MathRand()’ function. This tends to introduce a fatal flaw: non-repeatable test results and arguably performance. A pragmatic solution is often building a custom Pseudo-random number generator (PRNG) within the class, seeded deterministically by the current bar’s timestamp.
-
Wizard Modularity: As always, the real power of putting together these computer science ideas into the ‘CExpertTrailing’ framework is modularity. One no longer needs to hardcode this logic, but they can take it and pair it to different entry signals or money management methods.
Conclusion
The evolution from linear position management to probability-based risk shielding can be a necessary leap for traders operating in uncertain environments. By abandoning sequential constraints and integrating O(log n) efficiency of the skip list, we reduce latency and slippage of regular Expert Advisors.
| name | description |
|---|---|
| wz_91.mq5 | Wizard assembled Expert Adisor |
| TrailingSkipHopfield.mqh | Custom Trailing Class used by Wizard in Assembly |
| r1.set | Input settings for run only with algorithm |
| r2.set | Input settings with algoruthm and neural network. |
We tested with GBP JPY from 2025.01.01 to 2026.05.01 on the 4-hour timeframe and the entry signal was based on the in-built classes of the Envelopes and the RSI.
Warning: All rights to these materials are reserved by MetaQuotes Ltd. Copying or reprinting of these materials in whole or in part is prohibited.
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.
Publish Your Article Code to MQL5 Algo Forge in 10 Minutes: A Step-by-Step Guide
Overcoming Accessibility Problems in MQL5 Trading Tools (Part IV): Remote voice trading
Price Action Analysis Toolkit Development (Part 70): Turning Flag Pattern Signals into Automated Trade Execution
Trading with the MQL5 Economic Calendar (Part 11): Modular Canvas News Dashboard
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use