Problem Description
Solution
Here is a complete, fully functional Expert Advisor (EA) for MetaTrader 4 that implements the Envelopes breakout strategy.
Strategy Logic
- Buy Signal: The previous candle closes above the Upper Envelopes band, while the candle before that was below or equal to it (confirmed crossover).
- Sell Signal: The previous candle closes below the Lower Envelopes band, while the candle before that was above or equal to it (confirmed crossover).
- Risk Management: The EA allows you to set Stop Loss and Take Profit in pips. It also includes a "Magic Number" to identify its own trades.
- Execution: It opens one trade at a time. If a signal appears, it checks if a trade is already open.
MQL4 Code
//+------------------------------------------------------------------+
//| Envelopes_Breakout_EA.mq4 |
//| Copyright 2023, Quantitative |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double LotSize = 0.1; // Trade Volume
input int StopLoss = 50; // Stop Loss in pips (0 = none)
input int TakeProfit = 100; // Take Profit in pips (0 = none)
input int MagicNumber = 123456; // Unique EA Identifier
input int Slippage = 3; // Max slippage in pips
//--- Envelopes Indicator Settings
input int EnvPeriod = 14; // Envelopes Period
input int EnvShift = 0; // Envelopes Shift
input ENUM_MA_METHOD EnvMethod = MODE_SMA; // MA Method (Simple, Exponential, etc.)
input ENUM_APPLIED_PRICE EnvPrice = PRICE_CLOSE; // Applied Price
input double EnvDeviation = 0.1; // Deviation (%)
//--- Global Variables
double pipValue;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Adjust pip value for 3 or 5 digit brokers
if(Digits == 3 || Digits == 5) pipValue = Point * 10;
else pipValue = Point;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if we have enough bars to calculate
if(Bars < EnvPeriod + 2) return;
// 1. Get Envelopes Values for the previous bar (Index 1)
double upperEnv = iEnvelopes(Symbol(), 0, EnvPeriod, EnvMethod, EnvShift, EnvPrice, EnvDeviation, MODE_UPPER, 1);
double lowerEnv = iEnvelopes(Symbol(), 0, EnvPeriod, EnvMethod, EnvShift, EnvPrice, EnvDeviation, MODE_LOWER, 1);
// 2. Get Price Data (Close prices for crossover check)
double close1 = Close[1]; // Previous candle close
double close2 = Close[2]; // Candle before previous
// 3. Check for Open Trades managed by this EA
int openOrders = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
openOrders++;
}
}
}
// 4. Trading Logic
// Only trade if no orders are currently open
if(openOrders == 0)
{
// --- BUY CONDITION ---
// Price crossed FROM below TO above the Upper Band
if(close1 > upperEnv && close2 <= upperEnv)
{
OpenBuyOrder();
}
// --- SELL CONDITION ---
// Price crossed FROM above TO below the Lower Band
if(close1 < lowerEnv && close2 >= lowerEnv)
{
OpenSellOrder();
}
}
}
//+------------------------------------------------------------------+
//| Function to Open Buy Order |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
double sl = 0, tp = 0;
if(StopLoss > 0) sl = Ask - (StopLoss * pipValue);
if(TakeProfit > 0) tp = Ask + (TakeProfit * pipValue);
// Normalize prices
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, tp, "Env Buy", MagicNumber, 0, clrBlue);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Function to Open Sell Order |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
double sl = 0, tp = 0;
if(StopLoss > 0) sl = Bid + (StopLoss * pipValue);
if(TakeProfit > 0) tp = Bid - (TakeProfit * pipValue);
// Normalize prices
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, tp, "Env Sell", MagicNumber, 0, clrRed);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+
How to Install and Use
- Open MetaTrader 4.
- Press
F4to open the MetaEditor. - Click New -> Expert Advisor (template) -> Name it
Envelopes_Breakout. - Delete everything in the new file and paste the code provided above.
- Press
F7or click Compile. Ensure there are no errors in the "Errors" tab at the bottom. - Go back to the main MT4 window.
- Find
Envelopes_Breakoutin the Navigator panel under Expert Advisors. - Drag it onto a chart.
- Important: Ensure the "AutoTrading" button at the top of MT4 is green (On).
Key Features Explained
- Crossover Logic: The code uses
Close[1](previous bar) andClose[2](bar before previous) to detect the exact moment the price breaks the band. This prevents the EA from opening trades continuously if the price stays outside the bands for a long time. - 5-Digit Broker Support: The
OnInitfunction automatically detects if your broker uses 5 decimal places (e.g., EURUSD at 1.09123) and adjusts the pip calculation so that a 50 pip Stop Loss is calculated correctly as 500 points. - Magic Number: The
MagicNumberinput allows you to run this EA on multiple charts simultaneously without the EA confusing trades from one chart with another.
Q&A: Quantitative Trading with Envelopes
Q: What is the best timeframe for an Envelopes breakout strategy?
A: Breakout strategies generally work best on timeframes where noise is reduced, such as H1 (1-Hour), H4 (4-Hour), or D1 (Daily). On lower timeframes like M1 or M5, the price may frequently whip-saw across the bands, causing false signals and losses due to spread costs.
Q: How does the Deviation parameter affect the strategy?
A: The EnvDeviation parameter controls the width of the channel.
- Higher Deviation (e.g., 0.5%): The bands are wider. You will get fewer signals, but they imply a stronger volatility breakout.
- Lower Deviation (e.g., 0.05%): The bands are narrower. You will get more signals, but many may be false breakouts (noise).
Q: Can I use this for Mean Reversion instead of Breakout?
A: Yes, but the logic must be inverted. For mean reversion (betting the price will return to the center), you would Sell when the price breaks the Upper band and Buy when it breaks the Lower band. The code provided above is strictly for Trend Following/Breakouts.
Q: Why does the EA check OrdersTotal()?
A: This is a basic risk management check to ensure the EA does not open hundreds of trades if the signal remains valid for several ticks. The code provided allows only one open trade per chart per Magic Number at a time.