Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 221

 
fxsaber #:

Non sono sicuro di come mantenere la funzionalità (sottocampo e metodo) e l'usabilità. Forse questa opzione sarebbe adatta alle vostre esigenze.


Applicazione.

È stato velocissimo e ora funziona benissimo, grazie!


In Russia con amore❤️! ;-)

 
Una volta era facile scrivere una tale macro in MQL5.
class MqlRatestime
{
public:
  static void f( MqlRates &Value ) { Print(Value.time); }
};

class MqlTicktime
{
public:
  static void f( MqlTick &Value ) { Print(Value.time); }
};

void OnStart()
{  
  MqlRates Rates;
  MqlTick Tick;
  
  MACROS(Rates, time); // MqlRatestime::f(Rates);
  MACROS(Tick, time);  // MqlTicktime::f(Tick);
}


Questo è possibile nella versione attuale di MQL5? Non avevo l'ingegno per superare questo ostacolo:

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Una volta era facile scrivere una tale macro in MQL5.


Questo è possibile nella versione attuale di MQL5? Non ho avuto l'intraprendenza per superare questo ostacolo:

Non capisco il compito - hai bisogno che la classe MqlRatest (template per essa) sia dichiarata all'interno di una sostituzione macro?
 
mktr8591 #:
Non capisco il compito - hai bisogno che la classe MqlRatest (template per essa) sia dichiarata all'interno della sostituzione macro?
Mi sembra necessario avere diverse sostituzioni di macro per parametri di tipo diverso.
Solo che non capisco perché dovrebbe essere fatto con la sostituzione di macro invece che con l'overloading di funzioni.
 
mktr8591 #:
Non capisco il compito - hai bisogno che la classe MqlRatest (il suo template) sia dichiarata all'interno della sostituzione macro?

No, le classi sono già dichiarate. I commenti specificano il risultato che si vuole ottenere. L'input della macro è un oggetto e l'output è una classe che contiene il nome del tipo di quell'oggetto.

 
Sergey Gridnev #:
Mi sembra necessario avere diverse sostituzioni di macro per parametri di tipo diverso.
Solo che non capisco perché questo dovrebbe essere fatto usando la sostituzione di macro piuttosto che il sovraccarico di funzioni.

Il compito è nato da questo.

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

Peculiarità di mql5, consigli e trucchi

fxsaber, 2022.02.11 15:44

ArraySortStruct_Define(MqlRates, open)
ArraySortStruct_Define(MqlRates, high)
ArraySortStruct_Define(MqlRates, time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(MqlRates, Rates, open);
  ArrayPrint(Rates);

  Print("\nСортируем по high-цене.");
  ArraySortStruct(MqlRates, Rates, high);
  ArrayPrint(Rates);

  Print("\nСортируем по времени.");
  ArraySortStruct(MqlRates, Rates, time);
  ArrayPrint(Rates);
}

Ho colorato il parametro di input, in cui devo specificare il tipo. In questa macro ottengo tre parametri di input. E ne vorrei due - senza tipo.

 
fxsaber #:

No, le classi sono già dichiarate. I commenti specificano il risultato che si vuole ottenere. L'input della macro è un oggetto e l'output è una classe che contiene il nome del tipo di quell'oggetto.

Non so come risolvere questo problema.

E ad ArraySortStruct con due parametri - ecco come funziona:

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)

 ArraySortStruct_Define(SortOnField_, open)
ArraySortStruct_Define(SortOnField_, high)
ArraySortStruct_Define(SortOnField_, time)


void OnStart()
  {

   MqlRates Rates[];

   CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары

   Print("\nБары без сортировки - как получили.");
   ArrayPrint(Rates);

   Print("\nСортируем по open-цене.");
   ArraySortStruct(Rates, open);
   ArrayPrint(Rates);

   Print("\nСортируем по high-цене.");
   ArraySortStruct(Rates, high);
   ArrayPrint(Rates);

   Print("\nСортируем по времени.");
   ArraySortStruct(Rates, time);
   ArrayPrint(Rates);
  }
 
mktr8591 #:

E ad ArraySortStruct con due parametri - è così che funziona:

Hai ragione, grazie! Ho esagerato su un punto piatto. Lascerò la vostra variante per l'ordinamento.

// Сортировка массива структур и указателей на объекты по полю.
#define  ArraySortStruct_Define(FIELD)                                            \
namespace SortOnField_##FIELD                                                    \
{                                                                                \
  class SORT                                                                     \
  {                                                                              \
  private:                                                                       \
    template <typename T>                                                        \
    static void Swap( T &Array[], const int i, const int j )                     \
    {                                                                            \
      const T Temp = Array[i];                                                   \
                                                                                 \
      Array[i] = Array[j];                                                       \
      Array[j] = Temp;                                                           \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static int Partition( T &Array[], const int Start, const int End )           \
    {                                                                            \
      int Marker = Start;                                                        \
                                                                                 \
      for (int i = Start; i <= End; i++)                                         \
        if (Array[i].##FIELD <= Array[End].##FIELD)                              \
        {                                                                        \
          SORT::Swap(Array, i, Marker);                                          \
                                                                                 \
          Marker++;                                                              \
        }                                                                        \
                                                                                 \
       return(Marker - 1);                                                       \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = Partition(Array, Start, End);                          \
                                                                                 \
        SORT::QuickSort(Array, Start, Pivot - 1);                                \
        SORT::QuickSort(Array, Pivot + 1, End);                                  \
      }                                                                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
  public:                                                                        \
    template <typename T>                                                        \
    static void Sort( T &Array[], int Count = WHOLE_ARRAY, const int Start = 0 ) \
    {                                                                            \
      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array);                                              \
                                                                                 \
      SORT::QuickSort(Array, Start, Start + Count - 1);                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
  };                                                                             \
}

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)


Applicazione.

ArraySortStruct_Define(open)
ArraySortStruct_Define(high)
ArraySortStruct_Define(time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(Rates, open);
  ArrayPrint(Rates);
  
  Print("\nСортируем по high-цене.");
  ArraySortStruct(Rates, high);
  ArrayPrint(Rates);
  
  Print("\nСортируем по времени.");
  ArraySortStruct(Rates, time);
  ArrayPrint(Rates);
}


ZZY È un peccato che, per sottocampo o metodo, non funzioni.

 
Questa potrebbe non essere una novità per nessuno, ma per me è inaspettata.
Se una DLL viene utilizzata simultaneamente in diversi programmi MT5,
tenere presente che viene caricata una volta dal primo programma in esecuzione che la utilizza.
Cioè, l'ambiente DLL è in un processo comune, non importa quante volte lo importi.
Qual è la fregatura? I puntatori globali usati nella DLL sono tutti nello stesso spazio di processo condiviso.
E questo è molto conveniente.
 
Roman #:
Forse questa non è una novità per nessuno, ma per me è inaspettata.
Se la DLL è usata simultaneamente in diversi programmi MT5,
, tenete presente che viene caricata una volta dal primo programma che la usa.
Cioè, lo stato della DLL è in un processo comune, non importa quante volte la importi.
Qual è la fregatura? I puntatori globali usati nella DLL sono tutti nello stesso spazio di processo condiviso.
E questo è molto conveniente.

Questo non è niente di nuovo, è il modo in cui ha sempre funzionato dalla nascita.

Solo se i dati sono più grandi di __atomic__ l'accesso dovrebbe essere avvolto/protetto con sezioni critiche (o mutex al terminale std::thread)

Motivazione: