Caractéristiques du langage mql5, subtilités et techniques - page 229

 

English (original) : J'aimerais faire une demande de fonctionnalité linguistique pour MQL. Si ce n'est pas le bon fil de discussion, merci de me le faire savoir. La demande originale se trouve sur le forum anglais...

Russe (Google translate) : Je voudrais faire une demande de fonctionnalité linguistique pour MQL. Si ce n'est pas le bon fil de discussion, merci de me le faire savoir. La demande originale se trouve sur le forum anglais ...

 

Comment remplir un tableau avec une seule ligne ?

struct clr_struct{
   color uncheck;
};
clr_struct clr[];

//clr[0].uncheck=0x999999;
//clr[1].uncheck=0x999999;

clr[].uncheck={0x999999,0x999999};//как правильно?
 
Pavel Kolchin remplir un tableau avec une seule ligne ?
clr_struct clr[] = {{0x999999}, {0x999999}};
 

Encore une astuce pour les droits d'accès : Si vous avez un désir irrésistible de donner accès à des champs/fonctions privés d'une classe à une autre classe, vous pouvez faire ce qui suit en utilisant des outils MQL standard :

Nous devons : rendre l'accès à A::f1() à partir de B

//--------- как было
class   A
  {
   int               m;
   int               f1() {return m;}                       // нужно дать к нему доступ классу B
public:
                     A(int a): m(a) {}
  };

class B {};

Réécrivons-le comme suit :

class A;
class B
  {
private:
   class AB
     {
   public:
      virtual int    CallAf1(A&) const  = 0;
                     AB() {ABptr = &this;}
     } static *ABptr;

   // внутри B используем  этот метод для получения доступа к A::f1()
   static int        CallAf1(A & obj)
     {
      return ABptr.CallAf1(obj);
     }

public:
   class AB2: AB {};

   // вспомогательный метод - только для проверки
   static void       _f1_test(A & obj)
     {
      Print("test ", CallAf1(obj));
     }
  };
B::AB *B::ABptr = NULL;

class   A
  {
   int               m;
   int               f1() {return m;}
public:
                     A(int a): m(a) {}

   //--  добавлено
private:
   class AB3: B::AB2
     {
      int            CallAf1(A &obj) const {return obj.f1();}
     }   static  const     ABlink;
  };
const A::AB3 A::ABlink;

Pour appeler (A)a.f1() dans B, appelez CallAf1(a). Si f1() a des paramètres, nous les ajoutons à CallAf1().

Test :

void OnStart()
  {
    A f(2);
    B::_f1_test(f);
  }

Vous pouvez rendre CallAf1() protégé, mais ce sera un grand trou dans les droits d'accès - n'importe où dans le code, vous pouvez créer un descendant de la classe B et dans celui-ci une méthode publique pour appeler CallAf1() - c'est-à-dire que tout le monde aura accès à A::f1().


P.S. La construction est très lourde (si vous le souhaitez, vous pouvez l'intégrer dans des macros), mais elle présente un avantage par rapport à l'ami C++ : elle ne donne pas accès à tous les membres de la classe, mais seulement à certains d'entre eux.

 
mktr8591 #:

Encore une astuce pour les droits d'accès : Si vous avez un désir irrésistible d'accorder l'accès à des champs/fonctions privés d'une classe à une autre classe, vous pouvez le faire à l'aide des outils MQL standard

Il m'a fallu beaucoup de temps pour m'y mettre... bonne continuation avec la virtualisation, merci !
 
fxsaber #:
J'ai mis du temps à m'y mettre... bon coup de virtualisation, merci !
La seule chose que je n'ai pas écrite au début, c'est qu'il ne faut plus créer d'objets de classe B::AB2 (et ses descendants), sinon tout s'écroule :-)
 
L'exécution de cet Expert Advisor dans le Testeur en mode tous les symboles
input int inTmp = 0; // https://www.mql5.com/ru/forum/321656/page90#comment_44727856

bool Res = true;

// Проверяет, нормализована ли цена по алгоритму NormalizeDouble.
bool IsNDPrice( const double &Price )
{
  return(Price == NormalizeDouble(Price, 5));
}

// Проверяет, нормализована ли цена, как при парсинге или ручном вводе.
bool IsNDPrice2( const double &Price )
{
  return(Price == (double)DoubleToString(Price, 5));
}

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
//    Res &= IsNDPrice(Tick.bid) && IsNDPrice(Tick.ask); // OnTester == 1.
    Res &= IsNDPrice2(Tick.bid) && IsNDPrice2(Tick.ask); // OnTester == 0.
}

double OnTester()
{
  return(Res);
}
montre que tous les prix sont normalisés en utilisant l'algorithme NormalizeDouble. Et que si vous travaillez avec des prix obtenus non pas à partir du terminal, mais par analyse ou saisie manuelle, ils nécessitent une normalisation pour fonctionner correctement. Il n'y a pas lieu de se tromper.
 

REASON_ACCOUNT (même si le compte n'est pas modifié, mais que l 'on se reconnecte simplement), le conseiller expert est complètement déchargé et une nouvelle copie est chargée.

Pour cette raison, ExpertRemove dans OnDeinit n'affecte pas la nouvelle copie, car il touche la copie déchargée.

void OnInit() { Print(__FUNCSIG__); }

void OnDeinit( const int ) { Print(__FUNCSIG__); }


Résultat après la reconnexion.

2023.02.07 11:33:12.717 Test5-3 (EURUSD,M1)     void OnDeinit(const int)
2023.02.07 11:33:13.926 Test5-3 (EURUSD,M1)     void OnInit()


Après Deinit, la nouvelle copie d'EA attend plus d'une seconde (jusqu'à deux secondes) pour démarrer. Quelles sont les raisons d'une attente aussi longue et est-il possible de l'accélérer ?

 

SymbolInfoTick renverra le dernier tick à chacun de ces trois appels. En d'autres termes, la soi-disant collecte de ticks sans passer par des indicateurs est discutable, et c'est un euphémisme.


Preuve de l'impossibilité de collecter des ticks par un indicateur (sans saut).

// Аналог Sleep для индикатора.
void Sleep2( const uint Pause )
{
  const uint StartTime = GetTickCount();
  
  while (!IsStopped() && (GetTickCount() - StartTime) < Pause)
    ;
}

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

int OnCalculate( const int rates_total,
                 const int,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{  
  static const int period = PeriodSeconds();
  
  Sleep2(1000); // Расчеты.
  
  MqlTick Tick[1];
  
  if (SymbolInfoTick(_Symbol, Tick[0]) &&
      ((Tick[0].bid != close[rates_total - 1]) || // Свежий бар не соответсвует последнему тику.
       Tick[0].time / period > time[rates_total - 1] / period))
  {
    ArrayPrint(Tick);
    Print(TOSTRING(time[rates_total - 1]) + TOSTRING(close[rates_total - 1]));
  }

  return(rates_total);
}


Résultat.

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:39 1.54951 1.54959 0.0000        0 1675787319322      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:40 1.54948 1.54959 0.0000        0 1675787320719      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:41 1.54952 1.54960 0.0000        0 1675787321823     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54954 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:42 1.54954 1.54961 0.0000        0 1675787322223     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54951 00000000002 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:43 1.54955 1.54964 0.0000        0 1675787323721     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54948 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:44 1.54954 1.54962 0.0000        0 1675787324323     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:45 1.54956 1.54962 0.0000        0 1675787325421     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952
 
Une des constructions possibles du langage MQL5.

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Erreurs, bugs, questions

fxsaber, 2023.02.14 13:11

input string inStr = "B2";

class A {};

class B1 : public A {};
class B2 : public A {};
// .....
class B100 : public A {};

void OnStart()
{
  A* a = New2(inStr); // создает объект, который прописан в inStr.
}

// Решение.
template <typename T>
A* New( const string &ClassName ) { return((typename(T) == ClassName) ? new T : NULL); }

typedef A* (*TNew)( const string& );
static const TNew FuncNew[] = {New<B1>, New<B2>, /*....,*/ New<B100>};

A* New2( string ClassName )
{  
  A* Res = NULL;
  
  ClassName = "class " + ClassName;
  
  for (int i = ArraySize(FuncNew) - 1; !Res && (i >= 0); i--)
    Res = FuncNew[i](ClassName);  
    
  return(Res);
}

Malheureusement, MQL4 ne permet pas encore ce genre de travail.