Viewing the resource: Crafting a Daily Range Breakout Hunter with MQL5

Crafting a Daily Range Breakout Hunter with MQL5

Allan Munene Mutiiria 2025-06-21 14:00:06 115 Views
Join us for a detailed, professional, and engaging expedition through our MQL5 code that automates d...

Introduction

Greetings, forex explorers! Picture the forex market as a dense jungle, with prices prowling like wild beasts, ready to leap or dive at dawn. The Daily Range Breakout EA is your trusty expedition map, an MQL5 bot that charts the price range from midnight to 6 AM, draws it vividly on the chart, and signals breakouts between 6 AM and 11 AM. This EA doesn’t trade yet, but it sets the stage for you to pounce on buy or sell signals with precision. This article is your explorer’s log, guiding you through the code with crystal-clear detail for beginners, a flow smoother than a jungle stream, and examples—like hunting pips on EURUSD—to keep you engaged. We’ll quote variables (e.g., "maximum_price") and functions (e.g., "OnInit()") for clarity, balancing pro insights with a sprinkle of charm. Ready to track those breakouts? Let’s embark on this jungle hunt!

Strategy Blueprint

The Daily Range Breakout EA focuses on early daily price action:

  • Range Detection: Tracks the highest and lowest prices from midnight to 6 AM, defining a daily range.

  • Visualization: Draws a blue rectangle for the range, black upper line, red lower line, and arrows for breakouts.

  • Breakout Signals: Flags buy signals when prices break above the high or sell signals when breaking below the low, between 6 AM and 11 AM.

  • Settings: Uses a fixed midnight-to-6 AM window and 500-pip range threshold (configurable for trading logic). It’s like mapping a jungle clearing and signaling when the market beast breaks free, ready for traders to add execution logic. See below.

Code Implementation

Let’s trek through the MQL5 code like jungle explorers following a map, building our breakout hunter step by step. We’ll flow from setting up camp to mapping the range, signaling breakouts, visualizing them, and cleaning up, with transitions as seamless as a river’s current. Each section includes code blocks, detailed explanations of what we’re doing, and examples to keep you engaged, all while staying beginner-friendly and professional.

Step 1: Setting Up the Jungle Camp—Preparing the Expedition

We start by pitching our camp, defining the EA’s structure to hunt daily breakouts.

//+------------------------------------------------------------------+
//|                                      DAILY RANGE BREAKOUT EA.mq5 |
//|      Copyright 2025, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. |
//|                           https://youtube.com/@ForexAlgo-Trader? |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader"
#property link      "https://youtube.com/@ForexAlgo-Trader?"
#property description "======= IMPORTANT =======\n"
#property description "1. This is a FREE EA."
#property description "2. To get the source code of the EA, follow the Copyright link."
#property description "3. In case of anything, contact developer via the link provided."
#property description "Hope you will enjoy the EA Logic.\n"
#property description "*** HAPPY TRADING! ***"
#property version   "1.00"

double maximum_price = -DBL_MAX;
double minimum_price = +DBL_MAX;
datetime maximum_time, minimum_time;

bool isHaveDailyRange_Prices = false;
bool isHaveDailyRange_Break = false;

#define RECTANGLE_PREFIX "RANGE RECTANGLE "
#define UPPER_LINE_PREFIX "UPPER LINE"
#define LOWER_LINE_PREFIX "LOWER LINE"

int OnInit(){
   return(INIT_SUCCEEDED);
}

We set up our camp with a #property header, declaring the EA as a free offering by Allan in 2025 with a YouTube link, like carving our name on a jungle tree. We define global variables: "maximum_price" and "minimum_price" for range boundaries, "maximum_time" and "minimum_time" for timestamps, and flags "isHaveDailyRange_Prices" and "isHaveDailyRange_Break" to track range detection and breakouts, like marking our expedition log. Constants "RECTANGLE_PREFIX", "UPPER_LINE_PREFIX", and "LOWER_LINE_PREFIX" name our visual objects, like labeling map markers. In "OnInit()", we return INIT_SUCCEEDED, like signaling, “Camp’s ready, let’s trek!” This minimal setup primes us for the breakout hunt.

Step 2: Mapping the Clearing—Defining the Daily Range

With camp set, we map the jungle clearing by finding the daily range from midnight to 6 AM.

void OnTick(){
   static datetime midnight = iTime(_Symbol,PERIOD_D1,0);
   static datetime sixAM = midnight + 6 * 3600;
   static datetime scanBarTime = sixAM + 1 * PeriodSeconds(_Period);
   static datetime validBreakTime_start = scanBarTime;
   static datetime validBreakTime_end = midnight + (6+5) * 3600;

   if (isNewDay()){
      midnight = iTime(_Symbol,PERIOD_D1,0);
      sixAM = midnight + 6 * 3600;
      scanBarTime = sixAM + 1 * PeriodSeconds(_Period);
      validBreakTime_start = scanBarTime;
      validBreakTime_end = midnight + (6+5) * 3600;
      maximum_price = -DBL_MAX;
      minimum_price = +DBL_MAX;
      isHaveDailyRange_Prices = false;
      isHaveDailyRange_Break = false;
   }

   if (isNewBar()){
      datetime currentBarTime = iTime(_Symbol,_Period,0);
      if (currentBarTime == scanBarTime && !isHaveDailyRange_Prices){
         Print("WE HAVE ENOUGH BARS DATA FOR DOCUMENTATION. MAKE THE DATA EXTRACTION NOW");
         int total_bars = int((sixAM - midnight)/PeriodSeconds(_Period))+1;
         Print("Total bars for scan = ",total_bars);
         int highest_price_bar_index = -1;
         int lowest_price_bar_index = -1;
         for (int i=1; i<=total_bars; i++){
            double open_i = open(i);
            double close_i = close(i);
            double highest_price_i = (open_i > close_i) ? open_i : close_i;
            double lowest_price_i = (open_i < close_i) ? open_i : close_i;
            if (highest_price_i > maximum_price){
               maximum_price = highest_price_i;
               highest_price_bar_index = i;
               maximum_time = time(i);
            }
            if (lowest_price_i < minimum_price){
               minimum_price = lowest_price_i;
               lowest_price_bar_index = i;
               minimum_time = time(i);
            }
         }
         Print("Maximum Price = ",maximum_price,", Bar Index = ",highest_price_bar_index,", Time = ",maximum_time);
         Print("Minimum Price = ",minimum_price,", Bar Index = ",lowest_price_bar_index,", Time = ",minimum_time);
      }
   }
}
double open(int index){return (iOpen(_Symbol,_Period,index));}
double high(int index){return (iHigh(_Symbol,_Period,index));}
double low(int index){return (iLow(_Symbol,_Period,index));}
double close(int index){return (iClose(_Symbol,_Period,index));}
datetime time(int index){return (iTime(_Symbol,_Period,index));}
bool isNewDay(){
   bool newDay = false;
   MqlDateTime str_datetime;
   TimeToStruct(TimeCurrent(), str_datetime);
   static int prevday = 0;
   int currday = str_datetime.day;
   if (prevday == currday){
      newDay = false;
   }
   else if (prevday != currday){
      Print("WE HAVE A NEW DAY WITH DATE ",currday);
      prevday = currday;
      newDay = true;
   }
   return (newDay);
}
bool isNewBar(){
   static int prevbars = 0;
   int currbars = iBars(_Symbol,_Period);
   if (prevbars == currbars) return (false);
   prevbars = currbars;
   return (true);
}

In "OnTick()", we track time with "midnight", "sixAM", and "scanBarTime", using "iTime()", "PeriodSeconds()", and "isNewDay()" to reset daily at midnight via "TimeToStruct()", "TimeCurrent()". At 6 AM’s next bar, we scan from midnight using "open()", "close()", "time()", finding the highest and lowest prices via a loop, updating "maximum_price", "minimum_price", "maximum_time", "minimum_time". We log details with "Print()", like “Maximum Price = 1.2000, Time = 2025.06.21 03:00.” This maps the clearing, like marking EURUSD’s daily range from 1.1950 to 1.2000, setting our trap.

Step 3: Painting the Trap—Visualizing the Range

With the range mapped, we paint a blue rectangle and lines to mark it, like staking neon signs in the jungle.

void create_Rectangle(string objName,datetime time1,double price1,datetime time2,double price2,color clr){
   if (ObjectFind(0,objName) < 0){
      ObjectCreate(0,objName,OBJ_RECTANGLE,0,time1,price1,time2,price2);
      ObjectSetInteger(0,objName,OBJPROP_TIME,0,time1);
      ObjectSetDouble(0,objName,OBJPROP_PRICE,0,price1);
      ObjectSetInteger(0,objName,OBJPROP_TIME,1,time2);
      ObjectSetDouble(0,objName,OBJPROP_PRICE,1,price2);
      ObjectSetInteger(0,objName,OBJPROP_FILL,true);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,objName,OBJPROP_BACK,false);
      ChartRedraw(0);
   }
}
void create_Line(string objName,datetime time1,double price1,datetime time2,double price2,int width,color clr,string text){
   if (ObjectFind(0,objName) < 0){
      ObjectCreate(0,objName,OBJ_TREND,0,time1,price1,time2,price2);
      ObjectSetInteger(0,objName,OBJPROP_TIME,0,time1);
      ObjectSetDouble(0,objName,OBJPROP_PRICE,0,price1);
      ObjectSetInteger(0,objName,OBJPROP_TIME,1,time2);
      ObjectSetDouble(0,objName,OBJPROP_PRICE,1,price2);
      ObjectSetInteger(0,objName,OBJPROP_WIDTH,width);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,objName,OBJPROP_BACK,false);
      long scale = 0;
      if (!ChartGetInteger(0,CHART_SCALE,0,scale)){
         Print("UNABLE TO GET THE CHART SCALE. DEFAULT VALUE OF ",scale," IS CONSIDERED.");
      }
      int fontsize = 11;
      if (scale==0){fontsize=5;}
      else if (scale==1){fontsize=6;}
      else if (scale==2){fontsize=7;}
      else if (scale==3){fontsize=9;}
      else if (scale==4){fontsize=11;}
      else if (scale==5){fontsize=13;}
      string txt = " Right Price";
      string objNameDescr = objName + txt;
      ObjectCreate(0,objNameDescr,OBJ_TEXT,0,time2,price2);
      ObjectSetInteger(0,objNameDescr,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,objNameDescr,OBJPROP_FONTSIZE,fontsize);
      ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT);
      ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + text);
      ObjectSetString(0,objNameDescr,OBJPROP_FONT,"Calibri");
      ChartRedraw(0);
   }
}
void OnTick(){
   // ... (range detection)
   if (currentBarTime == scanBarTime && !isHaveDailyRange_Prices){
      // ... (price scanning)
      create_Rectangle(RECTANGLE_PREFIX+TimeToString(maximum_time),maximum_time,maximum_price,minimum_time,minimum_price,clrBlue);
      create_Line(UPPER_LINE_PREFIX+TimeToString(midnight),midnight,maximum_price,sixAM,maximum_price,3,clrBlack,DoubleToString(maximum_price,_Digits));
      create_Line(LOWER_LINE_PREFIX+TimeToString(midnight),midnight,minimum_price,sixAM,minimum_price,3,clrRed,DoubleToString(minimum_price,_Digits));
      isHaveDailyRange_Prices = true;
   }
}

We call "create_Rectangle()" to draw a blue, filled rectangle from "maximum_time" to "minimum_time", spanning "maximum_price" to "minimum_price", using "ObjectCreate(OBJ_RECTANGLE)", "ObjectSetInteger()", "ObjectSetDouble()". We use "create_Line()" to draw a black upper line and red lower line from midnight to 6 AM, labeled with prices via "DoubleToString()", adjusting font size with "ChartGetInteger(CHART_SCALE)". This paints our trap, like marking EURUSD’s range from 1.1950 to 1.2000 with a neon rectangle on the H1 chart.

Step 4: Springing the Trap—Signaling Breakouts

Range painted? We watch for breakouts between 6 AM and 11 AM, like a jaguar leaping from the clearing.

void drawBreakPoint(string objName,datetime time,double price,int arrCode,color clr,int direction){
   if (ObjectFind(0,objName) < 0){
      ObjectCreate(0,objName,OBJ_ARROW,0,time,price);
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,objName,OBJPROP_FONTSIZE,12);
      if (direction > 0) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if (direction < 0) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
      string txt = " Breakout";
      string objNameDescr = objName + txt;
      ObjectCreate(0,objNameDescr,OBJ_TEXT,0,time,price);
      ObjectSetInteger(0,objNameDescr,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,objNameDescr,OBJPROP_FONTSIZE,12);
      if (direction > 0) {
         ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
         ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + txt);
      }
      if (direction < 0) {
         ObjectSetInteger(0,objNameDescr,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
         ObjectSetString(0,objNameDescr,OBJPROP_TEXT, " " + txt);
      }
   }
   ChartRedraw(0);
}
void OnTick(){
   // ... (range visualization)
   double barClose = close(1);
   datetime barTime = time(1);
   if (barClose > maximum_price && isHaveDailyRange_Prices && !isHaveDailyRange_Break
       && barTime >= validBreakTime_start && barTime <= validBreakTime_end){
      Print("CLOSE Price broke the HIGH range. ",barClose," > ",maximum_price);
      isHaveDailyRange_Break = true;
      drawBreakPoint(TimeToString(barTime),barTime,barClose,234,clrBlack,-1);
   }
   else if (barClose < minimum_price && isHaveDailyRange_Prices && !isHaveDailyRange_Break
       && barTime >= validBreakTime_start && barTime <= validBreakTime_end){
      Print("CLOSE Price broke the LOW range. ",barClose," < ",minimum_price);
      isHaveDailyRange_Break = true;
      drawBreakPoint(TimeToString(barTime),barTime,barClose,233,clrBlue,+1);
   }
}

We check the latest bar’s close with "close(1)", "time(1)". If it breaks above "maximum_price" or below "minimum_price" within 6 AM to 11 AM ("validBreakTime_start" to "validBreakTime_end") and no breakout has occurred ("isHaveDailyRange_Break"), we log it with "Print()", like “CLOSE Price broke the HIGH range. 1.2010 > 1.2000,” and call "drawBreakPoint()" to draw a black (buy) or blue (sell) arrow with “Breakout” text via "ObjectCreate(OBJ_ARROW)", "ObjectCreate(OBJ_TEXT)". We set "isHaveDailyRange_Break" to true, like signaling, “Jaguar’s out!” This flags breakouts, like catching EURUSD jumping to 1.2010 at 7 AM.

Step 5: Packing Up Camp—Cleaning Up Tracks

When the expedition’s done, we clean up to leave the jungle pristine.

void OnDeinit(const int reason){
}

In "OnDeinit()", we leave it empty, as no cleanup is coded yet, like leaving our map markers in place. We could add "ObjectsDeleteAll()" for "RANGE RECTANGLE ", "UPPER LINE", "LOWER LINE" to clear visuals, like erasing our jungle tracks, but for now, it’s a light pack-up, ready for the next trek. See below.

Why This EA’s a Jungle Legend (and Keeps You Engaged!)

This EA is a breakout-hunting legend, mapping the daily range like a jungle explorer, visualizing it with flair, and signaling explosive moves. It’s pro-grade with a clear setup, ready for you to add trading logic, like arming your trap with spears. Example? On GBPUSD, it maps a 1.3500–1.3550 range by 6 AM, flags a buy breakout at 1.3560 by 8 AM, letting you trade 200 pips—pure jungle gold! Beginners can follow, and pros can customize, making it a must-have for breakout traders.

Putting It All Together

To launch this EA:

  1. Open MetaEditor in MetaTrader 5 like entering a jungle camp.

  2. Paste the code, compile (F5), and check for typos—no explorer wants a faulty map.

  3. Drop the EA on your chart, enable AutoTrading, and watch for blue rectangles and breakout arrows.

  4. Add trading logic (e.g., buy/sell orders) to act on signals, like setting spears for the jaguar.

  5. Test on a demo first—real pips deserve a practice hunt!

Conclusion

We’ve crafted a daily range breakout hunter that maps early price ranges, paints them blue, and signals explosive moves like a jaguar on the prowl. This MQL5 code is our expedition map, explained with detail to make you a trading explorer, a touch of charm to keep you engaged, and flow to carry you like a jungle stream. Ready to hunt? Check our video guide on the website for a front-row seat to this breakout adventure. Now go snare those pips! 🐆

Disclaimer: Trading’s like hunting a jungle beast—thrilling but risky. Losses can exceed deposits. Test on a demo account before going live.

Disclaimer: The ideas and strategies presented in this resource are solely those of the author and are intended for informational and educational purposes only. They do not constitute financial advice, and past performance is not indicative of future results. All materials, including but not limited to text, images, files, and any downloadable content, are protected by copyright and intellectual property laws and are the exclusive property of Forex Algo-Trader or its licensors. Reproduction, distribution, modification, or commercial use of these materials without prior written consent from Forex Algo-Trader is strictly prohibited and may result in legal action. Users are advised to exercise extreme caution, perform thorough independent research, and consult with qualified financial professionals before implementing any trading strategies or decisions based on this resource, as trading in financial markets involves significant risk of loss.

Recent Comments

Go to discussion to Comment or View other Comments

No comments yet. Be the first to comment!