- 1 1. What Is Modular EA Design in MQL5?
- 2 2. Overall Structure of Modular EA Design
- 3 3. Steps to Design a Modular EA in MQL5
- 4 4. Why Modular Design Is Necessary
- 5 5. Comparison with Other EA Design Methods
- 6 6. Common Failures and Warnings
- 7 7. Practical Use Cases
- 8 8. FAQ
- 8.1 8.1 Can beginners build a modular EA?
- 8.2 8.2 Are .mqh files required?
- 8.3 8.3 Does modular design make optimization unnecessary?
- 8.4 8.4 Can the same design be used in MT4?
- 8.5 8.5 How many filters are necessary?
- 8.6 8.6 How is a modular EA different from an AI or machine learning EA?
- 8.7 8.7 Does modular design reduce performance or processing speed?
- 8.8 8.8 Will modular design make an EA profitable?
- 9 9. Summary (Conclusion)
1. What Is Modular EA Design in MQL5?
1.1 Definition (Conclusion)
Conclusion: Modular EA design is a development method that divides trading logic by function and assembles each function as an independent component.
This structure greatly improves reproducibility, testability, and extensibility.
Definition: Modular design is a design approach that breaks a system into role-based units, or modules, and develops and manages each one independently.
In MQL5, an EA, or automated trading program, has traditionally often placed all logic in a single .mq5 file. However, this method creates the following problems.
- The logic becomes complex and difficult to modify.
- Support for specific conditions, such as spread and slippage, is often added later.
- The reproducibility of test results declines.
With modular design, roles are separated as follows, for example.
- Entry conditions, such as a moving average crossover
- Exit conditions, such as take profit and stop loss
- Filters, such as stopping trading when the spread widens
- Order processing, including execution and order conditions
This separation makes it possible to test each part individually and identify which logic contributes to profit.
A common beginner mistake is splitting the EA so much that it becomes harder to understand.
At first, it is enough to divide the EA into three parts: Entry, Exit, and Filter.
1.2 Why Modular Design Matters
Conclusion: Modular design is necessary because EA profitability depends not only on the quality of the logic but also on the accuracy of the testing process.
In EA development, simply creating logic that appears profitable is not enough.
The key question is whether the result can be reproduced.
For example, the following cases often occur.
- The backtest performs well, but the forward test fails.
- The EA is optimized only for a specific period, causing overfitting.
- The effects of spread and slippage are not considered.
All of these problems occur because the logic is not separated enough.
By using modular design, you can make the following improvements.
- Test a filter by itself.
- Replace only the entry logic and compare results.
- Isolate the impact of execution conditions.
In other words, you can break down and test what caused the EA to win.
In real trading, the following factors have a major impact on performance.
- spread, the difference between bid and ask prices
- slippage, the difference between the requested order price and the executed price
- execution, the mechanism used to process orders
If these are kept inside one combined block of logic, accurate evaluation is not possible.
1.3 Difference from Traditional EA Design
Conclusion: A traditional EA depends on one block of logic, while modular design creates a structure that can be combined and replaced by parts.
A traditional EA with a single structure usually has the following characteristics.
- All logic is concentrated inside OnTick.
- Conditional branches, such as if statements, keep increasing.
- A small change can affect the entire EA.
In modular design, the structure changes as follows.
- Each function is managed in a separate .mqh file.
- Modules are connected through a simple interface.
- Each component can be replaced independently.
A simple image of the structure is shown below.
// Example of a modular structure (simplified)
if(FilterCheck() && EntrySignal())
{
ExecuteOrder();
}
With this structure, the following changes become easy.
- Replace only the entry logic with another strategy.
- Add only a spread filter.
- Disable trading only during a specific time period.
One concern is whether a single-file EA is faster.
In practice, if the EA is designed properly, the performance difference is usually negligible, although it depends on the environment.
The benefits of better maintainability and testability are much greater.
2. Overall Structure of Modular EA Design

2.1 Basic Structure (Role Breakdown)
Conclusion: A modular EA becomes most practical and reusable when it is divided into five parts: Entry, Exit, Filter, Risk, and Execution.
In modular design, an EA is divided by function. The most basic and practical breakdown is as follows.
- Entry Module
Generates trading signals, such as moving average crossovers or RSI conditions. - Exit Module
Handles take profit, stop loss, trailing stop, and similar exit logic. - Filter Module
Avoids unfavorable conditions, such as wider spreads, major news events, and unsuitable trading hours. - Risk Module
Calculates lot size and controls maximum loss. - Execution Module
Handles order submission, slippage tolerance, and execution management.
This breakdown lets you test which element affects profit or loss on its own.
A common beginner mistake is placing everything inside Entry.
If you write a filter, such as a spread limit, inside Entry, it becomes impossible to test the filter separately.
2.2 Data Flow (Processing Order)
Conclusion: Keeping the processing order fixed as Filter → Entry → Risk → Execution → Exit maintains logical consistency.
An EA runs on every Tick, or price update. In a modular structure, processing should follow this order.
- Filter: Check whether trading is allowed.
- Entry: Evaluate the entry condition.
- Risk: Calculate the lot size.
- Execution: Place the order.
- Exit: Manage and close positions.
If this flow is broken, the following problems occur.
- Unnecessary orders, such as evaluating Entry before Filter
- Abnormal lot sizes because Risk was not applied
- Inaccurate backtests
Simple implementation example:
void OnTick()
{
if(!FilterCheck()) return;
if(EntrySignal())
{
double lot = CalculateLot();
ExecuteOrder(lot);
}
ManageExit();
}
The important point is that each module should have only one responsibility.
For example, Entry should not calculate lot size.
2.3 How to Design Interfaces
Conclusion: Connecting modules with simple return values keeps dependencies small.
In modular design, how modules connect is the most important point.
The basic policy is as follows.
- Input: price data and indicator values
- Output: bool or enum, meaning a simple state
Example:
bool EntrySignal()
{
return (iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE,0) >
iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE,0));
}
Returning true or false makes it easy to connect the function to other modules.
For a more advanced design, use enum.
enum SignalType
{
SIGNAL_NONE,
SIGNAL_BUY,
SIGNAL_SELL
};
This design makes the following possible.
- Easy logic replacement
- Automated testing
- Integration of multiple strategies
A key warning is that sharing global variables between modules is not recommended.
It increases dependencies and makes debugging extremely difficult.
2.4 Practical Design Points
Conclusion: If you do not design for future extension, you will almost certainly need to rebuild the EA later.
In practical development, keep the following points in mind.
- Make Filter independent first, especially for spread and slippage control.
- Always keep Risk independent because money management is a separate concern.
- Separate Execution because it depends on broker specifications.
Execution can change greatly depending on the environment.
- Instant Execution
- Market Execution
- ECN environment
If you mix this with Entry, the EA becomes hard to move to another environment.
3. Steps to Design a Modular EA in MQL5
3.1 Procedure (Overall Flow)
Conclusion: Beginners can build a stable modular EA by following four steps: break down, separate, connect, and verify.
Build a modular EA with the following procedure.
- 1. Break the logic down by function.
- 2. Separate each function into an .mqh file.
- 3. Design a common interface.
- 4. Integrate the modules in OnTick.
- 5. Test and verify the EA.
The reason for this order is to minimize the cost of rework.
If you start coding immediately, separation becomes difficult later.
Common beginner failure patterns:
- Writing all logic directly in OnTick
- Starting optimization before separating the logic
- Adding filters later as an afterthought
Even writing the breakdown on paper first improves accuracy.
3.2 Directory Structure Example
Conclusion: Separating modules into the Include folder greatly improves reusability and readability.
A basic structure is shown below.
/MQL5
├── Experts/
│ └── ModularEA.mq5
└── Include/
└── Modules/
├── Entry.mqh
├── Exit.mqh
├── Filter.mqh
├── Risk.mqh
└── Execution.mqh
Role of each file:
- Entry.mqh → entry judgment only
- Exit.mqh → exit management
- Filter.mqh → spread and time control
- Risk.mqh → lot calculation
- Execution.mqh → order processing
This separation creates the rule “one file equals one responsibility.”
Important notes:
- Do not make the files too granular. Three to five files are enough at first.
- Always name files based on their role. Names like Logic1.mqh should be avoided.
3.3 Code Example (Minimum Structure)
Conclusion: The minimum structure works with only three modules: Filter, Entry, and Execution.
Start with a simple structure.
Entry Module
// Entry.mqh
bool EntrySignal()
{
double ma_fast = iMA(NULL,0,10,0,MODE_SMA,PRICE_CLOSE,0);
double ma_slow = iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE,0);
return (ma_fast > ma_slow);
}
Filter Module
// Filter.mqh
bool FilterCheck()
{
double spread = (Ask - Bid) / _Point;
return (spread < 20); // Spread limit
}
Execution Module
// Execution.mqh
void ExecuteOrder(double lot)
{
MqlTradeRequest request;
MqlTradeResult result;
ZeroMemory(request);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lot;
request.type = ORDER_TYPE_BUY;
request.price = Ask;
request.deviation = 10; // slippage tolerance
OrderSend(request, result);
}
Main EA
#include <Modules/Entry.mqh>
#include <Modules/Filter.mqh>
#include <Modules/Execution.mqh>
void OnTick()
{
if(!FilterCheck()) return;
if(EntrySignal())
{
ExecuteOrder(0.1);
}
}
With this structure, a minimum modular EA is complete.
3.4 Testing Method (Important)
Conclusion: If you do not test by module, you will almost certainly fall into the optimization trap.
Testing should be done in the following order.
- 1. Unit testing by module
- 2. Integration testing for the whole EA
- 3. Forward testing in a live-like environment
Specific examples:
- Turn only Filter on and off to measure its impact.
- Replace only Entry and compare results.
- Change the slippage value and test the difference.
Important points:
- Backtest results are only a hypothesis.
- Many EAs fail during forward testing.
Common mistakes:
- Judging the EA complete based only on optimization
- Testing with a fixed spread
- Ignoring execution conditions
In practical work, publishing forward results on services such as Myfxbook can help maintain data transparency.
4. Why Modular Design Is Necessary
4.1 Ensuring Reproducibility
Conclusion: Modular design helps ensure reproducibility because it separates the factors that produced the result.
The most important question in EA evaluation is whether the same conditions produce the same result.
However, a single-structure EA mixes the following elements.
- Entry conditions
- Filters, such as spread and time period
- Execution conditions, such as execution method and slippage
When these are combined, you cannot identify why the EA won.
With modular design, the following tests become possible.
- Disable Filter and measure the impact.
- Change only Entry and compare results.
- Change only the slippage setting and test again.
In other words, you can break the result down by component.
Typical examples of EAs with low reproducibility:
- The backtest is good, but the forward test collapses.
- A small parameter change causes a major performance change.
- The EA stops working when the currency pair changes.
These problems come from logic that has not been separated.
4.2 Avoiding the Optimization Trap
Conclusion: Modular design structurally helps prevent over-optimization, also called overfitting.
In EA development, parameters are often adjusted with optimization tools.
However, the following problems can occur.
- Settings optimized only for a specific period
- Logic that only adapted to market noise
- Results that will not repeat in the future
This is the so-called optimization trap.
Modular design enables the following approach.
- Fix the Entry logic and adjust only Filter.
- Optimize Risk management on a separate axis.
- Test execution conditions independently.
This makes it possible to judge how much confidence you can place in the result.
Important ideas:
- Evaluate the structure, not only the parameters.
- Prioritize logic that can work across different conditions.
Typical beginner mistakes:
- Trying to win only by adjusting parameters
- Optimizing filters added after the fact
4.3 Resilience to Market Changes
Conclusion: Modular design makes it easy to replace logic, so the EA becomes more resilient to market changes.
Markets constantly change.
- Volatility changes
- Spreads widen
- Liquidity decreases
- The execution environment changes
With a single-structure EA, responding to these changes often requires rewriting the entire EA.
With modular design, the following changes are possible.
- Replace only Entry with new logic.
- Add a Filter, such as avoiding major economic events.
- Strengthen Risk management.
In short, the whole EA can be improved through partial changes.
Important practical points:
- Change Filter by currency pair.
- Adjust execution by broker.
- Replace Entry depending on market conditions.
Important warnings:
- If dependencies between modules are too strong, modular design loses its value.
- If the interface design breaks down, reuse becomes impossible.
5. Comparison with Other EA Design Methods
5.1 Design Methods to Compare
Conclusion: EA design can be broadly classified into single-logic, optimization-dependent, AI-based, and modular types. Each has different strengths and risks.
Representative design methods are as follows.
- Single-Logic EA
Built with only one trading rule, such as a moving average crossover. - Parameter-Optimized EA
Adjusts parameters to fit historical data. - AI or Machine Learning EA
Automatically generates rules from data, but can easily become a black box. - Modular EA Design
Divides functions and combines them as components.
A common beginner misunderstanding is that AI is automatically the strongest approach. In practice, testability and reproducibility are serious issues, so AI is not always superior.
5.2 Comparison by Criteria
Conclusion: For long-term operation, modular design has an advantage in reproducibility, extensibility, and resistance to over-optimization.
The comparison below uses these criteria.
| Design Method | Reproducibility | Extensibility | Development Cost | Optimization Resistance | Real Operation Suitability |
|---|---|---|---|---|---|
| Single logic | Low to medium | Low | Low | Low | Low |
| Optimization-based | Low | Low | Medium | Very low | Low |
| AI-based | Unknown, environment-dependent | Medium | High | Medium | Unstable |
| Modular | High | High | Medium | High | High |
Important points:
- Single logic is simple but fragile.
- Optimization-based EAs can look strong in the short term but have low reproducibility.
- AI-based EAs are hard to verify and can easily become black boxes.
- Modular EAs have a testable structure.
5.3 Practical Use Cases
Conclusion: A single-logic EA is reasonable for short-term validation, while modular design is better for long-term operation.
The use cases are as follows.
When a Single-Logic EA Is Suitable
- Early-stage logic testing
- Checking whether an idea has potential
- Learning purposes
When an Optimization-Based EA Is Suitable
- Limited short-term operation
- A strategy specialized for a specific market
However, the risk is high.
When an AI-Based EA Is Suitable
- Research that handles large amounts of data
- Pattern detection under specific conditions
Careful verification is required before operation.
When Modular Design Is Suitable
- Long-term operation, which is the most important use case
- Integration of multiple strategies
- Development that assumes forward testing
The most important practical questions are these.
- Can you explain why the EA is winning?
- Can it adapt when the market changes?
Modular design satisfies these two points.
5.4 Common Misunderstandings and Warnings
Conclusion: Modular design is not a universal solution. Its value depends on design quality.
Common misunderstandings:
- Splitting modules will make the EA profitable → Incorrect
- More modules are always better → Incorrect
- Combining it with AI makes it unbeatable → Uncertain
Warnings:
- If dependencies between modules are strong, modular design loses its meaning.
- If interface design is weak, the structure will break down.
- If the verification process is skipped, the design will not deliver value.
In short, modular design is a method for improving testability. It does not guarantee profit.
6. Common Failures and Warnings
6.1 Excessive Splitting (Anti-Pattern)
Conclusion: If modules are made too small, the result becomes a design that is harder to manage.
The most common beginner mistake in modular design is splitting too much.
Typical examples:
- Splitting Entry into too many parts, such as MA, RSI, and condition-specific files
- Splitting Filter too finely, such as by time, day, and spread
- Creating one file for every function
As a result, the following problems occur.
- You cannot tell where each process is handled.
- One fix requires changes across multiple files.
- Debugging cost increases.
A practical level of granularity is as follows.
- Entry, one module
- Exit, one module
- Filter, one module
- Risk, one module
Start with these units first.
Decision criterion:
- Can this module be tested by itself?
If not, it is probably split too much.
6.2 Inconsistent Interfaces
Conclusion: If connection rules between modules are inconsistent, reuse and extension become impossible.
Connection rules are critical in modular design.
If they break down, the design can become worse than a single-structure EA.
Common problems:
- Return value types are not consistent.
- Values are shared through global variables.
- Modules depend on other modules.
Bad example:
// Entry directly manipulates a global variable
double signal;
void EntryCheck()
{
signal = 1;
}
Improved example:
bool EntrySignal()
{
return true;
}
Design rules:
- Standardize return values as bool or enum.
- Pass necessary data through arguments.
- Avoid global variables as much as possible.
This preserves module independence.
6.3 Ignoring Filters (Critical Mistake)
Conclusion: If you ignore Filter, the EA can diverge between backtesting and real operation and eventually fail.
Beginners often focus on entry accuracy, but in practical trading the following factors matter.
- spread
- slippage
- execution
If these are ignored, the following issues can occur.
- The EA wins in backtesting but loses in real operation.
- Large losses occur during economic releases.
- Entries worsen when the spread widens.
Minimum filter example:
bool FilterCheck()
{
double spread = (Ask - Bid) / _Point;
if(spread > 20) return false; // Spread limit
if(Hour() < 6 || Hour() > 23) return false; // Time limit
return true;
}
Important idea:
- When not to trade is more important than when to trade.
6.4 Insufficient Testing (Most Common Failure)
Conclusion: If you judge the EA only by backtesting, real operation is likely to fail.
The most common failure in EA development is insufficient verification.
Typical mistakes:
- Judging the EA complete based only on optimization results
- Using only one backtest period
- Skipping forward testing
Correct verification flow:
- 1. Backtest to check the hypothesis
- 2. Parameter change test to check stability
- 3. Forward test to verify the real environment
Forward testing is especially important.
Reasons:
- slippage may not be reproduced accurately.
- execution conditions differ.
- Market structure changes.
In practice, evaluate the EA from the following viewpoints.
- Drawdown (DD)
- Profit factor (PF)
- Resistance to losing streaks
Important notes:
- Demo and live accounts can produce different results.
- Results can differ by broker.
6.5 Growing Module Dependencies
Conclusion: Once modules start depending on each other, the benefits of modular design disappear.
Bad design examples:
- Entry references the inside of Filter.
- Risk depends on Execution.
- Modules reference each other.
When this happens:
- Fixes cause chained changes.
- Testing becomes impossible.
- Bugs cannot be reproduced reliably.
Countermeasures:
- Limit dependencies to one direction.
- Connect modules only through central control, such as OnTick.
7. Practical Use Cases
7.1 EA Development (Commercial and Research)
Conclusion: Modular design is effective as a standard structure for commercial EAs and research because it preserves testing transparency.
When working with EAs in practice, the most important factor is explainability.
In other words, you must be able to explain why the EA is winning.
Modular design makes the following possible.
- Test the win rate and expected value of Entry alone.
- Analyze differences with and without Filter.
- Compare DD, or drawdown, by Risk setting.
For example:
- Entry has a high win rate but large DD.
→ Control it with the Risk module. - Adding Filter improves PF, or profit factor.
→ Adopt it for real operation.
This ability to structure the basis for decisions is a major strength.
It is also highly effective for research.
- A/B testing of multiple logic types
- Comparison under the same conditions
- Evaluation by logic unit
Important notes:
- Do not judge only by the result of a single module.
- Always check behavior after integration.
7.2 Portfolio Operation
Conclusion: Modular design makes it easier to integrate multiple strategies and directly supports portfolio operation.
A single EA depends on one logic set.
In practice, diversification like the following is needed.
- Currency pair diversification, such as EURUSD and USDJPY
- Logic diversification, such as trend-following and mean-reversion
- Timeframe diversification
Modular design can be structured as follows.
- EntryA, trend-following
- EntryB, mean-reversion
- Common Filter, such as spread and time filters
- Common Risk, or money management
This structure allows you to do the following.
- Compare performance by logic.
- Stop only an underperforming strategy.
- Build combinations with low correlation.
Important points:
- Correlation management to avoid simultaneous losses
- Combined DD, meaning total portfolio risk
Beginner mistake:
- Assuming that adding more logic automatically creates diversification
In reality, many strategies lose at the same time under the same market conditions.
7.3 EA Sales and Public Release (Ensuring Reliability)
Conclusion: Modular design helps improve reliability because it avoids black-box logic.
When publishing or selling an EA, the following problems can occur.
- Users cannot understand the logic.
- Users distrust backtest results.
- Forward results diverge from backtests.
Modular design makes the following possible.
- Explain the EA by logic unit.
- Clearly state the purpose of each filter.
- Present verification data by component.
For example:
- This EA runs only when the spread is 20 or lower.
- The design stops trading during major economic releases.
Being able to explain these points clearly reduces credibility cost, including reputation risk.
When combined with public forward testing, such as Myfxbook, it can show the following.
- Data that excludes the impact of deposits and withdrawals
- Pure automated behavior without discretionary intervention
Important notes:
- Logic that cannot be explained will not be trusted.
- Win rate alone is not enough for evaluation.
7.4 Practical Points During Operation
Conclusion: Modular design is strong for continuous operation because it speeds up the improvement cycle.
In real operation, the following cycle is repeated.
- Verification through backtesting
- Experimentation through forward testing
- Analysis to identify causes
- Improvement through module changes
A modular structure speeds up this cycle.
Examples:
- DD increases → Adjust the Risk module.
- Win rate falls → Replace Entry.
- Behavior becomes unstable → Add Filter.
The greatest value is the ability to make partial improvements.
With a single structure, by contrast:
- The entire EA must be rewritten.
- The impact range of a fix is unclear.
- Verification cost increases.
As a result, the speed of improvement drops sharply.
8. FAQ
8.1 Can beginners build a modular EA?
Conclusion: Yes, but it is realistic to start with the minimum structure: Entry, Filter, and Execution.
If you try to separate everything from the beginning, you may get stuck. Start with three modules, confirm that the EA works, and then expand gradually.
8.2 Are .mqh files required?
Conclusion: They are not strictly required, but they are practically necessary for modular design.
Using .mqh files allows separation by function and reuse. You can split logic inside one file, but maintainability is much lower.
8.3 Does modular design make optimization unnecessary?
Conclusion: No. Optimization is still useful, but the correct approach is to reduce dependence on it.
With modular design, optimization should be used as support, while the strength of the structure and logic itself should come first.
8.4 Can the same design be used in MT4?
Conclusion: Yes, but MQL5 is structurally better suited to it.
MQL5 has stronger support for classes, structures, and event processing, which makes it a good fit for modular design. MT4 can also use .mqh separation, but extensibility is more limited.
8.5 How many filters are necessary?
Conclusion: At minimum, spread, time period, and major economic event filters should be treated as essential.
Without them, backtest results and real operation can diverge.
Guidelines:
- Spread limit, such as 20 points or lower
- Time control, such as excluding low-liquidity hours
- News avoidance to handle high volatility
8.6 How is a modular EA different from an AI or machine learning EA?
Conclusion: A modular EA is explainable, while an AI EA can easily become a black box.
AI can be powerful, but it is often difficult to explain why it won and hard to verify. Modular design takes the opposite approach.
8.7 Does modular design reduce performance or processing speed?
Conclusion: In normal use, the difference is usually not a problem.
The overhead from function separation is very small, and it has almost no practical impact on Tick processing, although this depends on the environment.
8.8 Will modular design make an EA profitable?
Conclusion: No. Modular design is a method for improving verification accuracy, not a guarantee of profit.
However, it tends to improve long-term expected value because it improves reproducibility, improvement speed, and risk management.
9. Summary (Conclusion)
Conclusion: Modular EA design is a foundation for improving reproducibility, extensibility, and testability. If long-term operation is the goal, it is almost essential.
The key points of this article are as follows.
- Modular design builds an EA by separating functions.
- Separating Entry, Filter, Risk, and Execution improves testing accuracy.
- It is important to create an advantage through structure, not only optimization.
- It is better suited to long-term operation than single-structure or optimization-dependent EAs.
Practical decision criteria:
- Can the result be reproduced, or does it fail during forward testing?
- Can you break it down and explain the reason for the result?
- Can you improve it through partial changes when the market changes?
Recommended actions:
- First build an EA with three parts: Entry, Filter, and Execution.
- Always include filters for spread, slippage, and time.
- Test by module and make each impact visible.
Important understanding:
- Modular design is not magic that makes an EA win.
- However, it can create a structure that is harder to break and easier to improve.
By adopting this design, you can move from an EA that wins by chance to an EA with reproducible behavior.