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

 
Igor Makanu:

IsInf() et IsNaN() fonctionnent,

IsEqual() et IsZerro() sont discutables, ils ont été googlés à partir de certaines sources comme "truc pour le double".

IsNan() fonctionne, mais pas IsInf()

IsInf( DBL_MIN_DENORM) == true

Depuis quand les nombres dénormalisés deviennent-ils l'infini ?

Et toutes ces comparaisons avec epsilon - epsilon doit être augmenté proportionnellement aux opérandes. En général, il n'y a pas de recette universelle, j'utilise Point comme un epsilon (avec des opérandes arrondis) et je ne veux pas (et n'ai pas besoin) de comparer la différence avec DBL_EPSILON.

 
Vict:

Et toutes ces comparaisons avec epsilon - epsilon doit être augmenté proportionnellement aux opérandes. En général, il n'y a pas de recette universelle, j'utilise Point comme epsilon (avec des opérandes arrondis), je ne veux pas comparer la différence avec DBL_EPSILON(et je n'en ai pas besoin).

J'ai trouvé un article que j'ai lu hier sur TVhttps://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/.

Oui, vous devez utiliser un autre exemple où vous devez spécifier la précision de la comparaison.

Vict :

IsNan() fonctionne, mais pas IsInf()

Depuis quand les nombres dénormalisés deviennent-ils l'infini ?

MQL semble normaliser au 8ème chiffre, c'est-à-dire que si NormalizeDouble() est ajouté à IsInf(), le résultat ne sera toujours pas meilleur.

 
Igor Makanu:

la normalisation dans MQL semble aller jusqu'au 8ème chiffre, c'est-à-dire que si NormalizeDouble() est ajouté à IsInf(), le résultat n'est toujours pas meilleur.

La normalisation dans MQL n'est pas du tout la même, je ne sais pas pourquoi ils ont nommé la fonction de cette façon. https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0

 
J'ai découvert par hasard dans ME que vous pouvez créer des signets avec CTRL+1, CTRL+2, ...... Et passer de l'un à l'autre avec ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

  return(OrderSend(Request, Result) ? 0 : (int)Result.request_id + 1);
}

Indique le nombre total d'ordres commerciaux synchrones (OrderSend) et asynchrones réussis générés dans le terminal (depuis le début).

Je l'utilise dans le testeur (à la fin) pour voir combien de fois les commandes ont été modifiées.

 
Il y a peu de gens qui ne savent pas comment créer des classes TC avec leurs propres On-events, par exemple.

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

OnTick() ne fonctionne pas dans une instance de classe ?

fxsaber, 2019.10.31 23:45

class BASE
{  
private:
  static BASE* Objects[];
  
public:
  BASE()
  {
    BASE::Objects[::ArrayResize(BASE::Objects, ::ArraySize(BASE::Objects) + 1) - 1] = &this;
  }
  
  ~BASE()
  {
    const int Size = ::ArraySize(BASE::Objects);
    
    for (int i = Size - 1; i >= 0; i--)
      if (BASE::Objects[i] == &this)
      {
        for (int j = i; j < Size - 1; j++)
          BASE::Objects[j] = BASE::Objects[j + 1];
          
        ::ArrayResize(BASE::Objects, Size - 1);
        
        break;
      }
  } 
    
  virtual void OnTick() = 0;
  
  static void AllTick()
  {
    for (int i = ::ArraySize(BASE::Objects) - 1; i >= 0; i--)
      BASE::Objects[i].OnTick();
  }
};

static BASE* BASE::Objects[];


class A : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

class B : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

A a;
B b;

void OnTick()
{
  BASE::AllTick();
}


Héritez de BASE, alors les méthodes OnTick des classes seront appelées automatiquement.

 

Un exemple d'utilisation de la Macro X (ne faites pas attention aux types obscurs, je les ai arrachés à un code de travail. Vector est un tableau dynamique) :

Par exemple :

   vector_fund<upindex_t> seg2; vector_ref<vector_fund<upindex_t>> seg2_sub;
   vector_fund<upindex_t> seg3; vector_ref<vector_fund<upindex_t>> seg3_sub;
   vector_fund<upindex_t> seg4; vector_ref<vector_fund<upindex_t>> seg4_sub;
   for (uint i = 0;  i < 5114;  ++ i) {
      restore_image(seg2, "seg2"); restore_subimages(seg2_sub, "seg2");
      restore_image(seg3, "seg3"); restore_subimages(seg3_sub, "seg3");
      restore_image(seg4, "seg4"); restore_subimages(seg4_sub, "seg4");
      
      if (true) {} // тест №1, использует seg2 и seg2_sub
      if (true) {} // тест №2, использует seg3 и seg3_sub
      if (true) {} // тест №3, использует seg4 и seg4_sub
   }

1. Nous voulons définir des vecteurs derrière une boucle pour éviter les allocations constantes.

2. Chacun des tests peut être désactivé (en fait, il y en a plusieurs).

3. restore_image() et restore_subimages(), une fonction lourde et très gourmande en temps (lecture des objets du graphe).

4. Si aucun des tests n'utilise seg2, par exemple, je voudrais supprimer à la fois la définition et la restore...() correspondante en une seule action, pour éviter une situation où le vecteur est défini mais vide à cause de la restore...() commentée, ce qui donnerait des résultats erronés.

Que faire ?

#define  DEFSEG_LIST    \
   DEFSEG_HELPER(seg2) \
   DEFSEG_HELPER(seg3) \
   DEFSEG_HELPER(seg4)
   
#define  DEFSEG_HELPER(SEG) vector_fund<upindex_t> SEG; vector_ref<vector_fund<upindex_t>> SEG##_sub;
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
   
   for (uint i = 0;  i < 5114;  ++ i) {
#define  DEFSEG_HELPER(SEG) restore_image(SEG, #SEG);  restore_subimages(SEG##_sub, #SEG);
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
      ...
   }

Il suffit de commenter les segx inutiles dans DEFSEG_LIST. Cela produira les mêmes résultats que dans le premier code. En fait, c'est dommage que le compilateur ne soit pas capable de montrer la sortie du processeur (l'analogue gcc -E).

 

Parfois, dans l'optimisation génétique, les quelques milliers de premiers passages suffisent pour comprendre plus ou moins le résultat.

Lorsque vous exécutez automatiquement un grand nombre d'optimisations, vous voulez que tout soit plus rapide. C'est pourquoi nous aurons besoin d'un mécanisme pour interrompre l'optimisation.

#include <fxsaber\MultiTester\MTTester.mqh>  // https://www.mql5.com/ru/code/26132

// Выключает Оптимизацию ( и одиночный проход)
bool OptimizationStop( void )
{
  return(!MTTESTER::IsReady() && MTTESTER::ClickStart(false));
}


Utilisation.

// Демонстрация прерывания Оптимизации.

sinput int inAmountPasses = 20; // Через сколько проходов закончить
input int Range = 0; // 0..10000

double OnTester()
{
  int Data[];
  
  return(FrameAdd(NULL, 0, 0, Data)); // Сгенерировали TesterPass
}

void OnTesterPass()
{
  static int Amount = 0;
  
  ulong Pass;
  string Name;
  long ID;
  double Value;
  int Data[];

  while (FrameNext(Pass, Name, ID, Value, Data))
    if (++Amount > inAmountPasses)
    {
      OptimizationStop(); // Как достигли нужного количества проходов, выключили оптимизатор.
      
      break;
    }
}
 

Instructions pour ouvrir un graphique avec un caractère Null.


  1. Supprimer tous les graphiques de Market Watch.
  2. Démarrer l'optimisation d'un cadre EA (par exemple celui-ci) en mode mathématique.
  3. Arrêtez l'optimisation et supprimez le cadre EA du graphique Null-symbol.
Un tel tableau peut probablement être utile pour économiser les ressources.
 
J'ai rencontré cette particularité.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

A b; // Надо прописывать после static


Si une classe avec des champs statiques est immédiatement créée lors de la définition d'une classe, il y aura une erreur de compilation.

Raison: