iBands関数は、ボリンジャーバンド(中央線・上バンド・下バンド)の値をMQL5プログラムから取得する関数です。ボリンジャーバンドは「価格が平均からどれだけ離れたか(標準偏差)」を帯で表す指標で、レンジでの逆張りやバンド幅でのボラティリティ判定(スクイーズ)に使われます。この記事では、iBandsの構文と「ハンドル+CopyBufferの2段階」、そしてコピーしてすぐ動く4つのサンプル(3本線の取得・バンドタッチ判定・バンド抜けシグナル・逆張りの最小EA)を丁寧に解説します。
iBands(ボリンジャーバンド)とは
ボリンジャーバンドは、移動平均(中央線)の上下に「標準偏差 × 倍率(通常2.0)」ぶんの帯を描いた指標です。統計的に、価格はおおむね±2σの帯の内側に収まりやすいとされ、帯の外に出た価格の反発(逆張り)や、帯の幅の収縮・拡大(スクイーズ/エクスパンション)でボラティリティを読むのに使われます。MQL5では iBands() でこの3本の線を取得し、EAの条件に組み込めます。
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 等)と組み合わせ、レンジ場面に絞ると安定します。
バンド幅(上バンド − 下バンド)が縮むのがスクイーズ=エネルギーの溜まり。広がり始め(エクスパンション)はトレンド発生のサインです。逆張りとブレイクは、バンド幅で使い分けます。
ハンドルは
OnInit() で1回だけ/CopyBuffer() の戻り値を必ずチェック/ArraySetAsSeries(配列, true) を忘れない。iBands特有の注意として、0=中央・1=上・2=下のバッファ番号を取り違えないこと。まとめ
iBands()はボリンジャーバンドのハンドルを返す。値はCopyBuffer()で取り出す- バッファは 0=中央線 / 1=上バンド / 2=下バンド の3つ。番号の取り違えに注意
- 逆張りは「触れた」より「バンドから戻った瞬間」をシグナルにするとダマシが減る(サンプル③)
- トレンド(バンドウォーク)では逆張りが連敗しやすい。上位足フィルターやバンド幅で場面を選ぶ
- ハンドルはOnInitで1回・戻り値チェック・ArraySetAsSeries を忘れない

