朝スキャEAにマーチンゲールを実装するカスタマイズ【コピペで使用可能】
前回の記事では、単純な時間制限と逆張りのロジックに対して、トレーリングストップを実装することでどのような影響が出るのかを実験しました。
今回の記事では、「トレーリングストップ」ではなく「マーチンゲール」を実装することで、どのような結果になるのかを確認します。
マーチンゲールとは、主にカジノの攻略法として編み出された手法です。
手法は単純で、勝つまでベッド額を倍々にしていくというものです。
FXにおけるマーチンゲールでは、ロット数を2倍にしていくというのが一般的です。
マーチンゲールのメリットとデメリット
マーチンゲールのメリットとデメリットは、以下の通りです。
メリット
メリットは、それまでの負け分を一気に取り戻せるという点です。通常であれば、1回の負けは2回勝たなければ勝ち越すことはできませんが、マーチンゲールでは1回勝つだけで勝ち越せます。
デメリット
デメリットは、負け続けるとあっという間に資金が尽きてしまう点です。FXは、各トレードが独立した事象であり、連続で負けてしまうことがあり得ます。
そのため、初めに十分な資金を用意する必要があります。
例えば初回エントリーが0.01ロットで10連敗した場合、11回目のロット数は10.24ロットとなってしまいます。
マーチンゲールは資金が尽きると一気に破綻してしまうのです。
FXにおけるマーチンゲールの注意点
マーチンゲールは「1回勝つだけで勝ち越せる」と説明しましたが、これは損切り幅と利確幅が同じ場合に限ります。
損切り幅が利確幅に比べて大きい場合は、1回勝つだけでは勝ち越せません。
FXの場合、スプレッドやエントリータイミングの差などの要因もあり、一概に2倍すれば良いという単純な計算は避けるべきです。
仕様
まずは前回作成したEAの仕様をまとめます。
エントリー
時間が日本時間早朝かつRSIが売られすぎラインを下回ったら、買いエントリー
時間が日本時間早朝かつRSIが買われすぎラインを上回ったら、売りエントリー
決済
利確価格と損切り価格による決済
その他
著作権を「OANDA」に設定
スリッページ、スプレッドによってエントリーを制限する
ポジションは同時に1つのみ保有するようにする
マジックナンバーとロット数を変更できるようにする
以上です。
今回はマーチンゲールの回数を設定できるパラメータを追加します。
このパラメータの値が「3」の時、最大で3回までロット数を2倍にしていきます。
その後に4連敗した場合は2倍せず、そのままの値でエントリーを行うようにします。
EAを作成する
プログラムは「5.朝スキャのEAを作ってみよう」をもとに作成するので、前回までの内容は割愛し、今回追加する機能のみ紹介します。
フィールド
input int MAGICMA = 23198721; // マジックナンバー
input double Lots =0.01; // 1ロット十万通貨単位
input int Slippage = 4; // エントリー見送りスリッページ
input double MaxSpread = 5; // エントリー見送りスプレッド
input double TakeProfit = 10.0; // 利益確定幅(pips)
input double LossCut = 20.0; // 損切確定幅(pips)
input int RSIPeriod=6; // 期間
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 適用価格
input int UpLine = 85; // 上の線
input int DownLine = 25; // 下の線
input int TradeTime = 0; // トレードを行う時間
//マーチンゲール設定
input int NumMartin = 5; // マーチンゲールで倍々する最大回数
前回のパラメータの最後にNumMartinという変数を追加します。
OnTick関数
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
int loseCount = 0; //負けカウント
for( int i= OrdersHistoryTotal()-1; i>=0; i-- ){ //①
if( OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == true && OrderMagicNumber() == MAGICMA && OrderSymbol() == Symbol() ){
if( OrderProfit() <= 0 ){ //②
if(loseCount >= NumMartin)break; //③
loseCount++; //②
}
else{
break;
}
}
}
double lot = Lots * MathPow(2, loseCount); //④
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(lot); //⑤
}
OnTick関数です。
- ① マーチンゲール時のロット数は、直近で何回トレードに負けたかによって決まります。
そのため、OnTick関数のはじめに過去のトレードで何回負けたのかを調べます。 - ② 「OrderProfit() < =0」という条件によって、損益が0よりも小さければ変数「loseCount」をインクリメント(+1)します。
- ③ loseCountの値がパラメータNumMartinの値よりも大きくならないようにします。
- ④ loseCountの回数でロット数を計算します。
MathPow関数は第1引数の値を第2引数だけべき乗した値を返す関数です。 - ⑤ CheckForOpen関数に引数として渡します。
CheckForOpen関数
void CheckForOpen(double int lot)
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage, Bid - TrailWidth * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage, Ask + TrailWidth * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}
今回、ロット数はOnTick関数内で計算しているので、引数でロット数を指定できるようにします。
受け取ったロット数はOrderSend関数の第3引数に指定するのを忘れないようにしましょう
バックテスト
今回作成したマーチンゲールのEAと、前回作成した単ポジ型のEAのバックテスト結果を比較してみましょう。
条件は以下の通りです。
- 通貨ペア:GBPUSD
- 時間足:5分足
- 期間:2018年1月1日~2023年1月1日の5年間
- スプレッド:15固定
単ポジ型
マーチンゲールのEA
グラフを見ると下の「残量」に緑色のバーが表示されています。
これはエントリー時のロット数です。
つまり緑色のバーが長い部分は、連敗している部分です。
性能としては、取引回数、プロフィットファクター、勝率といった点で単ポジ型を上回る結果となりました。
ただ、ロット数が上下するので、最大ドローダウンについては単ポジ型のものよりも大きい結果となりました。
注意点
今回のバックテストは、スプレッドを固定で行っています。
日本時間早朝の相場が緩やかになる時間帯は、スプレッドが広がりやすいという特徴があります。
実運用を行うにはスプレッド制限をかけるなど対策が必要です。
マーチンゲールは自己資金を一瞬で失ってしまうリスクがあるので、運用には十分注意してください。
プログラム全文
#property copyright "Copyright(C) 2023, OANDA"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
input int MAGICMA = 23198721; // マジックナンバー
input double Lots =0.01; // 1ロット十万通貨単位
input int Slippage = 4; // エントリー見送りスリッページ
input double MaxSpread = 5; // エントリー見送りスプレッド
input double TakeProfit = 10.0; // 利益確定幅(pips)
input double LossCut = 20.0; // 損切確定幅(pips)
input int RSIPeriod=6; // 期間
input ENUM_APPLIED_PRICE RSIAppliedPrice = PRICE_CLOSE; // 適用価格
input int UpLine = 85; // 上の線
input int DownLine = 25; // 下の線
input int TradeTime = 0; // トレードを行う時間
//マーチンゲール設定
input int NumMartin = 5; // マーチンゲールで倍々する最大回数
double dSpread;
int OnInit()
{
return(INIT_SUCCEEDED);
}
void OnTick()
{
dSpread = (Ask - Bid) / (Point * 10);
int loseCount = 0; //負けカウント
for( int i= OrdersHistoryTotal()-1; i>=0; i-- ){
if( OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) == true && OrderMagicNumber() == MAGICMA && OrderSymbol() == Symbol() ){
if( OrderProfit() <= 0 ){
if(loseCount >= NumMartin)break;
loseCount++;
}
else{
break;
}
}
}
double lot = Lots * MathPow(2, loseCount);
if(CalculateCurrentOrders()==0 && dSpread < MaxSpread) CheckForOpen(lot);
}
void CheckForOpen(double lot)
{
int res;
double RSI = iRSI(Symbol(), 0, RSIPeriod, RSIAppliedPrice, 1);
if(TradeTime == TimeHour(Time[1]))
{
if(RSI < DownLine)
{
res=OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage, Bid - LossCut * Point * 10, Ask + TakeProfit * Point * 10,"", MAGICMA, 0, Red);
}
if(RSI > UpLine)
{
res=OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage, Ask + LossCut * Point * 10, Bid - TakeProfit * Point * 10, "", MAGICMA, 0, Blue);
}
}
}
int CalculateCurrentOrders()
{
int positions = 0;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
{
positions++;
}
}
return positions;
}
EA(自動売買)を学びたい方へオススメコンテンツ
OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。
本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。