🚀 AI One-Click Generation of mql4 Strategy Code

How to Manage Multiple Charts with an Mql4 Expert Advisor

mql4 | Published on: 2025/12/4
The following content is generated by EasyQuant .

Problem Description

How can I write code to automatically open and close charts, or find a specific chart that is already open?

Solution

To manage charts programmatically in MQL4, you utilize the ChartOpen, ChartClose, and the chart navigation functions (ChartFirst, ChartNext) to iterate through existing windows.

Below is a complete script that demonstrates three core functionalities:

  1. FindChartID: Iterates through all open charts to find a specific Symbol and Timeframe.
  2. OpenNewChart: Opens a new chart window.
  3. CloseChartWindow: Closes a specific chart window.

MQL4 Script: Chart Manager

//+------------------------------------------------------------------+
//|                                            ChartManagerScript.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
#property script_show_inputs

//--- Input parameters
input string           InpSymbol   = "EURUSD";       // Symbol to manage
input ENUM_TIMEFRAMES  InpPeriod   = PERIOD_H1;      // Timeframe to manage
input bool             InpCloseIfFound = false;      // Close chart if found?
input bool             InpOpenIfMissing = true;      // Open chart if not found?

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   // 1. Try to find an existing chart for the specified Symbol and Period
   long chartID = FindChartID(InpSymbol, InpPeriod);
   
   if(chartID > 0)
   {
      PrintFormat("Found existing chart for %s %s. ID: %I64d", 
                  InpSymbol, GetPeriodName(InpPeriod), chartID);
      
      // Bring the found chart to the foreground (optional)
      // ChartSetInteger(chartID, CHART_BRING_TO_TOP, true); 
      
      if(InpCloseIfFound)
      {
         // Prevent closing the chart the script is currently running on
         if(chartID == ChartID())
         {
            Print("Cannot close the chart where the script is running.");
         }
         else
         {
            Print("Closing chart ID: ", chartID);
            if(ChartClose(chartID))
               Print("Chart closed successfully.");
            else
               Print("Failed to close chart. Error: ", GetLastError());
         }
      }
   }
   else
   {
      PrintFormat("Chart for %s %s not found.", InpSymbol, GetPeriodName(InpPeriod));
      
      if(InpOpenIfMissing)
      {
         Print("Attempting to open new chart...");
         long newChartID = ChartOpen(InpSymbol, InpPeriod);
         
         if(newChartID > 0)
            PrintFormat("Successfully opened new chart. ID: %I64d", newChartID);
         else
            Print("Failed to open chart. Error: ", GetLastError());
      }
   }
}

//+------------------------------------------------------------------+
//| Function to find a chart ID by Symbol and Period                 |
//+------------------------------------------------------------------+
long FindChartID(string symbol, ENUM_TIMEFRAMES period)
{
   long currChartId = ChartFirst(); // Get the first chart ID
   
   // Loop through all open charts
   while(currChartId >= 0) 
   {
      // Check if Symbol and Period match
      if(ChartSymbol(currChartId) == symbol && ChartPeriod(currChartId) == period)
      {
         return(currChartId); // Return the ID if found
      }
      
      // Move to the next chart
      currChartId = ChartNext(currChartId);
   }
   
   return(0); // Return 0 if not found
}

//+------------------------------------------------------------------+
//| Helper function to convert period enum to string                 |
//+------------------------------------------------------------------+
string GetPeriodName(ENUM_TIMEFRAMES period)
{
   switch(period)
   {
      case PERIOD_M1:  return("M1");
      case PERIOD_M5:  return("M5");
      case PERIOD_M15: return("M15");
      case PERIOD_M30: return("M30");
      case PERIOD_H1:  return("H1");
      case PERIOD_H4:  return("H4");
      case PERIOD_D1:  return("D1");
      case PERIOD_W1:  return("W1");
      case PERIOD_MN1: return("MN1");
      default:         return("Unknown");
   }
}
//+------------------------------------------------------------------+

Explanation of Key Functions

  1. ChartOpen(symbol, period):

    • Opens a new chart window.
    • Returns a long value representing the Chart ID.
    • If it fails (returns 0), use GetLastError() to debug.
  2. ChartClose(chart_id):

    • Closes the specific chart identified by the ID.
    • Returns true if successful.
  3. ChartFirst() and ChartNext(chart_id):

    • There is no direct function to "Get Chart by Symbol". You must iterate through the list.
    • ChartFirst() gets the ID of the very first chart in the terminal list.
    • ChartNext(current_id) gets the ID of the chart following the current one.
    • The loop continues until ChartNext returns -1 (end of list).
  4. ChartSymbol(chart_id) and ChartPeriod(chart_id):

    • These retrieve the properties of the chart currently being examined in the loop to compare against your target criteria.

How to Use

  1. Copy the code into a new Script file in MetaEditor (e.g., ChartManager.mq4).
  2. Compile the script.
  3. Drag the script onto any chart in your terminal.
  4. In the inputs window:
    • InpSymbol: Type the symbol you want to find/open (e.g., "GBPUSD").
    • InpPeriod: Select the timeframe.
    • InpCloseIfFound: Set to true if you want to close that specific chart if it already exists.
    • InpOpenIfMissing: Set to true if you want to open it if it doesn't exist.

Q&A

Q: Can I open a chart for a symbol that is not in the Market Watch?
A: No. If the symbol is not selected in the Market Watch window, ChartOpen may fail or return error 4106 (ERR_UNKNOWN_SYMBOL). You should ensure the symbol is selected using SymbolSelect("SymbolName", true) before attempting to open the chart.

Q: Does ChartClose work on the chart running the script?
A: Yes, a script can close its own chart. However, this immediately terminates the script execution. In the provided code, I added a safety check if(chartID == ChartID()) to prevent accidental self-closing, but you can remove this if that is the desired behavior.

Q: How do I apply a template to the newly opened chart?
A: Immediately after getting the newChartID from ChartOpen, you can call ChartApplyTemplate(newChartID, "MyTemplate.tpl");. Note that this is an asynchronous command and is added to the chart's queue.