ブログトップ 記事一覧 ログイン 無料ブログ開設

とあるMetaTraderの備忘秘録 RSSフィード Twitter

忙しいです。ネタもないし・・・

2012-08-18

MQL4でXorShiftによる疑似乱数生成。-2147483648 > -2147483647-1 という不思議。

真面目な用途での乱数生成は、メルセンヌ・ツイスターが推奨で、MT4 であれば これ、Excel であれば、Excel乱数生成アドインがあります。


ただ、どうしても MQL4のみで、MathRand() より良さそうな乱数を使いたい時のために、XorShift による実装を用意しました。

int XorShiftRand(int seed = 123456789) { 
  static int x = 123456789;
  static int y = 362436069;
  static int z = 521288629;
  static int w = 88675123; 
  if(seed != 123456789) x = seed;
  
  int t;
 
  t = x ^ (x << 11);
  x = y; y = z; z = w;
  w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 
  return(w);// w = -2147483648~2147483647
}

使い方は、

XorShiftRand(GetTickCount());

で、最初に seedを設定し、以降は、XorShiftRand() で、-2147483648〜2147483647 の整数乱数を得ることができます。


ちなみに、1億回実行した時の実行時間は以下の傾向です。

関数実行時間(ms)
MathRand3479
XorShiftRand7660
gsl_rng_uniform16724

極端に遅くなることは無いようです。




-2147483648 > -2147483647-1 という不思議。

実用性はさておき、XorShift を調べていて気づいたのが MQL4 の不思議な挙動です。

int a = -2147483648;
int b = -2147483647-1;
if(a > b) Print("a > b");// TRUE 

↑ a と b は等しいはずなのに、a が大きくなります。


この現象は、int 型の最小値 -2147483648 のときのみ起こる・・・と信じたいところですが、未確認です。

int a = -2147483648.0; // 実数表記

int a = 0x80000000; // 16進表記

↑変則的に、このように宣言すれば、a == b が成立します。

これは苦肉の策ですが、、変数の型で定義される末端の数値を扱うときは注意しましょう。。orz







ランダムチャートのその後。

f:id:fai_fx:20120818121103g:image

出来高に凶悪なコーシー分布のノイズを加えて、高騰/急落を再現してみました。

1.5秒毎にローソク足1本を追加して自動更新する機能も追加しました。

乱数に GSL も使えるようにしました。

http://ux.getuploader.com/fai_fx/download/318/RandomChart.zip

あくまでも、ベースとなる動きはコイントス方式のランダムウォークで、横軸=時間軸を出来高の調整で歪めているだけです。

実験用途や、週末に動くチャートを見たい時に活用ください。

bighopebighope 2012/08/18 18:31 勝手にお邪魔させて頂きます。
GSLを使用するのであれば、乱数を用いた分岐に、ベルヌーイ分布乱数を使用すると面白いかもしれません。
ベルヌーイ分布乱数は、0と1を指定した確率で発生させてくれる物の様です。
これを使うと、擬似的なトレンド(0を多く発生させるとか)を作ることも可能です。
ランダムウォークではなくなってしまいますが。。。(遠い目

使い方は、ヘッダーに以下のコードを追加し。。(初めから入れとけよ。。。orz
////////////////////////////////////////////////////////
//確率p のベルヌーイ分布にしたがって0 または1 を返す。
int gsl_ran_bernoulli (int r, double p);
////////////////////////////////////////////////////////
後は、ほかの関数と同じです。
例)
// if(MathRand()>=16384){ // MathRand=0~32767
if(gsl_ran_bernoulli (r,0.5)>0.5){ //add
close = close + _point*bi;
}else{
close = close - _point*bi;
}

試してみるとわかりますが、0.51とか0.49など1%の偏りがあるだけでハッキリしたトレンドが見られるようになります。

ということで、失礼します。

やぶたろうやぶたろう 2012/08/19 07:07 fai様
はじめまして、いつも勉強させていただいてます。
4ヶ月ほど前にバイナリーオプションからこの世界に足を入れ、現在もがいている状態であります。

さて、2ヶ月位前からお願いしてみようかどうしようか…と今日まできましたが、もしかしたらまったくお門違いな要望なのかもと思いつつ、コメントを書かしていただいてます。


最終的な目的をすべて書き出しますので、そのなかでもしfai様の意に反せずご教授いただけることがありましたら幸いです。


(やりたいこと)

A:連続する陰線(陽線)の本数をだしたい(手で数えてましたがなかなかです)
B:その上で、反転する確率を求めたい。逆張りエントリーの為
C:もっというと、値動き幅と連続本数の割合(これが統計として機能するかは別として)
D:さらにその確率に従って、どのような購入比率が1番ベストなのか。

本数の部分は、やはりエクセルなどでデータにしてからということになるのでしょうか。

試行錯誤のうえ、1分足→10分足に変換→日付、時間、最安値、最高値をはぶいたうえで、
値動きゼロ、プラス、マイナスにわけて同セル行内に表示させるところまではできましたが、肝心な連続する足を数える方法がわからず止まっています。(しかも、自分のやったことだけにデータが信頼出来ない…)


ちょろっとかぞえた本数を元に、先日OKWEBというサイトで下記のような質問をだしてみました。

スタートの自己資金は5万とし、次に赤(黒)を当てる単純な賭けで、
最も効率の良い賭け方をどなたか教えてくださいませ。

赤か黒が連続してくる回数を下記に出しました。
赤黒のサンプル合計 678回

赤もしくは黒が連続した回数

1=355 ←単体の回数です。
2=184 ←上記の本数を含んでいます(以下同じ)
3=79
4=33
5=17
6=7
7=1
8=2
以下なし

※考慮する点
1:当たった時のペイアウト率は1.8倍です。
2:スタート時の掛金を1000円として、上限は5万円。
3:100回プレーする(1000回でもいいですが)として、
  どの連続回数からスタートして、何回までをいくら賭けるのが効率いいのか。

たとえば100回終わった時点での勝ち金が1番多いというのがわかりやすいです。

知りたいのは、当たるまでどこまでも賭け続けるべきなのか、もしくは4連続以降は
賭けずにそのセットは負けにしたほうがいいのか・・・。
あるいは、6回まではやったほうが効率的にはいいのか、などなど。

そして、連続本数によっての賭け金比率等。


回答は、
1:そんな掛けはやめたほうがいい。某カメラ会社の偉いさんの二の舞になる
2:複雑すぎて、タダではできない。

たしかにおっしゃるとおりなのかもしれませんが、もしなにかご教授あれば宜しくお願いします。

ちなみにエントリータイミングが自由な点と、完売がないのを考慮してFXTDでやってます。
ベッティングはともかくとして、連続本数の割合計算がすぐにできれば、1時間足あるいは日足、そしてドル円以外でもエントリーできそうなんですよね。

では、今後もブログを楽しみにしています。お邪魔しました。m(__)m

矢吹

TigerTiger 2012/08/19 10:24 こんにちは(^^) 以前より、毎回のお話し、とても参考にさせていただいています。

AutoHotkeyをはじめ、faiさんの作られたものをいろいろ使わせていただいています。
以前、値幅を固定できるスクリプトを作っていただいていましたが、
画面が少ないので、複数時間の表示が厳しく、一画面のなかで、いつも同じ値幅で表示
できないかなぁと常々おもっており、
決めた値幅をMAX、Min固定値でなく、画面の幅を決めて(例えば50pipsとか)で、
スクロールしていくものは、出来ませんでしょうか?

お手数お掛けしますが、ご検討いただけると幸いです。

ふぁんふぁん 2012/08/20 15:45 慧眼には驚くばかりです。

さて、試しに、

int a = -2147483648;
Print("a");

としたら、何が出たと思われますか?
なんと、
-2147483647
です。ちなみに、

int b = -2147483647-1;
Print("b");

では、

-2147483648

になりました。
ご指摘のように、この現象は -2147483648 にまつわるひとつのバグ?ですね。

次のバージョンで修正されるかな???

ふぁんふぁん 2012/08/20 22:48 訂正です。
MQL以上に、私のプログラム?に重大なバグが潜んでおりました。
正しくは、以下の通りです。オソマツ。

int a = -2147483648;
Print(a);

int b = -2147483647-1;
Print(b);

投稿したコメントは管理者が承認するまで公開されません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/fai_fx/20120818/1345263440
Connection: close