Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 147

 
Igor Makanu:

IsInf() e IsNaN() funzionano,

IsEqual() e IsZerro() sono discutibili, cercate su Google da alcune fonti come "trucco per il doppio".

IsNan() funziona, ma IsInf() no

IsInf( DBL_MIN_DENORM) == true

Da quando i numeri denormalizzati sono diventati infiniti?

E tutti questi confronti con epsilon - epsilon dovrebbe essere aumentato proporzionalmente agli operandi. In generale, non c'è una ricetta universale, io uso Point come epsilon (con operandi arrotondati) e non voglio (e non ho bisogno) di confrontare la differenza con DBL_EPSILON.

 
Vict:

E tutti questi confronti con epsilon - epsilon dovrebbe essere aumentato proporzionalmente agli operandi. In generale, non c'è una ricetta universale, io uso Point come epsilon (con operandi arrotondati), non voglio confrontare la differenza con DBL_EPSILON(e non ne ho bisogno).

ho trovato un articolo che ho letto ieri da TVhttps://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Sì, devi usare un altro esempio in cui dovresti specificare la precisione del confronto

Vittoria:

IsNan() funziona, ma IsInf() no

Da quando i numeri denormalizzati sono diventati infiniti?

MQL sembra normalizzare alla 8a cifra, cioè se NormalizeDouble() viene aggiunto a IsInf(), il risultato non sarà comunque migliore.

 
Igor Makanu:

La normalizzazione in MQL sembra essere fino all'ottava cifra, cioè se NormalizeDouble() viene aggiunta a IsInf(), il risultato non è ancora migliore

La normalizzazione in MQL non è affatto la stessa, non so perché hanno chiamato la funzione in quel modo. 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

 
Ho scoperto per caso in ME che si possono creare segnalibri con CTRL+1, CTRL+2, ..... E passare da uno all'altro con ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

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

Mostra quanti ordini di compravendita sincroni (OrderSend) e asincroni generati con successo nel terminale in totale (dall'inizio).

Lo uso nel Tester (alla fine) per vedere quante volte gli ordini sono stati modificati.

 
Ci sono poche persone che non sanno come creare classi TC con i propri On-events, per esempio.

Forum sul trading, sistemi di trading automatico e test di strategia

OnTick() non funziona in un'istanza di 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();
}


Eredita da BASE, allora i metodi OnTick nelle classi saranno chiamati automaticamente.

 

Un esempio di utilizzo di X Macro (non fate caso ai tipi oscuri, l'ho strappato da un codice funzionante. Vector è un array dinamico):

Per esempio:

   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. vogliamo definire dei vettori dietro un ciclo per evitare allocazioni costanti.

2. Ognuno dei test può essere disattivato (in realtà ce ne sono molti).

3. restore_image() e restore_subimages(), una funzione pesante e che richiede molto tempo (lettura di oggetti grafici dal grafico).

4. Se nessuno dei test usa seg2, per esempio, vorrei rimuovere sia la definizione che il corrispondente restore...() in una sola azione, per evitare una situazione in cui il vettore è definito ma vuoto a causa del commentato restore...(), che darebbe risultati errati.

Cosa fare?

#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
      ...
   }

Commentate semplicemente i segx non necessari in DEFSEG_LIST. Questo genererà gli stessi risultati del primo codice. In realtà è un peccato che il compilatore non sia in grado di mostrare l'output del processore (il gcc -E analogico).

 

A volte nell'ottimizzazione genetica le prime migliaia di passaggi sono sufficienti per capire già il risultato più o meno.

Quando si eseguono automaticamente molte ottimizzazioni, si vuole che tutto funzioni più velocemente. Ecco perché avremo bisogno di un meccanismo per interrompere l'ottimizzazione.

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

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


Uso.

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

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

Istruzioni per aprire un grafico con un carattere Null.


  1. Cancella tutti i grafici da Market Watch.
  2. Iniziare l'ottimizzazione di un EA frame (per esempio questo) in modalità matematica.
  3. Interrompi l'ottimizzazione e rimuovi il frame EA dal grafico Null-symbol.
Un tale grafico può probabilmente essere utile per risparmiare risorse.
 
Ho incontrato questa peculiarità.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

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


Se una classe con campi statici viene creata immediatamente durante la definizione di una classe, ci sarà un errore di compilazione.

Motivazione: