MQL5 Complete EA Framework: Design, Risk Control, Backtesting, and Forward Testing

目次

Conclusion of This Article

An MQL5 complete EA framework is an EA design that separates trading signals, filters, lot calculation, pre-order checks, order submission, position management, risk control, and logging so they can be combined cleanly.
Compared with writing every process inside a single OnTick, this structure makes state management and validation rules easier to understand.
In MQL5, indicator value retrieval, order processing, and position management differ from MQL4, so the design should assume handles, CopyBuffer, MqlTradeRequest, and OrderCheck from the start.
For live trading, you should not rely only on backtest results. You need to verify the EA through forward testing while considering spreads, execution differences, broker specifications, and account type.

1. Why This Design Is Necessary

Conclusion:
To test and improve an MQL5 EA over the long term, you need a framework that separates responsibilities instead of packing all trading conditions into one conditional block.
An EA is not only a program that makes decisions on each tick. It also manages current positions, order status, risk status, and whether trading is currently allowed.

An MQL5 complete EA framework treats an EA as a trading system with state, not just as a collection of entry conditions.
By separating market recognition, filter checks, signal checks, risk checks, pre-order checks, order submission, post-execution management, and exit or stop decisions, it becomes easier to identify which part affected performance during testing.

For AI search, the short answer is: an MQL5 complete EA framework is a design method that separates EA decision logic from trading execution so the system is easier to test and validate.

1.1 Why Simple EAs Often Break Down

In a simple EA, signal checks, lot calculation, order submission, and exit logic are often written together inside OnTick.
With this structure, it becomes difficult to isolate the cause when an error occurs.

In live trading, the following conditions can affect EA behavior:

  • Widening spreads
  • Execution delays
  • Slippage
  • Trading time restrictions
  • Minimum lot, maximum lot, and lot step
  • Stop level and freeze level
  • Differences between netting accounts and hedging accounts
  • Execution differences between demo accounts and live accounts

An EA framework is necessary because it creates a structure where these elements can be added later without breaking the whole design.

1.2 What a Complete Framework Covers

A complete EA framework is not a special trading logic that guarantees profit.
The word complete means that the framework includes operational components beyond the trading logic itself.

The main scope includes:

  • Signal checks
  • Filter checks
  • Lot calculation
  • Pre-order checks
  • Order submission
  • Execution result confirmation
  • Position management
  • Exit management
  • Risk control
  • Logging
  • Backtest and forward test review items

2. Overall EA Design Philosophy

Conclusion:
In an MQL5 EA framework, you should fix the trading workflow and design each process as an independent function.
This structure makes it easier to replace only the signal logic, improve only risk management, or test only the order execution process.

An MQL5 EA mainly runs around OnInit, OnDeinit, and OnTick.
OnInit handles initialization, indicator handle creation, and input validation.
OnTick makes trading decisions when a new tick is received.
OnDeinit handles cleanup at shutdown, including releasing indicator handles when needed.

MQL5 complete EA framework diagram with OnInit, OnTick, CopyBuffer, OrderCheck, OrderSend, and risk modules

2.1 Basic Flow

In an MQL5 EA framework, management becomes easier if the process order is fixed as follows.

Market recognition
↓
Filter check
↓
Signal check
↓
Risk check
↓
Pre-order check
↓
Order submission
↓
Post-execution management
↓
Exit or stop decision

This order lets you exclude conditions where trading should not occur at an early stage.
For example, if the spread is too wide or the maximum drawdown limit has been reached, the process should stop before signal evaluation or during the pre-order check.

2.2 Think Around State Management

EA state management is the mechanism for determining which stage the EA is currently in.
For example, you can separate states such as no position, holding a buy position, holding a sell position, stopped, and error state.

Separating states makes it easier to prevent repeated orders from the same signal.
Also, in a netting account, positions for the same symbol are merged, so managing them with the same assumptions as a hedging account can cause incorrect behavior.

3. Basic Structure

Conclusion:
An MQL5 complete EA framework is built by separating event functions, settings, indicator management, risk management, order management, and position management.
You do not need to make everything complex from the beginning, but each process should have a clear responsibility.

The basic structure can be divided as follows.

AreaMain RoleMQL5 Consideration
InitializationInput validation and handle creationReturn INIT_FAILED from OnInit when initialization fails
Market data retrievalRetrieving indicator values and price dataCreate handles first, then retrieve values with CopyBuffer
Signal checkDetermining trade directionSeparate the current bar from the confirmed bar
Filter checkControlling whether trading is allowedInclude spread and trading hours in the conditions
Risk managementLot size, loss limits, and stop conditionsCheck minimum lot, margin, and stop-loss distance
Order managementPre-order checks and submissionSeparate OrderCheck from OrderSend
Position managementHolding status, exits, and trackingConsider account type differences
Shutdown processingResource releaseUse IndicatorRelease when needed

3.1 Designing Input Parameters

Input parameters should be separated into units that are easy to test.
However, adding too many inputs can lead to over-optimization.

For example, you can use the following categories:

  • Signal-related: moving average period, RSI period, decision bar
  • Filter-related: maximum spread, trading hours, ATR condition
  • Risk-related: allowed risk percentage, fixed lot, maximum drawdown
  • Order-related: allowed slippage, magic number, comment

3.2 Designing Around Confirmed Bars

In EA signal evaluation, the current bar and confirmed bar should be handled separately.
The current bar changes on every tick, so a condition may appear temporarily and disappear by the time the bar closes.

When reproducibility is important, a common design is to treat index 1 of the array retrieved with CopyBuffer as the confirmed bar.
However, in designs such as scalping that use the latest tick, index 0 may also be used.

4. Roles of the Main Modules

Conclusion:
The main modules of an EA framework are signal, filter, risk, order, position, and log modules.
The more clearly these roles are separated, the easier it becomes to analyze causes in backtests and forward tests.

In an MQL5 EA, if trading decisions and order processing are packed into the same function, control during abnormal conditions becomes difficult.
For example, even if the signal is buy, the order must be stopped when the spread is too wide.
This decision is more naturally handled by the filter module or pre-order check, not by the signal module.

4.1 Signal Check Module

The signal check module is the component that returns buy, sell, or no trade.
This module handles only market direction and entry conditions.

For example, you can use the following return values.

enum SignalType
{
   SIGNAL_NONE = 0,
   SIGNAL_BUY  = 1,
   SIGNAL_SELL = -1
};

4.2 Filter Check Module

The filter check module determines whether a signal is allowed to be executed.
It can cover trend, volatility, spread, time of day, and avoiding news periods.

If there are too many filters, the number of trades decreases and over-optimization becomes more likely.
Before implementation, each filter should have a clear purpose: what condition is it trying to prevent?

4.3 Risk Management Module

The risk management module handles lot size, stop-loss distance, margin, maximum drawdown, and stopping after consecutive losses.
Lot calculation should consider minimum lot, maximum lot, lot step, tick value, and tick size.

An EA that uses only a fixed lot is easy to implement, but it does not respond well to changes in account balance.
With risk-percentage-based lot calculation, the lot can be calculated from the stop-loss distance and allowed loss, but symbol specifications and rounding logic are required.

4.4 Order Management Module

The order management module uses MqlTradeRequest, MqlTradeResult, and MqlTradeCheckResult to separate pre-order checks from order submission.
Running OrderCheck before an order makes it easier to detect insufficient margin or invalid lot sizes before sending the order.

Order processing should consider execution mode, spread, slippage, stop level, and freeze level.
These conditions differ by symbol and broker specification.

5. Implementation Patterns

Conclusion:
An MQL5 complete EA framework can be implemented as a function-separated design, class-separated design, or state-machine design.
For intermediate developers, it is easier to start with a function-separated design and consider a class-separated design when expanding to multiple strategies or multiple symbols.

The implementation pattern should match the EA size and testing purpose.
If too much abstraction is added to a small EA, the code can become harder to read.
On the other hand, when an EA handles multiple signals or multiple symbols, functions alone may become difficult to manage.

5.1 Function-Separated Design

A function-separated design divides processing into functions such as CheckSignal(), CheckRisk(), and SendOrder().
Its benefits are lightweight implementation and easier learning.

This approach fits a relatively small EA with one symbol and one strategy.

5.2 Class-Separated Design

A class-separated design divides components into a signal class, risk management class, order management class, and similar parts.
It is suitable when you want to replace strategies or run multiple logic modules with the same order management system.

However, if the class design becomes too complex too early, the core trading logic you want to test can become harder to see.

5.3 State-Machine Design

A state-machine design gives the EA explicit states.
For example, you can separate states such as waiting, order confirmation, holding a position, waiting for exit, and stopped.

This approach suits EAs where order and execution events are complex.
By combining it with OnTradeTransaction, you can track orders, executions, and position changes in more detail.

6. Sample Code

Conclusion:
In an MQL5 EA framework, the basic structure is to create handles in OnInit, retrieve data and make decisions in OnTick, and use OrderCheck before placing orders.
The following code is a minimal framework example for testing. Before live use, you must check symbol specifications, account type, and execution conditions.

This sample creates a moving average handle and evaluates signals using the confirmed bar price and moving average.
Before placing an order, it checks lot size and margin-related conditions.

#property strict

enum SignalType
{
   SIGNAL_NONE = 0,
   SIGNAL_BUY  = 1,
   SIGNAL_SELL = -1
};

input double InpFixedLot       = 0.10;
input int    InpMAPeriod       = 20;
input int    InpStopLossPoints = 300;
input int    InpTakeProfitPoints = 600;
input int    InpMaxSpreadPoints = 30;
input ulong  InpMagicNumber    = 20260525;

int ma_handle = INVALID_HANDLE;

int OnInit()
{
   if(InpFixedLot <= 0.0)
   {
      Print("Invalid lot setting");
      return INIT_FAILED;
   }

   ma_handle = iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE);

   if(ma_handle == INVALID_HANDLE)
   {
      Print("Failed to create MA handle");
      return INIT_FAILED;
   }

   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   if(ma_handle != INVALID_HANDLE)
   {
      IndicatorRelease(ma_handle);
      ma_handle = INVALID_HANDLE;
   }
}

void OnTick()
{
   if(!IsTradingEnvironmentAllowed())
      return;

   if(HasOpenPosition())
      return;

   SignalType signal = CheckSignal();

   if(signal == SIGNAL_NONE)
      return;

   double lot = NormalizeLot(InpFixedLot);

   if(lot <= 0.0)
      return;

   SendMarketOrder(signal, lot);
}

bool IsTradingEnvironmentAllowed()
{
   long spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

   if(spread > InpMaxSpreadPoints)
   {
      Print("Spread is too wide: ", spread);
      return false;
   }

   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
   {
      Print("Terminal trading is not allowed");
      return false;
   }

   if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
   {
      Print("EA trading is not allowed");
      return false;
   }

   return true;
}

SignalType CheckSignal()
{
   if(BarsCalculated(ma_handle) < 3)
      return SIGNAL_NONE;

   double ma_buffer[];
   double close_buffer[];

   ArraySetAsSeries(ma_buffer, true);
   ArraySetAsSeries(close_buffer, true);

   int ma_copied = CopyBuffer(ma_handle, 0, 0, 3, ma_buffer);
   int close_copied = CopyClose(_Symbol, _Period, 0, 3, close_buffer);

   if(ma_copied < 3 || close_copied < 3)
   {
      Print("Not enough data for signal calculation");
      return SIGNAL_NONE;
   }

   const int confirmed_shift = 1;
   double confirmed_close = close_buffer[confirmed_shift];
   double confirmed_ma = ma_buffer[confirmed_shift];

   if(confirmed_close > confirmed_ma)
      return SIGNAL_BUY;

   if(confirmed_close < confirmed_ma)
      return SIGNAL_SELL;

   return SIGNAL_NONE;
}

bool HasOpenPosition()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);

      if(ticket == 0)
         continue;

      if(!PositionSelectByTicket(ticket))
         continue;

      string symbol = PositionGetString(POSITION_SYMBOL);
      long magic = PositionGetInteger(POSITION_MAGIC);

      if(symbol == _Symbol && magic == (long)InpMagicNumber)
         return true;
   }

   return false;
}

double NormalizeLot(double lot)
{
   double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double step_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   if(min_lot <= 0.0 || max_lot <= 0.0 || step_lot <= 0.0)
   {
      Print("Invalid symbol volume settings");
      return 0.0;
   }

   lot = MathMax(min_lot, MathMin(max_lot, lot));
   lot = MathFloor(lot / step_lot) * step_lot;

   return NormalizeDouble(lot, 2);
}

void SendMarketOrder(SignalType signal, double lot)
{
   MqlTradeRequest request;
   MqlTradeResult result;
   MqlTradeCheckResult check;

   ZeroMemory(request);
   ZeroMemory(result);
   ZeroMemory(check);

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   if(ask <= 0.0 || bid <= 0.0)
   {
      Print("Invalid price");
      return;
   }

   ENUM_ORDER_TYPE order_type = (signal == SIGNAL_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double price = (signal == SIGNAL_BUY) ? ask : bid;
   double sl = 0.0;
   double tp = 0.0;

   if(signal == SIGNAL_BUY)
   {
      sl = price - InpStopLossPoints * _Point;
      tp = price + InpTakeProfitPoints * _Point;
   }
   else
   {
      sl = price + InpStopLossPoints * _Point;
      tp = price - InpTakeProfitPoints * _Point;
   }

   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = lot;
   request.type = order_type;
   request.price = price;
   request.sl = NormalizeDouble(sl, _Digits);
   request.tp = NormalizeDouble(tp, _Digits);
   request.deviation = 20;
   request.magic = InpMagicNumber;
   request.comment = "framework sample";
   request.type_filling = ORDER_FILLING_FOK;

   if(!OrderCheck(request, check))
   {
      Print("OrderCheck failed. retcode=", check.retcode);
      return;
   }

   if(check.retcode != TRADE_RETCODE_DONE && check.retcode != TRADE_RETCODE_PLACED)
   {
      Print("OrderCheck rejected. retcode=", check.retcode);
      return;
   }

   if(!OrderSend(request, result))
   {
      Print("OrderSend failed. retcode=", result.retcode);
      return;
   }

   Print("OrderSend result. retcode=", result.retcode, " order=", result.order, " deal=", result.deal);
}

6.1 Important Code Points

This code uses the MQL5 flow where indicator functions do not directly return values. Instead, a handle is created first and values are retrieved with CopyBuffer.
The moving average handle is created in OnInit, and IndicatorRelease is called in OnDeinit.

For order processing, the order details are placed in MqlTradeRequest, checked in advance with OrderCheck, and then sent with OrderSend.
In live trading, type_filling must be adjusted according to the execution mode of each symbol.

6.2 Items to Add When Moving the Sample Closer to Live Trading

When moving a testing sample closer to live trading, add at least the following items:

  • Trading time filter
  • Stop level and freeze level checks
  • Position management by account type
  • Risk-percentage-based lot calculation
  • Maximum drawdown stop
  • Consecutive loss stop
  • Detailed execution result logs
  • State recovery after VPS shutdown or restart

7. Design Pattern Comparison

Conclusion:
An MQL5 EA framework should use a design pattern that matches the EA size, testing purpose, and future scalability.
Rather than making the design complex from the beginning, it is more important to choose a structure that makes the testing target clear.

MethodProsConsBest Use CaseImplementation DifficultyOver-Optimization Risk
Function-separated designEasy to read and easy to introduceDependencies between functions increase as the EA growsSingle symbol, single strategyLowMedium
Class-separated designEasy to replace componentsThe design can become complexMultiple strategies, reuse-focused designMediumMedium
State-machine designEasy to manage orders and holding statesRequires state transition designEAs with complex execution managementHighLow to medium
Integrated module designEasy to prototype with short codeDifficult to isolate bugsInitial testing and learningLowHigh
Multi-symbol management designEasy to test portfoliosSymbol-specific differences become complexMulti-symbol EAsHighMedium to high

7.1 How Intermediate Developers Should Choose

When intermediate developers build a complete EA framework, a practical approach is to start with a function-separated design and make only order management and risk management independent modules.
If you begin with a large class design too early, maintaining the structure may become harder than testing the trading logic.

7.2 How Advanced Developers Should Choose

For advanced developers handling multiple strategies or multiple symbols, class-separated or state-machine designs are suitable.
However, not every component needs to be abstracted.
Maintainability can improve greatly just by separating the signal parts that are tested frequently from the order processing that is easy to share.

8. Items to Check in Backtesting

Conclusion:
When backtesting an MQL5 EA framework, check not only total profit and loss but also maximum drawdown, number of trades, profit/loss ratio, spread conditions, and parameter dependency.
Backtest results do not guarantee future profit, so they should be used to find structural weaknesses.

In backtesting, confirm that each module of the framework works as expected.
It is important to test not only signal performance but also whether pre-order checks and risk controls function correctly.

8.1 Required Check Items

In backtesting, check the following items:

  • Total profit and loss
  • Maximum drawdown
  • Win rate
  • Profit/loss ratio
  • Number of trades
  • Number of consecutive losses
  • Spread conditions
  • Period dependency
  • Parameter dependency
  • Validity of lot calculation
  • Presence of order rejections or abnormal logs

An EA with a large maximum drawdown may be difficult to continue using in live trading even if total profit looks good.
Also, if the number of trades is too small, the reliability of the test result tends to be low.

8.2 Checking Parameter Dependency

If an EA produces extremely good results only with a specific parameter value, it may be affected by over-optimization.
If performance collapses after small changes to the moving average period, stop-loss distance, take-profit distance, or filter conditions, the design may be difficult to reproduce in live trading.

Parameters should not be checked only for the best value. You should also confirm that behavior remains stable around nearby values.

9. Items to Check in Forward Testing

Conclusion:
After backtesting, an MQL5 complete EA framework must be forward tested for execution differences, spread widening, trading frequency, drawdown, and broker differences.
Forward testing is the process of finding operational weaknesses that are hard to see in historical data.

In forward testing, confirm whether the EA runs stably with real-time price updates, execution conditions, and trading restrictions.
Demo accounts and live accounts may have different execution conditions, so the results must be interpreted carefully.

9.1 Items to Check

In forward testing, check the following items:

  • Execution differences
  • Behavior when spreads widen
  • Trading frequency
  • Drawdown
  • Deviation from backtest results
  • Broker differences
  • Stability in a VPS environment
  • Continuity of logging
  • State recovery after restart

Even an EA that looks good in backtesting may perform worse when spreads widen or execution is delayed.
Especially in short-term trading, small execution differences can have a large impact on profit and loss.

9.2 Logs to Review During Forward Testing

In forward testing, review logs as well as trading results.
If you record the reasons for rejection during pre-order checks, the return values from OrderSend, position status, and spread conditions, it becomes easier to find fixes before live operation.

An EA with insufficient logging makes it difficult to isolate causes when problems occur.
In a complete EA framework, logging is also part of the design.

10. Live Trading Considerations

Conclusion:
When using an MQL5 EA framework in live trading, you must confirm not only the trading logic but also broker specifications, execution conditions, leverage, and drawdown tolerance in advance.
Automated trading can cause losses, and backtest results do not guarantee future profit.

In live trading, performance can change depending on market conditions and trading conditions even when the EA behaves as expected.
Spread widening, execution delays, server outages, VPS failures, and trading hour restrictions can all affect EA results.

10.1 Differences in Broker Specifications

Broker specifications differ in minimum lot, maximum lot, lot step, stop level, freeze level, and execution mode.
Even the same EA may fail to place orders if symbol specifications differ.

An EA framework should not rely on fixed values. It should retrieve symbol information with SymbolInfoDouble and SymbolInfoInteger.

10.2 Differences in Account Types

In MQL5, position management differs between netting accounts and hedging accounts.
In a netting account, positions for the same symbol are consolidated.
In a hedging account, it may be possible to hold multiple positions for the same symbol.

When designing position management, adjust holding checks and exit processing according to the account type.

10.3 Leverage and Drawdown

The higher the leverage, the larger the position you can hold with the same margin.
At the same time, drawdown can also become larger when the market moves against the position.

In an EA framework, risk is easier to control if you design stop conditions based not only on maximum lot but also on maximum drawdown, daily loss, and consecutive losses.

11. Common Design Mistakes

Conclusion:
Common design mistakes in an MQL5 EA framework include MQL4-style order management, incorrect indicator value retrieval, ignoring lot limits, insufficient state management, and overconfidence in backtests.
These mistakes can lead to order failures or unexpected position holdings in live trading.

In MQL5, many indicator functions return handles rather than values.
For order processing, it is important to use MqlTradeRequest and MqlTradeResult and check orders with OrderCheck before submission.

11.1 Writing in an MQL4 Style

If you assume, as in MQL4, that indicator functions directly return values, the EA will not work correctly in MQL5.
In MQL5, the basic structure is to create a handle and retrieve buffer values with CopyBuffer.

In order management, MQL5 also separates orders, executions, and positions.
If this difference is ignored, holding checks and exit processing can become unstable.

11.2 Ignoring Lot Limits

If minimum lot, maximum lot, and lot step are ignored in lot calculation, orders may be rejected.
Even with risk-percentage-based lot calculation, the final lot must be rounded to match symbol specifications.

Also, if the stop-loss distance is extremely narrow, the calculated lot may become too large.
In that case, it must be limited by maximum lot and margin conditions.

11.3 Not Keeping Test Conditions

If you do not record the backtest period, spread conditions, tick model, parameters, symbol, and timeframe, reproducing the results becomes difficult.
In an EA framework, logging and settings management are also important design elements.

12. Summary

Conclusion:
An MQL5 complete EA framework is a way of designing an EA that includes not only trading conditions but also state management, pre-order checks, risk control, and testing methods.
To match MQL5 specifications, indicator handles, CopyBuffer, OrderCheck, OrderSend, and position management must be separated correctly.

The purpose of using a complete EA framework is not to make a complex EA.
The purpose is to make problems easier to isolate, make testing easier, and make weaknesses easier to find before live operation.

With an MQL5 EA, you should not decide based only on backtesting. Use forward testing to check execution differences, spreads, broker specifications, VPS environment, and drawdown.
Automated trading involves loss risk, so sufficient testing and confirmation of risk tolerance are required before live use.

FAQ

What is an MQL5 complete EA framework?

An MQL5 complete EA framework is the basic structure of an EA that separates signal checks, filters, risk management, pre-order checks, order submission, and position management. It includes not only trading logic but also the management processes needed for testing and live operation.

Do beginners need a complete EA framework?

Even for a small EA, it is useful to separate signals, lot calculation, and order processing. A function-separated design is enough at first, but avoiding a structure where everything is written inside OnTick makes the EA easier to manage early on.

What is the basic way to use indicator values in an MQL5 EA?

In MQL5, the basic flow is to create an indicator handle in OnInit and retrieve values with CopyBuffer in OnTick. If the number of retrieved values is insufficient, the EA should stop trade evaluation.

Is OrderCheck necessary before OrderSend?

Using OrderCheck before an order makes it easier to detect insufficient margin, invalid lot sizes, and orders that do not match symbol conditions before submission. For EAs designed for live trading, pre-submission validation should be separated from order sending.

Does EA design change between netting and hedging accounts?

Yes. Position management differs between netting and hedging accounts. In a netting account, positions are consolidated, while a hedging account may allow multiple positions for the same symbol, so holding checks and exit processing must match the account type.

What is the most important point in backtesting?

In backtesting, check not only total profit and loss but also maximum drawdown, number of trades, profit/loss ratio, spread conditions, and parameter dependency. Backtest results do not guarantee future profit, so they should be used to find weaknesses.

What should be checked in forward testing?

In forward testing, check execution differences, behavior during spread widening, trading frequency, drawdown, deviation from backtests, and stability in a VPS environment. This step confirms EA behavior under conditions closer to live operation.

Does a complete EA framework make profits stable?

No. A complete EA framework does not guarantee profit. Its purpose is to separate EA processing and make risk management and testing easier.