🚀 AI One-Click Generation of mql4 Strategy Code

How to Reliably Detect a New Bar in Your Mql4 Expert Advisor

mql4 | Published on: 2025/11/28
The following content is generated by EasyQuant .

Problem Description

How can I make my trading robot execute a function only on the opening of a new candle?

Solution

To execute a function only once per candle in MQL4, you need to detect the exact moment the current bar's opening time changes. Since OnTick() triggers with every price movement, you must compare the current bar's time (Time[0]) against a stored variable representing the previous bar's time.

Here is the most robust and reusable way to implement this using a boolean check function.

Implementation Strategy

  1. Create a helper function (IsNewCandle): This function stores the time of the last processed bar in a static variable.
  2. Check Time[0]: It compares the current bar's open time with the stored time.
  3. Update and Return: If the times differ, it updates the stored time and returns true. Otherwise, it returns false.

MQL4 Code Example

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // Initialization logic here
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   // Check if a new candle has just opened
   if(IsNewCandle())
   {
      // Code inside this block runs only ONCE per bar
      Print("New candle opened at: ", TimeToString(TimeCurrent()));
      
      // Call your specific trading or analysis function here
      MyTradingLogic();
   }
}

//+------------------------------------------------------------------+
//| Custom Function: Detects New Candle                              |
//+------------------------------------------------------------------+
bool IsNewCandle()
{
   // 'static' ensures the variable retains its value between OnTick calls
   static datetime last_time = 0;
   
   // Time[0] is the open time of the current bar on the current chart
   if(Time[0] != last_time)
   {
      // Update the stored time to the current bar's time
      last_time = Time[0];
      return(true); // New candle detected
   }
   
   return(false); // Same candle, no new bar
}

//+------------------------------------------------------------------+
//| Your Custom Logic Function                                       |
//+------------------------------------------------------------------+
void MyTradingLogic()
{
   // Example: Check Moving Average Crossover
   double maFast = iMA(NULL, 0, 12, 0, MODE_EMA, PRICE_CLOSE, 1);
   double maSlow = iMA(NULL, 0, 26, 0, MODE_EMA, PRICE_CLOSE, 1);
   
   if(maFast > maSlow)
   {
      Print("Bullish condition on new bar.");
      // OrderSend logic would go here
   }
}

Key Concepts Explained

  1. static datetime last_time:
    • The static keyword is crucial. It ensures that the last_time variable is not reset to 0 every time the function is called. It remembers the value from the previous tick.
  2. Time[0]:
    • This is a predefined MQL4 array that holds the open time of the current bar. When a new bar forms, Time[0] changes to the new time (e.g., from 12:00 to 13:00 on an H1 chart).
  3. Execution Flow:
    • Tick 1 (New Bar): Time[0] is 13:00. last_time is 12:00. They are different. last_time updates to 13:00. Function returns true.
    • Tick 2 (Same Bar): Time[0] is 13:00. last_time is 13:00. They are equal. Function returns false.

Handling Specific Timeframes or Symbols

If you need to check for a new candle on a specific timeframe (e.g., H4) while the EA is running on a different chart (e.g., M15), replace Time[0] with iTime():

bool IsNewCandle_H4()
{
   static datetime last_time_h4 = 0;
   // Check H4 time specifically
   datetime current_h4_time = iTime(NULL, PERIOD_H4, 0);
   
   if(current_h4_time != last_time_h4)
   {
      last_time_h4 = current_h4_time;
      return(true);
   }
   return(false);
}

Q&A: MQL4 New Candle Detection

Q: Why shouldn't I just use Volume[0] == 1 to detect a new candle?
A: While Volume[0] == 1 theoretically indicates the first tick of a new bar, it is unreliable. In fast-moving markets, the EA might miss the very first tick due to network latency or processing delays. If the EA receives the data when the volume is already 2 or 3, the condition fails, and the logic never executes for that bar. Comparing time is always accurate regardless of how many ticks have passed.

Q: Will IsNewCandle() return true when I first attach the EA to the chart?
A: Yes. When the EA initializes, the static variable last_time is 0. The current Time[0] will be a valid date (e.g., 2023.10.27 10:00). Since 0 does not equal the current time, it returns true on the very first tick. If you want to skip the first execution, you can initialize last_time with Time[0] inside OnInit().

Q: Can I use this logic for backtesting?
A: Yes, this logic works perfectly in the Strategy Tester. It ensures that your strategy only calculates signals at the open of bars, which significantly speeds up backtesting compared to calculating on every tick.

Q: Does this work for Renko or non-time-based charts?
A: Standard MQL4 Time[] arrays rely on time-based bars. For offline charts (like Renko generated by indicators), the Time[0] usually still updates when a new brick is formed, so this logic generally works, provided the offline chart generator updates the history data correctly.