English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Créez votre propre Veille du Marché en utilisant les classes de bibliothèque standard

Créez votre propre Veille du Marché en utilisant les classes de bibliothèque standard

MetaTrader 5Exemples | 17 novembre 2021, 16:41
167 0
Dmitriy Skub
Dmitriy Skub

Introduction

L'objectif principal de la tâche était d’élaborer un outil convivial et extensible pour la sortie d'informations textuelles arbitraires sur le graphique du terminal client MetaTrader 5. Par exemple, les paramètres actuels de l'Expert Advisor, ou les résultats de son travail pendant un intervalle indiqué, présentés sous forme de tableau, les valeurs de prix ou un tableau de valeurs d'indicateurs, utilisés par le trader, ou un journal de l'Expert Advisor de trading . Toutes ces informations peuvent être affichées dynamiquement sur le graphique lors des travaux d'EA ou d'indicateur, qui utilise cette bibliothèque.

Comme base pour élaborer la bibliothèque, une collection de classes de bibliothèque standard du terminal client MetaTrader 5 a été utilisée. Dans un premier temps, nous considérerons ces classes et les étendrons ensuite pour remplir notre tâche.


Classes standard pour les Objets Graphiques

L'ensemble de classes qui nous intéresse se trouve dans les dossiers Include et Include\ChartObjects.

Ceux-ci sont les fichiers suivants :

  • Object.mqh - comporte la classe de base CObject pour la création de toutes les autres classes, liées aux objets graphiques.
  • ChartObject.mqh - comporte également la classe CChartObject, dérivée de CObject, qui étend les fonctionnalités et l'encapsulation des données et méthodes générales des objets graphiques.
  • ChartObjectsTxtControls.mqh - comporte un certain nombre de classes, destinées à afficher les divers objets graphiques sur le graphique, contenant du texte. (Classe de base CChartObjectText et ses descendants : CChartObjectLabel, CChartObjectEdit et CChartObjectButton.

Examinons ces classes plus en détail.


CObject : la classe de base

La description de la classe est courte, alors montrons-la ici :

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;
}

Comme vous pouvez le constater, cette classe ne comporte que les données et méthodes à usage général, elles ne sont pas directement liées à la sortie du graphique.

Cependant, elle dispose d’ une propriété très importante - elle peut être utilisée pour créer des listes simplement liées et doublement liées. Ces fonctionnalités sont fournies par les champs de données CObject::m_prev et CObject::m_next de type CObject* et les méthodes de leur lecture/écriture. Le champ CObject::m_prev fait référence à l'élément de liste précédent, tandis que CObject::m_next - fait référence au suivant. Plus de détails sur la construction des listes seront fournis plus loin.

De plus, il existe une méthode de comparaison de deux objets de type CObject* - la méthode CObject::Compare, qui peut être utilisée lors du tri des éléments de la liste. Il existe deux méthodes plus utiles, qui vous permettent de sauvegarder/compter les champs de données dans les fichiers - ce sont les méthodes CObject::Save etCObject::Load. Afin d'obtenir les fonctionnalités souhaitées, ces méthodes doivent être surchargées dans les classes descendantes.

Le CObject::Type est la méthode d'identification du type d'objet. Cette méthode est utile lors de la manipulation d'une liste, qui comporte des objets de différents types.

La classe CObject (et ses instances) dispose des fonctionnalités suivantes :

  • identification de sa position par rapport aux éléments avoisinants au sein de la liste.
  • identification du type d'objet.
  • méthode d'enregistrement et de chargement des données de l'objet.
  • méthode de comparaison avec les objets indiqués.

La plupart des méthodes décrites ci-dessus sont virtuelles et non implémentées dans la classe de base. La classe de base n'a pas de propriétés réelles ayant une signification physique. Comme d'habitude en POO, la fonctionnalité doit être implémentée dans les classes descendantes.


CChartObject : la classe de base pour les objets graphiques

Le CChartObject est un descendant de la classe CObject.

Dans son nom, on peut constater qu'il s'agit d'une classe pour décrire un objet graphique abstrait. Néanmoins, cet objet abstrait comporte déjà des propriétés physiques et des méthodes de travail avec ces propriétés. Ces propriétés sont communes à tous les objets graphiques de MetaTrader 5, il est donc logique de les placer dans cette classe.

Examinons-les plus en détail. Nous utiliserons les données suivantes pour attacher l'objet graphique à la fenêtre graphique :

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

Avant d’indiquer ou de lire les propriétés de l'objet graphique réel, il doit être attaqué avec l'objet (instance de classe). Ceci est fait par la méthode CChartObject::Attach. Dans les classes descendantes, il est appelé immédiatement après la création de l'objet graphique sur le tableau.

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);
}

Nous vérifions d'abord l'existence d'un objet graphique réel. S'il existe, ses propriétés sont stockées dans les champs internes de l'objet de classe CChartObject. Après cela, nous pouvons lire et modifier les propriétés de l'objet graphique (couleur, emplacement, etc.).

Les méthodes de sauvegarde/lecture des propriétés de l'objet graphique sont déjà implémentées dans les méthodes CChartObject::Save et CChartObject::Load. La méthode parent de save/read doit être appelée en premier dans la classe descendante avant sa propre méthode.

La classe CChartObject (et ses instances) dispose de nouvelles propriétés suivantes par rapport à celles de base :

  • rattachement de l'objet graphique réel sur la carte avec l'instance de classe.
  • lecture et modification des propriétés communes de tous les objets graphiques.
  • suppression de l'objet graphique du tableau
  • mouvement de l'objet graphique sur le tableau


CChartObjectText : une classe pour les objets Text-Graphic

Passons maintenant au fichier ChartObjectsTxtControls.mqh. On trouvera ici la description des classes développées pour la sortie des différents objets graphiques, contenant du texte, sur le tableau. Examinons leurs caractéristiques de base.

La classe de base pour eux est la classe CChartObjectText. Il encapsule les propriétés et les méthodes associées à la sortie de texte sur le tableau

Voici le descriptif de la classe :

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);
};

Par rapport à CChartObject, elle comporte des méthodes pour lire et modifier les propriétés des objets graphiques textuels - l'angle d'orientation du texte sur le tableau, le nom de la police du texte, la taille de la police et les coordonnées de l'objet graphique. Une nouvelle méthode est apparue CChartObjectText :: Créer nous permettant de créer un véritable objet graphique de type OBJ_TEXT sur la carte.

Son implémentation :

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);
}

Dans le cas d'une création réussie de l'objet graphique (la méthode ObjectCreate a renvoyé vrai), le CChartObject :: La méthode Attach est appelée, ce que nous avons examiné plus tôt.

Ainsi, par rapport à la classe parent, le CChartObjectText comprend de nouvelles fonctionnalités :

  • lecture et modification des propriétés des objets graphiques textuels.
  • créer un objet graphique réel de type OBJ_TEXT sur le tableau déroulant.


CChartObjectLabel : une classe pour les objets graphiques "Text Label"

La classe suivante dans la hiérarchie des classes standard est la classe CChartObjectLabel. Il permet de créer des objets graphiques de type OBJ_LABEL (Texte label) sur le tableau déroulant.

Voici une description de cette classe :

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);
};

Ici il faut noter la différence entre l'objet graphique de type OBJ_TEXT et l'objet de type OBJ_LABEL.

La première est contraignante sur le tableau des prix (coordonnées prix-temps) ou sur le tableau dans la sous-fenêtre. La seconde est contraignante sur les coordonnées cartographiques de la fenêtre ou sous-fenêtre (pixels) de la carte.

Ainsi, les objets de type OBJ_TEXT sont déplacés ensemble avec le tableau lors du défilement, tandis que les objets de type OBJ_LABEL demeurent fixes lors du défilement. Par conséquent, en fonction des tâches, nous devons choisir un type particulier d'objet textuel graphique.

Par rapport à la classe parent, la classe CChartObjectLabel comprend les caractéristiques distinctives suivantes :

  • les coordonnées du graphique sont utilisées lors de la localisation de l'objet graphique.
  • il permet de lire et de modifier le coin d'ancrage. En fait, il s'agit d'attribuer le début des coordonnées dans l'un des quatre coins de la fenêtre du graphique.
  • créer un objet graphique réel de type OBJ_LABEL sur la carte du terminal client.


CChartObjectEdit : une classe pour les objets graphiques « Input Field »

La classe suivante dans la hiérarchie est la classe CChartObjectEdit. Il s'agit d'une classe de création d'un objet graphique de type OBJ_EDIT (Champ de saisie).

L'objet de ce type est similairement contraignant que l'objet de type OBJ_LABEL en utilisant les coordonnées du graphique (pixels), il est logique de le dériver de la classe CChartObjectLabel de la même manière que les classes standards :

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);
};

La différence entre les champs de saisie de type OBJ_EDIT de l'étiquette de texte est la suivante :

  • le champ de saisie a les propriétés de largeur et de hauteur (indiquées en pixels d'écran), qui restreignent la taille de l'objet graphique sur le tableau. La taille de l'étiquette de texte est automatiquement ajustée afin que le texte entier puisse être vu.
  • il existe des méthodes pour activer/désactiver la modification de texte - CChartObjectEdit :: ReadOnly.
  • une méthode est ajoutée pour changer la couleur de fond de la zone, occupée par l'objet graphique.
  • il n'y a aucune possibilité de changer l'angle auquel l'objet est affiché. Le champ de saisie ne peut être affiché que dans un sens horizontal.
  • il permet de créer un véritable objet graphique de type OBJ_EDIT sur le tableau.


CChartObjectButton : une classe pour l'objet graphique "Button"

Une autre classe dans la hiérarchie des objets graphiques textuels est la classe CChartObjectButton. Cet objet s'appelle un bouton, il est élaboré pour créer un élément de contrôle sur le graphique, sous la forme d'un bouton enfoncé. Cette classe est une descendante de la classe CChartObjectEdit et hérite de ses fonctionnalités :

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);
};

La différence entre le bouton de type OBJ_BUTTON et le champ de saisie est la suivante :

  • elle ressemble à un bouton enfoncé, similaire à ceux utilisés dans les boîtes de dialogue Windows.
  • elle dispose de nouvelles méthodes pour lire/modifier l'état du bouton (appuyé/non enfoncé) - CChartObjectButton::State..
  • Elle permet de créer un véritable objet graphique de type OBJ_BUTTON sur le tableau.


La structure globale des classes standard pour les objets textuels graphiques

La structure (hiérarchie) des classes de la bibliothèque standard peut être résumée comme suit :

La structure globale des classes standard

Figure 1. La structure globale des classes standard

La classe CObject est une classe de base pour d'autres classes standard, par exemple, la classe CList, qui exploite la liste ainsi que les autres.


Extension de la fonctionnalité des classes de bibliothèque standard

Nous avons brièvement discuté de la hiérarchie des classes standard, qui sont élaborées pour générer des objets graphiques textuels sur le graphique. Étendons maintenant cette hiérarchie avec de nouvelles classes. Tout d'abord, nous devons décider de la fonctionnalité nécessaire à l’implémentation Formulons les exigences. Puisqu'il s'agit de la sortie d'informations textuelles, il est logique de fournir ces informations sous la forme structurée suivante :

TITRE TEXTE D'INFORMATION


Cette structure de représentation de l'information textuelle convient à la plupart des cas simples.

Par exemple, l'indicateur des paramètres de symbole pourrait ressembler à ceci :

Un exemple d'affichage structuré d'informations textuelles

Figure 2. Un exemple d'affichage structuré d'informations textuelles

Il utilise six champs d'information de la structure proposée ci-dessus. Certains éléments de la structure peuvent être absents. Par exemple, à la Figure 2, la tuile du champ supérieur n'est pas représentée. Les autres champs comportent le titre et le texte. Cet indicateur se trouve dans le fichier PricelInfo.mq5, joint à cet article.


Positionnement des objets graphiques

Le deuxième point que nous devons prendre en compte est la manière de positionner les objets textuels graphiques sur la carte. La méthode adoptée d’indication des coordonnées en pixels d'écran permet de positionner l'objet à un emplacement arbitraire de la carte.

En pratique, c’est incommode lorsqu'il faut loger plusieurs objets textuels dans différents endroits de la carte, puisque il faut calculer toutes les coordonnées de l'écran. De plus, si vous modifiez la taille du graphique, toutes les coordonnées en pixels doivent être recalculées pour s'assurer que la position relative des objets à l'écran n'a pas été modifiée.

Si nous traçons la fenêtre cartographique en rectangles (champs) de même taille et attribuons à chacun de ces rectangles une coordonnée horizontale et verticale, nous obtiendrons un système de positionnement universel, indépendant de la résolution de l'écran.

Lors de la création de l'objet texte graphique, l'utilisateur peut définir le nombre maximum de champs dans les directions verticale et horizontale, et les coordonnées de l'objet dans des champs tels que les paramètres. La fonctionnalité, intégrée dans la classe appropriée, ajustera automatiquement les coordonnées des objets graphiques lorsque vous modifiez la résolution de l'écran. De cette façon, les coordonnées sont indiquées une seule fois et ne nécessitent aucun réglage supplémentaire.


Génération Automatique de Noms d'Objets Uniques

La prochaine question qui doit être abordée est la génération automatique du nom de l'objet texte graphique. L'exigence principale de la méthode de génération est l'obtention d'un nom unique dans la fenêtre donnée. Cela permettra de localiser à l'écran un nombre suffisant d'objets, sans se soucier de devoir inventer des noms non dupliqués.

Nous proposons la méthode suivante pour générer un nom (une chaîne, constituée de champs) :

Date Heure
Nombre de millisecondes


Pour obtenir la partie de la chaîne contenant la date et l'heure, utilisez l'appel suivant :

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

Pour obtenir le nombre de millisecondes, utilisez l'appel suivant :

DoubleToString(GetTickCount(), 0);

Mais même si nous mesurons le temps à quelques millisecondes près, il est tout à fait possible que lorsque nous appelons consécutivement la fonction GetTickCount() deux fois ou plus, nous obtiendrons la même valeur. Cela est dû à la restriction de la discrétion des chronomètres internes du système d'exploitation et du processeur. Ainsi, il est nécessaire de prendre des mesures supplémentaires pour détecter une telle situation.

La méthode proposée est implémentée dans les fonctions suivantes :

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);
}

La limitation de cette méthode : la génération de pas plus de 4294967295 (UINT_MAX) noms uniques par seconde. Apparemment, cela devrait suffire dans la pratique. Au cas où, il y a une vérification supplémentaire de l'existence d'un objet graphique du même nom.


L'affichage du titre de la structure informationnelle - classe TTitleDisplay

La classe d'affichage du titre sur l'écran du terminal est illustrée ci-dessous :

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
};

La méthode de base, qui crée un objet textuel graphique :

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

L'affectation des paramètres d'entrée est la suivante :

  • chart_id - identifiant de fenêtre (0 - fenêtre principale);
  • window - numéro de la sous-fenêtre (0 - principale);
  • cols - le nombre maximum d'objets de texte graphique horizontalement (le nombre de colonnes);
  • lines - le nombre maximum d'objets de texte graphique verticalement (nombre de lignes);
  • col - la coordonnée horizontale de l'objet graphique (varie de zéro à cols - 1);
  • row - la coordonnée verticale de l'objet graphique (varie de zéro aux lignes - 1);

La méthode TTitleDisplay :: SetParams calcule les paramètres de l'objet, associés au positionnement à l'écran.

L’implémentation est la suivante :

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;
}

Ici, nous avons utilisé l'appel de fonction GetSystemMetrics WinAPI pour obtenir les paramètres d'affichage actuels. Cette fonction est importée de la bibliothèque système de Windows user32.dll.

Une classe pour créer le texte d'information TFieldDisplay est construite de la même manière. Les détails peuvent être trouvés dans la bibliothèque TextDisplay.mqh, jointe à cet article.


Classe CListe : Manipulation d'objets dans la liste

Examinons maintenant une autre classe standard, dont nous aurons besoin pour la réalisation de notre plan. Cette classe vous permet de regrouper des objets dans des listes. Elle se trouve dans le fichier Include\Arrays\List.mqh.  Ce fichier fournit la description et l'implémentation d'une classe CList standard, qui est la descendante de la classe de base CObject, examinée plus tôt dans cet article. Il comporte un ensemble de méthodes pour manipuler les objets de la liste (ajout à la liste, suppression de la liste, accès à un élément arbitraire de la liste et effacement de la liste).

Examinons les méthodes de base:

  • Ajout à la liste :
   int Add(CObject *new_node);
   int Insert(CObject *new_node,int index);

Il s'agit de deux méthodes pour ajouter un nouvel élément à la liste. Le premier CList:Add permet d'ajouter un nouvel élément new_node à la fin de la liste. Le second CList::Insert vous permet d'insérer un nouvel élément new_node à un endroit arbitraire (indiqué par index) dans la liste.

  • Suppression de la liste :
   bool  Delete(int index);

La méthode CList::Delete vous permet de supprimer un élément avec un index indiqué de la liste. Pendant ce temps, en plus de retirer l'élément de la liste, la mémoire, occupée par l'élément de type CObject est libérée, qui était occupée par l'élément de type CObject. En d'autres termes, l'objet sera supprimé "physiquement".

  • accès à l'élément arbitraire de la liste :
   int       IndexOf(CObject* node);
   CObject*  GetNodeAtIndex(int index);
   CObject*  GetFirstNode();
   CObject*  GetPrevNode();
   CObject*  GetNextNode();
   CObject*  GetLastNode();

La méthode CList::IndexOf renvoie l'index d'un élément spécifique de la liste. La numérotation des index part de zéro : le premier élément a un index de zéro. Cette méthode effectue l'opération inverse elle renvoie l'index par pointeur de l'élément. Si l'élément n'est pas dans la liste, il renvoie -1.

Quatre autres méthodes pour naviguer dans la liste CList : GetFirstNode renvoie l'élément précédent, la CList : : GetNextNode renvoie le suivant, le CList :: GetLastNode renvoie le dernier élément de la liste.

  • Effacer la liste :
   void  Clear();

La méthode CList::Clear permet de supprimer tous les éléments de la liste, et libère également la mémoire, occupée par les objets.

Ce sont les méthodes de base de la classe CList, les autres sont décrites dans la référence MQL5.


Classe TableDisplay : Création d'un tableau pour afficher le texte sur le graphique

Donc, nous avons tout ce dont nous avons besoin pour la réalisation du plan. Voici une classe simple qui vous permet d'organiser les objets graphiques textuels dans un tableau de taille arbitraire :

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();
};

Avant d'ajouter les objets graphiques au tableau, vous devez définir les paramètres : l'identifiant de caractère, l'index de sous-fenêtre et le point d'ancrage. Cela se fait en appelant le TableDisplay : : Méthode SetParams. Après cela, vous pouvez ajouter n'importe quel nombre de titres et de champs de texte au tableau.

Le texte complet de la bibliothèque, que nous avons élaboré, se trouve dans le fichier TextDisplay.mqh, joint à cet article.


3. Un exemple de création de la Veille du Marché

Prenons l'exemple de la création d'un tableau pour afficher les valeurs de plusieurs symboles, sous la forme d'un indicateur.

Cela devrait ressembler à peu près à ceci:

Un exemple d’écran tableau

Рисунок 3. Un exemple de table à écran

  • Étape 1 - Inclure la bibliothèque (dans le code source de l'indicateur) :
#include  <TextDisplay.mqh>
  • Étape 2 - Création de tableaux avec les noms et coordonnées des titres :
#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};
Les coordonnées sont ordonnées à partir de zéro.
  • Étape 3 - Créez un objet table de type TableDisplay pour stocker tous les objets texte affichés :
TableDisplay  Table1;
  • Étape 4 - Ajoutez des objets-titres et des champs d'informations sur les objets dans le tableau :
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);
}

Il est optimal de le faire dans le gestionnaire d'événements OnInit. Tout d'abord, ajoutez les champs d'information, en utilisant le TableDisplay : : Méthode AddFieldObject. Ajoutez-leur ensuite les titres, en utilisant le TableDisplay : : Méthode AddTitleObject.

L'ajout est réalisé en cycles séparés pour deux raisons : d'une part, le nombre de titres, en général, peut ne pas coïncider avec le nombre de champs d'information, et d'autre part, l'accès aux champs d'information mis à jour est plus facile à organiser lorsqu'ils sont indexés dans une ligne (dans ce cas, de zéro à la valeur NUMBER - 1).

  • Étape 5 - ajout du code pour mettre à jour les informations dynamiques :

Dans ce cas, la mise à jour des informations dynamiques est organisée par le gestionnaire d'événements Timer. Le gestionnaire OnTimer pour cet événement doit recevoir les valeurs de prix pour les instruments donnés et afficher ces valeurs sur le graphique.

Le texte de celui-ci est présenté ci-dessous :

//---------------------------------------------------------------------
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);
}

Au début du cycle, les données de tick pour l'instrument indiqué sont lues, puis la pertinence des données est vérifiée - si le temps de tick a changé par rapport au précédent, nous estimons que les données ne sont pas pertinentes. Ensuite, nous analysons la valeur de la cotation par rapport au tick précédent.

Si le prix actuel est supérieur au précédent, nous indiquons une couleur verte pour le champ d'information. Si c'est moins, qu'une couleur rouge et s'ils sont égaux - une couleur jaune. À la fin du cycle, la valeur actuelle du prix et l'heure du tick sont stockées pour analyse dans l'appel du gestionnaire d'événements OnTimer.

En général, le code de mise à jour des informations dynamiques dépend de la tâche. En principe, l'utilisateur n'a besoin d'implémenter que cette partie du code. Supposons que nous décidions d'ajouter un spread à droite du prix à la figure 2. Voyons comment cela peut être fait.

Il suffit d'ajouter des champs de données supplémentaires à la table :

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

et inclure le code, qui met à jour la valeur du spread, dans le gestionnaire d'événements OnTimer :

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

En conséquence, nous obtenons l'image suivante :

Prix avec un spread

Figure 4. Prix avec un spread

Notez que les champs d'index pour le spread, à partir de la valeur NOMBRE (si i est égal à zéro).

  • Étape 6 - Suppression des objets créés :
void OnDeinit(const int _reason)
{
  EventKillTimer();

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

Ici, la minuterie et le tableau sont effacés. Pendant ce temps, tous les objets sont également libérés de la mémoire.

Le texte complet de cet indicateur se trouve dans le fichier PriceList.mq5, joint à cet article. La pièce jointe comporte une version "améliorée" de l'indicateur, qui affiche le spread. Il dispose d'un certain nombre de paramètres externes pour la spécification de la couleur du titre et de la position d'un tableau dans le graphique.


Conclusion

Le MarketWatch.mq5 ci-joint (et le MarketWatch.mqh inclus) comporte l'indicateur pour afficher les paramètres de base des instruments de trading, sous la forme d'un tableau récapitulatif. Pour chaque symbole, les informations, similaires à celles de la figure 2, sont affichées.

De plus, il affiche le pourcentage de modification de prix pour les intervalles de temps indiqués L'ensemble de symboles (pas plus de 16) et les intervalles de temps sont indiqués sous forme de chaîne avec des éléments, séparés par un point-virgule.  Les résultats des travaux de cet indicateur sont présentés dans la Figure 5 :

Indicateur de la revue de marché

Figure 5. Indicateur de Surveillance du Marché

Nous avons envisagé un moyen d'afficher des informations textuelles sur le graphique du terminal client MetaTrader 5.

En utilisant les classes Standard Library, fournies avec le terminal client, nous avons pu élaborer assez facilement et rapidement la nouvelle fonctionnalité de représentation d'informations textuelles sous la forme d'un tableau bi-dimensionnel L'approche orientée-objet du langage MQL5 est très puissante.


Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/179

Fichiers joints |
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)
calcul de moyenne des Séries de Prix pour les Calculs Intermédiaires Sans Utiliser de Tampons Supplémentaires calcul de moyenne des Séries de Prix pour les Calculs Intermédiaires Sans Utiliser de Tampons Supplémentaires
Cet article concerne les algorithmes traditionnels et inhabituels de calcul de moyenne regroupés dans les classes les plus simples et à type unique. Ils sont destinés à une utilisation universelle dans presque toutes les élaborations d'indicateurs. J'espère que les classes proposées seront une bonne alternative aux appels « encombrants » d'indicateurs personnalisés et techniques.
L'exemple simple de création d'un indicateur à l'aide d'une logique floue L'exemple simple de création d'un indicateur à l'aide d'une logique floue
L’article est consacré à l’application pratique du concept de logique floue pour l’analyse des marchés financiers. Nous proposons l’exemple de l’indicateur générant des signaux basés sur deux règles floues fondées sur l’indicateur Enveloppes. L’indicateur développé utilise plusieurs tampons d’indicateurs: 7 tampons pour les calculs, 5 tampons pour l’affichage des graphiques et 2 tampons de couleur.
Construire un Analyseur de Spectre Construire un Analyseur de Spectre
Cet article est destiné à familiariser ses lecteurs avec une variante possible d'utilisation des objets graphiques du langage MQL5. Il analyse un indicateur, qui met implémente un panel de gestion d'un analyseur de spectre simple utilisant les objets graphiques. L'article est destiné aux lecteurs familiarisés avec les bases de MQL5.
Assistant MQL5 : Création d'Expert Advisors sans programmation Assistant MQL5 : Création d'Expert Advisors sans programmation
Souhaitez-vous tester une stratégie de trading sans perdre de temps en programmation ? Dans l'assistant MQL5, vous pouvez simplement sélectionner le type de signaux de trading, ajouter des modules de positions de suivi et de gestion de l'argent - et votre travail est terminé ! Créez vos propres implémentations de modules ou commandez-les via le service Jobs - et combinez vos nouveaux modules avec ceux existants.