「相場の勢いが強いのか弱いのか、数値で判断できたらいいのに…」と思ったことはありませんか?そんなときに役立つのがモメンタム(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をストラテジーテスターで動かして、パラメータを変えながら挙動を確認してみてください。実際に手を動かすことで、理解が一気に深まりますよ!

