モンテカルロ法の検証

   2020/03/12

モンテカルロ法は自動売買(EA)では比較的よく使われる「マーチンゲール」系の手法ですが、マーチンゲールよりもロットサイズの増加が少ない手法になります。

ただし、マーチンゲールでは「一発で損失を取り返す」ことが可能ですが、モンテカルロでは損失を取り返すのに時間がかかる傾向にあります。

モンテカルロ法のルール(FXアレンジ)

まずは紙に1,2,3を書きます。

そして「両端」を足した数をロット数とします。最初は4です。(1を1万通貨とした場合、4万通貨。)

損切りと利食いは同じ広さ(pips)にしてエントリー、勝敗を確認します。

勝ったら両端の数字を2つずつ消します。負けたら負けた時の数(ロット数)を右に書き加えます。

数字が1個以下になったら終了です。また1,2,3から開始します。

1回のセッションをすべて終了させると必ずプラス収支で終わることが可能です。

EAを作って検証してみる

単純に「ドル円相場」で「買い」だけするシステムを作ります。

※基本的には昨日投稿した「2連勝法・31法の検証」と同じです。

2連勝法と違って、紙に書く数字が固定されていないため、空の配列を用意しました。おそらく50もあれば十分でしょう。

int LotsArray[50];

この配列を初期化して使います。

void InitLotsArray()
{
   for(int i=0;i<50;i++)
   {
      LotsArray[i] = 0;
   }
   LotsArray[0] = 1;
   LotsArray[1] = 2;
   LotsArray[2] = 3;
   Lots = 4;
}

最初に0をセットした後で1,2,3を入れます。最初のロットは4になるので4も固定でセットしました。

勝敗判定は2連勝法と同じです。トレード履歴で最新のものの利益が0より大きいかどうかで判定するようにしています。

bool IsWinTrade()
{
   for(int i=OrdersHistoryTotal()-1; i>=0; i--)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
      {
         if(OrderMagicNumber() == Magic)
         {
            if(OrderType() == OP_BUY || OrderType() == OP_SELL)
            {
               if(OrderProfit() > 0) return true;
               else return false;
            }
         }
      }
   }
   OutputError("No trade history.");
   return false;
}

もっとも厄介な「勝敗の結果を見て配列の中身を操作する」処理を以下のようにしました。関数の引数isWinはIsWinTrade関数で返ってきた勝敗を渡しています。

void SetLots(bool isWin)
{
   if(isWin)
   {
      //左端の配列を2つ消す
      for(int i=0;i<48;i++)
      {
         LotsArray[i] = LotsArray[i+2];
      }
      
      //右端の配列を2つ消す。
      for(int i=2;i<50;i++)
      {
         if(LotsArray[i] == 0)
         {            
            if(i<4)
               InitLotsArray();  //残りの数列が3つ以下の場合には終了
            else
            {
               LotsArray[i-1] = 0;
               LotsArray[i-2] = 0;
            }
            break;
         }
         OutputError("Array deletion failed.");
      }
   }
   else
   {
      //配列の最後に現在Lotsを入れる
      for(int i=0;i<50;i++)
      {
         if(LotsArray[i] == 0)
         {
            LotsArray[i] = Lots;
            break;
         }
         OutputError("Failed to insert into array.");
      }
      
      //配列の両端の数値を加算、Lotsに設定
      Lots = LotsArray[0];
      for(int i=0;i<50;i++)
      {
         if(LotsArray[i] == 0)
         {
            Lots += LotsArray[i-1];
            break;
         }
         OutputError("Right array not found.");
      }
   }
}

大丈夫‥ですかね?間違っていないと良いのですが‥。
※「残りの数列が3つ以下の場合には終了」としているのは「2つ消す前の状態」で3つ以下だからです。

最後にロットの計算ですが、今回は単純に100で割っています。(1を0.01Lotsとして発注します)

double lots = (double)Lots / 100;

だいたいこんな感じかと思います。

それではバックテストを実行してみましょう。

バックテスト

ストップは100pipsとしました。

期間は2000年から2020年3月10日、通貨ペアはUSDJPY、スプレッドは5としました。時間軸は無関係です。(発注して放置するだけのシステム)

僅かに損失が出ています。これだけ見ると2連勝法の方が良さそうに見えますが‥。

2連勝法と同じようにストップロスを最適化してみます。

ほとんどのパターンで利益が出せました。その代わり、ドローダウンがかなり大きくなってしまうという問題はありますが‥。

十分な資金で運用するのであれば「まず確実に利益が出せる」EAになりました。

20年かけて1万ドルが1万2千ドルになる‥というのは資金効率的にはかなり残念ではありますが(苦笑)

モンテカルロ法では勝率50%でなくても良い

3回に1回の勝率で最も効果を発揮する‥らしいです。試しに利食い幅を損切り幅より広げて勝率を下げる代わりに利益を増やしてみます。

追加したパラメーターはTakeProfitRateでこの値が1.0の場合に利食いと損切りが同じになります。2.0だと丁度2倍でおそらく勝率は「3回に1回勝てるくらい」になるはずです。

TakeProfit = (int)(StopLoss * TakeProfitRate);

ストップロスを180pipsとして、TakeProfitRateを1.0~3.0の間で最適化してみました。

思った以上に利益が出ています。ドローダウンもかなり大きくなりますが‥。

もしかすると「使ってみようかな?」と思う方もいらっしゃるかもしれません。

ただし、TakeProfitRateが2.5を超えると破産してしまいます。相場の状況次第では2.0くらいでも1万ドルが無くなってしまうケースがあるかもしれません。(ロットはこれ以上小さくできません。最小値の0.01を基準にしていますので‥)

まとめ

単純に買うだけのシステムではさすがに使う気になりませんが、もっと良い条件下で使用するのであれば有用な手法になりそうです。

少なくとも「マーチンゲール方式」よりはずっと良いのではないでしょうか。

作ったソースコードを置いておきます。遊んでみたい方はどうぞご自由に‥。

MonteCarlo.zip

パラメーター

Magic = マジックナンバー
StopLoss=ストップロス
TakeProfitRate=テイクプロフィット(ストップロスとの割合)

ご注意

そのままリアル口座で動かす人はいないと思いますが、念の為‥

「このプログラムを利用して発生したいかなる損害も当方は責任を負いかねますのでご了承ください」

ウィナーズ法の検証に続きます

  • このエントリーをはてなブックマークに追加
  • Pocket

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。