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

 
Marat Sultanov #:
Il était autrefois possible (même dans les anciens compilateurs) d'utiliser une classe avant qu'elle ne soit déclarée :
Mais maintenant, nous obtenons une erreur lors de la compilation :
la classe indéfinie 'A' ne peut pas être utilisée

Si cela ne fonctionne plus, il serait bon de savoir si c'est correct.

Si vous utilisez des pointeurs au lieu d'objets, l'ancienne version fonctionnera également.

 
fxsaber #:

S'il a cessé de fonctionner, il est bon de savoir si c'est la bonne chose à faire.

Si vous utilisez des pointeurs au lieu d'objets, l'ancienne version fonctionnera également.

Excellente remarque et merci pour l'astuce !

Oui, en effet, la situation est parfaitement résolue avec un pointeur :

class A;

class B
{
   public: A * a;
   public: int Val;
};

class A
{
   public: B * b;
   public: int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   A a;
   
   b.a = GetPointer(a);
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}
 

Les amateurs d'algorithmes rapides. Ceux qui se battent pour les nanosecondes :)


Tâche : Trouver l'heure d'ouverture de la barre en fonction de l'heure et de la TF données, quand on sait que la barre existe à cet instant. Par exemple, en fonction de l'heure d'ouverture et de fermeture des positions.

La plupart des programmeurs utiliseront une combinaison de iTime et iBarShift. Il s'agit de l'implémentation la plus lente, en particulier parce qu'elle nécessite un historique à jour des données téléchargées ou des tableaux combinés. De plus, cette approche peut générer des erreurs si l'historique requis n'est pas disponible.

Les programmeurs plus avancés résoudront ce problème en utilisant la structure MqlDateTime et la fonction TimeToStruct(). Cette solution n'est pas mauvaise et est suffisamment rapide.

Mais il existe une troisième solution, qui est plusieurs fois plus productive que la précédente :

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

La principale difficulté de cet algorithme est le calcul de l'heure du début du mois (surligné en vert). Il y a là de la magie, qui est le résultat du passage du simple au complexe. Le chemin inverse, du complexe au simple, sera beaucoup plus difficile à parcourir.

Le gain de performance est également fourni par l'algorithme qui récupère les secondes d'une barre à partir du TF au lieu de la fonction standard PeriodSeconds() - surligné en jaune.


Je joins un script de test qui calcule et compare les performances des trois méthodes :

2023.11.14 12:15:29.145 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 21.20 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.10 наносекунд - Быстрый расчет
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 142.00 наносекунд - Расчет через iBarShift
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:34.226 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 19.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.70 наносекунд - Быстрый расчет
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 127.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_W1========
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 98.30 наносекунд - Расчет через iBarShift
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:52.770 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 4.10 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    контрольная сумма - 0, время выполнения 1 иттерации = 148466.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 3.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000017286960, время выполнения 1 иттерации = 110555.70 наносекунд - Расчет через iBarShift
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    ========================================================================

La somme de contrôle avec iBarShift ne correspondra pas, car iBarShift travaille avec des barres réelles. La somme de contrôle ne coïncidera que sur les périodes MN1 et W1, car il n'y a pas de trous dans l'historique de ces barres.
Les performances seront plus élevées si vous utilisez un petit pas de temps dans la boucle (moins d'un jour) lorsque l'algorithme commence à travailler afin de sauvegarder les calculs précédents :

2023.11.14 12:14:10.714 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:10.722 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 8.03 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:10.723 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 136.80 наносекунд - Расчет через iBarShift
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:14:17.502 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:17.510 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 7.70 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:17.511 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 137.54 наносекунд - Расчет через iBarShift
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    ========================================================================


Les valeurs excessives pour l'algorithme via iBarShift (surlignées en bleu) sont dues à l'absence actuelle de l'historique nécessaire ou des TF calculés par le tableau, ce qui déclenche leur téléchargement.
Après le téléchargement, le résultat sera le suivant :

2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 4.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 2.60 наносекунд - Быстрый расчет
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000009103200, время выполнения 1 иттерации = 129.10 наносекунд - Расчет через iBarShift
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 1.40 наносекунд - Быстрый расчет
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000038634480, время выполнения 1 иттерации = 381.30 наносекунд - Расчет через iBarShift
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    ========================================================================

Dossiers :
 
Nikolai Semko #:

Les amateurs d'algorithmes rapides. Ceux qui se battent pour les nanosecondes :)

...

😮😲😳🥴🤪

...

ah...

mmm....

oooh....

gkghm... Je ne pensais pas que ma simple question sortirait comme ça.

Juste comme ça. Oh.

 
Artyom Trishkin #:

😮😲😳🥴🤪

...

ah...

mmm.

ohhhh....

ahem. Je ne pensais pas que ma simple question prendrait une telle tournure.

Oh.

Oui, Artem, tu m'as trompé pendant un moment.
C'était un intérêt sportif.
J'espère que cela sera utile à quelqu'un, y compris à moi. :))

 
Nikolai Semko #:

Oui, Artem, tu m'as trompé pendant un moment.
J'ai travaillé sur l'intérêt sportif.
J'espère qu'il sera utile à quelqu'un, et à moi entre autres. :))

Bien sûr que oui. C'est génial. Merci encore !

S.F. Cela m'a amusé : "ne compte correctement que jusqu'au 28.02.2100 ! !!!".

Que fait-on ensuite ?

 
Artyom Trishkin #:

Bien sûr qu'il sera utile. C'est très bien. Je vous remercie encore une fois !

S.F. Cela m'a amusé : "ne compte correctement que jusqu'au 28.02.2100 ! !!!".

Que fait-on ensuite ?

haha.
Je doute que cet algorithme soit encore demandé dans 75 ans. Les ordinateurs quantiques domineront probablement déjà le monde, avec une programmation complètement différente.
Pour être honnête, c'était paresseux de prendre en compte le calendrier grégorien. L'année 2000 était très importante, l'année 2100 ne l'est plus.

 
Nikolai Semko #:

haha.
Je doute que cet algorithme soit demandé dans 75 ans. Les ordinateurs quantiques domineront probablement déjà le monde, avec une programmation complètement différente.
Pour être honnête, c'était paresseux de prendre en compte le calendrier grégorien dans son intégralité. L'année 2000 était très importante, l'année 2100 ne l'est plus.

Pour MN, vous pouvez utiliser un tableau pré-calculé, il n'y a presque rien dedans

Ln2(12 mois * cent ans)...11 if`s et comparaisons en recherche binaire, mais sans autres calculs.

 
Maxim Kuznetsov #:

Vous pouvez utiliser un tableau précalculé pour MN, il n'y a pratiquement pas de données.

Ln2(12 mois * cent ans)...11 if`s et comparaisons en recherche binaire, mais sans autres calculs.

Il n'y a pas de difficultés. Je sais comment l'implémenter.
C'est juste que je ne veux pas faire quelque chose dont je suis sûr à 100% qu'il ne sera jamais utile.
 
Maxim Kuznetsov #:

Vous pouvez utiliser un tableau précalculé pour MN, il n'y a pratiquement pas de données.

Ln2(12 mois * cent ans)...11 if`s et comparaisons en recherche binaire, mais sans autres calculs.

Ah, j'ai mal lu au début.
Non, vous vous trompez. L'augmentation des performances ne fonctionnera pas. Vous serez toujours bloqué dans les calculs. Et l'accès aux éléments du tableau ralentit considérablement l'algorithme.