Características da linguagem mql5, subtilezas e técnicas - página 221

 
fxsaber #:

Não sei como manter a funcionalidade (subcampo e método) e a usabilidade. Talvez esta opção se adapte às suas necessidades.


Aplicação.

Isso foi tão rápido e agora funciona muito bem, obrigado!


Para a Rússia com love❤️! ;-)

 
Era uma vez fácil escrever uma tal macro em 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);
}


Isto é possível na versão actual da MQL5? Não tive o engenho de ultrapassar este obstáculo:

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Era uma vez fácil escrever uma tal macro em MQL5.


Isto é possível na versão actual da MQL5? Não tenho tido os recursos necessários para ultrapassar este obstáculo:

Não compreendo a tarefa - precisa da classe MqlRatest (modelo para ela) para ser declarada dentro de uma macro substituição?
 
mktr8591 #:
Não compreendo a tarefa - precisa da classe MqlRatest (modelo para ela) para ser declarada dentro da substituição macro?
Parece-me necessário ter uma substituição macro diferente para parâmetros de tipo diferente.
Só não percebo porquê fazê-lo com a substituição de macros em vez de sobrecarga de funções.
 
mktr8591 #:
Não compreendo a tarefa - precisa da classe MqlRatest (o seu modelo) para ser declarada dentro da substituição macro?

Não, as aulas já estão declaradas. Os comentários especificam o resultado que se pretende obter. A entrada para a macro é um objecto, e a saída é uma classe que contém o nome do tipo desse objecto.

 
Sergey Gridnev #:
Parece-me necessário ter uma substituição macro diferente para parâmetros de diferentes tipos.
Só não compreendo porque é que isto deve ser feito usando a substituição de macros em vez de sobrecarga de funções.

A tarefa nasceu desta.

Fórum sobre comércio, sistemas de comércio automatizados e testes estratégicos

Peculiaridades de mql5, dicas e truques

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

Colori o parâmetro de entrada, no qual tenho de especificar o tipo. Nesta macro, obtenho três parâmetros de entrada. E eu gostaria de dois - sem tipo.

 
fxsaber #:

Não, as aulas já estão declaradas. Os comentários especificam o resultado que se pretende obter. A entrada para a macro é um objecto, e a saída é uma classe que contém o nome do tipo desse objecto.

Não sei como resolver este problema.

E ao ArraySortStruct com dois parâmetros - é assim que funciona:

#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 ao ArraySortStruct com dois parâmetros - é assim que funciona:

Tem razão, obrigado! Exagerei num ponto plano. Deixarei a sua variante para a triagem.

// Сортировка массива структур и указателей на объекты по полю.
#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)


Aplicação.

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


ZS É uma pena, por subcampo ou método, que não funcione.

 
Isto pode não ser novidade para ninguém, mas é inesperado para mim.
Se uma DLL for utilizada simultaneamente em diferentes programas MT5,
tenha em mente que é carregada uma vez pelo primeiro programa em execução que a utiliza.
Ou seja, o ambiente DLL está num processo comum, não importa quantas vezes se importe.
Qual é o senão? Os indicadores globais utilizados na DLL estão todos no mesmo espaço de processo partilhado.
E isto é muito conveniente.
 
Roman #:
Talvez isto não seja novidade para ninguém, mas é inesperado para mim.
Se a DLL for utilizada simultaneamente em diferentes programas MT5,
, tenha em mente que é carregada uma vez pelo primeiro programa que a utiliza.
Ou seja, o estado da DLL está num processo comum, não importa quantas vezes se importe.
Qual é o senão? Os indicadores globais utilizados na DLL estão todos no mesmo espaço de processo partilhado.
E isto é muito conveniente.

Isto não é nada de novo, é a forma como sempre funcionou desde o nascimento.

Apenas se os dados forem maiores do que __atómicos__ deve ser embalado/protegido com secções críticas (ou mutex para terminal std::thread)