「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つもあるため、順番を間違えやすいです。特にmodeとshiftを逆にするミスはよくあります。迷ったら公式リファレンスで確認する習慣をつけましょう。
まとめ
この記事では、MQL4のiMACD関数について以下のポイントを解説しました。
- iMACD関数は8つの引数を持ち、MACDのメインラインとシグナルラインの値を取得できる
- クロス判定はshift=1とshift=2の値を比較して行う
- EA開発では新規バー判定・マジックナンバー管理・ポジション管理関数が重要
- ゼロラインフィルターを追加するだけでダマシを軽減できる
- MT4とMT5でMACDの表示方法が異なる点に注意
今回のサンプルEAはシンプルな構成ですが、ストップロスやテイクプロフィット、トレーリングストップなどを追加していくことで、より実践的なEAに育てていくことができます。まずはバックテストで動作を確認し、少しずつカスタマイズしてみてください!

