🚀 AI One-Click Generation of mql4 Strategy Code

How to Build a Donchian Channel Breakout EA in Mql4 (Without Custom Indicators)

mql4 | Published on: 2025/12/15
The following content is generated by EasyQuant .

Problem Description

Please help me code a breakout trading strategy that buys when the price breaks the high of the last 20 bars.

Solution

Here is a complete, robust MQL4 Expert Advisor (EA) that implements a breakout strategy based on the High and Low of the last 20 bars.

Strategy Logic

  1. Buy Signal: If the current Ask price exceeds the Highest High of the previous 20 bars.
  2. Sell Signal: If the current Bid price drops below the Lowest Low of the previous 20 bars.
  3. Risk Management: Includes Stop Loss and Take Profit inputs.
  4. Order Management: Ensures only one trade is open at a time for this specific strategy to prevent over-trading.

MQL4 Code

//+------------------------------------------------------------------+
//|                                             BreakoutStrategy.mq4 |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Trading AI"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//--- Input Parameters
input int      InpPeriod      = 20;       // Breakout Period (Bars)
input double   InpLotSize     = 0.1;      // Lot Size
input int      InpStopLoss    = 50;       // Stop Loss (in Pips)
input int      InpTakeProfit  = 100;      // Take Profit (in Pips)
input int      InpMagicNum    = 123456;   // Magic Number (Unique ID)
input int      InpSlippage    = 3;        // Max Slippage (in Points)

//--- Global Variables
double pipMultiplier;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Adjust pip multiplier for 3 or 5 digit brokers (Jpy pairs etc)
   if(Digits == 3 || Digits == 5)
      pipMultiplier = 10;
   else
      pipMultiplier = 1;

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Clean up if necessary
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // 1. Check if we already have an open trade for this symbol and magic number
   if(CountOpenTrades() > 0) return;

   // 2. Calculate the Highest High and Lowest Low of the last 'InpPeriod' bars
   // We start at index 1 (previous bar) to avoid the current forming bar repainting the high/low
   int highestIndex = iHighest(NULL, 0, MODE_HIGH, InpPeriod, 1);
   int lowestIndex  = iLowest(NULL, 0, MODE_LOW, InpPeriod, 1);

   if(highestIndex < 0 || lowestIndex < 0) return; // Error check

   double resistanceLevel = High[highestIndex];
   double supportLevel    = Low[lowestIndex];

   // 3. Check for Buy Breakout
   // If Ask price is higher than the highest high of the last 20 bars
   if(Ask > resistanceLevel)
   {
      double sl = 0, tp = 0;
      
      // Calculate SL/TP prices
      if(InpStopLoss > 0) 
         sl = Ask - (InpStopLoss * pipMultiplier * Point);
      if(InpTakeProfit > 0) 
         tp = Ask + (InpTakeProfit * pipMultiplier * Point);
      
      // Normalize prices to prevent OrderSend errors
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);

      // Send Order
      int ticket = OrderSend(Symbol(), OP_BUY, InpLots(), Ask, InpSlippage, sl, tp, "Buy Breakout", InpMagicNum, 0, clrGreen);
      
      if(ticket < 0)
         Print("OrderSend failed with error #", GetLastError());
   }

   // 4. Check for Sell Breakout
   // If Bid price is lower than the lowest low of the last 20 bars
   if(Bid < supportLevel)
   {
      double sl = 0, tp = 0;
      
      // Calculate SL/TP prices
      if(InpStopLoss > 0) 
         sl = Bid + (InpStopLoss * pipMultiplier * Point);
      if(InpTakeProfit > 0) 
         tp = Bid - (InpTakeProfit * pipMultiplier * Point);
      
      // Normalize prices
      sl = NormalizeDouble(sl, Digits);
      tp = NormalizeDouble(tp, Digits);

      // Send Order
      int ticket = OrderSend(Symbol(), OP_SELL, InpLots(), Bid, InpSlippage, sl, tp, "Sell Breakout", InpMagicNum, 0, clrRed);
      
      if(ticket < 0)
         Print("OrderSend failed with error #", GetLastError());
   }
}

//+------------------------------------------------------------------+
//| Helper: Count open trades for this EA                            |
//+------------------------------------------------------------------+
int CountOpenTrades()
{
   int count = 0;
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // Check if the order belongs to this Symbol and this Magic Number
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagicNum)
         {
            count++;
         }
      }
   }
   return count;
}

//+------------------------------------------------------------------+
//| Helper: Verify Lot Size                                          |
//+------------------------------------------------------------------+
double InpLots()
{
   double minLot = MarketInfo(Symbol(), MODE_MINLOT);
   double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
   double step   = MarketInfo(Symbol(), MODE_LOTSTEP);
   
   double lots = InpLotSize;
   
   // Ensure lot size is within broker limits
   if(lots < minLot) lots = minLot;
   if(lots > maxLot) lots = maxLot;
   
   // Normalize to lot step
   return(MathFloor(lots / step) * step);
}
//+------------------------------------------------------------------+

How to Install and Run

  1. Open MetaTrader 4.
  2. Press F4 to open the MetaEditor.
  3. Click New -> Expert Advisor (template) -> Next.
  4. Name it BreakoutStrategy and click Finish.
  5. Delete everything in the new file and paste the code provided above.
  6. Press F7 or click Compile. Ensure there are no errors in the "Errors" tab at the bottom.
  7. Return to the main MT4 window.
  8. Find BreakoutStrategy in the Navigator panel under Expert Advisors.
  9. Drag it onto a chart (e.g., EURUSD H1).
  10. Ensure AutoTrading is enabled at the top of the terminal.

Key Features Explained

  • iHighest / iLowest: These are the core MQL4 functions used to find the index of the highest and lowest bars over the InpPeriod (20).
  • Shift 1: In iHighest(..., 1), the last parameter is the start index. We use 1 (the previous closed bar) instead of 0 (the current moving bar). This prevents the signal from flickering while the current bar is still forming.
  • pipMultiplier: This logic in OnInit automatically detects if your broker uses 5-digit pricing (e.g., EURUSD 1.12345) or 4-digit pricing. This ensures that if you input a 50 Pip Stop Loss, it remains 50 Pips, not 5 Pips.
  • CountOpenTrades: This function prevents the EA from opening 100 trades instantly if the price stays above the breakout line. It forces the EA to wait until the current trade hits SL or TP before opening a new one.

Q&A

Q: Can I change the period from 20 to 50?
A: Yes. When you attach the EA to the chart, go to the "Inputs" tab and change InpPeriod to 50.

Q: Why does the strategy check Ask > resistance for buying?
A: In MT4, Buy orders are executed at the Ask price. If you used the Bid price, the chart might show a breakout, but the spread might prevent the trade from actually being profitable immediately. Using Ask ensures the actual buy price has broken the level.

Q: Does this work on all timeframes?
A: Yes, it works on the timeframe of the chart you attach it to. If you attach it to M15, it looks for the 20-bar high of the M15 chart.