Viewing the resource: Midnight Range Break of Structure (BOS) Breakout Trading in MQL5

Midnight Range Break of Structure (BOS) Breakout Trading in MQL5

Allan Munene Mutiiria 2025-06-22 00:37:54 174 Views
This article details the MQL5 code for the Midnight Range BOS Breakout EA, automating trades on brea...

Introduction

Envision yourself as a master navigator, steering through the forex markets with a high-tech radar system designed for pinpoint accuracy. The Midnight Range BOS Breakout MT5 EA is your precision-engineered trading tool, automating breakout trades by leveraging the price range formed between midnight and 6 AM, confirmed by Break of Structure (BOS) signals on a shorter timeframe (e.g., "timeframe_bos"=PERIOD_M5). The EA identifies the highest ("maximum_price") and lowest ("minimum_price") prices during this period, draws a visual range ("RECTANGLE_PREFIX"), and triggers trades when prices break out between 6 AM and 11 AM, validated by BOS events—price surpassing a swing high ("swing_H") or low ("swing_L") within the range. Trades use 0.01 lots with stop losses and take profits set at the range’s boundaries, ensuring disciplined risk management. Visual markers, including rectangles and lines ("UPPER_LINE_PREFIX", "LOWER_LINE_PREFIX"), enhance clarity, like a radar display guiding your strategy.

This article is crafted with a professional, engaging, and seamless narrative, flowing like a well-calibrated trading system, designed to inform and captivate, as per your preference for beginner-friendly guides. Tailored for both novice and experienced traders, I’ll dissect each code component with clear, precise explanations, as if mentoring an apprentice navigator through a radar system’s controls. With vivid examples—like trading a breakout on EURUSD—and a polished tone, we’ll explore how the EA initializes, calculates ranges, detects breakouts, executes trades, and ensures cleanup. Using a precision market navigation metaphor, this guide will illuminate the code’s technical rigor, empowering you to harness breakout opportunities with confidence. Let’s activate the radar and begin this technical expedition!

Strategy Blueprint

Before delving into the code, let’s outline the EA’s navigation framework, like drafting a radar system’s specifications:

  • Range Calculation: Identifies the highest ("maximum_price") and lowest ("minimum_price") prices from midnight to 6 AM, drawing a rectangle ("RECTANGLE_PREFIX") and lines ("UPPER_LINE_PREFIX", "LOWER_LINE_PREFIX") to mark the range.

  • Breakout Detection: Triggers trades when prices break above/below the range between 6 AM and 11 AM, confirmed by a BOS on "timeframe_bos" (e.g., M5), where price surpasses a swing high ("swing_H") or low ("swing_L") within the range.

  • Trade Execution: Opens 0.01-lot buys on high breakouts or sells on low breakouts, with stop loss at the opposite range boundary and take profit at the range high/low.

  • Visualization: Draws markers for breakouts ("drawBreakPoint()") and swing points ("drawSwingPoint()") to enhance clarity.

  • Execution: Processes trades on new bars ("isNewBar()") with one trade per day ("isTakenTrade").

  • Enhancements: Adding lot size inputs or volatility filters could improve flexibility. This framework automates breakout trades with BOS confirmation, balancing precision with visual clarity.

Code Implementation

Let’s step onto the navigation bridge and dissect the MQL5 code that powers this Midnight Range BOS Breakout EA. I’ll guide you through each phase like a master navigator, ensuring the narrative flows seamlessly with professional clarity and engaging precision that captivates from start to finish. We’ll cover initialization, range calculation, breakout detection, trade execution, and cleanup, with detailed explanations and examples—like trading on EURUSD—to make it accessible for beginners. Each phase will build on the last, crafting a cohesive technical narrative that transforms code into a compelling navigation project. Let’s power up the radar and begin!

Phase 1: Activating the Radar—Initialization

Our expedition starts by activating the radar system, initializing variables and settings to prepare for market scanning.

//+------------------------------------------------------------------+
//|                           Midnight Range BOS Breakour MT5 EA.mq5 |
//|                           Copyright 2025, Allan Munene Mutiiria. |
//|                                   https://t.me/Forex_Algo_Trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link      "https://t.me/Forex_Algo_Trader"
#property version   "1.00"

#include <Trade/Trade.mqh>
CTrade obj_Trade;

double maximum_price = -DBL_MAX;
double minimum_price = DBL_MAX;
datetime maximum_time, minimum_time;
bool isHaveDailyRange_Prices = false;
bool isHaveRangeBreak = false;
bool isTakenTrade = false;
double swing_H = -1.0, swing_L = -1.0;

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

input ENUM_TIMEFRAMES timeframe_bos = PERIOD_M5;

int OnInit(){
   return(INIT_SUCCEEDED);
}

We begin by powering up the radar with the #property header, declaring the EA as a creation by Allan in 2025 with a Telegram link, like calibrating a navigation system’s core, aligning with your metadata preference. The "OnInit()" function initializes the setup, including "Trade/Trade.mqh" for trading via "obj_Trade", like installing a control panel.

We define variables: "maximum_price" and "minimum_price" for range boundaries, "maximum_time" and "minimum_time" for their timestamps, flags ("isHaveDailyRange_Prices", "isHaveRangeBreak", "isTakenTrade") to track states, and "swing_H", "swing_L" for BOS analysis, like configuring radar sensors. Constants ("RECTANGLE_PREFIX", "UPPER_LINE_PREFIX", "LOWER_LINE_PREFIX") name visual objects, and the input "timeframe_bos"=PERIOD_M5 sets the BOS timeframe, like adjustable system settings. Returning INIT_SUCCEEDED signals, “Radar is operational, ready to scan!” This minimalist setup primes the EA for breakout trading, like a navigation system ready for market currents.

Phase 2: Scanning the Market—Calculating the Midnight Range

With the radar active, we calculate the midnight to 6 AM range, like mapping a market zone for breakout detection.

void OnTick(){
   static datetime midnight = iTime(_Symbol,PERIOD_D1,0);
   static datetime sixAM = midnight + 6 * 3600;
   static datetime scanBarTime = sixAM + 1 * PeriodSeconds(_Period);
   static double midnight_price = iClose(_Symbol,PERIOD_D1,0);
   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);
      midnight_price = iClose(_Symbol,PERIOD_D1,0);
      Print("Midnight price = ",midnight_price,", Time = ",midnight);
      validBreakTime_start = scanBarTime;
      validBreakTime_end = midnight + (6+5) * 3600;
      maximum_price = -DBL_MAX;
      minimum_price = DBL_MAX;
      isHaveDailyRange_Prices = false;
      isHaveRangeBreak = false;
      isTakenTrade = false;
      swing_H = -1.0;
      swing_L = -1.0;
   }

   if (isNewBar()){
      datetime currentBarTime = iTime(_Symbol,_Period,0);
      if (currentBarTime == scanBarTime && !isHaveDailyRange_Prices){
         Print("WE HAVE ENOUGH BARS DATA FOR DOCUMENTATION. MAKE THE EXTRACTION");
         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);
         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;
      }
   }
}

In the scanning control room, "OnTick()" runs every tick, using static variables ("midnight", "sixAM", "scanBarTime", "midnight_price", "validBreakTime_start", "validBreakTime_end") to track daily timing, like radar timers. The "isNewDay()" function, using "iTime()", "TimeToStruct()", resets variables on new days ("maximum_price", "minimum_price", flags, "swing_H", "swing_L") with "Print()", like recalibrating sensors.

On new bars ("isNewBar()", "iBars()"), if the current bar matches "scanBarTime" and "isHaveDailyRange_Prices"=false, it scans bars from midnight to 6 AM ("total_bars") using "open()", "close()". It updates "maximum_price" and "minimum_price" by comparing open/close prices ("highest_price_i", "lowest_price_i") with "time()", logging results with "Print()". Visuals are drawn with "create_Rectangle()" (blue, "RECTANGLE_PREFIX") and "create_Line()" (black upper, red lower, "UPPER_LINE_PREFIX", "LOWER_LINE_PREFIX") using "ObjectCreate()", "ObjectSetInteger()", "ChartRedraw()", setting "isHaveDailyRange_Prices"=true. For example, on EURUSD H1, a range from midnight (1.2000) to 6 AM (high 1.2050, low 1.1950) is drawn as a blue rectangle with black/red lines, like a radar mapping a trading zone.

Phase 3: Detecting Breakouts—Validating Range and BOS Signals

With the range mapped, we detect breakouts with BOS confirmation, like locking onto a market signal.

void OnTick(){
   // ... (range calculation)
   double barClose = close(1);
   datetime barTime = time(1);

   if (barClose > maximum_price && isHaveDailyRange_Prices && !isHaveRangeBreak
       && barTime >= validBreakTime_start && barTime <= validBreakTime_end){
      Print("CLOSE Price broke the HIGH range. ",barClose," > ",maximum_price);
      isHaveRangeBreak = true;
      drawBreakPoint(TimeToString(barTime),barTime,barClose,234,clrBlack,-1);
   }
   else if (barClose < minimum_price && isHaveDailyRange_Prices && !isHaveRangeBreak
            && barTime >= validBreakTime_start && barTime <= validBreakTime_end){
      Print("CLOSE Price broke the LOW range. ",barClose," < ",minimum_price);
      isHaveRangeBreak = true;
      drawBreakPoint(TimeToString(barTime),barTime,barClose,233,clrBlue,1);
   }

   if (isHaveDailyRange_Prices){
      static bool isNewBar_bos = false;
      int currBars = iBars(_Symbol,timeframe_bos);
      static int prevBars = currBars;
      if (prevBars == currBars){isNewBar_bos = false;}
      else if (prevBars != currBars){isNewBar_bos = true; prevBars = currBars;}

      const int length = 4;
      int right_index, left_index;
      int curr_bar = length;
      bool isSwingHigh = true, isSwingLow = true;

      if (isNewBar_bos){
         for (int a=1; a<=length; a++){
            right_index = curr_bar - a;
            left_index = curr_bar + a;
            if ( (high(curr_bar,timeframe_bos) <= high(right_index,timeframe_bos)) || (high(curr_bar,timeframe_bos) < high(left_index,timeframe_bos)) ){
               isSwingHigh = false;
            }
            if ( (low(curr_bar,timeframe_bos) >= low(right_index,timeframe_bos)) || (low(curr_bar,timeframe_bos) > low(left_index,timeframe_bos)) ){
               isSwingLow = false;
            }
         }

         if (isSwingHigh){
            swing_H = high(curr_bar,timeframe_bos);
            Print("WE DO HAVE A SWING HIGH @ BAR INDEX ",curr_bar," H: ",high(curr_bar,timeframe_bos));
            drawSwingPoint(TimeToString(time(curr_bar,timeframe_bos)),time(curr_bar,timeframe_bos),high(curr_bar,timeframe_bos),77,clrBlue,-1);
         }
         if (isSwingLow){
            swing_L = low(curr_bar,timeframe_bos);
            Print("WE DO HAVE A SWING LOW @ BAR INDEX ",curr_bar," L: ",low(curr_bar,timeframe_bos));
            drawSwingPoint(TimeToString(time(curr_bar,timeframe_bos)),time(curr_bar,timeframe_bos),low(curr_bar,timeframe_bos),77,clrRed,+1);
         }
      }

In the signal detection hub, "OnTick()" checks the previous bar’s close ("close(1)", "time(1)"). If "barClose" exceeds "maximum_price" or falls below "minimum_price" within 6 AM to 11 AM ("validBreakTime_start", "validBreakTime_end") and "isHaveDailyRange_Prices"=true, "isHaveRangeBreak"=false, it sets "isHaveRangeBreak"=true, logs with "Print()", and draws a breakpoint with "drawBreakPoint()" (black arrow for high, blue for low, "OBJ_ARROW", "ObjectCreate()", "ObjectSetInteger()", "ChartRedraw()"). For example, on EURUSD H1 at 7 AM, a close at 1.2060 above 1.2050 sets a high breakout marker.

For BOS, if "isHaveDailyRange_Prices"=true, it checks new bars on "timeframe_bos" ("iBars()", "isNewBar_bos"). Using "length"=4, it analyzes bar "curr_bar"=4 against 4 bars left/right ("right_index", "left_index") with "high()", "low()". If the bar’s high is the highest ("isSwingHigh"=true) or low is the lowest ("isSwingLow"=true), it updates "swing_H" or "swing_L", logs with "Print()", and draws markers with "drawSwingPoint()" (blue/red arrows, "OBJ_ARROW", "OBJ_TEXT"). For example, on M5, a bar at 1.2040 higher than surrounding bars sets "swing_H"=1.2040 with a blue marker, like a radar confirming a signal.

Phase 4: Navigating the Trade—Executing BOS-Confirmed Breakouts

With signals detected, we execute trades on BOS-confirmed breakouts, like launching a trade on a locked signal.

void OnTick(){
   // ... (BOS detection)
      double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
      double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);

      if (swing_H > 0 && Ask > swing_H && swing_H <= maximum_price && swing_H >= minimum_price){
         Print("$$$$$$$$$ BUY SIGNAL NOW. BREAK OF SWING HIGH WITHIN RANGE");
         int swing_H_index = 0;
         for (int i=0; i<=length*2+1000; i++){
            double high_sel = high(i,timeframe_bos);
            if (high_sel == swing_H){
               swing_H_index = i;
               Print("BREAK HIGH FOUND @ BAR INDEX ",swing_H_index);
               break;
            }
         }
         drawBreakLevel(TimeToString(time(0,timeframe_bos)),time(swing_H_index,timeframe_bos),high(swing_H_index,timeframe_bos),
         time(0,timeframe_bos),high(swing_H_index,timeframe_bos),clrBlue,-1);

         if (isTakenTrade == false){
            obj_Trade.Buy(0.01,_Symbol,Ask,minimum_price,maximum_price);
            isTakenTrade = true;
         }
         swing_H = -1.0;
         return;
      }
      if (swing_L > 0 && Bid < swing_L && swing_L <= maximum_price && swing_L >= minimum_price){
         Print("$$$$$$$$$ SELL SIGNAL NOW. BREAK OF SWING LOW WITHIN RANGE");
         int swing_L_index = 0;
         for (int i=0; i<=length*2+1000; i++){
            double low_sel = low(i,timeframe_bos);
            if (low_sel == swing_L){
               swing_L_index = i;
               Print("BREAK LOW FOUND @ BAR INDEX ",swing_L_index);
               break;
            }
         }
         drawBreakLevel(TimeToString(time(0,timeframe_bos)),time(swing_L_index,timeframe_bos),low(swing_L_index,timeframe_bos),
         time(0,timeframe_bos),low(swing_L_index,timeframe_bos),clrRed,+1);

         if (isTakenTrade == false){
            obj_Trade.Sell(0.01,_Symbol,Bid,maximum_price,minimum_price);
            isTakenTrade = true;
         }
         swing_L = -1.0;
         return;
      }
   }
}

In the trade execution hub, "OnTick()" fetches "Ask" and "Bid" with "SymbolInfoDouble()", "NormalizeDouble()". If "Ask" exceeds "swing_H" within the range ("swing_H <= maximum_price && swing_H >= minimum_price") and "isTakenTrade"=false, it logs a buy signal with "Print()", finds the swing high bar with "high()", draws a blue break level with "drawBreakLevel()" ("OBJ_ARROWED_LINE", "OBJ_TEXT"), and executes a 0.01-lot buy with "obj_Trade.Buy()", setting stop loss at "minimum_price" and take profit at "maximum_price". It sets "isTakenTrade"=true, resets "swing_H", and exits. Sells mirror this for "swing_L", using "obj_Trade.Sell()", red break level, and "maximum_price" stop loss, "minimum_price" take profit. For example, on EURUSD M5, an ask at 1.2045 breaking a swing high at 1.2040 triggers a buy at 1.2045, stop loss at 1.1950, take profit at 1.2050, like a radar-locked trade launch.

Phase 5: Docking the System—Cleaning Up Resources

As our expedition concludes, we dock the system, ensuring resources are cleared for the next journey.

void OnDeinit(const int reason){
   ObjectsDeleteAll(0,RECTANGLE_PREFIX);
   ObjectsDeleteAll(0,UPPER_LINE_PREFIX);
   ObjectsDeleteAll(0,LOWER_LINE_PREFIX);
}

In the docking bay, "OnDeinit()" clears all visual objects with "ObjectsDeleteAll()" for "RECTANGLE_PREFIX", "UPPER_LINE_PREFIX", and "LOWER_LINE_PREFIX", like shutting down radar displays. This ensures a clean chart, preventing visual clutter, ready for the next navigation task, aligning with your preference for thorough cleanup.

Why This EA is a Navigation Triumph

The Midnight Range BOS Breakout MT5 EA is a breakout trading triumph, automating trades with Ichimoku Cloud and AO-like precision, using midnight range breakouts and BOS confirmation. Its visual markers ("create_Rectangle()", "drawBreakPoint()") and disciplined risk-reward ("obj_Trade.Buy()", "obj_Trade.Sell()") ensure clarity, with potential for lot size inputs or filters. Picture a buy on EURUSD at 1.2045, targeting 1.2050 with a 1.1950 stop loss—strategic excellence! Beginners will value the clear logic, while experts can enhance its framework, making it essential for breakout traders.

Putting It All Together

To deploy this EA:

  1. Open MetaEditor in MetaTrader 5, like stepping onto the navigation bridge.

  2. Copy the code, compile with F5, and verify no errors—no navigator wants a faulty radar!

  3. Attach the EA to your chart, enable AutoTrading, and watch it draw ranges and execute trades.

  4. Monitor logs (e.g., “BUY SIGNAL NOW”) and visual markers for trade tracking, like radar data.

  5. Test on a demo account first—real capital deserves a trial run!

Conclusion

We’ve engineered a Midnight BOS Breakout Navigator that automates range breakout trades with BOS confirmation, like a high-tech radar system. This MQL5 code is your navigation tool, brought to life with a seamless, professional narrative packed with clear explanations and vivid examples to fuel your trading ambition. Whether you’re a novice navigator or a seasoned market captain, this EA empowers you to conquer breakout opportunities with confidence. Ready to chart your course? Watch our video guide on the website for a step-by-step creation process. Now, navigate your trading legacy with precision! 🔍

Disclaimer: Trading is like navigating complex markets—challenging and risky. Losses can exceed deposits. Test strategies 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!