How to Change Chart Timeframe in MQL5?

Trading platforms like MetaTrader 5 provide a rich environment for technical analysis and automated trading. A fundamental aspect of this environment is the concept of chart timeframes. Understanding and manipulating timeframes programmatically is crucial for developing sophisticated trading systems, indicators, and utilities in MQL5.

Understanding Timeframes and Their Importance

Timeframes represent the duration covered by each candlestick or bar on a chart. Common timeframes range from M1 (1 minute) to MN1 (1 month). The choice of timeframe significantly impacts the visualization of price data, technical indicator calculations, and ultimately, trading strategy outcomes. Shorter timeframes reveal granular price movements and are suitable for scalping or day trading analysis, while longer timeframes smooth out noise and highlight long-term trends, preferred by swing traders and investors.

Overview of MQL5 and Chart Objects

MQL5 (MetaQuotes Language 5) is a high-level programming language specifically designed for developing technical indicators, trading robots (Expert Advisors), and utility scripts for the MetaTrader 5 platform. MQL5 provides extensive capabilities for interacting with the trading terminal, including accessing market data, managing orders, and manipulating chart properties. Charts themselves are represented as objects within the MQL5 environment, each having various properties that can be queried and modified programmatically, such as symbols, timeframes, scroll positions, and visibility settings.

Why Change Chart Timeframes Programmatically?

Programmatically changing a chart’s timeframe is a powerful capability for several reasons:

  • Dynamic Strategy Adjustment: Expert Advisors might need to analyze different timeframes simultaneously or switch timeframes based on specific market conditions or strategy logic.
  • Automated Analysis: Scripts can be created to cycle through multiple timeframes, performing analysis or generating reports for each one without manual intervention.
  • User Interface Interaction: Utility tools or indicators with custom interfaces (using graphical objects) might offer buttons or controls for users to switch timeframes directly from the chart.
  • Data Synchronization: When developing indicators or EAs that require data from timeframes other than the current chart’s, you often don’t change the current chart’s timeframe but rather access data series from other periods using functions like CopyBuffer or iBars, specifying the desired timeframe.

While the primary focus of this article is changing the visible chart’s timeframe, it’s essential to distinguish this from accessing data from other timeframes for calculations, which is a more common task for indicators and EAs running on a single chart.

Methods for Changing Chart Timeframe in MQL5

The standard and recommended method for changing the timeframe of a specific chart in MQL5 is by using the ChartSetInteger() function.

Using the ChartSetInteger() Function

The ChartSetInteger() function allows you to set the value of an integer property of a specified chart. Its signature is:

bool ChartSetInteger(
   long           chart_id,       // chart ID
   int            property_id,    // property identifier
   long           value           // value
);

To change the timeframe, you need to provide:

  • chart_id: The identifier of the chart. Use 0 for the current chart where the script, indicator, or EA is running.
  • property_id: The specific property to change. For the timeframe, this is CHART_PROPERTY_PERIOD.
  • value: The desired timeframe. This must be a value from the ENUM_TIMEFRAMES enumeration.

Employing the ENUMCHARTPROPERTY_INTEGER Enumeration

The CHART_PROPERTY_PERIOD identifier is part of the ENUM_CHART_PROPERTY_INTEGER enumeration, which lists various integer properties of a chart that can be set or retrieved. The possible values for the value parameter when changing the period come from the ENUM_TIMEFRAMES enumeration. Some common values include:

  • PERIOD_M1 (1 minute)
  • PERIOD_M5 (5 minutes)
  • PERIOD_M15 (15 minutes)
  • PERIOD_M30 (30 minutes)
  • PERIOD_H1 (1 hour)
  • PERIOD_H4 (4 hours)
  • PERIOD_D1 (Daily)
  • PERIOD_W1 (Weekly)
  • PERIOD_MN1 (Monthly)

Alternative Approaches and Considerations

While ChartSetInteger(..., CHART_PROPERTY_PERIOD, ...) is the direct method, it’s worth noting that interaction with charts can also occur via:

  • Terminal User Interface: Manual switching by the user or external tools interacting with the terminal’s UI (not programmatically via MQL5).
  • MQL4 Differences: In MQL4, changing the chart timeframe programmatically is generally not supported as a standard feature for the active chart from within an indicator or EA. Scripts could achieve this with non-standard methods (like sending Windows messages), which were platform-dependent and not recommended. MQL5’s ChartSetInteger provides a clean, native way.

It’s important to remember that changing the chart’s timeframe will typically cause the chart to reload data and re-initialize any indicators or EAs attached to it (specifically, their OnInit will be called again after OnDeinit). This is a significant side effect to consider.

Practical Examples and Code Snippets

Let’s look at some practical examples demonstrating how to change and retrieve chart timeframes using MQL5.

Changing Timeframe on Button Click

This example shows how to change the chart timeframe when a button graphical object is clicked. This requires handling chart events using OnChartEvent.

//+------------------------------------------------------------------+
//| Script changing timeframe on button click                        |
//+------------------------------------------------------------------+
#property script_show_inputs

input ENUM_TIMEFRAMES NewTimeframe = PERIOD_H4;

string buttonName = "ChangeTimeframeButton";

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
int OnInit()
{
   // Create a button object
   if(!ObjectCreate(0, buttonName, OBJ_BUTTON, 0, 0, 0))
   {
      Print("Error creating button: ", GetLastError());
      return INIT_FAILED;
   }

   // Set button properties
   ObjectSetInteger(0, buttonName, OBJPROP_XSIZE, 120);
   ObjectSetInteger(0, buttonName, OBJPROP_YSIZE, 25);
   ObjectSetInteger(0, buttonName, OBJPROP_XDISTANCE, 20);
   ObjectSetInteger(0, buttonName, OBJPROP_YDISTANCE, 20);
   ObjectSetString(0, buttonName, OBJPROP_TEXT, "Switch to " + EnumToString(NewTimeframe));
   ObjectSetInteger(0, buttonName, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, buttonName, OBJPROP_ZORDER, 0);

   // Redraw chart to show the button
   ChartRedraw();

   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(
   const int        id,        // Event ID
   const long       lparam,    // long parameter
   const double     dparam,    // double parameter
   const string     sparam     // string parameter
)
{
   // Handle click on graphical object
   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      // Check if the clicked object is our button
      if(sparam == buttonName)
      {
         // Attempt to change the timeframe
         if(ChartSetInteger(0, CHART_PROPERTY_PERIOD, NewTimeframe))
         {
            Print("Chart timeframe changed to ", EnumToString(NewTimeframe));
            // OnDeinit and OnInit will be called by the terminal
         }
         else
         {
            Print("Failed to change timeframe: ", GetLastError());
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Script program deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Delete the button object
   ObjectDelete(0, buttonName);
   Print("Button deleted. Deinit reason: ", reason);
}

Attach this script to a chart. It will create a button. Clicking the button will attempt to change the chart to the timeframe specified in the script’s input.

Dynamically Adjusting Timeframe Based on Market Conditions

An Expert Advisor might want to switch timeframes based on volatility, time of day, or other factors. This logic would reside within OnTick or OnTimer.

// Inside an Expert Advisor's OnTick or OnTimer function
void OnTick()
{
   // Example: Switch to M5 if volatility (measured by ATR) is low
   double atrValue = iATR(Symbol(), Period(), 14, 0);
   double currentATR = iATR(Symbol(), Period(), 14, 1);
   ENUM_TIMEFRAMES currentTimeframe = (ENUM_TIMEFRAMES)ChartGetInteger(0, CHART_PROPERTY_PERIOD);

   // Check if ATR is below a threshold and current timeframe is not already M5
   if(atrValue < 0.00020 && currentTimeframe != PERIOD_M5)
   {
      Print("Volatility low, switching to M5");
      if(!ChartSetInteger(0, CHART_PROPERTY_PERIOD, PERIOD_M5))
      {
         Print("Failed to switch to M5: ", GetLastError());
      }
   }
   // Example: Switch back to H1 if ATR is high and current timeframe is M5
   else if (atrValue > 0.00050 && currentTimeframe == PERIOD_M5)
   {
      Print("Volatility high, switching back to H1");
       if(!ChartSetInteger(0, CHART_PROPERTY_PERIOD, PERIOD_H1))
      {
         Print("Failed to switch to H1: ", GetLastError());
      }
   }
}

This is a simplified example. Real-world logic would be more complex, potentially involving checks to avoid frequent switching or switching during critical strategy phases.

Implementing Timeframe Switching in Expert Advisors

Integrating timeframe switching into an EA requires careful management of the EA’s state because OnDeinit and OnInit will be called upon switching. The reason parameter in OnDeinit can be REASON_CHARTCHANGE (or REASON_TIMEFRAME in MQL4 context, though MQL5 uses REASON_CHARTCHANGE for period changes). This allows saving state before deinitialization and restoring it in OnInit or immediately after the ChartSetInteger call if you can manage the state outside the indicator/EA’s instance lifecycle.

A robust EA might use a separate, non-visual component or external file to manage state across timeframe changes.

Displaying Current Timeframe Information

Retrieving the current timeframe of a chart is done using ChartGetInteger():

// Inside OnInit or OnTick of an EA or Indicator
ENUM_TIMEFRAMES currentPeriod = (ENUM_TIMEFRAMES)ChartGetInteger(0, CHART_PROPERTY_PERIOD);

if (currentPeriod != PERIOD_CURRENT)
{
    Print("Current chart timeframe: ", EnumToString(currentPeriod));
}
else
{
    // PERIOD_CURRENT is usually returned for indicators/EAs
    // Need to use Period() function instead for the attached timeframe
    currentPeriod = Period();
    Print("Attached timeframe (using Period()): ", EnumToString(currentPeriod));
}

Note: ChartGetInteger(0, CHART_PROPERTY_PERIOD) might return PERIOD_CURRENT when called from an indicator or EA’s primary event handlers (OnInit, OnTick, etc.) running on the chart. The standard function Period() is the reliable way to get the timeframe the current EA or indicator instance is attached to. ChartGetInteger(0, CHART_PROPERTY_PERIOD) is primarily used to set the period or get it from scripts or potentially from other contexts where Period() is not directly available or you need the currently displayed chart period, which might differ from the attached EA’s period if the user manually changed it after the EA was attached.

For changing the timeframe, ChartSetInteger(0, CHART_PROPERTY_PERIOD, ...) is correct as it modifies the chart itself, not the attached program’s context.

Advanced Techniques and Considerations

Programmatically changing chart timeframes, especially frequently or across multiple charts, requires attention to detail.

Handling Errors and Edge Cases

ChartSetInteger() returns true on success and false on failure. It’s crucial to check the return value and use GetLastError() to diagnose issues.

Potential failure reasons include:

  • Invalid chart ID.
  • Invalid property ID (CHART_PROPERTY_PERIOD is unlikely to be invalid).
  • Invalid timeframe value (e.g., a non-ENUM_TIMEFRAMES value).
  • Terminal busy or unable to switch at that moment.

Your code should gracefully handle these failures, perhaps logging an error or retrying.

Optimizing Performance for Frequent Timeframe Changes

Frequent, rapid timeframe changes on a chart are generally discouraged unless absolutely necessary. Each change triggers data loading and re-initialization of attached programs, which consumes resources and can potentially cause delays or unexpected behavior. If your goal is to analyze data across multiple timeframes, it is vastly more efficient to keep the main chart on one timeframe and access data from other periods without changing the chart’s visible timeframe, using functions like CopyClose, iMA, etc., specifying the desired symbol and timeframe as parameters.

Only change the chart’s visible timeframe when the user needs to see a different view or when your EA’s core logic dictates a change in the primary visual/processing context.

Interacting with Multiple Charts and Timeframes

MQL5 allows managing multiple chart windows. You can get a list of all open chart IDs using ChartFirst() and ChartNext(). Once you have a chart ID (e.g., from ChartOpen() or iterating through existing charts), you can change its timeframe using ChartSetInteger(chart_id, CHART_PROPERTY_PERIOD, new_period). This is useful for utility scripts that set up workspace layouts or EAs that monitor helper charts.

// Example: Open a new chart and set its timeframe
long newChartId = ChartOpen(Symbol(), PERIOD_H1);
if(newChartId > 0)
{
   Print("New chart opened with ID: ", newChartId);
   // Optionally set its timeframe explicitly (it might open with default)
   if(ChartSetInteger(newChartId, CHART_PROPERTY_PERIOD, PERIOD_H4))
   {
      Print("New chart timeframe set to H4");
   }
   else
   {
      Print("Failed to set new chart timeframe: ", GetLastError());
   }
} else {
    Print("Failed to open new chart: ", GetLastError());
}

Using Chart Properties to Manage Timeframes

The CHART_PROPERTY_PERIOD is just one of many chart properties (ENUM_CHART_PROPERTY_INTEGER, ENUM_CHART_PROPERTY_DOUBLE, ENUM_CHART_PROPERTY_STRING). You might combine changing the timeframe with other property modifications, such as auto-scrolling (CHART_AUTOSCROLL), chart shift (CHART_SHIFT), or even the symbol (CHART_SYMBOL) if opening/managing multiple charts. This allows for complete programmatic control over the visual charting environment.

Conclusion

Programmatically changing chart timeframes in MQL5 is a straightforward task primarily accomplished using the ChartSetInteger() function with the CHART_PROPERTY_PERIOD identifier and a value from the ENUM_TIMEFRAMES enumeration.

Recap of Key Methods

  • Use ChartSetInteger(0, CHART_PROPERTY_PERIOD, desired_period) for the current chart.
  • Use ChartSetInteger(chart_id, CHART_PROPERTY_PERIOD, desired_period) for a chart specified by its ID.
  • Retrieve the attached program’s timeframe using Period().
  • Retrieve the chart’s currently displayed timeframe using ChartGetInteger(0, CHART_PROPERTY_PERIOD) (though Period() is often more relevant for an EA/Indicator instance).
  • Handle chart events (OnChartEvent) for user interaction like button clicks.

Best Practices for Timeframe Management in MQL5

  • Avoid excessive or rapid timeframe changes as it incurs overhead.
  • Check the return value of ChartSetInteger() and handle errors.
  • When analyzing multiple timeframes, prefer using data access functions (CopyBuffer, iClose, etc.) that specify the symbol and timeframe, rather than changing the main chart’s timeframe.
  • Be aware that changing the chart’s timeframe causes attached EAs/Indicators to re-initialize (OnDeinit -> OnInit). Plan your state management accordingly if your program needs to maintain context across these changes.

Further Learning Resources

Explore the MQL5 Reference documentation for detailed information on:

  • ChartSetInteger()
  • ChartGetInteger()
  • ENUM_TIMEFRAMES
  • ENUM_CHART_PROPERTY_INTEGER
  • OnChartEvent and graphical objects
  • ChartOpen, ChartFirst, ChartNext

Mastering chart manipulation and data access across timeframes is a key step towards building sophisticated and flexible trading solutions in MQL5.


Leave a Reply