【MQL4入門】iBands関数でボリンジャーバンドを使いこなそう!引数・使い方・サンプルコード徹底解説

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

ボリンジャーバンドは、移動平均線を中心に「価格の散らばり具合(標準偏差)」を帯(バンド)として表示するテクニカル指標です。MQL4には、このボリンジャーバンドの値をプログラムから簡単に取得できるiBands関数が用意されています。

この記事では、iBands関数の引数の意味をひとつずつ丁寧に解説し、基本的な使い方から逆張りEAのサンプルコード、さらに応用テクニックやよくある間違いまで、徹底的にまとめました。ボリンジャーバンドをEAやインジケーターで活用したい方は、ぜひ最後まで読んでみてください。

ボリンジャーバンドとは?

ボリンジャーバンドは、アメリカの投資家ジョン・ボリンジャー氏が考案したテクニカル指標で、以下の3本のラインで構成されます。

  • ミドルバンド(中間線):単純移動平均線(SMA)そのもの
  • アッパーバンド(上方バンド):ミドルバンド + 標準偏差 × n
  • ロワーバンド(下方バンド):ミドルバンド − 標準偏差 × n

ここで「n」は標準偏差の倍率で、一般的には2σ(シグマ)がよく使われます。統計的には、価格が±2σの範囲に収まる確率は約95.4%とされています。この性質を利用して、バンドの上端・下端にタッチしたら逆張りする戦略や、バンドをブレイクした方向に順張りする戦略などに活用されます。

iBands関数の基本構文

MQL4でボリンジャーバンドの値を取得するには、組み込み関数iBandsを使います。基本構文は以下のとおりです。

double iBands(
   string       symbol,           // ① 通貨ペア名
   int          timeframe,        // ② 時間足
   int          period,           // ③ 計算期間
   double       deviation,        // ④ 標準偏差の倍率
   int          bands_shift,      // ⑤ インジケーターのシフト数
   int          applied_price,    // ⑥ 適用価格
   int          mode,             // ⑦ ライン種類
   int          shift             // ⑧ シフト数(何本前のバーか)
);

戻り値はdouble型で、指定した条件のボリンジャーバンドの値(価格)が返されます。引数が8つあるため少し多く感じますが、ひとつずつ見ていけば難しくありません。

各引数の詳細解説

① symbol(通貨ペア名)

計算対象の通貨ペアを文字列で指定します。現在のチャートの通貨ペアを使いたい場合はNULLまたはSymbol()を指定します。

// 現在のチャートの通貨ペアを使う場合
iBands(NULL, ...)
iBands(Symbol(), ...)

// 別の通貨ペアを指定する場合
iBands("USDJPY", ...)

② timeframe(時間足)

計算に使う時間足を指定します。現在のチャートの時間足を使う場合は0またはPERIOD_CURRENTを指定します。

定数 意味
PERIOD_CURRENT 0 現在のチャートの時間足
PERIOD_M1 1 1分足
PERIOD_M5 5 5分足
PERIOD_M15 15 15分足
PERIOD_M30 30 30分足
PERIOD_H1 60 1時間足
PERIOD_H4 240 4時間足
PERIOD_D1 1440 日足
PERIOD_W1 10080 週足
PERIOD_MN1 43200 月足

③ period(計算期間)

移動平均線の計算に使うバーの本数を指定します。一般的には20がよく使われます。期間を短くするとバンドが価格に敏感に反応し、長くすると滑らかになります。

④ deviation(標準偏差の倍率)

バンドの幅を決める標準偏差の倍率です。一般的には2.0が使われます。1.0を指定すれば±1σ、3.0なら±3σのバンドが取得できます。

⑤ bands_shift(インジケーターのシフト数)

ボリンジャーバンド全体を左右にずらす本数です。通常は0を指定します。正の値を指定するとバンドが右(未来方向)にずれます。特殊な用途でない限り0で問題ありません。

⑥ applied_price(適用価格)

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

定数 意味
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

⑦ mode(ライン種類)

取得したいラインを指定します。iBands関数は1回の呼び出しで1本のラインの値しか返さないため、3本すべてを取得するには3回呼び出す必要があります。

定数 意味
MODE_MAIN 0 ミドルバンド(中間線・移動平均線)
MODE_UPPER 1 アッパーバンド(上方バンド)
MODE_LOWER 2 ロワーバンド(下方バンド)

⑧ shift(シフト数)

何本前のバーの値を取得するかを指定します。0が現在のバー(まだ確定していないバー)、1が1本前の確定済みバー、2が2本前…という意味です。

EA(自動売買)で売買判断に使う場合は、確定済みの値であるshift=1を使うのが一般的です。shift=0は現在足の値なのでティックごとに変動し、判断がブレやすくなるためです。

基本的な使用例

まずは最もシンプルな例として、現在のチャートで期間20・偏差2.0のボリンジャーバンド3本の値を取得してみましょう。

void OnTick()
{
   // 1本前の確定足でボリンジャーバンドの値を取得
   double upper = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
   double middle = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_MAIN,  1);
   double lower = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_LOWER, 1);

   // ログに出力して確認
   Print("Upper: ", upper, " | Middle: ", middle, " | Lower: ", lower);
}

このコードでは、3つのiBands呼び出しでmode引数だけを変えて、上方バンド・中間線・下方バンドの3つの値をそれぞれ取得しています。それ以外の引数はすべて同じ値を指定します。

実践サンプル:ボリンジャーバンド逆張りEA

ここでは、ボリンジャーバンドの±2σを使ったシンプルな逆張りEAを作ってみましょう。ロジックは以下のとおりです。

  • 買いエントリー:1本前の終値がロワーバンド(-2σ)を下回ったら買い
  • 売りエントリー:1本前の終値がアッパーバンド(+2σ)を上回ったら売り
  • 決済:ミドルバンドに到達したら決済
//+------------------------------------------------------------------+
//| ボリンジャーバンド逆張りEA                                         |
//+------------------------------------------------------------------+
#property strict

// 入力パラメーター
input int    BB_Period    = 20;     // ボリンジャーバンドの期間
input double BB_Deviation = 2.0;    // 標準偏差の倍率
input double Lots         = 0.1;    // ロット数
input int    Slippage     = 3;      // スリッページ
input int    MagicNumber  = 12345;  // マジックナンバー

//+------------------------------------------------------------------+
//| OnTick関数                                                        |
//+------------------------------------------------------------------+
void OnTick()
{
   // ボリンジャーバンドの各ラインを取得(1本前の確定足)
   double upper  = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_UPPER, 1);
   double middle = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_MAIN,  1);
   double lower  = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_LOWER, 1);

   // 1本前の終値
   double prevClose = Close[1];

   // 現在のポジション数を確認
   int buyCount  = CountOrders(OP_BUY);
   int sellCount = CountOrders(OP_SELL);

   // --- エントリーロジック ---
   // 買いエントリー:終値がロワーバンドを下回った
   if(buyCount == 0 && prevClose < lower)
   {
      int ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0,
                             "BB Buy", MagicNumber, 0, clrBlue);
      if(ticket < 0)
         Print("Buy OrderSend Error: ", GetLastError());
   }

   // 売りエントリー:終値がアッパーバンドを上回った
   if(sellCount == 0 && prevClose > upper)
   {
      int ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, 0,
                             "BB Sell", MagicNumber, 0, clrRed);
      if(ticket < 0)
         Print("Sell OrderSend Error: ", GetLastError());
   }

   // --- 決済ロジック:ミドルバンドに到達したら決済 ---
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;

      // 現在のバーのミドルバンドを取得(決済判断用)
      double currentMiddle = iBands(NULL, 0, BB_Period, BB_Deviation, 0, PRICE_CLOSE, MODE_MAIN, 0);

      if(OrderType() == OP_BUY && Bid >= currentMiddle)
      {
         if(!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrBlue))
            Print("Buy OrderClose Error: ", GetLastError());
      }
      else if(OrderType() == OP_SELL && Ask <= currentMiddle)
      {
         if(!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrRed))
            Print("Sell OrderClose Error: ", GetLastError());
      }
   }
}

//+------------------------------------------------------------------+
//| 指定タイプのポジション数をカウントする関数                          |
//+------------------------------------------------------------------+
int CountOrders(int orderType)
{
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
         count++;
   }
   return count;
}

このEAのポイントをまとめます。

  • エントリー判断はshift=1(確定足)を使い、値がブレないようにしています
  • 決済判断はshift=0(現在足)を使い、リアルタイムの価格とミドルバンドを比較しています
  • CountOrders関数でポジション数を確認し、同方向に重複エントリーしないようにしています
  • MagicNumberを使うことで、他のEAのポジションと区別しています

応用テクニック

複数のσを同時に使う

ボリンジャーバンドの±1σ、±2σ、±3σを同時に取得すれば、より細かい分析が可能です。deviation引数を変えるだけで実現できます。

// ±1σ
double upper1 = iBands(NULL, 0, 20, 1.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lower1 = iBands(NULL, 0, 20, 1.0, 0, PRICE_CLOSE, MODE_LOWER, 1);

// ±2σ
double upper2 = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lower2 = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_LOWER, 1);

// ±3σ
double upper3 = iBands(NULL, 0, 20, 3.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lower3 = iBands(NULL, 0, 20, 3.0, 0, PRICE_CLOSE, MODE_LOWER, 1);

たとえば「±1σの範囲内ならレンジ相場と判断し取引を控える」「±3σにタッチしたら強い逆張りシグナル」といった使い方ができます。

バンド幅でボラティリティを判定する

アッパーバンドとロワーバンドの差を計算すれば、バンド幅(ボラティリティの目安)が分かります。

double upper  = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
double lower  = iBands(NULL, 0, 20, 2.0, 0, PRICE_CLOSE, MODE_LOWER, 1);

// バンド幅を計算
double bandWidth = upper - lower;

// バンド幅をポイント単位に変換(通貨ペアの桁数に応じて調整)
double bandWidthPoints = bandWidth / Point;

// ボラティリティ判定の例
if(bandWidthPoints < 200)
{
   Print("スクイーズ状態(低ボラティリティ):バンド幅 = ", bandWidthPoints, " points");
   // → この後のブレイクアウトに備える
}
else if(bandWidthPoints > 500)
{
   Print("エクスパンション状態(高ボラティリティ):バンド幅 = ", bandWidthPoints, " points");
   // → トレンドフォロー戦略を検討
}

バンドが極端に狭くなった状態(スクイーズ)は、その後大きなトレンドが発生する前兆とされています。バンドが急激に広がった状態(エクスパンション)はトレンドが発生中であることを示します。

よくある間違いと注意点

shift=0は未確定の値

最も多い間違いのひとつが、shift=0の値でエントリー判断をしてしまうことです。shift=0は現在のバー(まだローソク足が確定していない状態)の値なので、ティックが来るたびに値が変わります。

エントリー条件にはshift=1(確定済みのバー)を使うようにしましょう。バックテストとリアルトレードの結果が大きくずれる原因にもなります。

MODE定数の取り違え

iBands関数のmode引数で使う定数と、iMACD関数などの他のインジケーター関数のmode定数は名前が似ていても意味が異なる場合があります。iBandsではMODE_MAIN(0)、MODE_UPPER(1)、MODE_LOWER(2)の3つを使います。

特にMODE_MAINはiMACD関数でも使われる定数ですが、iBandsではミドルバンド(移動平均線)を意味します。関数ごとにどの定数がどのラインを表すか確認しましょう。

マルチタイムフレームでの注意

timeframe引数に現在のチャートと異なる時間足を指定すると、上位足のボリンジャーバンドを取得できます。しかし、いくつか注意点があります。

// 1時間足チャートで日足のボリンジャーバンドを取得
double dailyUpper = iBands(NULL, PERIOD_D1, 20, 2.0, 0, PRICE_CLOSE, MODE_UPPER, 1);
  • 上位足のデータが十分にダウンロードされていないとエラーや不正確な値が返されることがあります
  • 上位足のshift=0は上位足の現在のバーを指すため、確定タイミングがチャート時間足とは異なります
  • バックテストでは「全ティック」モデルを使わないとマルチタイムフレームの値が正しく取得できない場合があります

まとめ

この記事では、MQL4のiBands関数について、基本構文から各引数の詳細、実践的なEAサンプル、応用テクニックまで解説しました。最後にポイントを整理します。

  • iBands関数は8つの引数を持ち、ボリンジャーバンドの値をdouble型で返す
  • mode引数でMODE_MAIN(中間線)、MODE_UPPER(上方バンド)、MODE_LOWER(下方バンド)を切り替える
  • 3本のラインを取得するにはiBandsを3回呼び出す必要がある
  • エントリー判断にはshift=1(確定足)を使うのが基本
  • deviation引数を変えることで、±1σ/±2σ/±3σなど複数のバンドを簡単に取得できる
  • バンド幅の計算でボラティリティの判定(スクイーズ・エクスパンション)にも活用できる

iBands関数はシンプルながらも応用範囲が広い関数です。まずは基本的な使い方をマスターし、他のテクニカル指標と組み合わせたり、エントリー条件を工夫したりして、自分だけのEA開発に挑戦してみてください!