MQL5 インジケーター関数 完全ガイド|iMA・iRSI・iBands・iMACD・iATR全解説

MQL5のテクニカル指標関数を完全網羅。iMA・iRSI・iBollinger Bands・iMACD・iATR・iStochastic・iCCI・iADXなど、EA開発で使うすべてのインジケーター関数をコード付きで解説します。MQL4との違いも併記。

目次

MQL5とMQL4のインジケーター関数の根本的な違い

MQL4とMQL5ではインジケーター関数の使い方がまったく異なります。MQL4は1行で値が取れましたが、MQL5は「ハンドル取得→バッファコピー→値参照」の3ステップが必要です。

項目MQL4MQL5
値の取得iMA(NULL,0,20,0,MODE_SMA,PRICE_CLOSE,0)ハンドル取得→CopyBuffer()→配列参照
戻り値double(インジケーター値そのもの)int(ハンドル番号)
メモリ管理自動IndicatorRelease()で明示的に解放
パフォーマンス毎回計算ハンドルで一度だけ作成、以降はキャッシュ
複数バッファmodeパラメータで指定CopyBufferのbuffer_numで指定

MQL5の基本パターン(全インジケーター共通)

// ステップ1: OnInit()でハンドルを取得(1回だけ)
int maHandle;

int OnInit()
  {
   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
   if(maHandle == INVALID_HANDLE)
     {
      Print("インジケーター作成失敗");
      return INIT_FAILED;
     }
   return INIT_SUCCEEDED;
  }

// ステップ2: OnTick()でバッファをコピーして値を取得
void OnTick()
  {
   double ma[];
   ArraySetAsSeries(ma, true);  // 最新バーが[0]

   if(CopyBuffer(maHandle, 0, 0, 3, ma) < 3)
     {
      Print("データ取得失敗");
      return;
     }

   // ma[0] = 現在のバー、ma[1] = 1本前、ma[2] = 2本前
   double currentMA = ma[0];
   double prevMA    = ma[1];
  }

// ステップ3: OnDeinit()でハンドルを解放
void OnDeinit(const int reason)
  {
   if(maHandle != INVALID_HANDLE)
      IndicatorRelease(maHandle);
  }
重要

ArraySetAsSeries(ma, true)を忘れると、配列のインデックスが逆になります([0]が最古のバー)。EA開発では必ず設定してください。

iMA — 移動平均線

最も基本的なインジケーター関数です。SMA(単純移動平均)、EMA(指数移動平均)、SMMA(平滑移動平均)、LWMA(線形加重移動平均)の4種類に対応しています。

関数シグネチャ

// MQL5
int iMA(
   string              symbol,         // 通貨ペア(_Symbolまたは別銘柄)
   ENUM_TIMEFRAMES     period,         // 時間足(PERIOD_CURRENT等)
   int                 ma_period,      // 期間
   int                 ma_shift,       // 表示シフト(通常0)
   ENUM_MA_METHOD      ma_method,      // 移動平均の種類
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);
// 戻り値: インジケーターハンドル(失敗時INVALID_HANDLE)

// MQL4
double iMA(
   string symbol, int timeframe, int period,
   int ma_shift, int ma_method, int applied_price, int shift
);
// 戻り値: インジケーター値(double)

移動平均の種類(ENUM_MA_METHOD)

定数名称特徴
MODE_SMA単純移動平均全期間を均等に平均。安定だが遅い
MODE_EMA指数移動平均直近のデータに重み。SMAより反応が速い
MODE_SMMA平滑移動平均SMAの平滑版。最もなめらか
MODE_LWMA線形加重移動平均直近ほど大きな重み。EMAより更に敏感

適用価格(ENUM_APPLIED_PRICE)

定数説明
PRICE_CLOSE終値(最も一般的)
PRICE_OPEN始値
PRICE_HIGH高値
PRICE_LOW安値
PRICE_MEDIAN中央値 (High+Low)/2
PRICE_TYPICAL代表値 (High+Low+Close)/3
PRICE_WEIGHTED加重値 (High+Low+Close+Close)/4

ゴールデンクロス・デッドクロスの検出

int maFastHandle, maSlowHandle;

int OnInit()
  {
   maFastHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
   maSlowHandle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);

   if(maFastHandle == INVALID_HANDLE || maSlowHandle == INVALID_HANDLE)
      return INIT_FAILED;

   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double fast[], slow[];
   ArraySetAsSeries(fast, true);
   ArraySetAsSeries(slow, true);

   if(CopyBuffer(maFastHandle, 0, 0, 3, fast) < 3) return;
   if(CopyBuffer(maSlowHandle, 0, 0, 3, slow) < 3) return;

   // ゴールデンクロス: 短期MAが長期MAを下から上に抜けた
   bool goldenCross = fast[1] > slow[1] && fast[2] <= slow[2];

   // デッドクロス: 短期MAが長期MAを上から下に抜けた
   bool deadCross = fast[1] < slow[1] && fast[2] >= slow[2];

   if(goldenCross)
      Print("ゴールデンクロス発生 fast=", fast[1], " slow=", slow[1]);
   if(deadCross)
      Print("デッドクロス発生 fast=", fast[1], " slow=", slow[1]);
  }

クロス判定は確定足([1]と[2])で行います。[0]は形成中のバーなので、確定前に判定するとシグナルが消える(リペイント)可能性があります。

iRSI — RSI(相対力指数)

RSI(Relative Strength Index)は買われすぎ・売られすぎを判定する代表的なオシレーター系指標です。0〜100の範囲で推移し、一般的に70以上で買われすぎ、30以下で売られすぎと判断します。

// MQL5
int iRSI(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 ma_period,      // RSI期間(標準14)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);

// MQL4
double iRSI(string symbol, int timeframe, int period, int applied_price, int shift);

RSIによる売買判定

int rsiHandle;
input int    RSI_Period = 14;
input double RSI_Upper  = 70.0;
input double RSI_Lower  = 30.0;

int OnInit()
  {
   rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   if(rsiHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double rsi[];
   ArraySetAsSeries(rsi, true);
   if(CopyBuffer(rsiHandle, 0, 0, 3, rsi) < 3) return;

   // 売られすぎからの反転(買いシグナル)
   // RSIが30以下から30以上に戻った瞬間
   bool buySignal = rsi[2] < RSI_Lower && rsi[1] >= RSI_Lower;

   // 買われすぎからの反転(売りシグナル)
   // RSIが70以上から70以下に戻った瞬間
   bool sellSignal = rsi[2] > RSI_Upper && rsi[1] <= RSI_Upper;

   if(buySignal)
      Print("RSI買いシグナル: RSI=", rsi[1]);
   if(sellSignal)
      Print("RSI売りシグナル: RSI=", rsi[1]);
  }

RSIの期間はデフォルト14が最も一般的ですが、短期トレードでは7〜9、長期では21〜25を使うこともあります。期間が短いほど敏感になりますがダマシも増えます。

iBands — ボリンジャーバンド

ボリンジャーバンドは移動平均線を中心に、標準偏差で上下のバンドを描画するインジケーターです。バンドの収縮(スクイーズ)から拡大(エクスパンション)への転換でブレイクアウトを狙います。

// MQL5
int iBands(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 bands_period,   // 期間(標準20)
   int                 bands_shift,    // シフト(通常0)
   double              deviation,      // 標準偏差の倍数(標準2.0)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);
// バッファ: 0=ベース(中央線)、1=上バンド、2=下バンド

// MQL4
double iBands(string symbol, int timeframe, int period, double deviation,
              int bands_shift, int applied_price, int mode, int shift);
// mode: MODE_MAIN(0)=中央線, MODE_UPPER(1)=上, MODE_LOWER(2)=下

ボリンジャーバンド逆張り戦略

int bbHandle;

int OnInit()
  {
   bbHandle = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE);
   if(bbHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double base[], upper[], lower[];
   ArraySetAsSeries(base, true);
   ArraySetAsSeries(upper, true);
   ArraySetAsSeries(lower, true);

   // バッファ0=中央線、1=上バンド、2=下バンド
   if(CopyBuffer(bbHandle, 0, 0, 3, base)  < 3) return;
   if(CopyBuffer(bbHandle, 1, 0, 3, upper) < 3) return;
   if(CopyBuffer(bbHandle, 2, 0, 3, lower) < 3) return;

   double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);
   double close2 = iClose(_Symbol, PERIOD_CURRENT, 2);

   // 下バンドタッチからの反発(買い)
   bool buySignal = close2 <= lower[2] && close1 > lower[1];

   // 上バンドタッチからの反発(売り)
   bool sellSignal = close2 >= upper[2] && close1 < upper[1];

   // バンド幅(ボラティリティ判定に使用)
   double bandWidth = (upper[1] - lower[1]) / base[1] * 100;

   if(buySignal)
      Print("BB買いシグナル: Close=", close1, " Lower=", lower[1], " BW=", bandWidth, "%");
   if(sellSignal)
      Print("BB売りシグナル: Close=", close1, " Upper=", upper[1], " BW=", bandWidth, "%");
  }

ボリンジャーバンドの逆張りはレンジ相場では有効ですが、強いトレンド相場ではバンドウォーク(価格がバンドに沿って動き続ける現象)が発生し、大きな損失になります。必ずトレンドフィルターと併用してください。

iMACD — MACD

MACD(Moving Average Convergence Divergence)はトレンドの方向と強さを測定するインジケーターです。MACDラインとシグナルラインのクロス、ゼロラインとの位置関係、ヒストグラムの増減で判断します。

// MQL5
int iMACD(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 fast_ema_period, // 短期EMA(標準12)
   int                 slow_ema_period, // 長期EMA(標準26)
   int                 signal_period,  // シグナル期間(標準9)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);
// バッファ: 0=MACDライン、1=シグナルライン

// MQL4
double iMACD(string symbol, int timeframe, int fast_ema_period,
             int slow_ema_period, int signal_period, int applied_price,
             int mode, int shift);
// mode: MODE_MAIN(0)=MACDライン, MODE_SIGNAL(1)=シグナルライン

MACDクロスによる売買判定

int macdHandle;

int OnInit()
  {
   macdHandle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE);
   if(macdHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double macdLine[], signalLine[];
   ArraySetAsSeries(macdLine, true);
   ArraySetAsSeries(signalLine, true);

   if(CopyBuffer(macdHandle, 0, 0, 3, macdLine)   < 3) return;
   if(CopyBuffer(macdHandle, 1, 0, 3, signalLine) < 3) return;

   // ヒストグラム(MACDライン - シグナルライン)
   double hist1 = macdLine[1] - signalLine[1];
   double hist2 = macdLine[2] - signalLine[2];

   // MACDラインがシグナルラインを上抜け(買い)
   bool buySignal = macdLine[1] > signalLine[1] && macdLine[2] <= signalLine[2];

   // MACDラインがシグナルラインを下抜け(売り)
   bool sellSignal = macdLine[1] < signalLine[1] && macdLine[2] >= signalLine[2];

   // ゼロラインより上でのクロスはより信頼性が高い
   if(buySignal && macdLine[1] < 0)
      Print("MACD買い(ゼロ以下でのクロス=強いシグナル)");
   if(sellSignal && macdLine[1] > 0)
      Print("MACD売り(ゼロ以上でのクロス=強いシグナル)");
  }

iATR — ATR(真の値幅)

ATR(Average True Range)はボラティリティ(値動きの大きさ)を測定するインジケーターです。売買シグナルには使いませんが、SL/TPの設定、ポジションサイジング、エントリーフィルターとして非常に重要です。

// MQL5
int iATR(
   string           symbol,    // 通貨ペア
   ENUM_TIMEFRAMES  period,    // 時間足
   int              ma_period  // 期間(標準14)
);
// バッファ: 0=ATR値

// MQL4
double iATR(string symbol, int timeframe, int period, int shift);

ATRベースのSL/TP設定

int atrHandle;
input double ATR_SL_Multi = 2.0;  // SL = ATR × 2.0
input double ATR_TP_Multi = 3.0;  // TP = ATR × 3.0

int OnInit()
  {
   atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);
   if(atrHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

// ATRに基づくSL/TPを計算して返す
bool GetATR_SLTP(double &slDistance, double &tpDistance)
  {
   double atr[];
   ArraySetAsSeries(atr, true);
   if(CopyBuffer(atrHandle, 0, 0, 2, atr) < 2) return false;

   slDistance = atr[1] * ATR_SL_Multi;  // 確定足のATRを使用
   tpDistance = atr[1] * ATR_TP_Multi;
   return true;
  }

// 使用例
void OpenBuyWithATR(double lot)
  {
   double slDist, tpDist;
   if(!GetATR_SLTP(slDist, tpDist)) return;

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double sl  = NormalizeDouble(ask - slDist, _Digits);
   double tp  = NormalizeDouble(ask + tpDist, _Digits);

   trade.Buy(lot, _Symbol, ask, sl, tp, "ATR-based SL/TP");
  }

固定pipsではなくATRベースでSL/TPを設定すると、ボラティリティに応じて自動調整されます。ボラが高い時はSLが広がり、低い時は狭まるため、ストップ狩りに遭いにくくなります。

iStochastic — ストキャスティクス

ストキャスティクスは一定期間の高値・安値の範囲内で、現在の終値がどの位置にあるかを示すオシレーター指標です。%Kライン(メイン)と%Dライン(シグナル)の2本で構成されます。

// MQL5
int iStochastic(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 Kperiod,        // %K期間(標準5)
   int                 Dperiod,        // %D期間(標準3)
   int                 slowing,        // スローイング(標準3)
   ENUM_MA_METHOD      ma_method,      // 平均化方法
   ENUM_STO_PRICE      price_field     // 計算価格
);
// バッファ: 0=%Kライン(メイン)、1=%Dライン(シグナル)

// MQL4
double iStochastic(string symbol, int timeframe, int Kperiod, int Dperiod,
                   int slowing, int method, int price_field, int mode, int shift);
// mode: MODE_MAIN(0)=%K, MODE_SIGNAL(1)=%D

ストキャスティクス売買判定

int stoHandle;

int OnInit()
  {
   stoHandle = iStochastic(_Symbol, PERIOD_CURRENT, 5, 3, 3, MODE_SMA, STO_LOWHIGH);
   if(stoHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double kLine[], dLine[];
   ArraySetAsSeries(kLine, true);
   ArraySetAsSeries(dLine, true);

   if(CopyBuffer(stoHandle, 0, 0, 3, kLine) < 3) return;  // %K
   if(CopyBuffer(stoHandle, 1, 0, 3, dLine) < 3) return;  // %D

   // 売られすぎゾーン(20以下)で%Kが%Dを上抜け → 買い
   bool buySignal = kLine[2] < 20 && dLine[2] < 20
                    && kLine[1] > dLine[1] && kLine[2] <= dLine[2];

   // 買われすぎゾーン(80以上)で%Kが%Dを下抜け → 売り
   bool sellSignal = kLine[2] > 80 && dLine[2] > 80
                     && kLine[1] < dLine[1] && kLine[2] >= dLine[2];

   if(buySignal)
      Print("ストキャス買い: K=", kLine[1], " D=", dLine[1]);
   if(sellSignal)
      Print("ストキャス売り: K=", kLine[1], " D=", dLine[1]);
  }

iCCI — CCI(商品チャネル指数)

CCI(Commodity Channel Index)は統計的な平均からの乖離度を測定するオシレーターです。+100以上で買われすぎ、-100以下で売られすぎと判断します。トレンドフォローにも逆張りにも使える汎用性の高い指標です。

// MQL5
int iCCI(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 ma_period,      // 期間(標準14)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);
// バッファ: 0=CCI値

// MQL4
double iCCI(string symbol, int timeframe, int period, int applied_price, int shift);

CCI逆張り戦略

int cciHandle;

int OnInit()
  {
   cciHandle = iCCI(_Symbol, PERIOD_CURRENT, 14, PRICE_TYPICAL);
   if(cciHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double cci[];
   ArraySetAsSeries(cci, true);
   if(CopyBuffer(cciHandle, 0, 0, 3, cci) < 3) return;

   // CCI -100以下からの回復 → 買い
   bool buySignal = cci[2] < -100 && cci[1] >= -100;

   // CCI +100以上からの回復 → 売り
   bool sellSignal = cci[2] > 100 && cci[1] <= 100;

   if(buySignal)
      Print("CCI買いシグナル: CCI=", cci[1]);
   if(sellSignal)
      Print("CCI売りシグナル: CCI=", cci[1]);
  }

iADX — ADX(方向性指数)

ADX(Average Directional Index)はトレンドの強さを測定する指標です。方向は示しませんが、ADXが25以上ならトレンド相場、20以下ならレンジ相場と判断できます。+DI/-DIと組み合わせてトレンド方向を判定します。

// MQL5
int iADX(
   string           symbol,    // 通貨ペア
   ENUM_TIMEFRAMES  period,    // 時間足
   int              adx_period // 期間(標準14)
);
// バッファ: 0=ADXメインライン、1=+DI、2=-DI

// MQL4
double iADX(string symbol, int timeframe, int period, int applied_price, int mode, int shift);
// mode: MODE_MAIN(0)=ADX, MODE_PLUSDI(1)=+DI, MODE_MINUSDI(2)=-DI

ADXトレンドフィルター + DI クロス

int adxHandle;
input double ADX_Threshold = 25.0;

int OnInit()
  {
   adxHandle = iADX(_Symbol, PERIOD_CURRENT, 14);
   if(adxHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double adx[], plusDI[], minusDI[];
   ArraySetAsSeries(adx, true);
   ArraySetAsSeries(plusDI, true);
   ArraySetAsSeries(minusDI, true);

   if(CopyBuffer(adxHandle, 0, 0, 3, adx)     < 3) return;  // ADX
   if(CopyBuffer(adxHandle, 1, 0, 3, plusDI)   < 3) return;  // +DI
   if(CopyBuffer(adxHandle, 2, 0, 3, minusDI)  < 3) return;  // -DI

   // トレンド判定
   bool isTrending = adx[1] >= ADX_Threshold;

   // +DIが-DIを上抜け かつ トレンド中 → 買い
   bool buySignal = isTrending
                    && plusDI[1] > minusDI[1] && plusDI[2] <= minusDI[2];

   // -DIが+DIを上抜け かつ トレンド中 → 売り
   bool sellSignal = isTrending
                     && minusDI[1] > plusDI[1] && minusDI[2] <= plusDI[2];

   if(buySignal)
      Print("ADX買い: ADX=", adx[1], " +DI=", plusDI[1], " -DI=", minusDI[1]);
   if(sellSignal)
      Print("ADX売り: ADX=", adx[1], " +DI=", plusDI[1], " -DI=", minusDI[1]);
  }

ADXはトレンドフィルターとして他のインジケーターと併用すると効果的です。例えば「ADX > 25のときだけMAクロスでエントリー」とすることで、レンジ相場でのダマシを減らせます。

iIchimoku — 一目均衡表

一目均衡表は日本発のテクニカル指標で、5本の線と雲(先行スパン)で構成されます。トレンドの方向、強さ、転換点を総合的に判断できる強力なインジケーターです。

// MQL5
int iIchimoku(
   string           symbol,       // 通貨ペア
   ENUM_TIMEFRAMES  period,       // 時間足
   int              tenkan_sen,   // 転換線期間(標準9)
   int              kijun_sen,    // 基準線期間(標準26)
   int              senkou_span_b // 先行スパンB期間(標準52)
);
// バッファ: 0=転換線、1=基準線、2=先行スパンA、3=先行スパンB、4=遅行スパン

// MQL4
double iIchimoku(string symbol, int timeframe, int tenkan_sen, int kijun_sen,
                 int senkou_span_b, int mode, int shift);
// mode: 1=転換線, 2=基準線, 3=先行スパンA, 4=先行スパンB, 5=遅行スパン

一目均衡表の雲ブレイク戦略

int ichiHandle;

int OnInit()
  {
   ichiHandle = iIchimoku(_Symbol, PERIOD_CURRENT, 9, 26, 52);
   if(ichiHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double tenkan[], kijun[], spanA[], spanB[];
   ArraySetAsSeries(tenkan, true);
   ArraySetAsSeries(kijun, true);
   ArraySetAsSeries(spanA, true);
   ArraySetAsSeries(spanB, true);

   if(CopyBuffer(ichiHandle, 0, 0, 3, tenkan) < 3) return;
   if(CopyBuffer(ichiHandle, 1, 0, 3, kijun)  < 3) return;
   if(CopyBuffer(ichiHandle, 2, 0, 3, spanA)  < 3) return;
   if(CopyBuffer(ichiHandle, 3, 0, 3, spanB)  < 3) return;

   double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);

   // 雲の上端・下端
   double cloudTop    = MathMax(spanA[1], spanB[1]);
   double cloudBottom = MathMin(spanA[1], spanB[1]);

   // 三役好転(強い買いシグナル)
   // 1. 転換線 > 基準線
   // 2. 価格が雲の上
   // 3. 遅行スパンが価格の上(ここでは省略)
   bool bullish = tenkan[1] > kijun[1] && close1 > cloudTop;

   // 三役逆転(強い売りシグナル)
   bool bearish = tenkan[1] < kijun[1] && close1 < cloudBottom;

   // 転換線と基準線のクロス
   bool tenkanCrossBull = tenkan[1] > kijun[1] && tenkan[2] <= kijun[2];
   bool tenkanCrossBear = tenkan[1] < kijun[1] && tenkan[2] >= kijun[2];

   if(tenkanCrossBull && close1 > cloudTop)
      Print("一目買い: 転換線クロス+雲上");
   if(tenkanCrossBear && close1 < cloudBottom)
      Print("一目売り: 転換線クロス+雲下");
  }

一目均衡表の先行スパンは26本先にシフトされて表示されます。CopyBufferで取得する場合は現在のバーの値を参照するだけで、シフトは自動的に適用済みです。

iEnvelopes — エンベロープ

エンベロープは移動平均線から一定の割合(%)を上下に乖離させたバンドです。ボリンジャーバンドと似ていますが、標準偏差ではなく固定割合で計算するため、バンド幅が一定です。

// MQL5
int iEnvelopes(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 ma_period,      // MA期間(標準14)
   int                 ma_shift,       // シフト
   ENUM_MA_METHOD      ma_method,      // MA種類
   ENUM_APPLIED_PRICE  applied_price,  // 適用価格
   double              deviation       // 乖離率%(標準0.1)
);
// バッファ: 0=上バンド、1=下バンド

int envHandle;

int OnInit()
  {
   envHandle = iEnvelopes(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE, 0.1);
   if(envHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double upper[], lower[];
   ArraySetAsSeries(upper, true);
   ArraySetAsSeries(lower, true);

   if(CopyBuffer(envHandle, 0, 0, 3, upper) < 3) return;
   if(CopyBuffer(envHandle, 1, 0, 3, lower) < 3) return;

   double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);

   if(close1 < lower[1])
      Print("エンベロープ下限タッチ(買い候補): ", close1);
   if(close1 > upper[1])
      Print("エンベロープ上限タッチ(売り候補): ", close1);
  }

iSAR — パラボリックSAR

パラボリックSAR(Stop and Reverse)はトレンド追従型のインジケーターです。価格の上または下にドットが表示され、ドットが価格の下にあれば上昇トレンド、上にあれば下降トレンドと判定します。

// MQL5
int iSAR(
   string           symbol,    // 通貨ペア
   ENUM_TIMEFRAMES  period,    // 時間足
   double           step,      // ステップ(標準0.02)
   double           maximum    // 最大値(標準0.2)
);
// バッファ: 0=SAR値

// MQL4
double iSAR(string symbol, int timeframe, double step, double maximum, int shift);

int sarHandle;

int OnInit()
  {
   sarHandle = iSAR(_Symbol, PERIOD_CURRENT, 0.02, 0.2);
   if(sarHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double sar[];
   ArraySetAsSeries(sar, true);
   if(CopyBuffer(sarHandle, 0, 0, 3, sar) < 3) return;

   double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);
   double close2 = iClose(_Symbol, PERIOD_CURRENT, 2);

   // SARが価格の下に移動(上昇トレンド転換)
   bool buySignal = sar[1] < close1 && sar[2] >= close2;

   // SARが価格の上に移動(下降トレンド転換)
   bool sellSignal = sar[1] > close1 && sar[2] <= close2;

   // SARをトレーリングストップとして使用
   if(sar[1] < close1)
      Print("上昇トレンド中 SL候補=", sar[1]);
  }

iWPR — ウィリアムズ%R

ウィリアムズ%Rはストキャスティクスの%Kを反転させたようなオシレーターです。-100〜0の範囲で推移し、-20以上で買われすぎ、-80以下で売られすぎと判断します。

// MQL5
int iWPR(
   string           symbol,       // 通貨ペア
   ENUM_TIMEFRAMES  period,       // 時間足
   int              calc_period   // 期間(標準14)
);
// バッファ: 0=WPR値(-100〜0)

int wprHandle;

int OnInit()
  {
   wprHandle = iWPR(_Symbol, PERIOD_CURRENT, 14);
   if(wprHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double wpr[];
   ArraySetAsSeries(wpr, true);
   if(CopyBuffer(wprHandle, 0, 0, 3, wpr) < 3) return;

   // 売られすぎ(-80以下)からの回復 → 買い
   bool buySignal = wpr[2] < -80 && wpr[1] >= -80;

   // 買われすぎ(-20以上)からの回復 → 売り
   bool sellSignal = wpr[2] > -20 && wpr[1] <= -20;
  }

iMomentum — モメンタム

モメンタムは現在の価格とN期間前の価格の比率を計算するシンプルなインジケーターです。100を基準として、100以上なら上昇モメンタム、100以下なら下降モメンタムです。

// MQL5
int iMomentum(
   string              symbol,         // 通貨ペア
   ENUM_TIMEFRAMES     period,         // 時間足
   int                 mom_period,     // 期間(標準14)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格
);
// バッファ: 0=モメンタム値(100基準)

int momHandle;

int OnInit()
  {
   momHandle = iMomentum(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
   if(momHandle == INVALID_HANDLE) return INIT_FAILED;
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double mom[];
   ArraySetAsSeries(mom, true);
   if(CopyBuffer(momHandle, 0, 0, 3, mom) < 3) return;

   // 100ラインの上抜け → 上昇モメンタム
   bool bullish = mom[1] > 100 && mom[2] <= 100;

   // 100ラインの下抜け → 下降モメンタム
   bool bearish = mom[1] < 100 && mom[2] >= 100;
  }

iMAOnArray相当(MQL5でのカスタム計算)

MQL4にあったiMAOnArray()(配列データに対してMAを計算する関数)はMQL5には存在しません。代わりに自分で計算するか、iCustom()を使います。

// 配列に対してSMAを計算する関数(iMAOnArrayの代替)
double SimpleMA(const double &array[], int position, int period)
  {
   if(position < period - 1) return 0;

   double sum = 0;
   for(int i = 0; i < period; i++)
      sum += array[position - i];

   return sum / period;
  }

// 配列に対してEMAを計算する関数
void CalcEMA(const double &src[], double &dst[], int period)
  {
   int size = ArraySize(src);
   if(size < period) return;
   ArrayResize(dst, size);

   double k = 2.0 / (period + 1);

   // SMA = 最初のperiod個の平均値
   double sum = 0;
   for(int i = 0; i < period; i++)
      sum += src[i];
   dst[period - 1] = sum / period;

   // EMA計算(period以降)
   for(int i = period; i < size; i++)
      dst[i] = src[i] * k + dst[i - 1] * (1 - k);
  }

iCustom — カスタムインジケーター

iCustom()はユーザーが作成したカスタムインジケーターをEAから呼び出す関数です。標準関数にないインジケーター(ATR Bands、Keltner Channel、SuperTrend等)を使う場合に必要です。

// MQL5
int iCustom(
   string           symbol,        // 通貨ペア
   ENUM_TIMEFRAMES  period,        // 時間足
   string           name,          // インジケーター名(パス)
   ...                             // インジケーターのinputパラメータ
);

// MQL4
double iCustom(string symbol, int timeframe, string name, ..., int mode, int shift);

カスタムインジケーターの呼び出し例

// カスタムインジケーター「Examples\\SuperTrend」を呼び出す
int stHandle;

int OnInit()
  {
   // Indicatorsフォルダからの相対パス
   // パラメータはインジケーターのinput変数に対応
   stHandle = iCustom(_Symbol, PERIOD_CURRENT,
                      "Examples\\SuperTrend",  // インジケーター名
                      10,                       // Period
                      3.0                       // Multiplier
                      );

   if(stHandle == INVALID_HANDLE)
     {
      Print("カスタムインジケーター作成失敗: ", GetLastError());
      return INIT_FAILED;
     }
   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double buffer0[], buffer1[];
   ArraySetAsSeries(buffer0, true);
   ArraySetAsSeries(buffer1, true);

   // バッファ番号はカスタムインジケーターのSetIndexBuffer()に対応
   if(CopyBuffer(stHandle, 0, 0, 3, buffer0) < 3) return;
   if(CopyBuffer(stHandle, 1, 0, 3, buffer1) < 3) return;

   Print("Buffer0=", buffer0[1], " Buffer1=", buffer1[1]);
  }

iCustom()で指定するインジケーター名は、Indicatorsフォルダからの相対パスです。サブフォルダにある場合は"MyFolder\\MyIndicator"のように指定します。拡張子(.ex5)は不要です。

価格データの直接取得(iOpen / iHigh / iLow / iClose / iVolume)

インジケーターではありませんが、EA開発で頻繁に使う価格データ取得関数です。MQL5では単独の関数として用意されています。

// MQL5 — 各関数は1本のバーの値を返す
double open1  = iOpen(_Symbol, PERIOD_CURRENT, 1);   // 1本前の始値
double high1  = iHigh(_Symbol, PERIOD_CURRENT, 1);   // 1本前の高値
double low1   = iLow(_Symbol, PERIOD_CURRENT, 1);    // 1本前の安値
double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);  // 1本前の終値
long   vol1   = iVolume(_Symbol, PERIOD_CURRENT, 1); // 1本前のティック量
datetime time1 = iTime(_Symbol, PERIOD_CURRENT, 1);  // 1本前の時刻
int    bars   = iBars(_Symbol, PERIOD_CURRENT);       // バー数

// 複数本を一括取得(CopyRatesが高速)
MqlRates rates[];
ArraySetAsSeries(rates, true);
if(CopyRates(_Symbol, PERIOD_CURRENT, 0, 100, rates) > 0)
  {
   // rates[0] = 現在のバー、rates[1] = 1本前...
   double close = rates[1].close;
   double high  = rates[1].high;
   double low   = rates[1].low;
   double open  = rates[1].open;
   long   vol   = rates[1].tick_volume;
  }

大量の価格データが必要な場合はiClose()をループで呼ぶよりCopyRates()で一括取得する方がパフォーマンスが良いです。

CopyBuffer — バッファコピーの詳細

CopyBuffer()はMQL5のインジケーターから値を取得する唯一の方法です。3つのオーバーロードがあります。

// 方法1: 位置と本数で指定(最も一般的)
int CopyBuffer(
   int       indicator_handle,  // インジケーターハンドル
   int       buffer_num,        // バッファ番号
   int       start_pos,         // 開始位置(0=最新バー)
   int       count,             // 取得本数
   double    buffer[]            // 格納先配列
);

// 方法2: 日時で範囲指定
int CopyBuffer(int handle, int buffer_num,
               datetime start_time, int count, double buffer[]);

// 方法3: 日時範囲で指定
int CopyBuffer(int handle, int buffer_num,
               datetime start_time, datetime stop_time, double buffer[]);

// 戻り値: コピーされたデータ数(失敗時-1)

// 使用例
double ma[];
ArraySetAsSeries(ma, true);

// 最新から10本分を取得
int copied = CopyBuffer(maHandle, 0, 0, 10, ma);
if(copied < 10)
   Print("データ不足: ", copied, "本しか取得できませんでした");

// 特定の日時から取得
datetime from = D'2024.01.01 00:00';
copied = CopyBuffer(maHandle, 0, from, 100, ma);

IndicatorRelease — ハンドル解放

不要になったインジケーターハンドルはIndicatorRelease()で解放します。解放しないとメモリリークの原因になります。

void OnDeinit(const int reason)
  {
   // すべてのハンドルを解放
   if(maHandle != INVALID_HANDLE)
     {
      IndicatorRelease(maHandle);
      maHandle = INVALID_HANDLE;
     }
   if(rsiHandle != INVALID_HANDLE)
     {
      IndicatorRelease(rsiHandle);
      rsiHandle = INVALID_HANDLE;
     }
   // ... 他のハンドルも同様
  }

同じパラメータでiMA()等を複数回呼んだ場合、MT5内部では同じハンドルが再利用されます(参照カウント方式)。ただしIndicatorRelease()も同じ回数呼ぶ必要があります。

マルチタイムフレーム分析

異なる時間足のインジケーター値をEAで取得する方法です。例えば1時間足のEAで日足のMAトレンドを参照するケースです。

int maH1Handle;   // 1時間足のMA
int maD1Handle;   // 日足のMA

int OnInit()
  {
   // 同じ通貨ペアの異なる時間足
   maH1Handle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_EMA, PRICE_CLOSE);
   maD1Handle = iMA(_Symbol, PERIOD_D1, 20, 0, MODE_EMA, PRICE_CLOSE);

   if(maH1Handle == INVALID_HANDLE || maD1Handle == INVALID_HANDLE)
      return INIT_FAILED;

   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   double maH1[], maD1[];
   ArraySetAsSeries(maH1, true);
   ArraySetAsSeries(maD1, true);

   if(CopyBuffer(maH1Handle, 0, 0, 3, maH1) < 3) return;
   if(CopyBuffer(maD1Handle, 0, 0, 3, maD1) < 3) return;

   double close = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   // 日足が上昇トレンド(価格が日足MA上)のときだけ
   // 1時間足のMAクロスで買いエントリー
   bool dailyBullish = close > maD1[0];

   bool h1CrossUp = maH1[1] > maH1[0]; // 省略: 実際にはMAクロス等の条件

   if(dailyBullish && h1CrossUp)
      Print("マルチTF買い: 日足上昇 + H1シグナル");
  }
重要

上位時間足のデータは、その時間足のバーが確定するまで更新されません。例えば日足のMAは、1時間足のEAでティックごとに変化するわけではなく、日足のバーが切り替わるタイミングでのみ変わります。

インジケーター関数一覧

MQL5で利用可能なすべてのテクニカル指標関数の一覧です。

関数インジケーター名バッファ数主な用途
iMA移動平均線1トレンド判定、クロス売買
iRSIRSI1買われすぎ・売られすぎ
iBandsボリンジャーバンド3ボラティリティ、逆張り
iMACDMACD2トレンド方向・強さ
iATRATR1ボラティリティ測定、SL/TP
iStochasticストキャスティクス2買われすぎ・売られすぎ
iCCICCI1乖離度測定
iADXADX3トレンド強度、DI方向
iIchimoku一目均衡表5総合的なトレンド判定
iEnvelopesエンベロープ2乖離トレード
iSARパラボリックSAR1トレンド転換、トレーリング
iWPRウィリアムズ%R1買われすぎ・売られすぎ
iMomentumモメンタム1勢い判定
iDeMarkerデマーカー1買われすぎ・売られすぎ
iForceフォースインデックス1売買圧力
iOsMAOsMA1MACDヒストグラム
iOBVOBV1出来高分析
iVolumesボリューム1出来高
iMFIマネーフローインデックス1出来高加重オシレーター
iAOAwesome Oscillator1モメンタム
iACAccelerator/Decelerator1モメンタム加速度
iFrAMAフラクタル適応MA1適応型トレンド
iAMA適応型移動平均1ノイズ適応MA
iDEMA二重指数移動平均1高速トレンド
iTEMA三重指数移動平均1超高速トレンド
iVIDyA可変インデックス動的平均1ボラティリティ適応MA
iBWMFIBW MFI1ビル・ウィリアムズMFI
iFractalsフラクタル2スイングポイント
iAlligatorアリゲーター3トレンド判定
iGatorゲーターオシレーター2アリゲーター補助
iChaikinチャイキンオシレーター1出来高ベース
iStdDev標準偏差1ボラティリティ
iRVI相対活力指数2トレンド強度
iTriXTRIX1トリプル平滑化

実践:複数インジケーターの組み合わせ

実際のEA開発では、複数のインジケーターを組み合わせてシグナルの精度を高めます。ここでは代表的な組み合わせパターンを紹介します。

MA + RSI + ADXフィルター

#include <Trade\Trade.mqh>

CTrade trade;
int maFastHandle, maSlowHandle, rsiHandle, adxHandle;

input int    MA_Fast     = 20;
input int    MA_Slow     = 50;
input int    RSI_Period  = 14;
input double RSI_Lower   = 40.0;   // RSIフィルター下限
input double RSI_Upper   = 60.0;   // RSIフィルター上限
input double ADX_Min     = 25.0;   // 最低ADX値
input double Lot         = 0.1;
input int    SL_Points   = 500;
input int    TP_Points   = 1000;
input long   MagicNumber = 20240301;

int OnInit()
  {
   trade.SetExpertMagicNumber(MagicNumber);

   maFastHandle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast, 0, MODE_EMA, PRICE_CLOSE);
   maSlowHandle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow, 0, MODE_EMA, PRICE_CLOSE);
   rsiHandle    = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   adxHandle    = iADX(_Symbol, PERIOD_CURRENT, 14);

   if(maFastHandle == INVALID_HANDLE || maSlowHandle == INVALID_HANDLE
      || rsiHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE)
      return INIT_FAILED;

   return INIT_SUCCEEDED;
  }

void OnTick()
  {
   // ポジションチェック(1ポジションのみ)
   int posCount = 0;
   for(int i = 0; i < PositionsTotal(); i++)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetInteger(POSITION_MAGIC) == MagicNumber
         && PositionGetString(POSITION_SYMBOL) == _Symbol)
         posCount++;
     }
   if(posCount > 0) return;

   // インジケーター値取得
   double fast[], slow[], rsi[], adx[];
   ArraySetAsSeries(fast, true);
   ArraySetAsSeries(slow, true);
   ArraySetAsSeries(rsi, true);
   ArraySetAsSeries(adx, true);

   if(CopyBuffer(maFastHandle, 0, 0, 3, fast) < 3) return;
   if(CopyBuffer(maSlowHandle, 0, 0, 3, slow) < 3) return;
   if(CopyBuffer(rsiHandle,    0, 0, 3, rsi)  < 3) return;
   if(CopyBuffer(adxHandle,    0, 0, 3, adx)  < 3) return;

   // 条件判定(確定足[1][2]を使用)
   bool maCrossUp   = fast[1] > slow[1] && fast[2] <= slow[2];
   bool maCrossDown = fast[1] < slow[1] && fast[2] >= slow[2];
   bool trendStrong = adx[1] >= ADX_Min;

   // 買いシグナル: MAゴールデンクロス + RSIがまだ低い + トレンド強い
   if(maCrossUp && rsi[1] < RSI_Upper && trendStrong)
     {
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double sl  = NormalizeDouble(ask - SL_Points * _Point, _Digits);
      double tp  = NormalizeDouble(ask + TP_Points * _Point, _Digits);
      trade.Buy(Lot, _Symbol, ask, sl, tp, "MA+RSI+ADX Buy");
     }

   // 売りシグナル: MAデッドクロス + RSIがまだ高い + トレンド強い
   if(maCrossDown && rsi[1] > RSI_Lower && trendStrong)
     {
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double sl  = NormalizeDouble(bid + SL_Points * _Point, _Digits);
      double tp  = NormalizeDouble(bid - TP_Points * _Point, _Digits);
      trade.Sell(Lot, _Symbol, bid, sl, tp, "MA+RSI+ADX Sell");
     }
  }

void OnDeinit(const int reason)
  {
   IndicatorRelease(maFastHandle);
   IndicatorRelease(maSlowHandle);
   IndicatorRelease(rsiHandle);
   IndicatorRelease(adxHandle);
  }
  • MAクロスでエントリータイミングを決定
  • RSIフィルターで買われすぎ・売られすぎでのエントリーを回避
  • ADXフィルターでレンジ相場でのダマシを排除

プロが開発したEAをお探しの方は → シストレ.COM EA一覧

シストレ.COMで実績のあるEAが使い放題!/
無料会員登録はこちら
FX自動売買でEAを探すなら
シストレ.COM
実績あるEAが無料
厳格な審査を乗り越えた実績のあるEAが無料で使えます!
自由な口座選び
有料版を購入し柔軟な口座選びが可能!
フォワードテスト公開
全EAのフォワードテスト結果を公開中!
FX初心者も安心
初心者の方も安心して取引を始められます。
多様なEA選択肢
様々な種別のEAをご用意!自分の手法にあった取引が可能です。
信頼のFX会社と提携
人気のFX会社と提携中!様々なFX会社から選べます。
1分で登録完了!EA探すならシストレ.COM!/
無料会員登録はこちら
【FX自動売買】システムトレード完全ガイド|Forex Guide

この記事が気に入ったら
フォローしてね!

お役立ち情報をシェアする
  • URLをコピーしました!
目次