- 1 Key Takeaway
- 2 1. Why This Design Is Necessary
- 3 2. Overall EA Design Philosophy
- 4 3. Basic Structure
- 5 4. Roles of the Main Modules
- 6 5. Implementation Patterns
- 7 6. Sample Code
- 8 7. Design Pattern Comparison
- 9 8. Items to Check in Backtesting
- 10 9. Items to Check in Forward Testing
- 11 10. Notes for Live Operation
- 12 11. Common Design Mistakes
- 13 12. Summary
- 14 FAQ
- 14.1 Q1. What is slippage control in MQL5?
- 14.2 Q2. Can setting deviation prevent slippage?
- 14.3 Q3. What is the difference between spread control and slippage control?
- 14.4 Q4. Should OrderCheck always be used?
- 14.5 Q5. What happens if pips and points are confused?
- 14.6 Q6. Can slippage control be checked in backtesting?
- 14.7 Q7. What needs the most attention in live operation?
Key Takeaway
The purpose of designing slippage control in MQL5 is to make it easier to limit the risk that an EA order is filled far away from the expected price.
Do not rely only on MqlTradeRequest.deviation. Manage execution by combining spread checks, price refreshes, OrderCheck, filling mode checks, and post-fill result validation.
Slippage cannot be removed completely. Its conditions change depending on sharp market moves, liquidity, broker specifications, and the VPS environment.
Because backtest results do not guarantee future execution quality, forward testing must verify fill differences and behavior when spreads widen.
1. Why This Design Is Necessary
Conclusion:
Slippage control in MQL5 is execution management that keeps the gap between the order price and the actual fill price within a defined range.
In an EA, even when the trading signal is correct, a worse fill price changes profit and loss, stop-loss distance, and risk-reward.
Slippage is the difference between the price expected when an order is placed and the price where the order is actually filled. With market orders, price keeps moving, so the price at the time of sending may not match the price processed by the server.
In an MQL5 EA, slippage control should be treated as an execution quality issue, including the following points.
- Whether the spread is not too wide
- Whether Bid and Ask are refreshed immediately before the order
- Whether the allowed deviation is set according to the symbol’s digits
- Whether margin and trading conditions are checked with
OrderCheck - Whether the fill result and return code are checked after
OrderSend - Whether the difference between netting and hedging accounts is considered
Slippage control in MQL5 is not enough if you only set the allowed deviation at order time. As part of EA execution design, it must be checked in three stages: before the order, during order submission, and after the order.
1.1 How Slippage Affects EA Performance
Large slippage changes the practical balance between the entry price, stop-loss price, and take-profit price. In short-term trading, scalping, and high-frequency entries, even a small fill difference can affect performance.
However, if slippage is restricted too tightly, orders are more likely to be rejected. You need to decide whether fill rate or fill quality has priority based on the EA’s design purpose.
1.2 Think of It as Control, Not Complete Avoidance
Slippage is not determined only by communication speed. Market movement, liquidity, filling mode, server processing, symbol specifications, and trading hours all affect it.
In EA design, the goal is not to make slippage zero. The goal is to define an acceptable range and avoid orders outside that range.
2. Overall EA Design Philosophy
Conclusion:
Slippage control should be designed as an execution control module separated from signal judgment.
When trade conditions, risk checks, pre-order checks, order submission, and post-fill management are separated, the EA becomes easier to test.
The EA process is easier to implement when organized in the following order.
Market analysis
↓
Filter judgment
↓
Signal judgment
↓
Risk check
↓
Pre-order check
↓
Order submission
↓
Post-fill management
↓
Exit and stop judgment
Slippage control mainly relates to “pre-order check,” “order submission,” and “post-fill management.” If it is mixed with signal judgment, it becomes harder to separate an entry condition problem from an execution quality problem.
In an MQL5 EA, OnInit performs initial setup, OnTick makes decisions on each price update, and OnTradeTransaction can be used when needed to track orders, deals, and position changes.
2.1 Items to Check Before an Order
Before an order, check at least the following items.
- Whether the current spread is within the allowed range
- Whether the symbol is tradable
- Whether the lot size matches the minimum lot, maximum lot, and lot step
- Whether the stop-loss price violates the stop level
- Whether margin is sufficient
- How existing positions on the same symbol will be handled
- Whether the current price is not based on an old tick
Slippage control is not only about the fill difference. It is also a mechanism for deciding whether the market condition is suitable for placing an order.
2.2 Items to Check After an Order
After an order, check the contents of MqlTradeResult. Log whether the order was sent, whether it was filled, the fill price, and the return code.
Recording the post-fill price difference makes it easier to compare backtesting and forward testing.
3. Basic Structure
Conclusion:
MQL5 slippage control should be built around four basic elements: allowed deviation, spread limit, pre-order checks, and fill result logs.
Separating these four elements makes root cause analysis and parameter adjustment easier.
The basic structure can be divided as follows.
| Design Element | Role | Main Check | Note |
|---|---|---|---|
| Allowed deviation | Specifies the allowed shift from the order price | MqlTradeRequest.deviation | Match the symbol’s digits |
| Spread limit | Avoids orders in unfavorable markets | Difference between Bid and Ask | Often widens around news releases |
| Pre-order check | Checks trading conditions | OrderCheck, margin, lots | Success does not guarantee a fill |
| Post-fill log | Records the actual fill difference | Fill price, return code | Important for forward testing |

3.1 How to Think About deviation
MqlTradeRequest.deviation specifies the allowed price difference for a market order in points. A point depends on the symbol’s minimum price unit.
For example, on a 5-digit symbol, 1 point is a small price unit. If pips and points are confused, the allowed range may become much narrower or wider than intended.
3.2 Difference From a Spread Limit
A spread limit is a condition used to judge market conditions before placing an order. deviation is a condition used to allow a price difference after the order is sent.
Spread control and slippage control have different roles. Using both makes it easier to avoid orders under poor conditions.
4. Roles of the Main Modules
Conclusion:
To stabilize slippage control, separate price retrieval, spread judgment, lot normalization, pre-order checks, order execution, and result logging into different functions.
Splitting functions makes it easier to isolate problems during backtesting and forward testing.
Design the main modules as follows.
| Module | Role | Action on Failure |
|---|---|---|
| Price retrieval | Gets Bid, Ask, Point, and Digits | Do not place an order |
| Spread judgment | Checks whether the current spread is within the limit | Skip the entry |
| Lot adjustment | Rounds lots according to symbol specifications | Do not order if outside the minimum or maximum range |
| Pre-order check | Checks conditions with OrderCheck | Log the error details |
| Order submission | Places the order with OrderSend | Check the return code |
| Post-fill record | Records the difference between fill price and expected price | Use it for forward testing |
4.1 Price Retrieval Module
In MQL5, buy orders use Ask as the reference price, and sell orders use Bid. If the price is not refreshed immediately before the order, the EA may place the order using an old price.
In an EA, get Bid, Ask, and Point with SymbolInfoDouble. If retrieval fails, stop the order.
4.2 Lot Adjustment Module
Lots must be adjusted to the minimum lot, maximum lot, and lot step. Even when risk-percentage lot calculation is used, the final lot size must be rounded to the symbol specifications.
If lot restrictions are ignored, pre-order checks and order submission are more likely to fail.
5. Implementation Patterns
Conclusion:
Implementation patterns can be divided into four types: fixed allowed range, spread-linked control, volatility-linked control, and time-based control.
Beginners should start with a fixed allowed range and a spread limit because the behavior is easier to test.
Select a slippage control design pattern according to the EA’s trading frequency and timeframe.
| Method | Advantage | Disadvantage | Best Use Case |
|---|---|---|---|
| Fixed allowed range | Easy to implement | Does not adapt well to market movement | Initial implementation, low-frequency EAs |
| Spread-linked control | Easier to avoid poor conditions | May reduce trade opportunities | Short-term trading, scalping tests |
| Volatility-linked control | Can reflect market movement | Can become highly parameter-dependent | EAs that use ATR or similar measures |
| Time-based control | Easier to avoid news periods and thin liquidity | May have low generality | Symbols strongly affected by trading hours |
5.1 Fixed Allowed Range
A fixed allowed range is a method that keeps deviation at a constant value. Its advantage is that it is easy to implement and easy to compare in test results.
However, a fixed value alone may be insufficient during periods of sharp market movement or on symbols where spreads widen.
5.2 Spread-Linked Control
Spread-linked control places orders only when the current spread is within a defined range. This makes it easier to avoid entries when the spread is wide.
If the spread limit is too strict, fill quality may improve, but the number of trades may decrease.
5.3 Volatility-Linked Control
Volatility-linked control adjusts allowed conditions using a range measure such as ATR. When using ATR in MQL5, the usual flow is to create the indicator handle in OnInit and get values from CopyBuffer in OnTick.
This method is flexible, but adding too many parameters can easily lead to over-optimization.
6. Sample Code
Conclusion:
The sample code implements a spread limit, lot restrictions, OrderCheck, OrderSend, and result logging in one flow.
This code is a basic form for testing. In live use, it must be adjusted for symbol specifications and account type.
#property strict
input double InpLots = 0.10;
input int InpMaxSpreadPoints = 25;
input int InpDeviationPoints = 10;
input ulong InpMagicNumber = 20260518;
bool GetPrices(double &bid, double &ask, double &point)
{
if(!SymbolInfoDouble(_Symbol, SYMBOL_BID, bid))
{
Print("Failed to get bid price");
return false;
}
if(!SymbolInfoDouble(_Symbol, SYMBOL_ASK, ask))
{
Print("Failed to get ask price");
return false;
}
if(!SymbolInfoDouble(_Symbol, SYMBOL_POINT, point))
{
Print("Failed to get point size");
return false;
}
return true;
}
bool IsSpreadAcceptable()
{
double bid, ask, point;
if(!GetPrices(bid, ask, point))
return false;
int spread_points = (int)MathRound((ask - bid) / point);
if(spread_points > InpMaxSpreadPoints)
{
Print("Spread is too wide. spread_points=", spread_points);
return false;
}
return true;
}
double NormalizeLots(double lots)
{
double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(step <= 0.0)
return 0.0;
lots = MathMax(min_lot, MathMin(max_lot, lots));
lots = MathFloor(lots / step) * step;
return NormalizeDouble(lots, 2);
}
bool SendBuyOrder()
{
if(!IsSpreadAcceptable())
return false;
double bid, ask, point;
if(!GetPrices(bid, ask, point))
return false;
double lots = NormalizeLots(InpLots);
if(lots <= 0.0)
{
Print("Invalid lot size after normalization");
return false;
}
MqlTradeRequest request;
MqlTradeCheckResult check;
MqlTradeResult result;
ZeroMemory(request);
ZeroMemory(check);
ZeroMemory(result);
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lots;
request.type = ORDER_TYPE_BUY;
request.price = ask;
request.deviation = InpDeviationPoints;
request.magic = InpMagicNumber;
request.type_filling = ORDER_FILLING_FOK;
request.comment = "slippage-control-test";
if(!OrderCheck(request, check))
{
Print("OrderCheck failed. retcode=", check.retcode);
return false;
}
if(!OrderSend(request, result))
{
Print("OrderSend failed. retcode=", result.retcode);
return false;
}
if(result.retcode != TRADE_RETCODE_DONE &&
result.retcode != TRADE_RETCODE_PLACED)
{
Print("Order was not completed as expected. retcode=", result.retcode);
return false;
}
double slippage_points = MathAbs(result.price - request.price) / point;
Print("OrderSend result. retcode=", result.retcode,
" request_price=", request.price,
" result_price=", result.price,
" slippage_points=", slippage_points);
return true;
}
int OnInit()
{
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
}
void OnTick()
{
static datetime last_bar_time = 0;
datetime current_bar_time = iTime(_Symbol, _Period, 0);
if(current_bar_time == last_bar_time)
return;
last_bar_time = current_bar_time;
bool sample_signal = false;
if(sample_signal)
{
SendBuyOrder();
}
}
6.1 How to Read the Code
This code separates signal judgment as sample_signal. In a real EA, connect the result of moving average, RSI, breakout, or other conditions to this part.
Before the order, the code checks the spread, refreshes prices, and adjusts the lot size to the symbol specifications. After that, it checks order conditions with OrderCheck and then runs OrderSend.
6.2 Notes on type_filling
The available request.type_filling method differs depending on the symbol and broker specifications. For symbols that do not support ORDER_FILLING_FOK, another filling mode may be required.
In live operation, the EA must check the filling modes supported by the symbol and keep logs when orders fail.
7. Design Pattern Comparison
Conclusion:
The design of slippage control changes depending on whether fill rate or fill quality has priority.
Short-term EAs often need stricter control, while excessive restrictions in long-term EAs may create opportunity loss.
| Design Policy | Advantage | Disadvantage | Best Use Case | Live Operation Note |
|---|---|---|---|---|
| Fill rate priority | Orders are more likely to pass | More likely to accept unfavorable fills | Long-term holding, low-frequency EAs | Watch for worse P/L during sharp moves |
| Fill quality priority | Easier to avoid unfavorable fills | Order rejections may increase | Short-term trading, narrow-profit EAs | Check whether trade count decreases |
| Spread priority | Easier to avoid trades under poor conditions | May stop often around news releases | EAs strongly affected by spread | Check period dependency |
| Volatility priority | Easier to adapt to market movement | Design can become complex | ATR-linked EAs | Watch for over-optimization |
7.1 Trade-Off Between Fill Rate and Fill Quality
Widening the allowed deviation makes orders more likely to pass, but it may also cause fills at unfavorable prices. Narrowing the allowed deviation makes unfavorable fills easier to avoid, but the probability of order rejection increases.
In EA design, test both the risk that an order does not pass and the risk that it fills at an unfavorable price.
7.2 Difference Between Netting and Hedging Accounts
In a netting account, positions on the same symbol are generally consolidated into one position. In a hedging account, it may be possible to hold multiple positions on the same symbol.
The basic idea of slippage control is the same, but post-order position management changes depending on the account type. It is important to check which position was updated after the fill.
8. Items to Check in Backtesting
Conclusion:
In backtesting, check how slippage control changes not only profit and loss, but also trade count, maximum drawdown, consecutive losses, and spread conditions.
If you only look at total profit and loss, you may miss deterioration in execution quality.
Check the following items in backtesting.
- Total profit and loss
- Maximum drawdown
- Win rate
- Profit/loss ratio
- Number of trades
- Consecutive losses
- Spread conditions
- Period dependency
- Parameter dependency
- Conditions where order rejection is expected
8.1 Change in Number of Trades
If the spread limit or allowed deviation is made stricter, the number of trades may decrease. A backtest with an extremely small number of trades is more likely to depend on a small sample of trade results.
Slippage control is not only a design for improving performance. It is also a design for avoiding orders under poor conditions. Check trade count and fill quality together.
8.2 Parameter Dependency
If InpMaxSpreadPoints or InpDeviationPoints is optimized too finely, the settings may fit only a specific period.
To avoid over-optimization, check behavior across multiple periods, multiple symbols, and different spread conditions.
9. Items to Check in Forward Testing
Conclusion:
In forward testing, check actual fill differences, spread widening, order rejections, and stability in the VPS environment.
Execution conditions that are hard to reproduce in backtesting can affect performance in real-time operation.
Record the following items during forward testing.
- Fill difference
- Behavior when spreads widen
- Trading frequency
- Drawdown
- Gap from backtesting
- Broker differences
- Stability in the VPS environment
- Return code when an order fails
- Difference between demo and live accounts
9.1 Importance of Fill Difference Logs
Logging the expected order price and the actual fill price makes it easier to separate EA problems from trading environment problems.
If fill differences concentrate in specific time periods, the trading time filter or spread limit may need to be reviewed.
9.2 Difference Between Demo and Live Accounts
Demo and live accounts may have different fill conditions and spread conditions. Even if there are few problems on a demo account, the same behavior is not guaranteed on a live account.
Before live operation, run forward tests with small lots or limited conditions, and check order failures, fill differences, and drawdown.
10. Notes for Live Operation
Conclusion:
In live operation, slippage control alone cannot prevent losses.
Risk management must include spread widening, execution delays, insufficient margin, leverage, and broker specifications.
Pay attention to the following points in live operation.
- Spreads and fill differences can widen around economic news releases
- Unfavorable fills are more likely during low-liquidity hours
- VPS latency may affect order processing
- High leverage can make drawdown larger
- Order results may change depending on the broker’s filling mode
- Backtest results do not guarantee future profits
10.1 Relationship With Stop-Loss Width
In an EA with a narrow stop-loss width, slippage has a larger impact. Even a fill difference of a few points can break the expected risk-reward balance.
Stop-loss width, spread limit, and allowed deviation should not be set separately. They should be aligned as assumptions of the entire trading logic.
10.2 Handling Order Rejections
Avoid a design that repeats reorders unconditionally when an order is rejected. If repeated orders occur during sharp market moves, they may lead to unintended fills or excessive logs.
When retrying orders, combine a retry limit, waiting time, price refresh, and spread recheck.
11. Common Design Mistakes
Conclusion:
Common mistakes include assuming that deviation alone can control slippage, confusing pips and points, and skipping post-order result checks.
Slippage control should be designed to include state management before and after the order.
11.1 Confusing Pips and Points
deviation is specified in points. If values are entered with a pips-based assumption, the allowed range may become narrower or wider than intended.
Use the symbol’s SYMBOL_POINT and digits to make the meaning of values clear inside the EA.
11.2 Ordering With an Old Price
Avoid keeping the price received in OnTick for too long and not refreshing it immediately before the order. If the price is old, the order price and current price are more likely to diverge.
Immediately before placing an order, refresh Bid and Ask and recheck the spread.
11.3 Skipping OrderCheck
If OrderCheck is skipped, it becomes harder to detect causes such as insufficient margin, invalid lots, or stop-level violations before placing the order.
OrderCheck does not guarantee a fill, but it is useful as a pre-order condition check.
11.4 Not Keeping Logs
An EA that does not record fill price, expected price, spread, and return code is difficult to analyze during forward testing.
In tests close to live operation, record not only profit and loss but also execution quality logs.
12. Summary
Conclusion:
MQL5 slippage control should be designed by combining MqlTradeRequest.deviation, spread limits, OrderCheck, and result checks after OrderSend.
The important point is not to prevent order price differences completely. It is to define an acceptable range, avoid orders under poor conditions, and create a state where fills can be reviewed afterward.
In an MQL5 EA, separating trading signals from order execution makes execution quality issues easier to analyze. If spread, filling mode, lot restrictions, account type, and broker specifications are not considered, the gap between backtesting and live operation may become large.
Slippage control is not a mechanism that guarantees profit. Before live operation, use forward testing in addition to backtesting to check fill differences, order rejections, and behavior when spreads widen.
FAQ
Q1. What is slippage control in MQL5?
Slippage control in MQL5 is a design for managing the difference between the expected order price and the actual fill price. It is implemented by combining deviation, a spread limit, pre-order checks, and post-fill logs.
Q2. Can setting deviation prevent slippage?
deviation specifies the allowed price difference, but it does not completely prevent slippage. Results change depending on sharp market moves, filling mode, liquidity, and broker specifications.
Q3. What is the difference between spread control and slippage control?
Spread control judges market conditions before an order is placed. Slippage control manages execution so the gap between the order price and fill price stays within an acceptable range.
Q4. Should OrderCheck always be used?
When an EA handles order processing, using OrderCheck to check margin, lots, and trading conditions makes cause analysis easier. OrderCheck does not guarantee a fill, but it is useful as a pre-order check.
Q5. What happens if pips and points are confused?
Because deviation uses points, confusing pips and points can make the allowed range different from what you intended. Check the symbol’s digits and SYMBOL_POINT before setting the value.
Q6. Can slippage control be checked in backtesting?
Backtesting can show the impact on trade count, profit and loss, drawdown, and spread conditions. However, because actual fill differences and server processing cannot be fully reproduced, forward testing is required.
Q7. What needs the most attention in live operation?
In live operation, pay attention to spread widening around economic news releases, execution delays, VPS conditions, broker specifications, and account type differences. Backtest results do not guarantee future profits, so fill difference logs should be reviewed continuously.