MM機能イメージ

ここでは、MetaTrader4のEA(Expert Advisor)に複利機能(マネーマネジメント機能)を追加する方法をご紹介します。

EAに複利機能を搭載する方法

今回はシンプルに、証拠金残高の増減でロット数を増減させる方法を紹介します。
例えば、残高10万円でロット数0.01ロットとして、残高が20万円で0.02ロット、残高が50万円で0.05ロットになるような計算をします。

Dr.EADr.EA

説明の前に全体のコードを見てみるぞい!

extern double  Lots           = 0.01;
extern bool    UseMM          = true;
extern double  BalancePerLots = 100000;

double max_lot;   // 最大ロット数
double min_lot;   // 最小ロット数
int lot_digit;    // ロット小数桁数

int OnInit()
{
   max_lot = MarketInfo(Symbol(), MODE_MAXLOT);
   min_lot = MarketInfo(Symbol(), MODE_MINLOT);
   
   double lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(NormalizeDouble(lotstep, 3) <= 0.001)
      lot_digit = 3;
   else if(NormalizeDouble(lotstep, 2) <= 0.01)
      lot_digit = 2;
   else if(NormalizeDouble(lotstep, 1) <= 0.1)
      lot_digit = 1;
   else
      lot_digit = 0;

   return(INIT_SUCCEEDED);
}

void OnTick()
{
   // ロット数を算出
   double lots = Lots;
   if (UseMM == true)
   {
      lots = AccountBalance() / BalancePerLots * Lots;
      lots = MathFloor(lots * MathPow(10, lot_digit)) * MathPow(0.1, lot_digit);
      if (lots > max_lot) lots = max_lot;
      if (lots < min_lot) lots = 0;
   }
}

MM機能搭載例のサンプルEA【Sample_MM.mq4】をダウンロード

パラメーターを設置する

次のように、ロット数・複利機能ON/OFF・1ステップあたりの残高のパラメーターを設置します。

extern double  Lots           = 0.01;
extern bool    UseMM          = true;
extern double  BalancePerLots = 100000;

取引業者のロットの最大値・最小値と小数以下桁数を取得する

まず、最大ロット数・最小ロット数・ロット小数以下桁数を格納するグローバル変数を宣言します。

double max_lot;   // 最大ロット数
double min_lot;   // 最小ロット数
int lot_digit;    // ロット小数桁数

OnInit()関数内で、それぞれの値を取得します。

   max_lot = MarketInfo(Symbol(), MODE_MAXLOT);
   min_lot = MarketInfo(Symbol(), MODE_MINLOT);
   
   double lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(NormalizeDouble(lotstep, 3) <= 0.001)
      lot_digit = 3;
   else if(NormalizeDouble(lotstep, 2) <= 0.01)
      lot_digit = 2;
   else if(NormalizeDouble(lotstep, 1) <= 0.1)
      lot_digit = 1;
   else
      lot_digit = 0;

最小ロット数とロットの最小ステップ数が違う場合があるので、ロットの最小ステップ数で小数以下桁数が決まるようにしています。

証拠金残高からロット数を算出する

OnTick()関数のエントリー注文のコードの手前あたりで、次のようにロット数を算出します。

   double lots = Lots;
   if (UseMM == true)
   {
      lots = AccountBalance() / BalancePerLots * Lots;
      lots = MathFloor(lots * MathPow(10, lot_digit)) * MathPow(0.1, lot_digit);
      if (lots > max_lot) lots = max_lot;
      if (lots < min_lot) lots = 0;
   }
   lots に Lots を代入
   もし UseMM が true なら
   {
      lots は 残高 ÷ BalancePerLots × Lots
      lots は 小数以下桁数 lot_digit に切り捨て
      lots が max_lot より大きい場合、 lots は max_lot
      lots が min_lot より小さい場合、 lots は 0
   }

切り捨てのところが少しややこしいので、簡単な例で説明します。

lots = MathFloor(lots * MathPow(10, lot_digit)) * MathPow(0.1, lot_digit);

このコードに使用しているMathFloor()関数は小数以下を切り捨てる関数です。MathPow()関数は累乗をする関数です。
例えば、ロット数が1.2345でlot_digitが2の場合、次のような計算をします。

lots * MathPow(10, lot_digit)
→ 1.2345 × 100 = 123.45

MathFloor(123.45)
→ 123

123 * MathPow(0.1, lot_digit)
→ 123 × 0.01 = 1.23

この場合、lotsの計算結果は1.23になります。

あとがき

切り捨ての計算が難しい場合は、少し妥協して四捨五入のNormalizeDouble(lots, lot_digit)としてもよいと思います。
それ以外は意外と簡単ですね^^
パラメーターBalancePerLotsは、日本円口座やドル口座など口座通貨によって入力値を調整してください。

続きの記事では、連勝・連敗によってロット数を変化させる方法を解説しています。