Генерация случайных чисел

Многие алгоритмы в трейдинге требуют генерации случайных чисел. MQL5 предоставляет 2 функции, позволяющие инициализировать и затем опрашивать генератор псевдослучайных целых чисел.

Для получения более качественной "случайности" можно использовать поставляемую с MetaTrader 5 библиотеку Alglib (см. MQL5/Include/Math/Alglib/alglib.mqh).

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

Функция устанавливает некое начальное состояние генератора псевдослучайных целых чисел. Её следует вызывать однократно перед началом алгоритма. Сами случайные значения следует получать с помощью последовательного вызова функции MathRand.

Инициализация генератора одним и тем же значением seed позволяет получать воспроизводимые последовательности чисел. Значение seed не является первым случайным числом, полученным из MathRand.

Генератор поддерживает некое внутреннее состояние, которое в каждый момент времени (между обращениями к нему за новым случайным числом), характеризуется целочисленным значением: оно доступно из программы как встроенная переменная uint _RandomSeed. Именно это начальное значение состояния и устанавливает вызов MathSrand.

Работа генератора при каждом вызове MathRand описывается двумя формулами:

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

Функция Tf назывется переходной (transition) функцией: она вычисляет новое внутреннее состояние генератора Xn, основываясь на предыдущем состоянии Xp.

Функция Gf генерирует очередное "случайное" значение, которое вернет функция MathRand, пользуясь для этого новым внутренним состоянием.

В MQL5 эти формулы реализованы следующим образом (псевдокод):

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

Рекомендуется передавать в качестве seed значение функции GetTickCount или TimeLocal.

int MathRand() ≡ int rand()

Функция возвращает псевдослучайное целое число в диапазоне от 0 до 32767. Последовательность генерируемых чисел меняется в зависимости от начальной инициализации, выполненной с помощью вызова MathSrand.

Пример работы с генератором приведен в файле MathRand.mq5. В нем производится подсчет статистики по распределению генерируемых чисел по заданному количеству поддиапазонов (корзинок). В идеале мы должны получить равномерное распределение.

#define LIMIT 1000 // количество попыток (генерируемых чисел)
#define STATS 10   // количество корзинок
   
int stats[STATS] = {}; // подсчет статистики попаданий в корзинки
   
void OnStart()
{
   const int bucket = 32767 / STATS;
   // сброс генератора
   MathSrand((int)TimeLocal());
   // повторяем эксперимент в цикле
   for(int i = 0i < LIMIT; ++i)
   {
      // получение нового случайного числа и обновление статистики
      stats[MathRand() / bucket]++;
   }
   ArrayPrint(stats);
}

Пример результатов для трех запусков (каждый раз будем получать новую последовательность):

 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