【MQL5】iBands関数の使い方|ボリンジャーバンドで逆張り・スクイーズを判定するサンプルコード

【MQL5】iBands関数の使い方|ボリンジャーバンドで逆張り・スクイーズを判定するサンプルコード MQL5リファレンス

iBands関数は、ボリンジャーバンド(中央線・上バンド・下バンド)の値をMQL5プログラムから取得する関数です。ボリンジャーバンドは「価格が平均からどれだけ離れたか(標準偏差)」を帯で表す指標で、レンジでの逆張りバンド幅でのボラティリティ判定(スクイーズ)に使われます。この記事では、iBandsの構文と「ハンドル+CopyBufferの2段階」、そしてコピーしてすぐ動く4つのサンプル(3本線の取得・バンドタッチ判定・バンド抜けシグナル・逆張りの最小EA)を丁寧に解説します。

iBands(ボリンジャーバンド)とは

ボリンジャーバンドは、移動平均(中央線)の上下に「標準偏差 × 倍率(通常2.0)」ぶんの帯を描いた指標です。統計的に、価格はおおむね±2σの帯の内側に収まりやすいとされ、帯の外に出た価格の反発(逆張り)や、帯の幅の収縮・拡大(スクイーズ/エクスパンション)でボラティリティを読むのに使われます。MQL5では iBands() でこの3本の線を取得し、EAの条件に組み込めます。

前提:値の取り出しは「2段階」
MQL5のインジケーターは「① OnInit() でハンドルを作る → ② OnTick()CopyBuffer() により値を取り出す」の2段階です(詳しくは iMAの記事 を参照)。iBandsも同じ作法ですが、線が3本=バッファが3つある点だけ異なります。

iBands() の構文と引数

int  iBands(
   string              symbol,         // 通貨ペア(_Symbol で現在のペア)
   ENUM_TIMEFRAMES     period,         // 時間足(PERIOD_CURRENT 等)
   int                 bands_period,   // 期間(一般的に 20)
   int                 bands_shift,    // シフト(通常 0)
   double              deviation,      // 標準偏差の倍率(通常 2.0)
   ENUM_APPLIED_PRICE  applied_price   // 適用価格(通常 PRICE_CLOSE)
);

戻り値はハンドル(整数のID)です。後で CopyBuffer() に渡すための「取っ手」だと考えてください。ボリンジャーバンドのバッファ番号は次の3つです。

バッファ番号(ここが重要)
0 = 中央線(ベース=移動平均)/ 1 = 上バンド(UPPER)/ 2 = 下バンド(LOWER)。RSIやMAは0番だけでしたが、iBandsは0・1・2を使い分けます

サンプル①:上・中・下の3本を取得して表示する

ボリンジャーバンド(20, 2.0) の現在値(3本)をチャート左上に表示する、最小のコードです。

コピペOK

int bbHandle = INVALID_HANDLE;

int OnInit()
{
   // ① ハンドルを1回だけ作る(期間20・シフト0・偏差2.0・終値ベース)
   bbHandle = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE);
   if(bbHandle == INVALID_HANDLE)
   {
      Print("iBandsハンドルの作成に失敗: ", GetLastError());
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   double mid[], up[], low[];
   ArraySetAsSeries(mid, true);              // [0]を最新足にそろえる
   ArraySetAsSeries(up,  true);
   ArraySetAsSeries(low, true);

   // ② 3本それぞれを、バッファ番号を指定して取り出す
   if(CopyBuffer(bbHandle, 0, 0, 2, mid) < 2) return;   // 0=中央線
   if(CopyBuffer(bbHandle, 1, 0, 2, up)  < 2) return;   // 1=上バンド
   if(CopyBuffer(bbHandle, 2, 0, 2, low) < 2) return;   // 2=下バンド

   Comment("上 ", DoubleToString(up[0], _Digits),
           "  中 ", DoubleToString(mid[0], _Digits),
           "  下 ", DoubleToString(low[0], _Digits));
}

void OnDeinit(const int reason)
{
   IndicatorRelease(bbHandle);               // 後始末
}

サンプル②:上バンド・下バンドへのタッチを判定する

確定した足の終値が「下バンドより下(行きすぎ)/上バンドより上」かを判定します。形成中の足ではなく確定足で、新しい足ができた時だけチェックします。

コピペOK

datetime lastBar = 0;

void OnTick()
{
   datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(t == lastBar) return;                  // 新しい足の時だけ
   lastBar = t;

   double up[], low[];
   ArraySetAsSeries(up,  true);
   ArraySetAsSeries(low, true);
   if(CopyBuffer(bbHandle, 1, 0, 2, up)  < 2) return;
   if(CopyBuffer(bbHandle, 2, 0, 2, low) < 2) return;

   double close1 = iClose(_Symbol, PERIOD_CURRENT, 1);  // 直近の確定足の終値

   if(close1 < low[1])      Print("下バンド割れ(売られすぎ):", DoubleToString(close1, _Digits));
   else if(close1 > up[1])  Print("上バンド超え(買われすぎ):", DoubleToString(close1, _Digits));
}

サンプル③:バンドを「戻した瞬間」でシグナルを出す

バンドの外に出ただけで逆張りすると、強いトレンド(バンドウォーク)で連敗します。そこで「下バンドの外から内側に戻った=売られすぎからの反発」のように、バンドをまたいで戻った瞬間をシグナルにします。確定足の [1] と [2] を比較します。

コピペOK

double low[], up[];
ArraySetAsSeries(low, true);
ArraySetAsSeries(up,  true);
if(CopyBuffer(bbHandle, 2, 0, 3, low) < 3) return;   // 下バンド [1],[2]
if(CopyBuffer(bbHandle, 1, 0, 3, up)  < 3) return;   // 上バンド [1],[2]

double c1 = iClose(_Symbol, PERIOD_CURRENT, 1);     // 直近の確定足
double c2 = iClose(_Symbol, PERIOD_CURRENT, 2);     // その1本前

// 下バンドの外→内に戻した=買いシグナル(売られすぎからの反発)
bool buySignal  = (c2 < low[2] && c1 > low[1]);

// 上バンドの外→内に戻した=売りシグナル(買われすぎからの反落)
bool sellSignal = (c2 > up[2]  && c1 < up[1]);

if(buySignal)  Print("買いシグナル(下バンドから回帰)");
if(sellSignal) Print("売りシグナル(上バンドから回帰)");

サンプル④:ボリンジャーバンド逆張りの最小EA

サンプル③の買いシグナルでエントリーし、価格が中央線まで戻ったら決済する、動く最小EAです。CTrade を使います。

コピペOK(デモ口座で動作確認用)

#include <Trade\Trade.mqh>
CTrade   trade;
int      bbHandle;
datetime lastBar = 0;
input double InpLot = 0.10;

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

void OnTick()
{
   datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(t == lastBar) return;
   lastBar = t;

   double mid[], low[];
   ArraySetAsSeries(mid, true);
   ArraySetAsSeries(low, true);
   if(CopyBuffer(bbHandle, 0, 0, 3, mid) < 3) return;   // 中央線
   if(CopyBuffer(bbHandle, 2, 0, 3, low) < 3) return;   // 下バンド

   double c1 = iClose(_Symbol, PERIOD_CURRENT, 1);
   double c2 = iClose(_Symbol, PERIOD_CURRENT, 2);

   bool buySignal = (c2 < low[2] && c1 > low[1]);        // 下バンドから回帰
   bool exitLong  = (c1 >= mid[1]);                      // 中央線まで戻ったら利確(簡易)

   if(buySignal && PositionsTotal() == 0)
      trade.Buy(InpLot, _Symbol);

   if(exitLong)
   {
      for(int i = PositionsTotal() - 1; i >= 0; i--)
      {
         ulong ticket = PositionGetTicket(i);
         if(PositionSelectByTicket(ticket) &&
            PositionGetString(POSITION_SYMBOL) == _Symbol)
            trade.PositionClose(ticket);
      }
   }
}

void OnDeinit(const int reason)
{
   IndicatorRelease(bbHandle);
}
これは学習用の最小サンプルです
損切り(SL)・利確(TP)・スプレッド確認・資金管理は入っていません。実運用にはこれらの安全装置が必須です。まずはデモ口座で動きを確認してください。

ボリンジャーバンドを使うときの注意・落とし穴

① トレンドでは「バンドウォーク」で逆張りが効かない
強いトレンドでは、価格が上(下)バンドに沿って走り続けます(バンドウォーク)。「バンドに触れた=即逆張り」は危険。上位足のトレンドiMA 等)と組み合わせ、レンジ場面に絞ると安定します。
② バンド幅で「レンジ/ブレイク前」を見分ける
バンド幅(上バンド − 下バンド)が縮むのがスクイーズ=エネルギーの溜まり。広がり始め(エクスパンション)はトレンド発生のサインです。逆張りとブレイクは、バンド幅で使い分けます。
③ お決まりの3点 + バッファ番号
ハンドルは OnInit() で1回だけ/CopyBuffer() の戻り値を必ずチェック/ArraySetAsSeries(配列, true) を忘れない。iBands特有の注意として、0=中央・1=上・2=下のバッファ番号を取り違えないこと。

まとめ

  • iBands() はボリンジャーバンドのハンドルを返す。値は CopyBuffer() で取り出す
  • バッファは 0=中央線 / 1=上バンド / 2=下バンド の3つ。番号の取り違えに注意
  • 逆張りは「触れた」より「バンドから戻った瞬間」をシグナルにするとダマシが減る(サンプル③)
  • トレンド(バンドウォーク)では逆張りが連敗しやすい。上位足フィルターやバンド幅で場面を選ぶ
  • ハンドルはOnInitで1回・戻り値チェック・ArraySetAsSeries を忘れない
タイトルとURLをコピーしました