MQL4のMathRand()の計算式は・・・

最悪のアフターエピソードというのはね。
長いことブログを書かないでいると、書き方すら忘れてしまうことだったんだ。
URLのリンクに title 属性付けるときはどう書くんだっけ?
引用部分を囲むのは > or >> or >| ?
画像のサイズ指定はどう書くの?
はてな記法なんて、ブログでしか使わないから、毎日書いていないと直ぐに忘れてしまう。(涙)


そんな時のために「はてな記法壁紙があるじゃないか!」と言われても、そこまでするモチベーションが湧かないよ...。(泣)




・・・とまぁ、本題に入る前に一発ネタを入れたほうが良いかなって書いてみたけど、これ以上続けるともっと哀しくなってゆくので、止めておきます。
さて、昨日紹介した、ランダムウォークのチャート作成スクリプトによる人工チャートと、実際の為替チャートとの違いは、いろいろあるのでしょうけど、分かりやすいところでは、指標発表時特有の動きの有無でしょうか。
価格が突然大きく動くジャンプ拡散過程のような要素が計算式に入っていないと長期間で見たとき少し違和感があります。




ただ、それ以前に、MQL4の MathRand() で乱数シミュレーションするのはどうよ? と思ったので、MathRand()の計算式を調べました。

int start()
  {
   MathSrand(100);
   MQ4Rand(100);// 同一のseedを設定する。
   for(int i=0;i<10;i++)
      Print(i+ " MathRand="+MathRand()+" MQ4Rand="+MQ4Rand());
  }
//+------------------------------------------------------------------+
int MQ4Rand(int seed = -1){
   static int x = 1;//Seed
   if(seed != -1){x = seed; return(0);}
   x = x*214013 + 2531011; // N倍して、Mを足すだけ....
   return((x >> 16) & 32767);
}

↑このスクリプトを実行した結果が、下図です。

MathRand と MQ4Rand が同一の結果を返していますので、計算式は合っていると思います。
この解説によると、これは線形合同法による乱数で、周期は 2147483648 だそうです。最下位ビットの周期は131072 になります。


つまり、、乱数値を2で割って余りを求めた場合、131073回目以降は同じ並びになるということです。

for(int i=1;i<=131072+10;i++){
   int x = MathRand();
   if(i<=10 || i>131072)
      Print(i+" mod="+ DoubleToStr(MathMod(x,2),0));
}

↑その確認用コードの結果が下図です。

見事に繰り返していますね。
MathRand の計算式が、実質わずか2行であることに驚き(2行なのに計算結果が想像つかない..)、その周期が想像よりはるかに短いという..。これこそが、最悪のアフターエピソードです。苦笑。


まとめ

『Expert advisor』は、おもしろい! で紹介されている、GSL(The GNU Scientific Library) であれば、デフォルト設定でメルセンヌ・ツイスタ(Mersenne twister)を乱数発生器として、 MQL4から使えるので、そちらを使いましょう..。