¿Cómo obtener la longitud del enum y del ítem en MQL4/MQL5? - página 4

 
Creo que está buscando una manera de capturar todas las entradas de los indicadores
en un EA eludiendo la necesidad de valores de entrada para cada indicador.
La alternativa en su backtester es editar manualmente cada indicador
con un buffer de señales .
 

Intenta esto un poco directo pero el único enfoque posible hasta ahora.

enum XXX {x1 = -10, x2 = 0, x3 = 11};

template<typename E>
int EnumToArray(E dummy, int &values[], const int start = INT_MIN, const int stop = INT_MAX)
{
  string t = typename(E) + "::";
  int length = StringLen(t);
  
  ArrayResize(values, 0);
  int count = 0;
  
  for(int i = start; i < stop && !IsStopped(); i++)
  {
    E e = (E)i;
    if(StringCompare(StringSubstr(EnumToString(e), 0, length), t) != 0)
    {
      ArrayResize(values, count + 1);
      values[count++] = i;
    }
  }
  return count;
}

int OnInit()
{
  Print("ENUM elements:");
  XXX a;
  int result[];
  int n = EnumToArray(a, result, -100, 100);
  Print("Count=", n);
  for(int i = 0; i < n; i++)
  {
    Print(i, " ", EnumToString((XXX)result[i]), "=", result[i]);
  }
  
  return 0;
}

Salidas:

Elementos ENUM:

Count=3

0 x1=-10

1 x2=0

2 x3=11

Es importante especificar valores razonables para los parámetrosstart ystop, ya que el ciclo de valor entero mínimo a máximo (que se utiliza por defecto cuando se omiten los parámetros) se ejecuta demasiadoooo lento teniendo en cuenta que se utilizan funciones de cadena en su interior.

 
   template<typename ENUMTYPE>
   bool              AddEnum(ENUMTYPE enumIn) {
      enumIn = 0;
      
      //iterate through enum and add as combo box
      for(int i = 0; i<sizeof(enumIn); i++, enumIn++) {
         m_list.AddItem(EnumToString(enumIn),i);
         PrintFormat("adding %i = %s", i, EnumToString(enumIn));            
       }
      return(0);  
   }


Añadí esto a la clase CComboBox, para poder pasar cualquier tipo ENUM, y lo añadiría como un cuadro combinado.


Pero puedes cambiarlo para hacer lo que necesitas.

El problema es que si no pasas un ENUM y pasas algo como un double o un float, podrías colapsar tu aplicación.

No creo que haya ninguna manera de comprobar el tipo de datos pasado.

 
dazamate:
   template<typename ENUMTYPE>
   bool              AddEnum(ENUMTYPE enumIn) {
      enumIn = 0;
      
      //iterate through enum and add as combo box
      for(int i = 0; i<sizeof(enumIn); i++, enumIn++) {
         m_list.AddItem(EnumToString(enumIn),i);
         PrintFormat("adding %i = %s", i, EnumToString(enumIn));            
       }
      return(0);  
   }


Añadí esto a la clase CComboBox, para poder pasar cualquier tipo de ENUM, y lo añadiría como un cuadro combinado.


Pero puedes cambiarlo para hacer lo que necesitas.

El problema es que si no pasas un ENUM y pasas algo como un double o un float, podrías colapsar tu aplicación.

No creo que haya ninguna manera de comprobar el tipo de datos pasado.

Me temo que sizeof(enumIn) siempre es igual a 4.
 

Sí lo hace, oops. Me acabo de dar cuenta.

Lo que pasa es que cuando hice esto, el ENUM que estaba usando en realidad tenía 4 propiedades:\N -.

 

enum Combolist1{item1, item2, item3, item4, item5};

for(int i = 0; GetLastError()==0; i++) {
ComboBox1.ItemAdd(EnumToString(Combolist1(i)),Combolist1(0));
}
 
Xiangdong Guo: ¿Como obtener la longitud de un enum y un item en MQL4/MQL5?

Por ejemplo, hay una definición de enum:

enum ENUM_FRUIT {APPLE, BANANA, GRAPE};

A continuación, quiero usarlo en el bucle:

for (int i = 0; i < length_of_enum; i++) {
  Print(EnumToString(get_enum_item(i)));
} 
No hay ninguna manera, tienes que codificarla.
Si no va a ser una entrada, uso este patrón
enum ENUM_FRUIT {APPLE, BANANA, GRAPE,
                 FRUIT_FIRST=APPLE, FRUIT_LAST=GRAPE};
for (ENUM_FRUIT i = APPLE; i <= FRUIT_LAST; ++i) {
  Print(EnumToString(i));
}
Si lo uso con un incremento (++i) asumo que son adyacentes numéricamente.
Si va a ser una entrada, uso este patrón
enum ENUM_FRUIT {APPLE, BANANA, GRAPE}
#define FRUIT_FIRST APPLE
#define FRUIT_LAST  GRAPE
for (ENUM_FRUIT i = APPLE; i <= FRUIT_LAST; ++i) {
  Print(EnumToString(i));
}
Si no son numéricamente adyacentes
const ENUM_TIMEFRAMES  gcPeriods[]={   PERIOD_CURRENT,
   PERIOD_M1,  PERIOD_M2,  PERIOD_M3,  PERIOD_M4,  PERIOD_M5,  PERIOD_M6,
   PERIOD_M10, PERIOD_M12, PERIOD_M15, PERIOD_M20, PERIOD_M30, PERIOD_H1,
   PERIOD_H2,  PERIOD_H3,  PERIOD_H4,  PERIOD_H6,  PERIOD_H8,  PERIOD_H12,
   PERIOD_D1,  PERIOD_W1,  PERIOD_MN1};
ENUM_TIMEFRAMES  next(ENUM_TIMEFRAMES curr){
   for(int i=0; gcPeriods[i] != curr; ++i){}
   return gcPeriods[i+1];
}
 
Lorentzos Roussos:
Mal diseño de lo que

¿Significa el número de miembros de la tienda enum?

 

Sé que esta conversación es bastante antigua pero aquí hay una manera fácil de llenar un array de cualquier tipo enum.


void OnStart()
{
   ENUM_TIMEFRAMES array[];
   int total_elements = enumFillArray(array);
   printf("There are %d elements in the ENUM_TIMEFRAMES array.",
      total_elements
   );
   
   for(int i=0;i<total_elements;i++)
      Print(EnumToString(array[i]));
}
   
template<typename T>
int enumFillArray(T& res_array[])
{
   ArrayResize(res_array,0);
   int iter = 100000;
   for(int i=-iter;i<iter;i++)
      if(StringFind(EnumToString((T)i),"::")<0)
      {
         int index = ArrayResize(res_array,ArraySize(res_array)+1)-1;
         res_array[index] = (T)i;
      }
   return ArraySize(res_array);
}
 

Sólo añadir mi solución para las generaciones futuras sobre cómo he resuelto esto.

Así que el problema es saber el número de entradas en el enum dinámicamente con la capacidad de añadir o eliminar los valores del enum. Necesito saber esto para crear arrays de tamaño fijo con valores de enum como índice del array. Lo que suelo hacer es añadir un valor reservado al final del enum que sólo se utiliza como valor de longitud. Aquí hay un ejemplo.

enum ENUM_ENTRIES
{
        SMALL_ENTRY = 0,
        MEDIUM_ENTRY,
        LARGE_ENTRY,
        VERY_LARGE_ENTRY,
        _ENUM_ENTRIES
};

ObjectType *entryArray[_ENUM_ENTRIES];

// Setting individual entries
entryArray[MEDIUM_ENTRY] = new ObjectType();
entryArray[LARGE_ENTRY] = new ObjectType();

// Looping through the array
for(int i = 0; i < _ENUM_ENTRIES; i++) {

        entryArray[i] = new ObjectType();       
}
Esto es agradable y fácil porque no necesitas estar fijado a la última entrada en todas partes como
// Fixed to last entry +1
ObjectType *entryArray[VERY_LARGE_ENTRY + 1];

for(int i = 0; i <= VERY_LARGE_ENTRY; i++) {

}

o puedes añadir más entradas al final del enum y el array y el bucle seguirán funcionando.

/*
 *  Expanded enum entries
 */
enum ENUM_ENTRIES
{
        SMALL_ENTRY = 0,
        MEDIUM_ENTRY,
        LARGE_ENTRY,
        VERY_LARGE_ENTRY,
        EXTRA_LARGE_ENTRY,
        EXTREMELY_LARGE_ENTRY,
        _ENUM_ENTRIES
};

/* 
 * Previous code untouched and still works
 */

ObjectType *entryArray[_ENUM_ENTRIES];

// Setting individual entries
entryArray[MEDIUM_ENTRY] = new ObjectType();
entryArray[LARGE_ENTRY] = new ObjectType();

// Looping through the array
for(int i = 0; i < _ENUM_ENTRIES; i++) {

        entryArray[i] = new ObjectType();       
}
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
To obtain the current market information there are several functions: SymbolInfoInteger(), SymbolInfoDouble() and SymbolInfoString(). The first parameter is the symbol name, the values of the second function parameter can be one of the identifiers of ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE and ENUM_SYMBOL_INFO_STRING. Some symbols...