Características del lenguaje mql5, sutilezas y técnicas - página 221

 
fxsaber #:

No estoy seguro de cómo mantener la funcionalidad (subcampo y método) y la usabilidad. Tal vez esta opción se adapte a sus necesidades.


Aplicación.

Ha sido muy rápido y ahora funciona bien, ¡gracias!


¡A Rusia con amor❤️! ;-)

 
Antes era fácil escribir una macro de este tipo en 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);
}


¿Es esto posible en la versión actual de MQL5? No tuve el ingenio necesario para superar este obstáculo:

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Antes era fácil escribir una macro de este tipo en MQL5.


¿Es esto posible en la versión actual de MQL5? No he tenido recursos para superar este obstáculo:

No entiendo la tarea - ¿necesitas que la clase MqlRatest (plantilla para ella) sea declarada dentro de una macro sustitución?
 
mktr8591 #:
No entiendo la tarea - ¿necesitas que la clase MqlRatest (plantilla para ella) sea declarada dentro de la sustitución de la macro?
Me parece que es necesario tener una macro sustitución diferente para parámetros de diferente tipo.
Sólo que no entiendo por qué hay que hacerlo con la sustitución de macros en lugar de la sobrecarga de funciones.
 
mktr8591 #:
No entiendo la tarea - ¿necesitas que la clase MqlRatest (su plantilla) sea declarada dentro de la sustitución de la macro?

No, las clases ya están declaradas. En los comentarios se especifica el resultado que se quiere obtener. La entrada de la macro es un objeto, y la salida es una clase que contiene el nombre del tipo de ese objeto.

 
Sergey Gridnev #:
Me parece que es necesario tener una macro sustitución diferente para los parámetros de diferentes tipos.
Sólo que no entiendo por qué hay que hacerlo utilizando la sustitución de macros en lugar de la sobrecarga de funciones.

La tarea nació de ésta.

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Peculiaridades de mql5, consejos y trucos

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

He coloreado el parámetro de entrada, en el que tengo que especificar el tipo. En esta macro obtengo tres parámetros de entrada. Y me gustaría tener dos - sin tipo.

 
fxsaber #:

No, las clases ya están declaradas. En los comentarios se especifica el resultado que se quiere obtener. La entrada de la macro es un objeto, y la salida es una clase que contiene el nombre del tipo de ese objeto.

No sé cómo resolver este problema.

Y a ArraySortStruct con dos parámetros - así es como 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 #:

Y a ArraySortStruct con dos parámetros - así es como funciona:

Tienes razón, ¡gracias! Me excedí en un punto plano. Dejaré su variante para que la clasifique.

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


Aplicación.

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 Es una pena que, por subcampo o método, no funcione.

 
Puede que esto no sea una novedad para nadie, pero es inesperado para mí.
Si una DLL se utiliza simultáneamente en diferentes programas de MT5,
tenga en cuenta que se carga una vez por el primer programa que la utiliza.
Es decir, el entorno de la DLL está en un proceso común, no importa cuántas veces se importe.
¿Cuál es la trampa? Los punteros globales utilizados en la DLL están todos en el mismo espacio de proceso compartido.
Y esto es muy conveniente.
 
Roman #:
Tal vez esto no sea una novedad para nadie, pero para mí es inesperado.
Si la DLL se utiliza simultáneamente en diferentes programas MT5,
, tenga en cuenta que se carga una vez por el primer programa que la utiliza.
Es decir, el estado de la DLL está en un proceso común, no importa cuántas veces se importe.
¿Cuál es la trampa? Los punteros globales utilizados en la DLL están todos en el mismo espacio de proceso compartido.
Y esto es muy conveniente.

Esto no es nada nuevo, es la forma en que siempre ha funcionado desde su nacimiento.

Sólo si los datos son mayores que __atomic__, el acceso debe ser envuelto/protegido con secciones críticas (o mutex a la terminal std::thread)

Razón de la queja: