385 lines
13 KiB
HTML
385 lines
13 KiB
HTML
|
|
# 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.
|