【MQL4】iMACD関数の使い方を徹底解説!MACDの値を取得してEAに組み込もう【サンプルコード付き】

関数

「MACDのクロスで自動売買したい!」──テクニカル分析の定番指標MACDをEAに組み込むなら、まず覚えるべきなのがiMACD関数です。

この記事では、MQL4のiMACD関数の書式・引数の意味から、ゴールデンクロス・デッドクロスの判定ロジック、そして実際に動くEAのサンプルコードまで、ステップバイステップで解説します。初心者の方でも、この記事を読み終える頃にはMACDを使ったEAの原型が作れるようになるはずです。

MACDのおさらい

コードの話に入る前に、MACD(Moving Average Convergence Divergence)の基本をおさらいしておきましょう。MACDは以下の3つの要素で構成されます。

MACDの3つの構成要素

  • メインライン(MACDライン):短期EMA(通常12期間)と長期EMA(通常26期間)の差
  • シグナルライン:メインラインのEMA(通常9期間)
  • ヒストグラム:メインライン − シグナルラインの差をバーで表示したもの

基本的な売買シグナル

  • ゴールデンクロス(買いシグナル):メインラインがシグナルラインを下から上に抜ける
  • デッドクロス(売りシグナル):メインラインがシグナルラインを上から下に抜ける

このクロスをプログラムで検出するのが、MACD系EAの基本中の基本です。

iMACD関数の書式と引数

MQL4でMACDの値を取得するには、iMACD関数を使います。書式は以下のとおりです。

double iMACD(
   string       symbol,           // 通貨ペア名
   int          timeframe,        // 時間足
   int          fast_ema_period,  // 短期EMAの期間
   int          slow_ema_period,  // 長期EMAの期間
   int          signal_period,    // シグナルラインの期間
   int          applied_price,    // 適用価格
   int          mode,             // 取得するライン
   int          shift             // シフト(何本前のバーか)
);

各引数の詳細

引数 説明 よく使う値
symbol 通貨ペア名。現在のチャートならNULL NULL, Symbol()
timeframe 時間足。0で現在のチャートの時間足 0, PERIOD_H1 など
fast_ema_period 短期EMAの期間 12
slow_ema_period 長期EMAの期間 26
signal_period シグナルラインの期間 9
applied_price 計算に使う価格の種類 PRICE_CLOSE
mode 取得するライン(後述) MODE_MAIN, MODE_SIGNAL
shift 何本前のバーの値を取得するか 0(現在), 1(1本前)

modeパラメータの値

modeには以下の2つの定数を指定できます。

  • MODE_MAIN(0):MACDメインラインの値を返す
  • MODE_SIGNAL(1):シグナルラインの値を返す

なお、ヒストグラムの値は直接取得する定数がありません。メインライン − シグナルラインを自分で計算して求めます。

適用価格(applied_price)の定数一覧

定数名 説明
PRICE_CLOSE 0 終値
PRICE_OPEN 1 始値
PRICE_HIGH 2 高値
PRICE_LOW 3 安値
PRICE_MEDIAN 4 中央値 (High+Low)/2
PRICE_TYPICAL 5 代表値 (High+Low+Close)/3
PRICE_WEIGHTED 6 加重終値 (High+Low+Close+Close)/4

特別な理由がなければ、PRICE_CLOSE(終値)を使うのが一般的です。

基本的な使い方

まずは最もシンプルな使い方を見てみましょう。現在のチャートでMACDのメインラインとシグナルラインの値を取得するコードです。

void OnTick()
{
   // 1本前の確定バーからMACDメインラインの値を取得
   double macdMain = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
   
   // 1本前の確定バーからシグナルラインの値を取得
   double macdSignal = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);
   
   // ヒストグラムの値を計算
   double histogram = macdMain - macdSignal;
   
   // ログに出力して確認
   Print("MACD Main: ", macdMain, " Signal: ", macdSignal, " Histogram: ", histogram);
}

ポイント:shiftに1を指定しているのは、「1本前の確定したバー」の値を取得するためです。shift=0は現在形成中のバーなので値が変動します。売買判定にはshift=1以降の確定した値を使うのが基本です。

MACDクロス判定ロジック

MACDのゴールデンクロス・デッドクロスを判定するには、1本前と2本前のバーの値を比較します。

// --- 1本前のバー(直近の確定バー)---
double macdMain1   = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);
double macdSignal1 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);

// --- 2本前のバー ---
double macdMain2   = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 2);
double macdSignal2 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 2);

// ゴールデンクロス判定:2本前ではメインがシグナル以下 → 1本前でメインがシグナルを超えた
bool goldenCross = (macdMain2 <= macdSignal2) && (macdMain1 > macdSignal1);

// デッドクロス判定:2本前ではメインがシグナル以上 → 1本前でメインがシグナルを下回った
bool deadCross = (macdMain2 >= macdSignal2) && (macdMain1 < macdSignal1);

この「2時点を比較してクロスを検出する」パターンは、移動平均線やRSIなど他のインジケーターでも応用できる重要なテクニックです。

実践!MACDクロスEAのサンプルコード

ここからは、MACDのゴールデンクロスで買い、デッドクロスで売り(ドテン方式)のEAを作ってみましょう。実際にMT4で動作する完全なコードです。

//+------------------------------------------------------------------+
//|                                              MACD_Cross_EA.mq4   |
//|                        MACDクロスで売買するシンプルなEA            |
//+------------------------------------------------------------------+
#property strict

// --- 入力パラメータ ---
input int    FastEMA        = 12;          // 短期EMA期間
input int    SlowEMA        = 26;          // 長期EMA期間
input int    SignalPeriod    = 9;           // シグナル期間
input double LotSize        = 0.1;         // ロット数
input int    MagicNumber    = 20240101;    // マジックナンバー
input int    Slippage       = 3;           // スリッページ(ポイント)

//+------------------------------------------------------------------+
//| 新しいバーが形成されたか判定する関数                                |
//+------------------------------------------------------------------+
bool IsNewBar()
{
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(NULL, 0, 0);
   
   if(lastBarTime != currentBarTime)
   {
      lastBarTime = currentBarTime;
      return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| 自分のEAが持つポジションの種類を返す関数                           |
//| 戻り値: 1=買いポジあり, -1=売りポジあり, 0=ポジなし                |
//+------------------------------------------------------------------+
int GetMyPosition()
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            if(OrderType() == OP_BUY)  return 1;
            if(OrderType() == OP_SELL) return -1;
         }
      }
   }
   return 0;
}

//+------------------------------------------------------------------+
//| 自分のEAが持つポジションを全決済する関数                           |
//+------------------------------------------------------------------+
void CloseMyPositions(int posType)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            if(posType == 1 && OrderType() == OP_BUY)
               OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrNone);
            if(posType == -1 && OrderType() == OP_SELL)
               OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrNone);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| メインのティック処理                                               |
//+------------------------------------------------------------------+
void OnTick()
{
   // 新しいバーが形成されたときだけ処理する
   if(!IsNewBar()) return;
   
   // --- MACDの値を取得 ---
   double macdMain1   = iMACD(NULL, 0, FastEMA, SlowEMA, SignalPeriod, PRICE_CLOSE, MODE_MAIN, 1);
   double macdSignal1 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalPeriod, PRICE_CLOSE, MODE_SIGNAL, 1);
   double macdMain2   = iMACD(NULL, 0, FastEMA, SlowEMA, SignalPeriod, PRICE_CLOSE, MODE_MAIN, 2);
   double macdSignal2 = iMACD(NULL, 0, FastEMA, SlowEMA, SignalPeriod, PRICE_CLOSE, MODE_SIGNAL, 2);
   
   // --- クロス判定 ---
   bool goldenCross = (macdMain2 <= macdSignal2) && (macdMain1 > macdSignal1);
   bool deadCross   = (macdMain2 >= macdSignal2) && (macdMain1 < macdSignal1);
   
   // --- 現在のポジション状態を取得 ---
   int myPos = GetMyPosition();
   
   // --- ゴールデンクロス → 買いエントリー ---
   if(goldenCross)
   {
      // 売りポジションがあれば先に決済
      if(myPos == -1) CloseMyPositions(-1);
      
      // 買いポジションがなければ新規注文
      if(GetMyPosition() != 1)
      {
         int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, Slippage, 0, 0,
                                "MACD GC Buy", MagicNumber, 0, clrBlue);
         if(ticket < 0)
            Print("Buy OrderSend Error: ", GetLastError());
         else
            Print("Buy Order Success! Ticket: ", ticket);
      }
   }
   
   // --- デッドクロス → 売りエントリー ---
   if(deadCross)
   {
      // 買いポジションがあれば先に決済
      if(myPos == 1) CloseMyPositions(1);
      
      // 売りポジションがなければ新規注文
      if(GetMyPosition() != -1)
      {
         int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, Slippage, 0, 0,
                                "MACD DC Sell", MagicNumber, 0, clrRed);
         if(ticket < 0)
            Print("Sell OrderSend Error: ", GetLastError());
         else
            Print("Sell Order Success! Ticket: ", ticket);
      }
   }
}

サンプルEAのポイント解説

  • IsNewBar関数:新しいバーが形成されたときだけ処理を実行します。これにより無駄な重複注文を防ぎます。
  • MagicNumber:このEAが出した注文を識別するための番号です。他のEAや手動注文と区別できます。
  • ドテン方式:ゴールデンクロスで買いに転換、デッドクロスで売りに転換する仕組みです。反対ポジションを先に決済してから新規注文を出します。
  • GetMyPosition関数:自分のEAが持つポジションの状態を調べる関数です。ポジション管理はEA開発で必須のテクニックです。

応用:ゼロラインフィルターでダマシを減らす

MACDクロスだけだと「ダマシ」(偽のシグナル)が多くなりがちです。精度を上げるテクニックとして、ゼロラインフィルターがあります。

考え方はシンプルです。

  • 買いシグナル:ゴールデンクロス かつ MACDメインラインがゼロより下で発生したとき(底からの反転を狙う)
  • 売りシグナル:デッドクロス かつ MACDメインラインがゼロより上で発生したとき(天井からの反転を狙う)

コードに組み込むなら、クロス判定の条件に1行追加するだけです。

// ゼロラインフィルター付きのゴールデンクロス判定
bool filteredGoldenCross = goldenCross && (macdMain1 < 0);

// ゼロラインフィルター付きのデッドクロス判定
bool filteredDeadCross = deadCross && (macdMain1 > 0);

たった1行の条件追加ですが、トレンドの初動を捉えやすくなり、レンジ相場でのダマシを軽減できます。バックテストで効果を確認してみてください。

注意点・よくあるつまずきポイント

1. MT4とMT5でMACDの表示が異なる

MT4のMACDインジケーターでは、メインラインがヒストグラム(バー)で表示され、シグナルラインが点線で表示されます。一方MT5では、メインラインもシグナルラインもラインで表示され、別途ヒストグラムが描画されます。見た目は違いますが、iMACD関数で取得できる値の意味は同じです。

2. ヒストグラムは自分で計算する

iMACD関数にはヒストグラムを直接取得するモードがありません。ヒストグラムが必要な場合は、以下のように計算してください。

double histogram = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1)
                 - iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);

3. マルチタイムフレーム分析に使える

iMACD関数の第2引数(timeframe)を変えれば、現在のチャートと違う時間足のMACDを取得できます。例えば、5分足チャート上で1時間足のMACDを確認してフィルターに使う、といった活用が可能です。

// 1時間足のMACDメインラインを取得
double macdH1 = iMACD(NULL, PERIOD_H1, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1);

4. 引数の順番に注意

iMACD関数は引数が8つもあるため、順番を間違えやすいです。特にmodeshiftを逆にするミスはよくあります。迷ったら公式リファレンスで確認する習慣をつけましょう。

まとめ

この記事では、MQL4のiMACD関数について以下のポイントを解説しました。

  • iMACD関数は8つの引数を持ち、MACDのメインラインとシグナルラインの値を取得できる
  • クロス判定はshift=1とshift=2の値を比較して行う
  • EA開発では新規バー判定マジックナンバー管理ポジション管理関数が重要
  • ゼロラインフィルターを追加するだけでダマシを軽減できる
  • MT4とMT5でMACDの表示方法が異なる点に注意

今回のサンプルEAはシンプルな構成ですが、ストップロスやテイクプロフィット、トレーリングストップなどを追加していくことで、より実践的なEAに育てていくことができます。まずはバックテストで動作を確認し、少しずつカスタマイズしてみてください!