| # MQL5 Expert Advisor: Multi-Indicator Breakout Scalper
|
|
|
| ## What This EA Does
|
|
|
| This Expert Advisor combines **Envelopes**, **Fractals**, **RSI**, and **Bollinger Bands** to identify breakout and scalping opportunities on the M5 timeframe. The logic works like this:
|
|
|
| ### Trading Logic
|
|
|
| **Buy Signal (Upward Breakout)**
|
| 1. Price closes above the upper Envelope (bullish momentum)
|
| 2. RSI is above 50 (uptrend confirmation)
|
| 3. Price is above the lower Bollinger Band (not oversold)
|
| 4. Upper Fractal is broken (price action confirmation)
|
|
|
| **Sell Signal (Downward Breakout)**
|
| 1. Price closes below the lower Envelope (bearish momentum)
|
| 2. RSI is below 50 (downtrend confirmation)
|
| 3. Price is below the upper Bollinger Band (not overbought)
|
| 4. Lower Fractal is broken (price action confirmation)
|
|
|
| **Exit Rules**
|
| - Take profit: 20 pips (configurable)
|
| - Stop loss: 15 pips (configurable)
|
| - Max one trade per candle to avoid overtrading
|
|
|
| ---
|
|
|
| ## How to Use This Code
|
|
|
| ### Step 1: Open MQL5 Editor
|
| - In MetaTrader 5, press **F4** or click Tools → MetaEditor
|
| - Click File → New → Expert Advisor (template)
|
| - Name it "MultiIndicatorScalper"
|
| - Click Finish
|
|
|
| ### Step 2: Copy the Code
|
| Delete everything in the editor and paste the complete code below
|
|
|
| ### Step 3: Compile
|
| - Press **F7** or click Compile
|
| - Fix any errors (unlikely if you copied correctly)
|
| - You'll get a "successful" message
|
|
|
| ### Step 4: Test on M5 Chart
|
| - Open any currency pair on M5 timeframe
|
| - Drag the EA from Navigator (Ctrl+N) onto the chart
|
| - Enable "Allow live trading" if testing live (tick the checkbox)
|
| - Click OK
|
|
|
| ### Step 5: Monitor
|
| Watch the Expert tab at the bottom for trade signals and execution
|
|
|
| ---
|
|
|
| ## The Complete Code
|
|
|
| //+------------------------------------------------------------------+
|
| //| Multi-Indicator Breakout Scalper EA for M5 Timeframe |
|
| //+------------------------------------------------------------------+
|
| #property strict
|
| #property copyright "Copyright 2025"
|
| #property description "Envelopes + Fractals + RSI + Bollinger Bands"
|
| #property version "1.00"
|
|
|
| // Input parameters - you can adjust these
|
| input double LotSize = 0.01; // Trade size (0.01 = 10k units for most pairs)
|
| input int TakeProfit = 20; // Take profit in pips
|
| input int StopLoss = 15; // Stop loss in pips
|
| input int EnvelopePeriod = 14; // Envelope MA period
|
| input double EnvelopeDeviation = 0.3; // Envelope deviation
|
| input int RSIPeriod = 14; // RSI period
|
| input int BBPeriod = 20; // Bollinger Bands period
|
| input int BBDeviation = 2; // Bollinger Bands deviation
|
|
|
| // Global variables
|
| int envelopeHandle; // Stores the Envelope indicator
|
| int rsiHandle; // Stores the RSI indicator
|
| int bbHandle; // Stores the Bollinger Bands indicator
|
| CTrade trade; // Trading object
|
| datetime lastTradeTime = 0; // Prevents multiple trades per candle
|
|
|
| //+------------------------------------------------------------------+
|
| //| Expert initialization function |
|
| //+------------------------------------------------------------------+
|
| int OnInit()
|
| {
|
| // Create Envelope indicator handle
|
| envelopeHandle = iEnvelopes(_Symbol, _Period, EnvelopePeriod, 0, MODE_SMA, PRICE_CLOSE, EnvelopeDeviation);
|
|
|
| // Create RSI indicator handle
|
| rsiHandle = iRSI(_Symbol, _Period, RSIPeriod, PRICE_CLOSE);
|
|
|
| // Create Bollinger Bands indicator handle
|
| bbHandle = iBands(_Symbol, _Period, BBPeriod, 0, BBDeviation, PRICE_CLOSE);
|
|
|
| // Check if all indicators initialized successfully
|
| if(envelopeHandle == INVALID_HANDLE || rsiHandle == INVALID_HANDLE || bbHandle == INVALID_HANDLE)
|
| {
|
| Alert("Failed to create indicator handles");
|
| return(INIT_FAILED);
|
| }
|
|
|
| return(INIT_SUCCEEDED);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Expert deinitialization function |
|
| //+------------------------------------------------------------------+
|
| void OnDeinit(const int reason)
|
| {
|
| // Release indicator handles (cleanup)
|
| IndicatorRelease(envelopeHandle);
|
| IndicatorRelease(rsiHandle);
|
| IndicatorRelease(bbHandle);
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Expert tick function (runs every price update) |
|
| //+------------------------------------------------------------------+
|
| void OnTick()
|
| {
|
| // Get current bar time
|
| datetime currentBarTime = iTime(_Symbol, _Period, 0);
|
|
|
| // Prevent multiple trades on the same candle
|
| if(currentBarTime == lastTradeTime)
|
| return;
|
|
|
| // Read indicator values for the closed bar (candle 1 = previous candle)
|
| double envelopeUpper = GetEnvelopeValue(UPPER_BAND, 1);
|
| double envelopeLower = GetEnvelopeValue(LOWER_BAND, 1);
|
| double rsiValue = GetRSIValue(1);
|
| double bbUpper = GetBBValue(UPPER_BAND, 1);
|
| double bbLower = GetBBValue(LOWER_BAND, 1);
|
|
|
| // Get the closed price of the previous candle
|
| double closedPrice = iClose(_Symbol, _Period, 1);
|
|
|
| // Get fractal levels (fractal_up = resistance, fractal_down = support)
|
| double fractalUp = GetFractalHigh(1);
|
| double fractalDown = GetFractalLow(1);
|
|
|
| // Get current ask and bid
|
| double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
| double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
|
| // BUY SIGNAL: Price breaks above envelope with RSI bullish
|
| if(closedPrice > envelopeUpper &&
|
| rsiValue > 50 &&
|
| closedPrice > bbLower &&
|
| closedPrice > fractalUp &&
|
| !HasOpenTrade())
|
| {
|
| Print("BUY Signal: Envelope break, RSI bullish, price above BB lower");
|
| double buyStopLoss = bid - (StopLoss * _Point);
|
| double buyTakeProfit = ask + (TakeProfit * _Point);
|
|
|
| if(trade.Buy(LotSize, _Symbol, ask, buyStopLoss, buyTakeProfit))
|
| {
|
| lastTradeTime = currentBarTime;
|
| }
|
| }
|
|
|
| // SELL SIGNAL: Price breaks below envelope with RSI bearish
|
| if(closedPrice < envelopeLower &&
|
| rsiValue < 50 &&
|
| closedPrice < bbUpper &&
|
| closedPrice < fractalDown &&
|
| !HasOpenTrade())
|
| {
|
| Print("SELL Signal: Envelope break, RSI bearish, price below BB upper");
|
| double sellStopLoss = ask + (StopLoss * _Point);
|
| double sellTakeProfit = bid - (TakeProfit * _Point);
|
|
|
| if(trade.Sell(LotSize, _Symbol, bid, sellStopLoss, sellTakeProfit))
|
| {
|
| lastTradeTime = currentBarTime;
|
| }
|
| }
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Get Envelope indicator value |
|
| //+------------------------------------------------------------------+
|
| double GetEnvelopeValue(int buffer, int shift)
|
| {
|
| double envelope[1];
|
| int copied = CopyBuffer(envelopeHandle, buffer, shift, 1, envelope);
|
| if(copied <= 0)
|
| {
|
| Print("Error copying envelope buffer");
|
| return 0;
|
| }
|
| return envelope[0];
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Get RSI indicator value |
|
| //+------------------------------------------------------------------+
|
| double GetRSIValue(int shift)
|
| {
|
| double rsi[1];
|
| int copied = CopyBuffer(rsiHandle, 0, shift, 1, rsi);
|
| if(copied <= 0)
|
| {
|
| Print("Error copying RSI buffer");
|
| return 0;
|
| }
|
| return rsi[0];
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Get Bollinger Bands value |
|
| //+------------------------------------------------------------------+
|
| double GetBBValue(int buffer, int shift)
|
| {
|
| double bb[1];
|
| int copied = CopyBuffer(bbHandle, buffer, shift, 1, bb);
|
| if(copied <= 0)
|
| {
|
| Print("Error copying BB buffer");
|
| return 0;
|
| }
|
| return bb[0];
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Get Fractal High (simple method using 5 bars) |
|
| //+------------------------------------------------------------------+
|
| double GetFractalHigh(int shift)
|
| {
|
| // Fractal: a high with lower highs on both sides
|
| // Simplified: just check 2 bars before and after
|
| double high1 = iHigh(_Symbol, _Period, shift + 2);
|
| double high2 = iHigh(_Symbol, _Period, shift + 1);
|
| double high3 = iHigh(_Symbol, _Period, shift);
|
| double high4 = iHigh(_Symbol, _Period, shift - 1);
|
| double high5 = iHigh(_Symbol, _Period, shift - 2);
|
|
|
| if(high3 > high2 && high3 > high4 && high3 > high1 && high3 > high5)
|
| return high3;
|
|
|
| return high3; // Return current high if no clear fractal
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Get Fractal Low (simple method using 5 bars) |
|
| //+------------------------------------------------------------------+
|
| double GetFractalLow(int shift)
|
| {
|
| // Fractal: a low with higher lows on both sides
|
| double low1 = iLow(_Symbol, _Period, shift + 2);
|
| double low2 = iLow(_Symbol, _Period, shift + 1);
|
| double low3 = iLow(_Symbol, _Period, shift);
|
| double low4 = iLow(_Symbol, _Period, shift - 1);
|
| double low5 = iLow(_Symbol, _Period, shift - 2);
|
|
|
| if(low3 < low2 && low3 < low4 && low3 < low1 && low3 < low5)
|
| return low3;
|
|
|
| return low3; // Return current low if no clear fractal
|
| }
|
|
|
| //+------------------------------------------------------------------+
|
| //| Check if there's already an open trade |
|
| //+------------------------------------------------------------------+
|
| bool HasOpenTrade()
|
| {
|
| int posTotal = PositionsTotal();
|
| for(int i = 0; i < posTotal; i++)
|
| {
|
| if(PositionGetTicket(i) > 0)
|
| {
|
| if(PositionGetString(POSITION_SYMBOL) == _Symbol)
|
| return true;
|
| }
|
| }
|
| return false;
|
| }
|
|
|
| ---
|
|
|
| ## Breaking Down How It Works
|
|
|
| ### The Core Structure
|
|
|
| Your EA has four main sections:
|
|
|
| **1. Indicator Initialization (OnInit)**
|
| When the EA starts, it creates "handles" for each indicator. A handle is like a reference card that tells MT5 "I want data from this specific indicator with these settings." The system stores this for later use.
|
|
|
| **2. The Main Loop (OnTick)**
|
| This runs every time the price ticks (moves). It:
|
| - Gets current indicator values
|
| - Compares them against your rules
|
| - Generates buy or sell signals
|
| - Executes trades if conditions match
|
|
|
| **3. Helper Functions**
|
| These retrieve values from indicators safely. Without them, you'd get crashes if the indicator wasn't ready. These functions return the value or zero if something fails.
|
|
|
| **4. Position Management**
|
| `HasOpenTrade()` checks if you're already in a trade, preventing multiple positions on the same pair.
|
|
|
| ### How Each Indicator Works
|
|
|
| **Envelopes**
|
| - Upper band = Moving Average + Deviation (resistance)
|
| - Lower band = Moving Average - Deviation (support)
|
| - Signal: Price closing outside these bands indicates breakout
|
|
|
| **Bollinger Bands**
|
| - Upper = SMA(20) + 2 × StdDev
|
| - Lower = SMA(20) - 2 × StdDev
|
| - Signal: Price touching bands shows overbought/oversold conditions
|
|
|
| **RSI (Relative Strength Index)**
|
| - Range: 0 to 100
|
| - Above 50 = uptrend bias
|
| - Below 50 = downtrend bias
|
| - Above 70 = overbought, Below 30 = oversold
|
|
|
| **Fractals**
|
| - Highs with lower highs on both sides (resistance point)
|
| - Lows with higher lows on both sides (support point)
|
| - Breaks confirm breakout trades
|
|
|
| ### The Entry Logic (Why Buy?)
|
|
|
| IF price > upper envelope AND
|
| RSI > 50 (trending up) AND
|
| price > lower BB (not oversold) AND
|
| price > fractal high (breaking resistance) AND
|
| no open trade
|
| THEN: Buy
|
|
|
| This combines momentum (RSI), volatility (Envelopes & BB), and price action (Fractals). Multiple confirmations reduce false signals.
|
|
|
| ---
|
|
|
| ## Adjusting for Your Style
|
|
|
| ### For Tighter Scalping (faster entries/exits)
|
| TakeProfit = 10 // Close faster
|
| StopLoss = 8
|
| EnvelopeDeviation = 0.2 // Tighter bands = more signals
|
|
|
| ### For Less Noise (fewer but stronger trades)
|
| TakeProfit = 30
|
| StopLoss = 20
|
| EnvelopePeriod = 20 // Slower moving average
|
| RSIPeriod = 21 // Less sensitive RSI
|
|
|
| ### For Testing on XAUUSD
|
| Gold moves differently than forex. Adjust:
|
| TakeProfit = 2 // Gold moves in dollars, not pips
|
| StopLoss = 1.5
|
| LotSize = 0.01 // Start small
|
|
|
| ---
|
|
|
| ## Common Errors and Fixes
|
|
|
| **Error: "Invalid Handle"**
|
| - Indicator won't initialize
|
| - **Fix**: Check your chart is M5 timeframe. Check _Symbol and _Period are correct in the code
|
|
|
| **Trade doesn't execute**
|
| - You probably don't have "Allow Live Trading" enabled
|
| - **Fix**: In EA settings dialog, tick "Allow live trading"
|
|
|
| **EA stops running**
|
| - Usually from an error. Check the Expert tab for messages
|
| - **Fix**: Restart MT5, reattach the EA
|
|
|
| ---
|
|
|
| ## Next Steps
|
|
|
| 1. Test this on a demo account first (paper trading)
|
| 2. Use the Strategy Tester (Ctrl+R) to backtest before live
|
| 3. Monitor the Expert tab for entry/exit messages
|
| 4. Once confident, adjust lot size and risk parameters
|
|
|
| The EA will tell you exactly when it trades via Print() statements in the Expert tab. This helps you understand if the logic is working.
|