【MQL4入門】iMomentum関数の使い方を徹底解説!モメンタムで相場の勢いを判定するEAを作ろう

【初級編】MQLプログラミング基礎

「相場の勢いが強いのか弱いのか、数値で判断できたらいいのに…」と思ったことはありませんか?そんなときに役立つのがモメンタム(Momentum)というテクニカル指標です。

MQL4には、モメンタムの値を簡単に取得できるiMomentum関数が用意されています。この記事では、iMomentum関数の基本的な使い方から、実際にコピペで動くEAサンプルまで、初心者の方にもわかりやすく徹底解説します。

モメンタムとは?相場の「勢い」を測る指標

モメンタム(Momentum)は、現在の価格と過去の価格の差を見ることで、相場の勢い(速度)を測るテクニカル指標です。MetaTraderのモメンタムは、差ではなく比率(パーセンテージ)で表現されます。

計算式

MetaTraderにおけるモメンタムの計算式は以下のとおりです。

Momentum = (現在の終値 ÷ N期間前の終値) × 100

たとえば期間を14に設定した場合、現在の終値と14本前の終値を比較します。

100ラインの見方

モメンタムの基準値は100です。以下のように判断します。

  • 100より上:現在の価格がN期間前より高い → 上昇の勢いがある
  • 100より下:現在の価格がN期間前より低い → 下降の勢いがある
  • 100ちょうど:N期間前と同じ価格 → 勢いがない

つまり、モメンタムが100ラインを上抜けたら「上昇の勢いが出てきた」、下抜けたら「下降の勢いが出てきた」と判断できるわけです。

iMomentum関数の構文と引数

MQL4でモメンタムの値を取得するには、iMomentum関数を使います。構文は以下のとおりです。

double iMomentum(
   string       symbol,          // 通貨ペア名
   int          timeframe,       // 時間軸
   int          mom_period,      // モメンタムの期間
   int          applied_price,   // 適用価格
   int          shift            // シフト(何本前のバーか)
);

それぞれの引数を詳しく見ていきましょう。

第1引数:symbol(通貨ペア名)

モメンタムを計算する通貨ペアを文字列で指定します。現在のチャートの通貨ペアを使う場合は、NULL または Symbol() を指定します。

第2引数:timeframe(時間軸)

どの時間軸のデータを使うかを指定します。現在のチャートの時間軸を使う場合は 0 または PERIOD_CURRENT を指定します。主な定数は以下のとおりです。

  • PERIOD_M1:1分足
  • PERIOD_M5:5分足
  • PERIOD_M15:15分足
  • PERIOD_M30:30分足
  • PERIOD_H1:1時間足
  • PERIOD_H4:4時間足
  • PERIOD_D1:日足
  • PERIOD_W1:週足

第3引数:mom_period(期間)

モメンタムの計算期間です。一般的には14がよく使われます。値を小さくすると敏感に反応し、大きくすると滑らかになります。

第4引数:applied_price(適用価格)

計算に使う価格の種類を指定します。通常は終値(PRICE_CLOSE)を使います。

  • PRICE_CLOSE(0):終値
  • PRICE_OPEN(1):始値
  • PRICE_HIGH(2):高値
  • PRICE_LOW(3):安値
  • PRICE_MEDIAN(4):中央値((高値+安値)÷2)
  • PRICE_TYPICAL(5):典型価格((高値+安値+終値)÷3)
  • PRICE_WEIGHTED(6):加重終値((高値+安値+終値+終値)÷4)

第5引数:shift(シフト)

何本前のバーの値を取得するかを指定します。0で現在のバー、1で1本前のバーです。確定した値を使いたい場合は1以上を指定するのが基本です。

基本的な使い方 ― 値を取得してログに出力する

まずは最もシンプルな例として、モメンタムの値を取得してエキスパートログに出力するコードを見てみましょう。

void OnTick()
{
   // 現在のバーのモメンタム値を取得(期間14、終値ベース)
   double mom_current = iMomentum(NULL, 0, 14, PRICE_CLOSE, 0);

   // 1本前のバーのモメンタム値を取得
   double mom_prev = iMomentum(NULL, 0, 14, PRICE_CLOSE, 1);

   // ログに出力
   Print("現在のモメンタム: ", mom_current, " | 1本前: ", mom_prev);

   // 100ラインとの比較
   if(mom_current > 100.0)
   {
      Print("上昇の勢いあり");
   }
   else if(mom_current < 100.0)
   {
      Print("下降の勢いあり");
   }
   else
   {
      Print("勢いなし(ニュートラル)");
   }
}

このコードをEAとしてコンパイルしてチャートにセットすれば、ティックごとにモメンタムの値がログに表示されます。まずはこの基本形を理解しておきましょう。

実践サンプル①:100ラインクロスでエントリーするEA

ここからが本番です。モメンタムが100ラインを上抜けたら買い、下抜けたら売りという、シンプルなEAを作ってみましょう。

//+------------------------------------------------------------------+
//| Momentum Cross EA                                                 |
//+------------------------------------------------------------------+
#property strict

// 入力パラメータ
input int    MomPeriod   = 14;       // モメンタム期間
input double LotSize     = 0.01;     // ロットサイズ
input int    Slippage    = 3;        // スリッページ
input int    StopLoss    = 100;      // ストップロス(ポイント)
input int    TakeProfit  = 200;      // テイクプロフィット(ポイント)
input int    MagicNumber = 12345;    // マジックナンバー

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
{
   // 新しいバーが確定したときだけ処理する
   static datetime lastBarTime = 0;
   if(Time[0] == lastBarTime) return;
   lastBarTime = Time[0];

   // モメンタム値を取得(確定バーを使うためshift=1と2)
   double mom1 = iMomentum(NULL, 0, MomPeriod, PRICE_CLOSE, 1);
   double mom2 = iMomentum(NULL, 0, MomPeriod, PRICE_CLOSE, 2);

   // 現在のポジション数を確認
   int buyCount  = 0;
   int sellCount = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(OrderMagicNumber() != MagicNumber) continue;

      if(OrderType() == OP_BUY)  buyCount++;
      if(OrderType() == OP_SELL) sellCount++;
   }

   // SLとTPの価格を計算するための変数
   double sl = 0, tp = 0;

   // 買いシグナル:モメンタムが100を下から上にクロス
   if(mom2 <= 100.0 && mom1 > 100.0)
   {
      // 売りポジションがあれば決済
      ClosePositions(OP_SELL);

      // 買いポジションがなければエントリー
      if(buyCount == 0)
      {
         sl = (StopLoss  > 0) ? Ask - StopLoss  * Point : 0;
         tp = (TakeProfit > 0) ? Ask + TakeProfit * Point : 0;
         int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, sl, tp, "Mom Buy", MagicNumber, 0, clrBlue);
         if(ticket < 0)
            Print("Buy OrderSend error: ", GetLastError());
      }
   }

   // 売りシグナル:モメンタムが100を上から下にクロス
   if(mom2 >= 100.0 && mom1 < 100.0)
   {
      // 買いポジションがあれば決済
      ClosePositions(OP_BUY);

      // 売りポジションがなければエントリー
      if(sellCount == 0)
      {
         sl = (StopLoss  > 0) ? Bid + StopLoss  * Point : 0;
         tp = (TakeProfit > 0) ? Bid - TakeProfit * Point : 0;
         int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, sl, tp, "Mom Sell", MagicNumber, 0, clrRed);
         if(ticket < 0)
            Print("Sell OrderSend error: ", GetLastError());
      }
   }
}

//+------------------------------------------------------------------+
//| 指定タイプのポジションを全決済する関数                            |
//+------------------------------------------------------------------+
void ClosePositions(int type)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() != Symbol()) continue;
      if(OrderMagicNumber() != MagicNumber) continue;
      if(OrderType() != type) continue;

      double closePrice = (type == OP_BUY) ? Bid : Ask;
      if(!OrderClose(OrderTicket(), OrderLots(), closePrice, Slippage, clrWhite))
         Print("OrderClose error: ", GetLastError());
   }
}

コードのポイント解説

  • 新しいバー判定Time[0]を使って、バーが確定したタイミングだけ処理を実行します。これにより無駄な注文の重複を防ぎます。
  • shift=1と2を使用:確定済みのバーを使ってクロス判定を行います。shift=0は未確定バーなので、シグナルがチラつく原因になります。
  • マジックナンバー:このEAのポジションだけを管理するための識別番号です。他のEAとの干渉を防ぎます。
  • 決済処理:反対シグナルが出たら既存ポジションを決済してからエントリーする、ドテン売買のロジックです。

実践サンプル②:移動平均線と組み合わせたフィルター関数

モメンタム単体だとダマシが多くなりがちです。そこで、移動平均線(MA)をトレンドフィルターとして組み合わせる方法を紹介します。

//+------------------------------------------------------------------+
//| モメンタム+移動平均線のシグナル判定関数                          |
//+------------------------------------------------------------------+
int GetFilteredSignal(int momPeriod, int maPeriod)
{
   // モメンタム値(確定バー)
   double mom1 = iMomentum(NULL, 0, momPeriod, PRICE_CLOSE, 1);
   double mom2 = iMomentum(NULL, 0, momPeriod, PRICE_CLOSE, 2);

   // 移動平均線の値(確定バー)
   double ma = iMA(NULL, 0, maPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);

   // 現在の終値(確定バー)
   double closePrice = Close[1];

   // 買いシグナル:MA より上 かつ モメンタム100上抜け
   if(closePrice > ma && mom2 <= 100.0 && mom1 > 100.0)
   {
      return 1;  // 買い
   }

   // 売りシグナル:MA より下 かつ モメンタム100下抜け
   if(closePrice < ma && mom2 >= 100.0 && mom1 < 100.0)
   {
      return -1;  // 売り
   }

   return 0;  // シグナルなし
}

この関数の使い方はシンプルです。OnTick内で以下のように呼び出します。

void OnTick()
{
   int signal = GetFilteredSignal(14, 50);

   if(signal == 1)
   {
      // 買い処理
      Print("フィルター通過:買いシグナル発生!");
   }
   else if(signal == -1)
   {
      // 売り処理
      Print("フィルター通過:売りシグナル発生!");
   }
}

ポイントは、価格がMAより上のときだけ買いシグナルを採用し、MAより下のときだけ売りシグナルを採用するという点です。これにより、トレンドに逆らったエントリーを減らすことができます。

iMomentum関数を使う際の注意点

1. shift値は1以上を使おう

shift=0は現在形成中のバーの値です。ティックごとに値が変わるため、シグナル判定には確定済みのshift=1以降を使うのが鉄則です。shift=0は参考表示用として使いましょう。

2. マルチタイムフレーム使用時の注意

第2引数で現在のチャートと異なる時間軸を指定すると、マルチタイムフレーム分析ができます。ただし、上位足のデータが読み込まれていない場合は正しい値が返りません。必要に応じて事前にチャートを開くか、iMomentumの戻り値が0でないかチェックしましょう。

// 日足のモメンタムを取得
double momDaily = iMomentum(NULL, PERIOD_D1, 14, PRICE_CLOSE, 1);
if(momDaily == 0)
{
   Print("日足データが取得できません");
   return;
}

3. ブローカーによる桁数の違いに注意

StopLossやTakeProfitをポイント単位で指定する場合、3桁/5桁ブローカーでは値の調整が必要です。モメンタム自体の値は比率(パーセンテージ)なので桁数の影響は受けませんが、EA全体のロジックでは注意しましょう。

まとめ

今回は、MQL4のiMomentum関数について基礎から実践まで解説しました。最後に要点を整理しておきます。

  • モメンタムは相場の勢いを数値化する指標で、基準値は100
  • iMomentum関数は5つの引数(symbol, timeframe, period, applied_price, shift)で値を取得できる
  • シグナル判定には確定バー(shift=1以降)を使うのが基本
  • 100ラインのクロスでエントリータイミングを判断するEAが作れる
  • 移動平均線などと組み合わせることで、ダマシを減らしてシグナルの精度を高められる

モメンタムはシンプルながら奥が深い指標です。まずは今回のサンプルEAをストラテジーテスターで動かして、パラメータを変えながら挙動を確認してみてください。実際に手を動かすことで、理解が一気に深まりますよ!