Problem Description
Solution
To check if there is at least one year of historical data available before your strategy runs, you should perform a time-based calculation within the OnInit() function.
The most robust method is to compare the current server time with the opening time of the oldest available bar on the chart. This approach is timeframe-independent, whereas counting specific numbers of bars (e.g., "2000 bars") varies significantly depending on whether you are on an M1 or D1 chart.
Implementation Logic
- Calculate One Year in Seconds: $365 \times 24 \times 60 \times 60 = 31,536,000$ seconds.
- Find the Oldest Bar: Use
Barsto get the total count, then access the time of the last index (Bars - 1) usingiTime. - Compare: Calculate the difference between
TimeCurrent()and the oldest bar's time. If it is less than one year, returnINIT_FAILEDto prevent the EA from running.
MQL4 Code Example
Here is the complete implementation. You can copy the CheckHistoryAvailability function and call it inside OnInit.
//+------------------------------------------------------------------+
//| CheckHistoryYear.mq4|
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
// Define seconds in a non-leap year (365 * 24 * 60 * 60)
#define SECONDS_IN_YEAR 31536000
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Perform the history check before any other logic
if(!CheckHistoryAvailability())
{
// Return INIT_FAILED to stop the EA and remove it from the chart
return(INIT_FAILED);
}
Print("History check passed. Strategy initializing...");
// Continue with normal initialization...
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up code here
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Strategy logic here
}
//+------------------------------------------------------------------+
//| Helper function to verify historical data duration |
//+------------------------------------------------------------------+
bool CheckHistoryAvailability()
{
// Get the total number of bars available in the local history
int totalBars = iBars(_Symbol, _Period);
if(totalBars <= 0)
{
Print("Error: No bars available on the chart.");
return(false);
}
// Get the open time of the oldest available bar
// Index is totalBars - 1 because arrays are 0-indexed
datetime oldestBarTime = iTime(_Symbol, _Period, totalBars - 1);
// Get the current server time
datetime currentTime = TimeCurrent();
// Calculate the duration of available history in seconds
long historyDuration = currentTime - oldestBarTime;
// Check if history is less than one year
if(historyDuration < SECONDS_IN_YEAR)
{
string errMessage = StringFormat(
"Insufficient history data! Required: 1 Year (%d seconds). Available: %d seconds (approx %.2f days).",
SECONDS_IN_YEAR,
historyDuration,
(double)historyDuration / 86400.0
);
Alert(errMessage);
Print(errMessage);
Print("Please scroll the chart back to download more history or download via History Center (F2).");
return(false);
}
return(true);
}
Key Considerations
- Local History vs. Server History:
iBarsandiTimeread from the data currently stored on your computer (local history). If you have just installed MT4, you might only have a few months of data loaded, even if the broker has years of data on their server. - Triggering Downloads: If the check fails, you usually need to manually scroll the chart backward (press the
Homekey) to force MT4 to download older data from the broker, or use the History Center (F2) to download data explicitly. - Timeframe Relevance: This check works on any timeframe. However, having 1 year of M1 data is significantly more data (in terms of bytes and bar count) than 1 year of D1 data. Ensure your Max Bars in History setting (Tools -> Options -> Charts) is high enough to hold the required bars for lower timeframes.
Q&A
Q: Why use iTime instead of just checking Bars > X?
A: Checking the number of bars is inaccurate because the number of bars in a year changes based on the timeframe. 1 year of Daily bars is ~260 bars, while 1 year of H1 bars is ~6,000 bars. Using timestamps ensures the check is accurate regardless of the selected timeframe.
Q: Will this code automatically download the missing data?
A: No. MQL4 cannot force a synchronous download of deep history during OnInit. If the data is missing, the EA must alert the user. The user must then manually download the data (by scrolling back or using the History Center) and restart the EA.
Q: Does this account for weekends and holidays?
A: Yes. By subtracting the oldest timestamp from the current timestamp, we are calculating the absolute time elapsed (calendar time), which includes weekends and holidays. This is generally the correct way to define "One Year" of data availability.