MQL5 Bootstrap (I): Reusable Functions for Working with Positions and Orders - MQL5 Articles

What's wrong with regular VPS?Here are the 8 most common problems that algorithmic traders may encounterRead
MetaTrader 5 / Trading
Content
- Introduction
- Position existence checkers
- Position counters
- Closing positions
- Getting recent position information
- Getting oldest position information
- SMA crossover reversal strategy example
- Conclusion
Introduction
Do you frequently find yourself rewriting the same functions during your MQL5 development process? If you've created multiple Expert Advisors, Scripts, or Indicators, the answer is likely yes.
Many fundamental tasks in trading systems are repetitive. For instance, almost every Expert Advisor requires features such as trade monitoring and management, trailing stops, breakeven triggers, partial closes, position counting, order detection, inspecting trade history, and robust methods for closing or removing trades. These functionalities are not specific to any particular strategy; they are essential structural components.
While every developer has their preferred coding style, recreating these standard functions for each new program is inefficient and counterproductive for several reasons:
-
Increased risk of bugs. Each time you duplicate logic, you introduce the potential for new inconsistencies or subtle errors. For example, a trailing stop that worked flawlessly in one EA might behave differently in another due to a minor oversight. A routine for closing positions might succeed with one broker but fail with another because of varying fill modes. Reimplementing the same logic repeatedly significantly increases the chance of small, yet costly, mistakes.
-
Inconsistent behavior across projects. Without a shared core library, each Expert Advisor might handle tasks like position detection, order cancellation, risk calculations, and trade closing logic slightly differently. Over time, this lack of uniformity complicates debugging and makes code maintenance far more challenging.
-
Wasted development time. "Time spent reinventing boilerplate code is time that could be better used improving strategy logic, optimizing performance, or fostering innovation." Developers should focus on strategy design and system robustness, rather than constantly reimplementing basic trade utilities or position filters.
-
Difficult maintenance. Imagine discovering a bug in your position-closing logic. If you've copied that code across 10 different EAs, you now have 10 separate files to update. A centralized, reusable module allows for a single fix that benefits all interconnected projects.
-
Poor scalability. As projects grow in size and complexity, duplicated code becomes increasingly difficult to manage.
-
Reduced code readability. Essential strategy logic can get lost amidst extensive, repetitive utility code. You’ve likely encountered an Expert Advisor that is so dense and compact that pinpointing the actual trading logic becomes a challenge!
When fundamental utilities are abstracted into reusable libraries and modules within the include folder, MQL5 programs like Expert Advisors become cleaner, more readable, and solely focused on their core trading logic.
A reusable code layer fosters a cleaner architecture, promotes separation of concerns, enhances project organization, and simplifies collaboration. This is what I refer to as "Bootstrap."
Inspired by Bootstrap (formerly Twitter Bootstrap), a front-end framework for web developers, which gained immense popularity by offering a collection of pre-written CSS and JavaScript components to eliminate designing common interface elements from scratch.
In this first article of the series, we will develop and compile reusable functions and code specifically for managing positions and orders.
Position Existence Checkers
These functions are particularly useful in strategies where trading is based on a single signal or only one directional trade at a time. They help determine if an existing position is open before initiating a new one or prevent unintended additional trades.
1//+------------------------------------------------------------------+
2//| Returns true if a position exists filtered by |
3//| symbol, magic, type, or ticket |
4//+------------------------------------------------------------------+
5bool PositionExists(const string symbol="",
6 const long magic=LONG_MAX,
7 const int type=-1,
8 const long ticket=-1)
9 {
10 bool use_symbol = (symbol != "");
11 bool use_magic = (magic != LONG_MAX);
12 bool use_type = (type != -1);
13 bool use_ticket = (ticket != -1);
14
15 CPositionInfo pos;
16
17 for(int i = PositionsTotal-1; i >= 0; --i)
18 {
19 if(!pos.SelectByIndex(i))
20 continue;
21
22 if(use_symbol && pos.Symbol != symbol)
23 continue;
24 if(use_magic && pos.Magic != magic)
25 continue;
26 if(use_type && (int)pos.PositionType != type)
27 continue;
28 if(use_ticket && pos.Ticket != ticket)
29 continue;
30
31 //--- passed all active filters
32 return true;
33 }
34 return false;
35 }To ensure this function's versatility, it accepts four optional parameters: symbol, magic, position type, and ticket. This allows for flexible filtering and checking of positions based on specific criteria.
All arguments are provided with default values, making them optional.
The function returns true if a position passes all active filters; otherwise, it returns false.
To simplify our development process, let's create derived functions (variants) for the same purpose, each with a more specific name.
A: Checking if a position exists using its magic number
Magic numbers are crucial for differentiating trades (orders and positions) initiated by various Expert Advisors or strategies. Often, we need to quickly verify the existence of positions associated with a particular magic number.
1//+------------------------------------------------------------------+
2//| Returns true if a position exists with a specified ticket number|
3//+------------------------------------------------------------------+
4bool PositionExistsByMagic(int magic)
5 {
6 return PositionExists("", magic);
7 }B: Checking if a position exists on a particular instrument
For operations focused on specific financial instruments, the following function is highly useful. It checks whether a position exists for a given symbol.
1//+------------------------------------------------------------------+
2//| Returns true if a position exists with a specified symbol |
3//+------------------------------------------------------------------+
4bool PositionExistsBySymbol(string symbol)
5 {
6 return PositionExists(symbol);
7 }C: Checking if a position of a given type exists
1//+------------------------------------------------------------------+
2//| Returns true if a position exists with a specified type |
3//+------------------------------------------------------------------+
4bool PositionExistsByType(ENUM_POSITION_TYPE type)
5 {
6 return PositionExists("", LONG_MAX, type);
7 }The function above takes a position type as an argument and returns true if a position of that type exists, or false otherwise.
D: Checking if a position with a given ticket exists
Although less frequently used than other function variants, this function is valuable in trading panels for manually closing trades identified by a specific ticket.
1//+------------------------------------------------------------------+
2//| Returns true if a position exists with a specified type |
3//+------------------------------------------------------------------+
4bool PositionExistsByType(ENUM_POSITION_TYPE type)
5 {
6 return PositionExists("", LONG_MAX, type);
7 }Position Counters
Position counter functions are highly beneficial in nearly every Expert Advisor. They not only inform us about the number of active positions in the market but can also function similarly to the methods discussed above for detecting if a position generally exists.
1//+------------------------------------------------------------------+
2//| Counts positions filtered by symbol, magic, type, or ticket |
3//+------------------------------------------------------------------+
4int PositionCount(const string symbol="",
5 const long magic=LONG_MAX,
6 const int type=-1,
7 const long ticket=-1)
8 {
9 bool use_symbol = (symbol != "");
10 bool use_magic = (magic != LONG_MAX);
11 bool use_type = (type != -1);
12 bool use_ticket = (ticket != -1);
13
14 CPositionInfo pos;
15
16 int count = 0;
17 for(int i = PositionsTotal-1; i >= 0; --i)
18 {
19 if(!pos.SelectByIndex(i))
20 continue;
21
22 if(use_symbol && pos.Symbol != symbol)
23 continue;
24 if(use_magic && pos.Magic != magic)
25 continue;
26 if(use_type && (int)pos.PositionType != type)
27 continue;
28 if(use_ticket && pos.Ticket != ticket)
29 continue;
30
31 //--- passed all active filters
32 count++;
33 }
34
35 return count;
36 }The underlying logic is largely similar to the existence checkers. However, instead of returning a boolean value upon finding a position, this function increments a count variable and returns the total count at the end.
Similar to the previous methods, we will introduce several variants for counting positions based on specific attributes.
A: Counting Positions With a Specific Magic Number
1//+------------------------------------------------------------------+
2//| Counts positions with a specified magic number |
3//+------------------------------------------------------------------+
4int PositionCountByMagic(int magic)
5 {
6 return PositionCount("", magic);
7 }B: Counting Positions for a Specific Instrument
1//+------------------------------------------------------------------+
2//| Counts positions with a specified symbol |
3//+------------------------------------------------------------------+
4int PositionCountBySymbol(string symbol)
5 {
6 return PositionCount(symbol);
7 }C: Counting Positions of a Specific Type
1//+------------------------------------------------------------------+
2//| Counts positions with a specified type |
3//+------------------------------------------------------------------+
4int PositionCountByType(int type)
5 {
6 return PositionCount("", LONG_MAX, type);
7 }Closing Positions
While stop-loss and take-profit orders handle many trade exits, an instant position closing function is crucial for situations where a strategy needs to exit the market rapidly due to various circumstances.
Examples of scenarios requiring position closures:
- Before high-impact news releases in forex to avoid extreme market volatility.
- When predefined risk limits are breached, such as when account balance, margin, or equity falls below an acceptable threshold.
1//+------------------------------------------------------------------+
2//| Closes positions filtered by symbol, magic, type, or ticket |
3//+------------------------------------------------------------------+
4void PositionClose(const long deviation_points=LONG_MAX,
5 const string symbol="",
6 const long magic=LONG_MAX,
7 const int type=-1,
8 const long ticket=-1)
9 {
10 bool use_symbol = (symbol != "");
11 bool use_magic = (magic != LONG_MAX);
12 bool use_type = (type != -1);
13 bool use_ticket = (ticket != -1);
14
15 CPositionInfo pos;
16 CTrade trade;
17
18 for(int i = PositionsTotal-1; i >= 0; --i)
19 {
20 if(!pos.SelectByIndex(i))
21 continue;
22
23 if(use_symbol && pos.Symbol != symbol)
24 continue;
25 if(use_magic && pos.Magic != magic)
26 continue;
27 if(use_type && (int)pos.PositionType != type)
28 continue;
29 if(use_ticket && pos.Ticket != (ulong)ticket)
30 continue;
31
32 const string sym = pos.Symbol;
33
34 //---
35
36 trade.SetExpertMagicNumber(magic);
37 trade.SetTypeFillingBySymbol(pos.Symbol);
38
39 if (!trade.PositionClose(pos.Ticket, deviation_points))
40 printf("Failed to close position #%I64u", pos.Ticket);
41 }
42 }All arguments are optional, meaning that if no filters are provided, the function will close all open positions in the MetaTrader 5 terminal.
To streamline development, we require specific variations of this function.
| Function | Description |
|---|---|
mq5<br>void ClosePositionsBySymbol(string symbol, long deviation_points=LONG_MAX)<br> | Closes positions based on the specified symbol as a filter. |
mq5<br>void ClosePositionsByMagic(int magic, long deviation_points=LONG_MAX)<br> | Closes positions marked with a specific magic number. |
mq5<br>void ClosePositionsByType(ENUM_POSITION_TYPE type, long deviation_points=LONG_MAX)<br> | Closes positions of a given type. |
Furthermore, we can introduce functions specifically designed for closing profitable and losing trades.
| Function | Description |
|---|---|
mq5<br>void CloseProfitablePositions(const long deviation_points=LONG_MAX,<br> const string symbol="",<br> const long magic=LONG_MAX,<br> const int type=-1,<br> const long ticket=-1)<br> | Closes all profitable positions matching the specified properties. |
mq5<br>void CloseLosingPositions(const long deviation_points=LONG_MAX,<br> const string symbol="",<br> const long magic=LONG_MAX,<br> const int type=-1,<br> const long ticket=-1)<br> | Closes all losing positions matching the specified properties. |
Getting Recent Position Information
The latest position information is critical for trading systems and strategies that need the most current trade data to determine how and where to place new positions or orders.
Functions for such tasks are applicable in:
- Pyramiding or grid-based trading strategies. In these strategies, the calculation for the next position's opening price often depends on the placement of the previous position.
- Time-based strategies. Have you ever encountered or implemented strategies that close trades after a certain duration since the position was opened?
- Money management and lot sizing for grid or semi-grid trading strategies.
Below is a function for retrieving the most recently opened position's information.
1//+------------------------------------------------------------------+
2//| Returns the most recently opened position filtered by |
3//| symbol, magic, or type |
4//+------------------------------------------------------------------+
5bool GetRecentPosition(CPositionInfo &pos_info,
6 const string symbol="",
7 const long magic=LONG_MAX,
8 const int type=-1)
9 {
10 bool use_symbol = (symbol != "");
11 bool use_magic = (magic != LONG_MAX);
12 bool use_type = (type != -1);
13
14 ulong recent_ticket = 0;
15 ulong last_time_msc = 0;
16
17 CPositionInfo pos;
18
19 for(int i = PositionsTotal-1; i >= 0; --i)
20 {
21 if(!pos.SelectByIndex(i))
22 continue;
23
24 if(use_symbol && pos.Symbol != symbol)
25 continue;
26 if(use_magic && pos.Magic != magic)
27 continue;
28 if(use_type && (int)pos.PositionType != type)
29 continue;
30
31 //--- passed all active filters
32
33 ulong t = pos.TimeMsc;
34 if (t > last_time_msc)
35 {
36 last_time_msc = t;
37 recent_ticket = pos.Ticket;
38 }
39 }
40
41 if(recent_ticket == 0)
42 return false;
43
44 return pos_info.SelectByTicket(recent_ticket); //--- select the latest position using it's ticket
45 }Unlike previous functions, this one accepts a CPositionInfo object argument by reference. This object is then populated with the details of the most recent position.
The function identifies the position with the newest timestamp and stores its ticket for subsequent use after the loop completion. The SelectByTicket method then populates the pos_info variable using this ticket.
The table below lists variations of this function.
| Function | Description |
|---|---|
| GetRecentPositionBySymbol | Retrieves the newest position using only its symbol as a filter. |
| GetRecentPositionByMagic | Retrieves the newest position using only its magic number as a filter. |
| GetRecentPositionByType | Retrieves the newest position from the terminal using only its position type as a filter. |
Getting Oldest Position Information
While less practically common (in my opinion) than retrieving the most recent position, it is still beneficial to have a function that performs the inverse operation.
The logic employed here is the opposite of its counterpart:
1//+-------------------------------------------------------------------+
2//|Returns the oldest open position filtered by symbol, magic, or type|
3//+-------------------------------------------------------------------+
4bool GetOldestPosition(CPositionInfo &pos_info,
5 const string symbol="",
6 const long magic=LONG_MAX,
7 const int type=-1)
8 {
9 bool use_symbol = (symbol != "");
10 bool use_magic = (magic != LONG_MAX);
11 bool use_type = (type != -1);
12
13 ulong oldest_ticket = 0;
14 ulong oldest_time_msc = ULONG_MAX;
15
16 CPositionInfo pos;
17
18 for(int i = PositionsTotal-1; i >= 0; --i)
19 {
20 if(!pos.SelectByIndex(i))
21 continue;
22
23 if(use_symbol && pos.Symbol != symbol)
24 continue;
25 if(use_magic && pos.Magic != magic)
26 continue;
27 if(use_type && (int)pos.PositionType != type)
28 continue;
29
30 //--- passed all active filters
31
32 ulong t = pos.TimeMsc;
33 if (t < oldest_time_msc)
34 {
35 oldest_time_msc = t;
36 oldest_ticket = pos.Ticket;
37 }
38 }
39
40 if(oldest_ticket == 0)
41 return false;
42
43 return pos_info.SelectByTicket(oldest_ticket); //--- select the oldest position using it's ticket
44 }This function identifies the position with the earliest opening time in milliseconds. Once located, it is selected and assigned to the referenced pos_info variable.
The table below lists variations of this function.
| Function | Description |
|---|---|
| GetOldestPositionBySymbol | Retrieves the oldest position using only its symbol as a filter. |
| GetOldestPositionByMagic | Retrieves the oldest position using only its magic number as a filter. |
| GetOldestPositionByType | Retrieves the oldest position from the terminal using only its position type as a filter. |
Let's create a simple Expert Advisor to demonstrate some of the functions discussed.
SMA Crossover Reversal Strategy Example
This strategy is built upon two Simple Moving Averages (SMAs) with periods of 10 and 20. When a bullish crossover occurs, meaning the 10-period SMA crosses above the 20-period SMA, a buy signal is generated, and a buy position should be opened. Simultaneously, any existing sell position (in the opposite direction) should be closed.
Conversely, if the 10-period SMA crosses below the 20-period SMA, the inverse action should take place: a sell trade should be opened, and any existing buy position should be closed.
SMA crossover EA.mq5
1#include <Bootstrap\positions.mqh>
2#include <Bootstrap\orders.mqh>
3
4#include <Trade\Trade.mqh>
5#include <Trade\SymbolInfo.mqh>
6
7CTrade m_trade;
8CSymbolInfo m_symbol;
9
10//+------------------------------------------------------------------+
11
12input int magic_number = 14022026;
13input uint slippage = 100;
14
15input uint short_sma_period = 10;
16input uint long_sma_period = 20;
17
18//+------------------------------------------------------------------+
19
20int short_handle, long_handle;
21double long_sma_buff[], short_sma_buff[];
22//+------------------------------------------------------------------+
23//| Expert initialization function |
24//+------------------------------------------------------------------+
25int OnInit
26 {
27//---
28 if(!m_symbol.Name(Symbol))
29 {
30 printf("Failed to get symbolinfo, error = %d", GetLastError);
31 return INIT_FAILED;
32 }
33//---
34 m_trade.SetExpertMagicNumber(magic_number);
35 m_trade.SetDeviationInPoints(slippage);
36 m_trade.SetTypeFillingBySymbol(Symbol);
37//---
38 short_handle = iMA(Symbol, Period, short_sma_period, 0, MODE_SMA, PRICE_CLOSE);
39 long_handle = iMA(Symbol, Period, long_sma_period, 0, MODE_SMA, PRICE_CLOSE);
40 TesterHideIndicators(false);
41//ChartIndicatorAdd(0, 0, short_handle);
42//ChartIndicatorAdd(0, 0, long_handle);
43//---
44 ArraySetAsSeries(long_sma_buff, true);
45 ArraySetAsSeries(short_sma_buff, true);
46 return(INIT_SUCCEEDED);
47 }
48//+------------------------------------------------------------------+
49//| Expert deinitialization function |
50//+------------------------------------------------------------------+
51void OnDeinit(const int reason)
52 {
53//---
54 }
55//+------------------------------------------------------------------+
56//| Expert tick function |
57//+------------------------------------------------------------------+
58void OnTick
59 {
60//---
61 if(!m_symbol.RefreshRates)
62 {
63 printf("Failed to fetch latest tick information, error = %d", GetLastError);
64 return;
65 }
66 if(CopyBuffer(long_handle, 0, 0, 2, long_sma_buff) < 0)
67 return;
68 if(CopyBuffer(short_handle, 0, 0, 2, short_sma_buff) < 0)
69 return;
70 double curr_long_sma = long_sma_buff[0], prev_long_sma = long_sma_buff[1],
71 curr_short_sma = short_sma_buff[0], prev_short_sma = short_sma_buff[1];
72//--- long signal
73 if(curr_short_sma > curr_long_sma && prev_short_sma < prev_long_sma)
74 if(!PositionExists(Symbol, magic_number, POSITION_TYPE_BUY))
75 {
76 ClosePositions(slippage, Symbol, magic_number, POSITION_TYPE_SELL); //close an opposite trade
77 m_trade.Buy(m_symbol.LotsMin, Symbol, m_symbol.Ask);
78 }
79//--- short signal
80 if(curr_short_sma < curr_long_sma && prev_short_sma > prev_long_sma)
81 if(!PositionExists(Symbol, magic_number, POSITION_TYPE_SELL))
82 {
83 ClosePositions(slippage, Symbol, magic_number, POSITION_TYPE_BUY); //close an opposite trade
84 m_trade.Sell(m_symbol.LotsMin, Symbol, m_symbol.Bid);
85 }
86 }Results.
Conclusion
The functions presented in this article, sourced from Bootstrap\positions.mqh (linked in the attachments), address the most common "every-EA-needs-this" tasks for managing open positions. These include checking for existence, counting positions, performing bulk closures, and retrieving the newest or oldest position based on opening time.
Given the clear naming and purpose of these helper functions, I chose not to extend this article with their pending-order equivalents beyond mentioning their existence. However, the accompanying project includes a dedicated module—Bootstrap\orders.mqh—that provides similar reusable wrappers for working with orders (specifically pending orders), encompassing functionalities such as:
CancelOrders,CancelOrdersByMagic,CancelOrdersBySymbol,CancelOrdersByTicket,CancelOrdersByTypeOldestOrder,RecentOrderOrderCount,OrderCountByMagic,OrderCountBySymbol,OrderCountByTicket,OrderCountByTypeOrderExists,OrderExistsByMagic,OrderExistsBySymbol,OrderExistsByTicket,OrderExistsByType
In practical development, separating helpers into positions.mqh and orders.mqh aligns with MetaTrader 5's own distinction between trading objects:
- Positions represent the current net exposure for each symbol (and, in netting accounts, typically one position per symbol).
- Orders are instructions (especially pending orders) that may or may not eventually become deals or positions.
- Therefore, closing positions and canceling orders are distinct operations: positions are closed via trade requests, while pending orders are removed or canceled.
This library is purposefully not intended to replace MQL5's Standard Library. Many tasks are already implemented effectively within MetaQuotes' built-in trade classes (e.g., CTrade, CPositionInfo, COrderInfo, CHistory* helpers), and duplicating these would only increase maintenance costs without adding value. Instead, the objective is to provide a thin, reusable layer that standardizes common repetitive tasks: filtering by symbol, magic number, position type, or ticket, and executing bulk operations consistently.
The key takeaway is that these helpers serve as a blueprint and foundational layer—a "bootstrap" for your MQL5 projects. You are encouraged to expand upon this base with project-specific utilities, such as:
- Risk and exposure management (e.g., maximum positions per symbol/magic, maximum volume, maximum drawdown rules).
- Partial close routines.
- Breakeven and trailing-stop frameworks.
- Time-in-trade filters.
- Spread and slippage guards, along with advanced filling-mode handling.
- Historical and deal analytics to inform smarter execution decisions.
The included "Experts\SMA crossover EA.mq5" provides a minimal test Expert Advisor that illustrates how these helper functions allow the strategy code to concentrate solely on signal generation (SMA cross), while the underlying library manages the repetitive "plumbing" of checking, counting, closing, and selecting positions.
Best regards.
Attachments Table
| Filename | Description & Usage |
|---|---|
| Bootstrap\orders.mqh | Contains utility functions for working with pending orders. |
| Bootstrap\positions.mqh | Contains utility functions for working with positions. |
| Experts\SMA crossover EA.mq5 | An expert Advisor for testing functions discussed in this article on a simple moving average crossover trading strategy. |
Attached files |
Download ZIP
Attachments.zip(4.81 KB)
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.
Omega J Msigwa
- Machine Learning Expert at Omegafx
- Tanzania
- 34801
Welcome to my profile! I'm a dedicated and passionate Full-Stack Web Developer with an impressive track record of over 4 years in the field.
My journey in the world of programming has been an exciting one, marked by a relentless pursuit of knowledge and innovation. I thrive on the challenges of the digital realm, constantly seeking opportunities to expand my skill set and deliver exceptional results.
My favorite programming language is Python, a versatile and powerful tool that I have mastered to a tee. I have harnessed the capabilities of Python in various domains, including backend web development, automation, and much more. Whether it's crafting elegant web solutions, streamlining processes through automation, or delving into data analysis, Python is my trusted companion in these endeavors.
Other articles by this author
- Python-MetaTrader 5 Strategy Tester (Part 05): Multi-Symbols and Timeframes Strategy Tester
- Data Science and ML (Part 48): Are Transformers a Big Deal for Trading?
- Python-MetaTrader 5 Strategy Tester (Part 04): Tester 101
- Python-MetaTrader 5 Strategy Tester (Part 03): MetaTrader 5-Like Trading Operations — Handling and Managing
- Python-MetaTrader 5 Strategy Tester (Part 02): Dealing with Bars, Ticks, and Overloading Built-in Functions in a Simulator
- Implementing Practical Modules from Other Languages in MQL5 (Part 06): Python-Like File IO operations in MQL5
Last comments |
Go to discussion
(1)
Chacha Ian Maroa
|
2 Jun 2026 at 17:26
MetaQuotes:
Check out the new article: MQL5 Bootstrap (I): Reusable Functions for Working with Positions and Orders.
Author: Omega J Msigwa
Yeah, this is a great project and idea too. MQL5 should have standardised libraries for various common patterns and tasks.
MQL5 Wizard Techniques you should know (Part 92): Using B-Tree Indexing and a Bayesian NN in a Custom Signal Class
In this article we present yet another custom MQL5 Signal Class that we are labelling ‘CSignalBTreeBayesian’. We are marrying the algorithm of a balanced tree with a neural network that is built on Bayesian principles to formulate yet another custom signal testable independently or with other signals thanks to the MQL5 Wizard.
Modular Indicator Architecture in MQL5 (Part 1): Stop Copy-Pasting and Start Writing Scalable, Reusable Code
This article develops an object-oriented framework for MQL5 indicators by evolving a primitive example into reusable modules. It formalizes partial buffer recalculation in OnCalculate, moves logic into header-based classes (CAppliedPrice, CSma), and introduces CSubIndiBase, CIndicatorBase, and a registry to centralize requirements. You get portable components, isolated inputs, and clean buffers with minimal boilerplate, making new indicators faster to assemble and easier to maintain.
Position Management: Scaling Into Winners With A Falling-Risk Pyramid
We introduce CPyramidBridge, a thin MQL5 layer that maps bet-sizing results to CPyramidEngine. The bridge applies probability to initial lot sizing, enforces a capacity-aware entry gate, promotes add-ons from dynamic divergence, adapts the trailing stop to reserve estimates, and syncs signals on close, allowing an Expert Advisor to convert model confidence and concurrency into a structured, decreasing-risk pyramid.
Encoding Candlestick Patterns (Part 2): Modeling Price Action as an Ordered Sequence
Developing permutation-based tools in MQL5 provides a systematic way to analyze candlestick pattern combinations for trading strategies. This article introduces a permutation calculator and generator designed to compute and enumerate all possible ordered candlestick sequences from bullish and bearish sets, with or without repetition. By generating exhaustive pattern combinations, traders can perform data-driven analysis to identify high-probability market patterns and improve decision-making in automated trading systems.
MetaTrader VPS vs regular cloud hosting services8 reasons why our solution is the best option for automated tradingRead
This website uses cookies. Learn more about our Cookies Policy.
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
RegistrationLog in
latin characters without spaces
a password will be sent to this email
An error occurred
- Log in With Google
You agree to website policy and terms of use
If you do not have an account, please register
Allow the use of cookies to log in to the website.
Please enable the necessary setting in your browser, otherwise you will not be able to log in.
Forgot your login/password?
- Log in With Google
