Enumeraciones

En la API de MQL5, un valor de enumeración se puede convertir en una cadena utilizando la función EnumToString. No existe ninguna transformación inversa preparada.

string EnumToString(enum value)

La función convierte el valor (es decir, el ID del elemento pasado) de una enumeración de cualquier tipo en una cadena.

Vamos a utilizarlo para resolver una de las tareas más populares: averiguar el tamaño de la enumeración (cuántos elementos contiene) y qué valores corresponden exactamente a todos los elementos. Para ello, en el archivo de encabezado EnumToArray.mqh implementamos la función de plantilla especial (debido al tipo de plantilla E, funcionará para cualquier enum):

template<typename E>
int EnumToArray(E dummyint &values[],
   const int start = INT_MIN
   const int stop = INT_MAX)
{
   const static string t = "::";
   
   ArrayResize(values0);
   int count = 0;
   
   for(int i = starti < stop && !IsStopped(); i++)
   {
      E e = (E)i;
      if(StringFind(EnumToString(e), t) == -1)
      {
         ArrayResize(valuescount + 1);
         values[count++] = i;
      }
   }
   return count;
}

El concepto de su funcionamiento se basa en lo siguiente. Dado que las enumeraciones en MQL5 se almacenan como enteros de tipo int, se admite una conversión implícita de cualquier enumeración a (int), y también se permite una conversión explícita int de vuelta a cualquier tipo de enumeración. En este caso, si el valor corresponde a uno de los elementos de la enumeración, la función EnumToString devuelve una cadena con el ID de este elemento. En caso contrario, la función devuelve una cadena de la forma ENUM_TYPE::value.

Así, recorriendo los enteros en el rango aceptable y convirtiéndolos explícitamente a un tipo enum, se puede analizar la cadena de salida EnumToString en busca de la presencia de '::' para determinar si el entero dado es un miembro enum o no.

La función StringFind utilizada aquí se presentará en el capítulo siguiente, al igual que otras funciones de cadena.

Vamos a crear el script ConversionEnum.mq5 para probar el concepto. En él, implementamos una función auxiliar process, que llamará a la plantilla EnumToArray, informará del número de elementos de enum, e imprimirá el array resultante con las coincidencias entre los elementos de enum y sus valores.

template<typename E>
void process(E a)
{
  int result[];
  int n = EnumToArray(aresult0USHORT_MAX);
  Print(typename(E), " Count="n);
  for(int i = 0i < ni++)
  {
    Print(i" "EnumToString((E)result[i]), "="result[i]);
  }
}

Como enumeración con fines de investigación, utilizaremos la enumeración integrada con los tipos de precio ENUM_APPLIED_PRICE. Dentro de la función OnStart, asegurémonos primero de que EnumToString produce cadenas como se ha descrito anteriormente. Así, para el elemento PRICE_CLOSE, la función devolverá la cadena «PRICE_CLOSE», y para el valor (ENUM_APPLIED_PRICE)10, que obviamente está fuera de rango, devolverá «ENUM_APPLIED_PRICE::10».

void OnStart()
{
   PRT(EnumToString(PRICE_CLOSE));            // PRICE_CLOSE
   PRT(EnumToString((ENUM_APPLIED_PRICE)10)); // ENUM_APPLIED_PRICE::10
   
   process((ENUM_APPLIED_PRICE)0);
}

A continuación, llamamos a la función process para cualquier valor convertido a ENUM_APPLIED_PRICE (o a una variable de ese tipo) y obtenemos el siguiente resultado:

ENUM_APPLIED_PRICE Count=7
0 PRICE_CLOSE=1
1 PRICE_OPEN=2
2 PRICE_HIGH=3
3 PRICE_LOW=4
4 PRICE_MEDIAN=5
5 PRICE_TYPICAL=6
6 PRICE_WEIGHTED=7

Aquí vemos que se definen 7 elementos en la enumeración, y la numeración no empieza por 0, como es habitual, sino por 1 (PRICE_CLOSE). Conocer los valores asociados a los elementos permite en algunos casos optimizar la escritura de algoritmos.