MT4 EAの作り方 ランダムエントリーにマーチンゲール法を組み込む
マーチンゲール法はギャンブルの世界では昔から有名な手法で、
簡単にいえば、負けたら倍掛けにする手法で、負けた分を1回で取り戻すというものです。
資産が無制限にあれば絶対に負けない手法ではありますが、連敗が続くと掛ける金額がとても大きくなります。
どうしても損大利小になってしまうので、個人的にはあまり好きな手法ではありません。
ですが、今回は実験したいことがあり、コードを書いてみました マーチンゲール法を自分のEAに組み込みたい方は参考にしてみてください。
ランダムエントリーにマーチンゲール法を組み込んだEA
作ったEAはこちらからダウンロードしてくださいrandom_martin.zip
ロット数を出す関数は、詳解 MT4 様を参考にさせてもらいました。
今回作ったEAは以前に作成した、ランダムエントリーのEAを流用しています
以前の記事はこちら
これが今回のコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
//+------------------------------------------------------------------+ //| random_martin.mq4 | //| fxzeniken | //| https://fx.zeniken.net | //+------------------------------------------------------------------+ #property copyright "fxzeniken" #property link "https://fx.zeniken.net" #property version "1.00" #property strict //--- input parameters input double BaseLots=0.1; input double M_bairitu=2; input int M_max=2; input int Slippage=30; input int SL=50; input int TP=50; input int MagicNo=002; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //--------決済用独自関数-------------------------------- void Kessai() { //ポジションの数だけループを回す for(int i=0; i<OrdersTotal(); i++) { //オーダーセレクトでエラーが出た場合ループを抜ける if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; //買いポジションを持っていた場合 if(OrderType()==OP_BUY) OrderClose(OrderTicket(),OrderLots(),Bid,3,Orange); //売りポジションを持っていた場合 if(OrderType()==OP_SELL) OrderClose(OrderTicket(),OrderLots(),Ask,3,Orange); break; } } //決済関数ここまで----------------------------------------------- //---------マーチンゲールロットサイズ計算------------------------------- double Martin(double BaseLots,double M_bairitu,int M_max) { int renpai=0; for(int i= OrdersHistoryTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) { if(OrderMagicNumber()==MagicNo && OrderSymbol()==Symbol()) { if(OrderProfit()<=0)renpai++; else if(OrderProfit()>0)break; } } } if(renpai>=M_max)renpai=M_max; double Lots= BaseLots*MathPow(M_bairitu,renpai); return(Lots); } //--マーチンロットサイズ---------------------------------------------------- //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- double Lots= Martin(BaseLots,M_bairitu,M_max); int ent =MathRand() %2; //Buy or Sell if(OrdersTotal()==0 && ent==0) // 乱数が0の場合買いオーダーを出す { OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,Ask-(SL*Point),Ask+(TP*Point),"buy",MagicNo,0,Blue); } if(OrdersTotal()==0 && ent==1)//1の場合は売りオーダー { OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,Bid+(SL*Point),Bid-(TP*Point),"sell",MagicNo,0,Red); } } //+------------------------------------------------------------------+ |
エントリー部とは別に、エントリーに使用するロットサイズを計算する関数を作りました。
以下がコードです
引数のBaseLotsは、最初のロットサイズ、M_bairituは負けた時にポジション数を何倍にするか、M_maxは最大何回までマーチンゲール法を使うかを指定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//---------マーチンゲールロットサイズ計算------------------------------- double Martin(double BaseLots,double M_bairitu,int M_max) { int renpai=0; for(int i= OrdersHistoryTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) { if(OrderMagicNumber()==MagicNo && OrderSymbol()==Symbol()) { if(OrderProfit()<=0)renpai++; else if(OrderProfit()>0)break; } } } if(renpai>=M_max)renpai=M_max; double Lots= BaseLots*MathPow(M_bairitu,renpai); return(Lots); } |
マーチンゲールのロットサイズ計算の流れ
マーチンゲール法を使う場合、まず現在が何連敗しているかを調べなければいけません。
このコードではrenpai変数に何回連敗しているかを格納します。
OrdersHistoryTotal()という、今までの決済済みの注文の合計数を返す関数を使い、古い決済から新しい決済注文に向けて検索をかけます。
1 2 3 4 5 6 7 8 9 10 11 |
for(int i= OrdersHistoryTotal()-1; i>=0; i--) { if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true) { if(OrderMagicNumber()==MagicNo && OrderSymbol()==Symbol()) { if(OrderProfit()<=0)renpai++; else if(OrderProfit()>0)break; } } } |
ループ内ではOrderSelectをMODE_HISTORYとし過去のオーダーを選択して、
マジックナンバーと通貨が一致するかを調べ、トレードがマイナスならrenpaiカウンタを+1
プラストレードならループを終了させます。
OrderProfitは選択した取引の損益を取得することができます。
1 2 3 |
if(renpai>=M_max)renpai=M_max; double Lots= BaseLots*MathPow(M_bairitu,renpai); return(Lots); |
ループ終了後 renpai数が マーチンを行う最大数を超えていた場合、最大数を変数renpaiに格納します。
実際のポジション数はべき乗で計算するので、MathPow関数を使用します。
今回は、ポジションを増やす倍率を連敗数分乗算します。
バックテスト結果
まずはこちらはマーチンの最大回数を5回にしたものです
典型的な利少損大な動きです。
お次は最大回数10回にしてみました。 1万通貨単位で口座残高100万でスタートしてもすぐ破産だったので、1000万円スタートですが結局は証拠金不足でポジションが持てなくなりました。
いろいろ実験してみてください