随机数生成

交易中的很多算法要求生成随机数。MQL5 提供了两个函数可用于初始化然后轮询伪随机整数生成器。

为获得更好的“随机性”,可以使用 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 函数称为转换。它基于之前的 Xp 状态计算 Xn 生成器的新内部状态。

Gf 函数使用新的内部状态生成 MathRand 函数将返回的另一个“随机”值。

在 MQL5 中,这些公式按以下方式实现(伪代码):

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

建议传递 GetTickCountTimeLocal 函数作为 seed 值。

int MathRand() ≡ int rand()

该函数返回一个范围从 0 到 32767 的伪随机整数。生成的数字序列各不相同,具体取决于调用 MathSrand 完成的开端初始化。

该生成器的用法示例在 MathRand.mq5 文件中提供。它计算关于生成的数字在给定数量的子范围(组)上的分布统计。理想情况下,应获得均匀的分布。

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

三次运行的结果示例(每次将获得一个新序列):

 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