マーチンゲールは、初期ロット数から始めて、勝てば初期ロット数のままトレードを続けますが、負けた場合は、次のトレードのロット数を前回の2倍にする方法です。

毎回のトレードでの利益と損失の大きさが等しければ、必ず負けを取り戻せる博打の必勝法ともいえるものです。ただし、負けが連続すると、ロット数が2倍、4倍、8倍と倍々ゲームで増えていくリスクもあります。

ここでは、マーチンゲールにロット数の上限を定めて、それ以上には増えない安全策をとった方法を考えてみます。

コード

//共通ライブラリ
#include "LibEA.mqh"

//ティック時実行関数
void Tick()
{
   int sig_entry = EntrySignal(); //仕掛けシグナル
   //ポジション決済
   MyOrderCloseMarket(sig_entry, sig_entry);
   //ロット数算出
   double lots = CalculateLots();
   //成行注文
   MyOrderSendMarket(sig_entry, 0, lots);
}

input int BBPeriod = 10;  //ボリンジャーバンドの期間
input double BBDev = 2.0; //標準偏差の倍率

//仕掛けシグナル関数
int EntrySignal()
{
   //1本前と2本前のボリンジャーバンド
   double BBUpper1 = iBands(_Symbol, 0, BBPeriod, BBDev, 0, PRICE_CLOSE, MODE_UPPER, 1);
   double BBLower1 = iBands(_Symbol, 0, BBPeriod, BBDev, 0, PRICE_CLOSE, MODE_LOWER, 1);
   double BBUpper2 = iBands(_Symbol, 0, BBPeriod, BBDev, 0, PRICE_CLOSE, MODE_UPPER, 2);
   double BBLower2 = iBands(_Symbol, 0, BBPeriod, BBDev, 0, PRICE_CLOSE, MODE_LOWER, 2);

   int ret = 0; //シグナルの初期化

   //買いシグナル
   if(Close[2] >= BBLower2 && Close[1] < BBLower1) ret = 1;
   //売りシグナル
   if(Close[2] <= BBUpper2 && Close[1] > BBUpper1) ret = -1;

   return ret; //シグナルの出力
}

input double InitialLots = 0.1; //初期ロット数
input double MaxLots = 1.6;   //最大ロット数

//ロット数算出関数
double CalculateLots()
{
   double lots;
   //前回が負けトレードの場合、ロット数を前回の2倍にする
   if(MyOrderLastProfit() < 0) lots = MyOrderLastLots()*2;
   else lots = InitialLots; //それ以外の場合、初期ロット数に戻す
   if(lots > MaxLots) lots = MaxLots; //最大ロット数に制限

   return lots; //ロット数の出力
}

説明

マーチンゲールに従ってロット数を算出する関数をCalculateLots()として定義します。これは、前回が負けトレードの場合、ロット数を前回のトレードに2倍にする関数です。

ここでは、共通ライブラリの[MyOrderLastProfit()](<https://www.notion.so/MyOrderLastProfit-bf32e9f9b954418f8d5cec9eca3b4733>)[MyOrderLastLots()](<https://www.notion.so/MyOrderLastLots-a7d692bf7b004b46a96665bba4d07a84>)を利用します。

前回の損益[MyOrderLastProfit()](<https://www.notion.so/MyOrderLastProfit-bf32e9f9b954418f8d5cec9eca3b4733>)がマイナスの場合、ロット数lots[MyOrderLastLots()](<https://www.notion.so/MyOrderLastLots-a7d692bf7b004b46a96665bba4d07a84>)の2倍にします。前回の損益が0以上であれば、ロット数を初期ロット数InitialLotsに戻します。

ただし、lotsが最大ロット数MaxLotsを超えた場合は、最大ロット数に制限します。

このように前回のポジション情報を利用する場合、注意することがあります。

[MyOrderSendMarket()](<https://www.notion.so/MyOrderSendMarket-3e0c92f431514dc6ba54b78b23c1afc6>)では、新しいシグナルが入った場合にポジションを決済して、すぐに新規にポジションを建ててしまいます。すると、前回のポジション情報から次のトレードのロット数を算出するCalculateLots()を組み込むことができないのです。

そこで、シグナルからポジションを決済する部分だけを別に行う必要があります。そのための関数が[MyOrderCloseMarket()](<https://www.notion.so/MyOrderCloseMarket-9e6b25d1db414f5caf709ab4f964d559>)です。まず、この関数を実行することでポジションの決済だけ行います。そして、CalculateLots()で次のトレードのロット数を算出して、[MyOrderSendMarket()](<https://www.notion.so/MyOrderSendMarket-3e0c92f431514dc6ba54b78b23c1afc6>)に渡します。これによりマーチンゲールに従ってロット数を変化させることができるのです。