Generación de números aleatorios

Muchos algoritmos de trading requieren la generación de números aleatorios. MQL5 proporciona dos funciones que inicializan y luego sondean el generador de enteros pseudoaleatorios.

Para obtener una mayor «aleatoriedad», puede utilizar la biblioteca Alglib disponible en MetaTrader 5 (véase MQL5/Include/Math/Alglib/alglib.mqh).

void MathSrand(int seed) ≡ void srand(int seed)

La función establece un estado inicial del generador de enteros pseudoaleatorios. Debe llamarse una vez antes de iniciar el algoritmo. Los valores aleatorios propiamente dichos deben obtenerse mediante la llamada secuencial de la función MathRand.

Inicializando un generador con el mismo valor seed se pueden obtener secuencias de números reproducibles. El valor seed no es el primer número aleatorio obtenido de MathRand. El generador mantiene un cierto estado interno, que en cada momento del tiempo (entre llamadas a él para un nuevo número aleatorio) se caracteriza por un valor entero que está disponible desde el programa como la variable uint integrada _RandomSeed. Es este valor de estado inicial el que establece la llamada a MathSrand.

El funcionamiento del generador en cada llamada a MathRand se describe mediante dos fórmulas:

Xn = Tf(Xp)
R = Gf(Xn)

La función Tf se denomina transición. Calcula el nuevo estado interno del generador Xn a partir del estado anterior Xp.

La función Gf genera otro valor «aleatorio» que devolverá la función MathRand, utilizando para ello un nuevo estado interno.

En MQL5, estas fórmulas se implementan de la siguiente manera (pseudocódigo):

Tf_RandomSeed = _RandomSeed * 214013 + 2531011
GfMathRand = (_RandomSeed >> 16) & 0x7FFF

Se recomienda pasar la función GetTickCount o TimeLocal como el valor seed.

int MathRand() ≡ int rand()

La función devuelve un entero pseudoaleatorio en el rango de 0 a 32767. La secuencia de números generados varía en función de la inicialización de apertura realizada al llamar a MathSrand.

En el archivo MathRand.mq5 se ofrece un ejemplo de trabajo con el generador. Calcula estadísticas sobre la distribución de los números generados en un número determinado de subrangos (cestas). Lo ideal sería obtener una distribución uniforme.

#define LIMIT 1000 // number of attempts (generated numbers)
#define STATS 10   // number of baskets
   
int stats[STATS] = {}; // calculation of statistics of hits in baskets
   
void OnStart()
{
   const int bucket = 32767 / STATS;
   // generator reset
   MathSrand((int)TimeLocal());
   // repeat the experiment in a loop
   for(int i = 0i < LIMIT; ++i)
   {
      // getting a new random number and updating statistics
      stats[MathRand() / bucket]++;
   }
   ArrayPrint(stats);
}

Ejemplo de resultados para tres ejecuciones (cada vez obtendremos una nueva secuencia):

 96  93 117  76  98  88 104 124 113  91
110  81 106  88 103  90 105 102 106 109
 89  98  98 107 114  90 101 106  93 104