Questions des débutants MQL5 MT5 MetaTrader 5 - page 1332

 
Mikhail Tkachev:

En fouillant dans la documentation et les forums ...
Comment rendre les variables de type pointeur globales [dans l'exemple var], si elles sont créées dans OnInit() par string :

et le nombre d'objets et les paramètres du constructeur sont inconnus à l'avance et sont calculés dans OnInit() ?

C'est facile.

CObj* var1 = NULL;
CObj* var2 = NULL;
CObj* var3 = NULL;

int OnInit()
{
   var1 = new CObj( p1, p2, p3 );
   var2 = new CObj( p1, p2, p3 );
   var3 = new CObj( p1, p2, p3 );
}
 

Bonjour

mt5 a un bouton crosshair

Lorsque vous appuyez sur ce bouton sur le graphique, il indique le nombre de barres, le nombre de pips et le pourcentage.

Aidez-moi à calculer correctement cette valeur afin que je puisse la lier à mon robot.

Merci.

 
Artyom Trishkin:

La nouvelle classe de bar est-elle déjà en place ?

Et à quoi ressemblent exactement les paramètres d'entrée ?

La classe est empruntée à: https://www.mql5.com/ru/code/768, modifications mineures apportées

//+------------------------------------------------------------------+
//|                                                     IsNewBar.mqh |
//|                               Copyright © 2011, Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "2011,   Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
#property version   "1.00"
//+------------------------------------------------------------------+
//|  Алгоритм определения момента появления нового бара              |
//| Для каждого таймфрейма каждого символа нужно создавать объект    |
//+------------------------------------------------------------------+  
#include <Object.mqh>

class CIsNewBar : public CObject // Сделан наследником класса для возможности работы с классом CArrayObj (из библиотеки)
// class CIsNewBar   // Первоначальная редакция
  {
   //----
public:

      //---- функция определения момента появления нового бара
   bool IsNewBar()
     {
      //---- получим время появления текущего бара
      datetime TNew=datetime(SeriesInfoInteger(m_Symbol,m_TimeFrame,SERIES_LASTBAR_DATE));

      if(TNew!=m_TOld && TNew) // проверка на появление нового бара
        {
         m_TOld=TNew;
         return(true); // появился новый бар!
        }
      //----
      return(false); // новых баров пока нет!
     };

   //---- конструктор класса    
                     CIsNewBar(const string &pSymbol, const ENUM_TIMEFRAMES pTimeFrame){
                        m_Symbol=pSymbol; m_TimeFrame=pTimeFrame;
                        m_TOld=-1;};

protected:
   datetime          m_TOld;        // Время хранится 
   ENUM_TIMEFRAMES   m_TimeFrame;   //    для каждого таймфрейма
   string            m_Symbol;      //    каждого символа

   //---- 
  };
//+------------------------------------------------------------------+

Il est destiné à être appliqué comme suit :

int OnInit()
{
    // Переменная NB_M1 - объект для контроля нового бара по символу currSymbol для таймфрейма M1

    CIsNewBar* NB_M1=new CIsNewBar(currSymbol,PERIOD_M1);
}

void OnTick()
{
    if (NB_M1.IsNewBar())  // (1) Если появился новый бар M1
        {....}
    ......
}
 
Koldun Zloy:

Facile.

Merci pour la réponse)
C'est ce que j'ai fait au début.
L'objet est donc créé deux fois, d'abord vide, puis comme il devrait l'être par un constructeur avec des paramètres.
Mais... Dans ce cas, le compilateur imprime un avertissement sur la ligne dans OnInit() :

la déclaration de 'var1' cache la variable globale -> sur la ligne dans OnInit()
voir la déclaration précédente de 'var1'.

Donc une variable locale cache une variable globale ... Alors, que se passe-t-il ?
Quelle variable sera ensuite vue par une autre fonction, OnTick(), par exemple ? La variable globale est =NULL, la variable locale est initialisée correctement mais ne peut être vue par une autre fonction ...

 
Mikhail Tkachev:

La classe est empruntée à: https://www.mql5.com/ru/code/768, avec des modifications mineures

Il est censé être appliqué comme suit :

Extraire toutes les sous-chaînes des paramètres d'entrée et les utiliser pour créer les noms des symboles et des délais correspondants.

Créez ensuite de nouveaux objets barres à partir de ces listes et placez le pointeur de chaque objet à créer - "New Bar" - dans CArrayObj qui est déclaré globalement.

Ensuite, il reçoit un pointeur vers le prochain objet de la liste dans la boucle OnTimer() et vérifie la présence d'une nouvelle barre. S'il n'y a pas de nouvel objet, vous devez passer au suivant, s'il y en a un, vous devez faire ce que vous devez faire lorsqu'un nouveau bar s'ouvre.

Le minuteur doit être réglé en fonction de vos besoins - milliseconde, seconde, minute - en général, avec la fréquence que vous jugez suffisante pour répondre à une nouvelle barre sur un symbole non courant.

 
Mikhail Tkachev:

Merci pour la réponse)
Au début, je l'ai fait.
L'objet est donc créé deux fois, d'abord vide, puis comme il devrait l'être par un constructeur avec des paramètres.
Mais... Dans ce cas, le compilateur imprime un avertissement sur la ligne dans OnInit() :

la déclaration de 'var1' cache la variable globale -> sur la ligne dans OnInit()
voir la déclaration précédente de 'var1'.

Donc une variable locale cache une variable globale ... Alors, que se passe-t-il ?
Quelle variable sera ensuite vue par une autre fonction, OnTick(), par exemple ? La variable globale est =NULL et la variable locale est initialisée correctement, mais ne peut pas être vue par une autre fonction.

Regardez bien. Ce n'est pas ce que vous avez fait.

 
Artyom Trishkin:

À partir des paramètres d'entrée, toutes les sous-chaînes doivent être extraites, à partir desquelles les noms des symboles et les délais correspondants doivent être compilés.

Ensuite, créez de nouveaux objets barres à partir de ces listes et placez un pointeur vers chaque nouvel objet dans CArrayObj qui est déclaré au niveau global.

Ensuite, il reçoit un pointeur vers l'objet suivant de la liste dans la boucle OnTimer() et vérifie la présence d'une nouvelle barre. S'il n'y a pas de nouvel objet, vous devez passer au suivant, s'il y en a un, vous devez faire ce que vous devez faire lorsqu'un nouveau bar s'ouvre.

Créez un minuteur en fonction de vos besoins - milliseconde, seconde, minute - en général, avec la fréquence que vous jugez suffisante pour répondre à une nouvelle barre sur un symbole non courant.

C'est ce que je faisais, mais ArrObj.At(0) n'appelle pas les fonctions membres de laclasse...

 
Koldun Zloy:

Regardez de plus près. Ce n'est pas ce que tu faisais.

Déjà remarqué)
La solution consiste donc à déclarer des objets globalement vides.....
Et si vous ne savez pas à l'avance combien il y en aura ? Il suffit de déclarer "avec réserve" :)
P.S. Je n'ai pas trouvé cette façon de déclarer des objets dans l'aide intégrée.

CObj* var1 = NULL;
 
Mikhail Tkachev:

Déjà remarqué)
La solution consiste donc à déclarer des objets globalement vides.....
Et si vous ne savez pas à l'avance combien il y en aura ? Il suffit de les déclarer "avec réserve" :)

Mettre dansCArrayObj.

La fonctionArrObj.At(0) renvoie un pointeur vers la classe de base, qui ne sait rien des membres de la classe dérivée.

Pour y faire référence, il suffit d'effectuer une conversion de type.

CIsNewBar* newBar = (CIsNewBar*)ArrayObj.At(0);
newBar.method( parameter );
 
Koldun Zloy:

Mettre dansCArrayObj.

La fonctionArrObj.At(0) renvoie un pointeur vers la classe de base, qui ne sait rien des membres de la classe dérivée.

Il suffit de faire une conversion de type pour s'y référer.

Merci pour la réponse, vous n'êtes pas maléfique du tout)
Tout s'explique maintenant)
UPD
C'est la construction qui fonctionne aussi

CIsNewBar* newBar = ArrayObj.At(0);
newBar.method( parameter )
Raison: