Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Create your own Market Watch using the Standard Library Classes

Create your own Market Watch using the Standard Library Classes

MetaTrader 5Examples | 28 December 2010, 17:23
11 838 13
Dmitriy Skub
Dmitriy Skub

Introduction

The main objective of the task was to develop a user-friendly and extensible tool for the output of arbitrary textual information on the chart of the MetaTrader 5 client terminal. For example, the current settings of the Expert Advisor, or the results of its work during a specified interval, presented as a table, the price values or a table of indicator values, used by the trader, or a log of the trading Expert Advisor. All of this information can be displayed dynamically on the chart during the work of EA or indicator, which uses this library.

As a basis for developing the library, a collection of Standard Library classes of the MetaTrader 5 client terminal was used. The first we will consider these classes and then extend them to fulfill our task.


Standard Classes for Graphic Objects

The set of classes, which we are interested in, are located in the Include and Include\ChartObjects folders.

These are the following files:

  • Object.mqh - contains the CObject base class for creation all other classes, related with graphic objects.
  • ChartObject.mqh - also contains the CChartObject class, derived from CObject, which extends the functionality and encapsulation of the graphic objects general data and methods.
  • ChartObjectsTxtControls.mqh - contain a number of classes, intended to display the various graphic objects on the chart, containing text. (CChartObjectText base class and its descendants: CChartObjectLabel, CChartObjectEdit, and CChartObjectButton.

Let's consider these classes in more detail.


CObject: the Base Class

The class description is short, so let's show it here:

class CObject
{
protected:
   CObject          *m_prev;
   CObject          *m_next;

public:
                     CObject();

   CObject          *Prev()                { return(m_prev); }
   void              Prev(CObject *node)   { m_prev=node;    }
   CObject          *Next()                { return(m_next); }
   void              Next(CObject *node)   { m_next=node;    }

   virtual bool      Save(int file_handle) { return(true);   }
   virtual bool      Load(int file_handle) { return(true);   }

   virtual int       Type() const          { return(0);      }

protected:
   virtual int       Compare(const CObject *node,int mode=0) const { return(0); }
};

//+------------------------------------------------------------------+
void CObject::CObject()
{
   m_prev=NULL;
   m_next=NULL;
}

As you can see, this class contains only the general purpose data and methods, they are not related directly with output on the chart.

However, it does have a very important property - it can be used to create the simply linked and doubly-linked lists. These features provided by CObject::m_prev and CObject::m_next data-fields of CObject* type and methods of their reading/writing. The CObject::m_prev field refers to the previous list element, while CObject::m_next - refers to the next one. More details about the construction of the lists will be provided further.

In addition, there is a method for comparing two objects of CObject* type - the CObject::Compare method, which can be used when sorting the list elements. There are two more helpful methods, which allow you to save/count the data-fields in the files - these are the CObject::Save and CObject::Load methods. In order to obtain the desired functionality these methods should be overloaded in the descendant classes.

The CObject::Type is the object type identification method. This method is useful when manipulating a list, which contains objects of different types.

The CObject class (and its instances) has the following features:

  • identification of its position relative to the neighboring elements within the list.
  • object type identification.
  • method for saving and loading the object data.
  • method for compare with the specified objects.

Most of the methods, described above are virtual and not implemented in the base class. The base class doesn't have any real properties with physical meaning. As is usual in OOP, the functionality should be implemented in the descendant classes.


CChartObject: the Base Class for Graphic Objects

The CChartObject is a descendant of CObject class.

In its name, one can see this is a class for describing some abstract graphic object. Nevertheless, this abstract object already contains some physical properties and methods of working with these properties. These properties are common to all graphic objects in MetaTrader 5, so it is logical to place them into this class.

Let's consider them in more detail. We will use the following data to attach the graphic object to the chart window:

protected:
  long       m_chart_id;    // identifier of the chart, which contains 
                               // specified graphic object (0 - current chart)
  int        m_window;      // number of chart sub-window (0 - main window)
  string     m_name;        // unique name of the object on the chart
  int        m_num_points;  // number of points for anchoring the object

Before we specify or read off the properties of the real graphic object, it must be attacted with the object (class instance). This is done by the CChartObject::Attach method. In descendant classes, it is called immediately after creation of the graphic object on the chart.

bool CChartObject::Attach(long chart_id,string name,int window,int points)
{
  if(ObjectFind(chart_id,name)<0)
  {
    return(false);
  }

  if(chart_id==0) chart_id=ChartID();

  m_chart_id  =chart_id;
  m_window    =window;
  m_name      =name;
  m_num_points=points;

  return(true);
}

First we verify the existence of a real graphic object. If it exists, its properties are stored to the internal fields of the CChartObject class object. After this, we can read and modify the graphic object properties (color, location, etc.).

The methods of saving/reading of the graphic object properties are already implemented in CChartObject::Save and CChartObject::Load methods. The parent method of save/read should be called first in the descendant class before its own method.

The CChartObject class (and its instances) has the following new properties compared with the base ones:

  • attaching of the real graphic object on the chart with the class instance.
  • reading and modification of the common properties of all graphics objects.
  • deletion of the graphic object from the chart.
  • movement of the graphic object on the chart.


CChartObjectText: a Class for Text-Graphic objects

Let us now turn to the ChartObjectsTxtControls.mqh file. Here, we will find the description of classes developed for output of the various graphic objects, containing text, onto the chart. Let us consider their basic features.

The basic class for them is the CChartObjectText class. It encapsulates the properties and methods, associated with the text output on the chart.

Here is the class description:

class CChartObjectText : public CChartObject
{
public:
   double            Angle() const;
   bool              Angle(double angle);
   string            Font() const;
   bool              Font(string font);
   int               FontSize() const;
   bool              FontSize(int size);
   ENUM_ANCHOR_POINT  Anchor() const;
   bool              Anchor(ENUM_ANCHOR_POINT anchor);

   bool              Create(long chart_id,string name,int window,datetime time,double price);

   virtual int       Type() const { return(OBJ_TEXT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

Compared with the CChartObject, it contains methods for reading and modifying the properties of textual graphic objects - the angle of text orientation on the chart, the font name of the text, the font size, and the coordinates of the graphic object. A new method has appeared CChartObjectText:: Create allowing us to create a real graphic object of OBJ_TEXT type on the chart.

Its implementation:

bool CChartObjectText::Create(long chart_id,string name,int window,datetime time,double price)
{
  bool result = ObjectCreate( chart_id, name, OBJ_TEXT, window, time, price );
  if(result)
  {
    result &= Attach(chart_id, name, window, 1 );
  }

  return(result);
}

In the case of a successful creation of the graphic object (the ObjectCreate method returned true), the CChartObject:: Attach method is called, which we have considered earlier.

Thus, compared with the parent class, the CChartObjectText includes new features:

  • reading and modification of the properties of textual graphic objects.
  • creating a real graphic object of OBJ_TEXT type on the chart.


CChartObjectLabel: a Class for "Text Label" Graphic objects

The next class in the hierarchy of the standard classes is the CChartObjectLabel class. It allows you to create graphic objects of OBJ_LABEL type (Text label) on the chart.

Here is a description of this class:

class CChartObjectLabel : public CChartObjectText
{
public:
   int               X_Distance() const;
   bool              X_Distance(int X);
   int               Y_Distance() const;
   bool              Y_Distance(int Y);
   int               X_Size() const;
   int               Y_Size() const;
   ENUM_BASE_CORNER  Corner() const;
   bool              Corner(ENUM_BASE_CORNER corner);

   bool              Time(datetime time) { return(false);  }
   bool              Price(double price) { return(false);  }

   bool              Create(long chart_id,string name,int window,int X,int Y);

   virtual int       Type() const        { return(OBJ_LABEL); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

Here we must note the difference between the graphic object of OBJ_TEXT type and the object of OBJ_LABEL type.

The first one is binding on the price chart (price-time coordinates) or on the chart in the sub-window. The second one is binding on the chart coordinates of the window or sub-window (pixels) of the chart.

Therefore, the objects of OBJ_TEXT type are moved together with the chart when scrolling, while the objects of OBJ_LABEL type remain fixed when scrolling. Therefore, depending on taks, we must choose a particular type of graphic textual object.

Compared with the parent class, the CChartObjectLabel class includes the following distinctive features:

  • the chart coordinates is used when locating the graphic object.
  • it allows to read and modify the anchor corner. In fact, this is assigning the beginning of the coordinates in one of the four corners of the graph's window.
  • creating a real graphic object of OBJ_LABEL type on the chart of the client terminal.


CChartObjectEdit: a Class for "Input Field" Graphic Objects

The next class in the hierarchy is the CChartObjectEdit class. This is a class for creating a graphic object of OBJ_EDIT type (Input field).

The object of this type is binding the same way as the object of OBJ_LABEL type using the chart coordinates (pixels), it is logical to derive it from the CChartObjectLabel class the same way as the standard classes:

class CChartObjectEdit : public CChartObjectLabel
{
public:
   bool              X_Size(int X);
   bool              Y_Size(int Y);
   color             BackColor() const;
   bool              BackColor(color new_color);
   bool              ReadOnly() const;
   bool              ReadOnly(bool flag);

   bool              Angle(double angle) { return(false);    }

   bool              Create(long chart_id,string name,int window,int X,int Y,int sizeX,int sizeY);

   virtual int       Type() const        { return(OBJ_EDIT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

The difference between the input fields of OBJ_EDIT type from the text label is following:

  • the input field has the width and height properties (specified in screen pixels), which restrict the size of the graphic object on the chart. The size of the text label is automatically adjusted so that the entire text could be seen.
  • there are methods to enable/disable the text modification - CChartObjectEdit:: ReadOnly.
  • a method is added to change the background color of the area, occupied by the graphic object.
  • there is no possibility to change the angle, at which the object is displayed. The input field can only be displayed in a horizontal direction.
  • it allows creating a real graphic object of OBJ_EDIT type on the chart.


CChartObjectButton: a Class for "Button" Graphic object

Another class in the hierarchy of textual graphic objects is the CChartObjectButton class. This object is called a button, it is developed to create a control element on the chart, in the form of a pressed down button. This class is a descendant of the CChartObjectEdit class, and inherits its functionality:

class CChartObjectButton : public CChartObjectEdit
{
public:
  bool             State() const;
  bool             State(bool state);

  virtual int       Type() const { return(OBJ_BUTTON); }

  virtual bool      Save(int file_handle);
  virtual bool      Load(int file_handle);
};

The difference of the button of OBJ_BUTTON type from the input field is the following:

  • It looks like a pressed down button, similar to those used in Windows dialogs.
  • it has new methods for reading/modifying the button state (pressed/unpressed) - CChartObjectButton::State.
  • it allows creating a real graphic object of OBJ_BUTTON type on the chart.


The overall structure of the Standard Classes for graphic textual objects

The structure (hierarchy) of the Standard Library classes, can be summarized as follows:

The overall structure of the standard classes

Figure 1. The overall structure of the standard classes

The CObject class is a base class for other standard classes, for example, the CList class, which operates the list as well as the others.


Extending the Functionality of Standard Library Classes

We have briefly discussed the hierarchy of standard classes, which are developed to generate textual graphic objects on the chart. Now let's extend this hierarchy with new classes. First of all, we must decide on the functionality that is needed for the implementation. Let's formulate the requirements. Since we are dealing with the output of textual information, it is logical to provide this information in the following structured form:

TITLE INFORMATION TEXT


This structure of the representation of textual information is suitable for the majority of simple cases.

For example, the indicator of symbol parameters might look like this:

An example of a structured display of textual information

Figure 2. An example of a structured display of textual information

It uses six information fields of the structure proposed above. Some elements of the structure may be absent. For example, at Figure 2, the tile of top field is not shown. The other fields contain the title and the  text. This indicator can be found in the PricelInfo.mq5 file, attached to this article.


Positioning of the graphic objects

The second point that we need to consider is the way of positioning the graphic textual objects on the chart. The adopted method of specifying the coordinates in screen pixels allows for the positioning of the object in an arbitrary location of the chart.

It is inconvenient in practice when you need to accommodate several textual objects in different places on the chart, since it is necessary to calculate all of the screen's coordinates. In addition, if you change the chart size, all the pixel coordinates need to be recalculated to make sure that the relative position of objects on the screen hasn't been changed.

If we trace out the chart window into rectangles (fields) of the same size, and assign each such rectangle a horizontal and vertical coordinate, we will obtain a universal positioning system, which is independent from the screen resolution.

When creating the graphic text object, the user can set the maximum number of fields in the vertical and horizontal directions, and the coordinates of the object in such fields as the parameters. The functionality, embedded in the appropriate class, will automatically adjust the coordinates of the graphic objects when you change the screen resolution. In this way, the coordinates are specified once and do not require any further adjustments.


Automatic Generation of Unique Object Names

The next question that must be addressed is the automatic generation of the name of the graphic text object. The main requirement for the method of generation is the obtainment of a unique name within the given window. This will allow to locate on the screen a sufficient number of objects, without worrying about the need to invent non-duplicated names.

We propose the following method for generating a name (a string, consisting of fields):

Date Time
Number of milliseconds


To get the part of the string, containing the date and time, use the following call:

TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);

To obtain the number of milliseconds, use the following call:

DoubleToString(GetTickCount(), 0);

But even if we measure the time to within milliseconds, it is quite possible that when we consecutively call the GetTickCount () function two or more times, we will get the same value. This is due to the restriction of the discreteness of the internal timers of the operating system and processor. Thus, it is necessary to take additional measures to detect such a situation.

The proposed method is implemented in the following functions:

string GetUniqName()
{
  static uint prev_count = 0;

  uint count = GetTickCount();
  while(1)
  {
    if(prev_count == UINT_MAX)
    {
      prev_count = 0;
    }
    if(count <= prev_count)
    {
      prev_count++;
      count = prev_count;
    }
    else
    {
      prev_count = count;
    }

//  Verify that there is no object already existing with such a name:
    string name = TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" "+DoubleToString(count, 0);
    if(ObjectFind(0, name) < 0)
    {
      return(name);
    }
  }

  return(NULL);
}

The limitation of this method: the generation of no more than 4294967295 (UINT_MAX) unique names per second. Apparently, this should be enough in practice. Just in case, there is an additional verification of the existence of a graphic object with the same name.


The display of the title of the informational structure - class TTitleDisplay

The class for displaying the title on the terminal screen is demonstrated below:

class TTitleDisplay : public CChartObjectLabel
{
protected:
  long    chart_id;
  int     sub_window;
  long    chart_width;       // width of the chart in pixels
  long    chart_height;      // height of the chart graph in pixels
  long    chart_width_step;  // step of the coordinates grid in the horizontal direction
  long    chart_height_step; // step of the coordinates grid in the vertical direction
  int     columns_number;    // number of columns
  int     lines_number;      // number of lines
  int     curr_column;
  int     curr_row;

protected:
  void    SetParams(long chart_id, int window, int cols, int lines);// specify the object's parameters

protected:
  string  GetUniqName();    // get a unique name
  bool    Create(long chart_id, int window, int cols, int lines, int col, int row);
  void    RecalcAndRedraw();// recount the coordinates and re-draw

        
public:
  void    TTitleDisplay();  // constructor
  void    ~TTitleDisplay(); // destructor
};

The basic method, which creates a graphic textual object:

bool Create(long chart_id, int window, int _cols, int _lines, int _col, int _row);

Assignment of input parameters is as follows:

  • chart_id - window identifier (0 - main window);
  • window - number of the sub-window (0 - main);
  • cols - the maximum number of graphic text objects horizontally (the number of columns);
  • lines - the maximum number of graphic text objects vertically (number of rows);
  • col - the horizontal coordinate of the graphic object (vary from zero to cols - 1);
  • row - the vertical coordinate of the graphic object (vary from zero to lines - 1);

The method TTitleDisplay:: SetParams calculates the parameters of the object, associated with the positioning on the screen.

The implementation is as follows:

void TTitleDisplay::SetParams(long _chart_id, int _window, int _cols, int _lines)
{
  this.chart_id = _chart_id;
  this.sub_window = _window;
  this.columns_number = _cols;
  this.lines_number = _lines;

//  Specify the size of the window in pixels:
  this.chart_width = GetSystemMetrics(SM_CXFULLSCREEN);
  this.chart_height = GetSystemMetrics(SM_CYFULLSCREEN);

//  Calculate the step of the coordinates grid:
  this.chart_width_step = this.chart_width/_cols;
  this.chart_height_step = this.chart_height/_lines;
}

Here we used the GetSystemMetrics WinAPI function call to obtain the current display settings. This function is imported from the user32.dll Windows system library.

A class for creating the informational text TFieldDisplay is constructed similarly. The details can be found in the TextDisplay.mqh library, attached to this article.


CList Class: Manipulation of Objects in the List

Now let's consider another standard class, which we will need for the realization of our plan. This class allows you to group objects into lists. It is located in the Include\Arrays\List.mqh file.  This file provides the description and implementation of a standard CList class, which is the descendant of the CObject base class, considered earlier in this article. It contains a set of methods for manipulating objects in the list (addition to the list, removing from the list, accessing an arbitrary element of the list, and clearing the list).

Let's consider the basic methods:

  • Adding to the list:
   int Add(CObject *new_node);
   int Insert(CObject *new_node,int index);

These are two methods for adding a new item to the list. The first one CList::Add allows you to add a new element new_node to the end of the list. The second one CList::Insert lets you insert a new element new_node to an arbitrary place (specified by index) in the list.

  • Removal from the list:
   bool  Delete(int index);

The CList::Delete method allows you to remove an element with a specified index from the list. Meanwhile, in addition to removing the item from the list, the memory, occupied by element of CObject type is released, which was occupied by the element of type CObject. In other words, the object will be deleted "physically".

  • access to the arbitrary element of the list:
   int       IndexOf(CObject* node);
   CObject*  GetNodeAtIndex(int index);
   CObject*  GetFirstNode();
   CObject*  GetPrevNode();
   CObject*  GetNextNode();
   CObject*  GetLastNode();

The CList:: IndexOf method returns the index of a specific element in the list. The numbering of the indexes starts from zero: the first element has an index of zero. This method performs the inverse operation it returns the index by pointer of the element. If the element is not in the list, it returns -1.

Four more methods for navigating through the list CList:: GetFirstNode returns the previous element, the CList:: GetNextNode returns the next one, the CList:: GetLastNode returns the last element in the list.

  • Clearing the list:
   void  Clear();

The CList::Clear method allows you to remove all of the elements from the list, and also frees up the memory, occupied by the objects.

These are the basic methods of CList class, the rest are described in the MQL5 Reference.


TableDisplay Class: Creating a Table for Displaying the Text on the Chart

So, we have all we need for the realization of the plan. Here is a simple class that allows you to organize the textual graphic objects in a table of an arbitrary size:

class TableDisplay : public CList
{
protected:
  long  chart_id;
  int   sub_window;

public:
  void  SetParams(long _chart_id, int _window, ENUM_BASE_CORNER _corner = CORNER_LEFT_UPPER);
  int   AddTitleObject(int _cols, int _lines, int _col, int _row, 
                      string _title, color _color, string _fontname = "Arial", int _fontsize = 8);
  int   AddFieldObject(int _cols, int _lines, int _col, int _row, 
                          color _color, string _fontname = "Arial", int _fontsize = 8);
  bool  SetColor(int _index, color _color);
  bool  SetFont(int _index, string _fontname, int _fontsize);
  bool  SetText(int _index, string _text);

public:
  void  TableDisplay();
  void  ~TableDisplay();
};

Before adding the graphic objects to the table, you must set the parameters: the char identifier, the sub-window index, and the anchor point. This is done by calling the TableDisplay:: SetParams method. After this you can add any number of titles and text fields to the table.

The complete text of the library, which we developed, can be found in the TextDisplay.mqh file, attached to this article.


3. An Example of Creating the Market Watch

Consider the example of creating a table for displaying the values of several symbols, in the form of an indicator.

It should look roughly like this:

An example of a screen table

Рисунок 3. An example of a screen table

  • Step 1 - Include the library (in the source code of the indicator):
#include  <TextDisplay.mqh>
  • Step 2 - Creation of arrays with the names and coordinates for the titles:
#define  NUMBER  8
//---------------------------------------------------------------------
string  names[NUMBER]   = {"EURUSD", "GBPUSD", "AUDUSD", "NZDUSD", "USDCHF", "USDCAD", "USDJPY", "EURJPY"};
int     coord_y[NUMBER] = {2,        3,        4,        5,        6,      7,        8,       9};
Coordinates are ordered starting from zero.
  • Step 3 - Create a table object of TableDisplay type to store all of the displayed text objects:
TableDisplay  Table1;
  • Step 4 - Add objects-titles and object-information fields into the table:
int OnInit()
{
//  Creating a table
  Table1.SetParams(0, 0);

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 3, coord_y[i], Yellow);
  }

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddTitleObject(40, 40, 1, coord_y[i], names[i]+":", White);
  }

  ChartRedraw(0);
  EventSetTimer(1);

  return(0);
}

It is optimal to do it in the OnInit event handler. First, add the information fields, using the TableDisplay:: AddFieldObject method. Then add the titles to them, using the TableDisplay:: AddTitleObject method.

The adding is implemented in separate cycles for two reasons: first, the number of titles, in general, may not coincide with the number of information fields, and secondly, the access to updated information fields is easier to organize when they are indexed in a row (in this case, from zero to value NUMBER - 1).

  • Step 5 - adding the code to update the dynamic information:

In this case the updating of dynamic information is organized by the Timer event handler. The OnTimer handler for this event should receive the price values for the given instruments and display these values on the chart.

The text of this is shown below:

//---------------------------------------------------------------------
double    rates[NUMBER];
datetime  times[NUMBER];
MqlTick   tick;
//---------------------------------------------------------------------
// OnTimer event handler
//---------------------------------------------------------------------
void OnTimer()
{
  for(int i=0; i<NUMBER; i++)
  {
//  Obtain the price values:
    ResetLastError();
    if(SymbolInfoTick(names[i], tick) != true)
    {
      Table1.SetText(i,"Err "+DoubleToString(GetLastError(),0));
      Table1.SetColor(i,Yellow);
      continue;
    }

    if(tick.time>times[i])
    {
       Table1.SetText(i, DoubleToString(tick.bid, (int)(SymbolInfoInteger(names[i], SYMBOL_DIGITS))));

       if(tick.bid>rates[i])
       {
         Table1.SetColor(i, Lime);
       }
       else if(tick.bid<rates[i])
       {
         Table1.SetColor(i, Red);
       }
       else
       {
         Table1.SetColor(i, Yellow);
       }
       rates[i] = tick.bid;
       times[i] = tick.time;
    }
  }

  ChartRedraw(0);
}

At the beginning of the cycle the tick data for the specified instrument is read, then, the relevance of the data is verified - if the tick time has changed from the previous, we consider the data irrelevant. Further we analyze the value of the quote in respect to the previous tick.

If the current price is larger than the previous one, then we specify a green color for the information field. If it is less, than a red color and if they are equal - a yellow color. At the end of the cycle, the current value of the price and the ticke time are stored for analysis in the call of OnTimer event handler.

In general, the code for updating the dynamic information is dependent on task. Basically, the user only needs to implement this part of the code. Suppose we decided to add a spread to the right of the price at Figure 2. Let's see how this can be done.

All that is needed is to add additional data fields to the table:

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 5, coord_y[i], Yellow);
  }

and include the code, which updates the value of the spread, into the OnTimer event handler:

  Table1.SetText(i+NUMBER, DoubleToString((tick.ask-tick.bid)/SymbolInfoDouble(names[i], SYMBOL_POINT), 0));

As a result, we obtain the following picture:

Prices with a spread

Figure 4. Prices with a spread

Note that the index fields for the spread, starting from the value NUMBER (if i is equal to zero).

  • Step 6 - Removing the created objects:
void OnDeinit(const int _reason)
{
  EventKillTimer();

//  Removing the elements of display:
  Table1.Clear();
}

Here the timer and table are cleared. Meanwhile, all of the objects are also released from the memory.

The complete text of this indicator can be found in the PriceList.mq5 file, attached to this article. The attachment contains an "improved" version of the indicator, which displays the spread. It has a number of external parameters for the specification of the color of the title and the position of a table within the chart.


Conclusion

The attached MarketWatch.mq5 (and the included MarketWatch.mqh) contains the indicator for displaying the basic parameters of trading instruments, in the form of a summary table. For each symbol, the information, similar to Figure 2 is shown.

In addition, it shows the percentage of price change for the specified time intervals. The set of symbols (not more than 16) and time intervals are specified as a string with elements, separated by a semicolon.  The results of the work of this indicator are shown in Figure 5:

Indicator of the market review

Figure 5. Market Watch Indicator

We have considered one way to display text information on the chart of MetaTrader 5 client terminal.

By using the Standard Library classes, provided with the client terminal, we were able to fairly easily and quickly develop the new functionality for representing textual information in the form of a two-dimensional table. The object-oriented approach of MQL5 Language is very powerful.


Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/179

Attached files |
marketwatch.mq5 (11.51 KB)
priceinfo.mq5 (8.76 KB)
pricelist.mq5 (7.29 KB)
textdisplay.mqh (15.54 KB)
marketwatch.mqh (9.48 KB)
Last comments | Go to discussion (13)
Alain Verleyen
Alain Verleyen | 6 Apr 2013 at 23:50
ns_k:

Sorry, I figured out that Dima is Russian and as that thread about this article was empty, so I posted it here. 

In fact I am too very doubtful about any response at all as a lot of time has passed since the article was posted.

This leads me to the next thought. Why it is so, that forum doesn't have "notify me by email" feature?

Thank you! 

Yes there is such a function (Profile - Favorites - Notifications). But it's not actived by default.

As an alternative you can also PM the author.

Nikolai Karetnikov
Nikolai Karetnikov | 7 Apr 2013 at 00:27
angevoyageur:

Yes there is such a function (Profile - Favorites - Notifications). But it's not actived by default.

As an alternative you can also PM the author.

Thank you! You help is very welcomed as usual :)

Wonder why there isn't "notify me at once" and "notify me when thread I started get updates" options.

 

Alain Verleyen
Alain Verleyen | 7 Apr 2013 at 12:42
ns_k:

Thank you! You help is very welcomed as usual :)

Wonder why there isn't "notify me at once" and "notify me when thread I started get updates" options.

 

Probably because MQ don't want become a spamming service ;-)
Nikolai Karetnikov
Nikolai Karetnikov | 7 Apr 2013 at 14:53
angevoyageur:
Probably because MQ don't want become a spamming service ;-)

:) that is mostly applied to "at once" feature. How about those "I started"? It is not a great deal, of course, to manually add the thread to your favourites, but that option will make the forum a little bit more user-friendly.

Thank you!! :) 

mima
mima | 24 Sep 2014 at 21:30
How to code to put Market Watch in pull down list meaning to select any symbol in market watch from pull down list ( no prices or anything else just symbols)? example is shown on attached picture for something else but that is idea?
MQL5 Wizard: Creating Expert Advisors without Programming MQL5 Wizard: Creating Expert Advisors without Programming
Do you want to try out a trading strategy while wasting no time for programming? In MQL5 Wizard you can simply select the type of trading signals, add modules of trailing positions and money management - and your work is done! Create your own implementations of modules or order them via the Jobs service - and combine your new modules with existing ones.
Andrey Voitenko: Programming errors cost me $15,000 (ATC 2010) Andrey Voitenko: Programming errors cost me $15,000 (ATC 2010)
Andrey Voitenko is participating in the Automated Trading Championship for the first time, but his Expert Advisor is showing mature trading. For already several weeks Andrey's Expert Advisors has been listed in the top ten and seems to be continuing his positive performance. In this interview Andrey is telling about his EA's features, errors and the price they cost him.
MQL5 Wizard: How to Create a Module of Trading Signals MQL5 Wizard: How to Create a Module of Trading Signals
The article discusses how to write your own class of trading signals with the implementation of signals on the crossing of the price and the moving average, and how to include it to the generator of trading strategies of the MQL5 Wizard, as well as describes the structure and format of the description of the generated class for the MQL5 Wizard.
Creating an Indicator with Multiple Indicator Buffers for Newbies Creating an Indicator with Multiple Indicator Buffers for Newbies
The complex codes consist of a set of simple codes. If you are familiar with them, it doesn't look so complicated. In this article, we will consider how to create an indicator with multiple indicator buffers. As an example, the Aroon indicator is analyzed in details, and two different versions of the code are presented.