MQL5 iBandsの使い方|ボリンジャーバンド取得・CopyBufferで値を取得する方法

目次

1. MQL5の iBands とは何か

iBands は、MQL5でボリンジャーバンド(Bollinger Bands)を取得するための標準関数です。 MetaTrader 5(MT5)では、テクニカル指標の値をEA(自動売買プログラム)やスクリプトから取得する場合、インジケータハンドル(indicator handle:指標の計算結果へアクセスする識別番号)を作成し、そのハンドルを使ってデータを読み取る仕組みになっています。 一般的な処理の流れは次のとおりです。
  1. iBands でボリンジャーバンドのインジケータハンドルを作成
  2. CopyBufferバンド値を取得
  3. 取得した値を売買ロジックに使用
この構造は、MQL4のインジケータ取得方法と大きく異なる点です。 MQL4ではインジケータ関数を呼ぶだけで値を取得できましたが、MQL5では次のような2段階の仕組みになっています。
  • ハンドル生成
  • バッファから値取得
この違いを理解していないと、初心者は次のような問題に直面します。 よくある失敗
  • iBands を呼んだだけで値が取得できると思ってしまう
  • CopyBuffer を使わずにバンド値を取得しようとする
  • OnTick() 内で毎回 iBands を作成してしまい、EAが重くなる
特に3つ目のミスは、EAのパフォーマンス低下の原因になります。 インジケータハンドルは通常 OnInit() で一度だけ作成するのが基本です。

1.1 ボリンジャーバンド(Bollinger Bands)の基本

ボリンジャーバンドは、価格の変動幅(ボラティリティ)を可視化するテクニカル指標です。 ジョン・ボリンジャーによって考案され、トレードでは非常に広く使われています。 ボリンジャーバンドは次の3つのラインで構成されます。
ライン 内容
中央線 移動平均(通常はSMA)
上バンド 移動平均 + 標準偏差
下バンド 移動平均 – 標準偏差
ここでの 標準偏差とは、価格が平均値からどれくらい離れているかを示す統計値です。 つまり、ボリンジャーバンドは次のような特徴を持ちます。
  • 相場のボラティリティが高い → バンドが広がる
  • 相場が静かな → バンドが狭くなる
この特性を利用して、トレードでは次のような判断が行われます。 代表的な利用方法
  • 上バンド付近 → 買われ過ぎ
  • 下バンド付近 → 売られ過ぎ
  • バンド拡張 → トレンド発生
  • バンド収縮 → レンジ相場
ただし、これらは絶対的な売買シグナルではありません。 市場環境や時間足によって挙動は大きく変わるため、EA開発では他の指標と組み合わせて使用することが一般的です。

1.2 EA開発での主な用途

MQL5で iBands を使う目的は、ボリンジャーバンドを利用した売買ロジックの実装です。 EAでは主に次のような用途で使われます。

逆張り戦略

価格がバンドの外側に到達した場合、行き過ぎと判断して反転を狙う方法です。 例
  • 上バンド到達 → 売り
  • 下バンド到達 → 買い
この戦略はレンジ相場で有効な場合が多いですが、強いトレンドでは機能しないことがあります。

ブレイクアウト戦略

バンドの外側へ価格が突破した場合、トレンドの開始と判断する方法です。 例
  • 上バンド突破 → 買い
  • 下バンド突破 → 売り
この手法はトレンドフォロー型EAでよく使われます。

ボラティリティ判定

バンド幅を計算することで、相場の状態を判断できます。 例
  • バンド幅が狭い → 相場が静か
  • バンド幅が拡大 → トレンド開始の可能性
この情報は、次のような用途に使われます。
  • トレード開始タイミング
  • ロットサイズ調整
  • トレード停止フィルター

注意点(初心者がよく誤解する点)

ボリンジャーバンドは方向を示す指標ではありません。 あくまで「価格の変動幅」を示す指標です。 そのため、次のような誤解がよくあります。 よくある誤解
  • 上バンド到達 = 必ず下がる
  • 下バンド到達 = 必ず上がる
実際には、強いトレンドではバンド沿いに価格が動き続けることもあります。 EAロジックでは、RSIやATRなどの他指標と組み合わせることが多いです。 MQL5 iBands indicator workflow diagram showing how to create an indicator handle in OnInit, retrieve Bollinger Bands values using CopyBuffer (middle, upper, lower buffers), and apply them to trading logic decisions on a MetaTrader chart with code and data flow arrows.

2. iBands の構文(シンタックス)とパラメータ

iBands は、ボリンジャーバンドインジケータのハンドル(識別番号)を作成する関数です。 この関数を実行すると、MetaTrader内部でボリンジャーバンドの計算インジケータが生成され、そのハンドル(整数値)が返されます。 このハンドルは、その後 CopyBuffer を使ってバンド値を取得するために使用します。 MQL5での基本構文は次の通りです。
int iBands(
   string           symbol,
   ENUM_TIMEFRAMES  period,
   int              bands_period,
   int              bands_shift,
   double           deviation,
   ENUM_APPLIED_PRICE applied_price
);
戻り値
  • 成功:インジケータハンドル(0以上の整数)
  • 失敗:INVALID_HANDLE
そのため、EAでは通常次のようにエラーチェックを行います。
int bandsHandle = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE);

if(bandsHandle == INVALID_HANDLE)
{
   Print("iBandsの作成に失敗しました");
}
このエラーチェックを行わないと、後続の CopyBuffer原因不明のエラーが発生することがあります。

2.1 各パラメータの意味

iBands には6つのパラメータがあります。 それぞれの意味を理解しておくことは、EA開発では非常に重要です。
パラメータ 内容
symbol 通貨ペア(例:EURUSD)
period 時間足
bands_period 移動平均期間
bands_shift バンドのシフト
deviation 標準偏差
applied_price 使用する価格
以下で個別に解説します。

symbol(通貨ペア)

インジケータを計算する通貨ペアを指定します。 例
_Symbol
これは「現在のチャートの通貨ペア」を意味します。 例
iBands("EURUSD", PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE);
複数通貨EAでは、異なる通貨ペアを指定することも可能です。 注意点
  • 通貨名を間違えると INVALID_HANDLE になります
  • ブローカーによっては EURUSD.m のような接尾辞が付く場合があります

period(時間足)

ボリンジャーバンドを計算する時間足です。 主な指定方法
PERIOD_CURRENT
PERIOD_M1
PERIOD_M5
PERIOD_M15
PERIOD_H1
PERIOD_D1
PERIOD_H1
これは1時間足のボリンジャーバンドを意味します。 よくあるミス
  • EAの時間足とインジケータ時間足を混同する
  • マルチタイムフレーム処理を理解せず使う
初心者はまず
PERIOD_CURRENT
を使うと安全です。

bands_period(移動平均期間)

中央線の移動平均期間です。 例
20
これは一般的なボリンジャーバンド設定です。 代表的な設定
期間 用途
20 一般的
14 短期トレード
50 中期トレンド
期間が小さいほど、反応が速いがノイズが増えます

bands_shift(バンドシフト)

インジケータの表示位置を右へずらす値です。 通常は
0
を使用します。 この値は主にチャート表示の都合のためのものであり、EAロジックではほとんど使用されません。 初心者は 0固定で問題ありません

deviation(標準偏差)

バンド幅を決める標準偏差倍率です。 代表例
2.0
これは最も一般的な設定です。 例
deviation 特徴
1.0 狭いバンド
2.0 標準
3.0 非常に広い
値が大きいほど、バンドは広くなります。

applied_price(適用価格)

インジケータ計算に使う価格の種類です。 主な値
PRICE_CLOSE
PRICE_OPEN
PRICE_HIGH
PRICE_LOW
PRICE_MEDIAN
PRICE_TYPICAL
PRICE_WEIGHTED
初心者は通常
PRICE_CLOSE
を使用します。 これは終値ベースのボリンジャーバンドです。

2.2 iBands を使う基本コード

EAでは通常、OnInit() でハンドルを作成します。 例
int bandsHandle;

int OnInit()
{
   bandsHandle = iBands(
      _Symbol,
      PERIOD_CURRENT,
      20,
      0,
      2.0,
      PRICE_CLOSE
   );

   if(bandsHandle == INVALID_HANDLE)
   {
      Print("iBands作成エラー");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}
この方法により、EA起動時に1回だけインジケータを生成できます。

よくある失敗

初心者がよくやるミスをまとめます。

OnTick()で毎回iBandsを作る

// 悪い例
void OnTick()
{
   int handle = iBands(...);
}
これは毎ティックでインジケータ生成するため、EAが重くなります。

エラーチェックをしない

int handle = iBands(...);
これだけでは、失敗しても気づけません

CopyBuffer前にハンドル確認をしない

ハンドルが無効だと
array out of range
などのエラー原因になります。

3. CopyBuffer を使ってボリンジャーバンドの値を取得する方法

iBandsボリンジャーバンドの計算インジケータを生成する関数ですが、 この関数だけではバンドの値を取得することはできません。 実際に値を取得するためには、CopyBuffer 関数を使用してインジケータバッファからデータをコピーする必要があります。 MQL5では、インジケータは内部的に複数のバッファ(データ配列)を持っています。 ボリンジャーバンドの場合、次の3つのラインがそれぞれ別のバッファに格納されています。
バッファ番号 内容
0 中央線(Middle Band / Moving Average / BASE_LINE)
1 上バンド(Upper Band / UPPER_BAND)
2 下バンド(Lower Band / LOWER_BAND)
このバッファ番号を指定して CopyBuffer を呼び出すことで、 EAは任意のバンド値を取得できます。

3.1 CopyBuffer の基本構文

CopyBuffer の基本構文は次の通りです。
int CopyBuffer(
   int       indicator_handle,
   int       buffer_num,
   int       start_pos,
   int       count,
   double    buffer[]
);
各パラメータの意味は次の通りです。
パラメータ 内容
indicator_handle iBandsで取得したハンドル
buffer_num バッファ番号
start_pos 取得開始位置
count 取得するデータ数
buffer データ格納配列
戻り値
  • コピーした要素数
  • 失敗すると -1
そのため、実際のEAでは戻り値チェックを行うことが重要です。

3.2 上バンドを取得するコード例

まず、上バンド(Upper Band)を取得する例を見てみます。
double upperBand[];

if(CopyBuffer(bandsHandle, 1, 0, 1, upperBand) < 0)
{
   Print("CopyBufferエラー");
}
このコードの意味は次の通りです。
パラメータ 意味
bandsHandle iBandsハンドル
1 上バンド
0 最新バー
1 1本取得
結果は次のように取得できます。
double upper = upperBand[0];

3.3 下バンドと中央線を取得する方法

同じ方法で、中央線と下バンドも取得できます。

中央線(移動平均)

double middleBand[];

CopyBuffer(bandsHandle, 0, 0, 1, middleBand);

下バンド

double lowerBand[];

CopyBuffer(bandsHandle, 2, 0, 1, lowerBand);

3.4 実践的なコード例

EAでは通常、3つのバンドを同時に取得します。
double middle[1];
double upper[1];
double lower[1];

if(CopyBuffer(bandsHandle,0,0,1,middle) < 0) return;
if(CopyBuffer(bandsHandle,1,0,1,upper) < 0) return;
if(CopyBuffer(bandsHandle,2,0,1,lower) < 0) return;

double middleBand = middle[0];
double upperBand  = upper[0];
double lowerBand  = lower[0];
これにより、EA内でボリンジャーバンドの3ラインを使用できます。

3.5 よくある失敗と注意点

CopyBuffer は初心者が最もつまずきやすい部分です。 特に次のミスが非常に多く見られます。

配列サイズを確保していない

次のコードは危険です。
double upper[];

CopyBuffer(handle,1,0,1,upper);
配列サイズが確保されていない場合、エラーになる可能性があります。 安全な方法
double upper[1];
または
ArrayResize(upper,1);

バッファ番号を間違える

初心者が混乱しやすいポイントです。
バッファ 内容
0 中央線
1 上バンド
2 下バンド
この順番を間違えると、ロジックが完全に崩れます

データがまだ準備されていない

EA起動直後などでは、インジケータ計算がまだ完了していない場合があります。 その場合、CopyBuffer-1 を返します。 安全な処理
if(CopyBuffer(...) <= 0)
   return;

最新バーと確定バーを混同する

start_pos = 0現在進行中のバーです。 そのため、EAロジックでは次のように使う場合があります。
start_pos 意味
0 最新バー
1 確定バー
トレードロジックでは 確定バー(1) を使うケースも多いです。

4. EAで iBands を使う実装例

iBands は、単にボリンジャーバンドを表示するための関数ではありません。 EAでは、取得したバンド値と現在価格を比較し、売買条件を機械的に判定するための材料として使います。 ただし、ボリンジャーバンドはそれ単体で万能な売買シグナルではありません。 実務では、次のように役割を分けて使うことが多いです。
  • 逆張り判定
  • ブレイクアウト判定
  • 相場の静かさ・荒さの判定
  • エントリー禁止フィルター
このセクションでは、初心者が理解しやすいように、まずはもっとも基本的な2パターンを扱います。
  • バンド到達で反転を狙う逆張り型
  • バンド突破で流れに乗るブレイクアウト型

4.1 逆張りロジックの基本例

逆張り型では、価格がバンド外側まで到達したときに、行き過ぎからの戻りを狙います。 典型例は次の通りです。
  • 現在価格が上バンド以上 → 売りを検討
  • 現在価格が下バンド以下 → 買いを検討
コード例は次のようになります。
double upper[1];
double lower[1];

if(CopyBuffer(bandsHandle, 1, 0, 1, upper) <= 0) return;
if(CopyBuffer(bandsHandle, 2, 0, 1, lower) <= 0) return;

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

if(bid >= upper[0])
{
   Print("売りシグナル候補:価格が上バンドに到達");
}

if(ask <= lower[0])
{
   Print("買いシグナル候補:価格が下バンドに到達");
}
このコードでは、まだ注文は出していません。 まずは条件判定だけをログ出力する形にしておくと、ロジック検証がしやすくなります。

4.2 ブレイクアウトロジックの基本例

ブレイクアウト型では、価格がバンド外へ出たことを勢いの発生とみなし、その方向へ追随します。 典型例は次の通りです。
  • 終値が上バンドを上抜け → 買い候補
  • 終値が下バンドを下抜け → 売り候補
この場合、現在進行中のバーではなく、確定したバーを使う方が安全です。 そのため、CopyBuffer では start_pos = 1 を使うことが多くなります。
double upper[1];
double lower[1];
double closePrice[1];

if(CopyBuffer(bandsHandle, 1, 1, 1, upper) <= 0) return;
if(CopyBuffer(bandsHandle, 2, 1, 1, lower) <= 0) return;
if(CopyClose(_Symbol, PERIOD_CURRENT, 1, 1, closePrice) <= 0) return;

if(closePrice[0] > upper[0])
{
   Print("買いブレイク候補:確定足終値が上バンドを上抜け");
}

if(closePrice[0] < lower[0])
{
   Print("売りブレイク候補:確定足終値が下バンドを下抜け");
}
この方法の利点は、未確定バーの一時的な飛び出しを除外しやすいことです。

4.3 バンド幅を使ったボラティリティ判定

ボリンジャーバンドは、上バンドと下バンドの差を取ることで、相場の変動の大きさを数値化できます。 計算式は単純です。
double bandWidth = upper[0] - lower[0];
コード例は次の通りです。
double upper[1];
double lower[1];

if(CopyBuffer(bandsHandle, 1, 1, 1, upper) <= 0) return;
if(CopyBuffer(bandsHandle, 2, 1, 1, lower) <= 0) return;

double bandWidth = upper[0] - lower[0];

if(bandWidth < 0.0010)
{
   Print("バンド幅が小さいため見送り");
}
else
{
   Print("バンド幅が十分あるため売買候補");
}

5.2 CopyBuffer が失敗する原因

iBands が正常でも、CopyBuffer が必ず成功するわけではありません。 MQL5では、インジケータ計算がまだ準備できていない段階CopyBuffer を呼ぶと失敗することがあります。 たとえば次のコードは、戻り値チェックがないため危険です。
double upper[1];
CopyBuffer(bandsHandle, 1, 0, 1, upper);
double value = upper[0];
この場合、コピー失敗時でもそのまま upper[0] を使ってしまい、 ロジック異常や誤判定の原因になります。 安全な書き方は次の通りです。
double upper[1];

if(CopyBuffer(bandsHandle, 1, 0, 1, upper) <= 0)
{
   Print("上バンドの取得に失敗");
   return;
}

5.3 バッファ番号の取り違え

iBands は3本のラインを扱いますが、 初心者が最も混乱しやすいのがバッファ番号の順番です。 MQL5公式ドキュメントでは、iBands のバッファ番号は次の通りです。
バッファ番号 内容
0 中央線(BASE_LINE)
1 上バンド(UPPER_BAND)
2 下バンド(LOWER_BAND)
ここを逆に覚えると、ロジックはコンパイル上問題なく動いても、売買判定が完全に誤る可能性があります。 たとえば、本来は上バンド判定のつもりで buffer_num = 0 を指定すると、 実際には中央線を比較してしまい、エントリー条件が別物になります。

ありがちな状況

  • 上バンドと中央線を取り違える
  • コードコメントと実際のバッファ番号が一致していない
  • 他記事や過去コードを流用して順番が混在する
この種のミスは、見た目では気付きにくいのが厄介です。 デバッグ時は、取得した3本の値をログへ出力し、上下関係が正しいか確認すると安全です。
Print("Upper=", upper[0], " Middle=", middle[0], " Lower=", lower[0]);

5.4 未確定バーと確定バーの混同

CopyBufferstart_pos = 0 を指定すると、現在進行中のバーを取得します。 一方、start_pos = 1直近で確定したバーです。 この違いは、EAロジックでは非常に重要です。

start_pos = 0 の特徴

  • リアルタイム性が高い
  • 値が刻々と変わる
  • シグナルの先出しができる
  • ダマシも増えやすい

start_pos = 1 の特徴

  • バー確定後の値を使える
  • ロジックが安定しやすい
  • バックテストと実運用の差が出にくい
たとえば次のように明確に使い分けます。
// 未確定バーの上バンドを見る
CopyBuffer(bandsHandle, 1, 0, 1, upper);

// 確定バーの上バンドを見る
CopyBuffer(bandsHandle, 1, 1, 1, upper);
実運用を安定させたい場合は、まず確定バー基準から始めるのが無難です。

6.2 バッファ番号の理解が曖昧なまま使う

iBands は3本のラインを持つため、どのバッファがどのラインかを正しく理解していないと、ロジック全体が崩れます。 MQL5公式ドキュメントでは、次の対応になっています。
バッファ番号 内容
0 中央線(BASE_LINE)
1 上バンド(UPPER_BAND)
2 下バンド(LOWER_BAND)
ここで起きやすい失敗は次の通りです。
  • 上バンドと中央線を混同する
  • 中央線と下バンドを混同する
  • コードコメントと実際の番号が一致していない
このミスの厄介な点は、コードが正常に動いて見えることです。 コンパイルエラーにもならず、CopyBuffer() も成功するため、見落としやすくなります。

実務での確認方法

取得後にログへ出して、数値の大小関係を確認します。
Print("Upper=", upper[0], " Middle=", middle[0], " Lower=", lower[0]);
通常は、同一バーで
  • 上バンド > 中央線
  • 中央線 > 下バンド
となるはずです。 この関係が崩れているなら、バッファ指定やデータ取得方法を見直すべきです。

6.3 配列の扱い方を曖昧にしてしまう

CopyBuffer() は配列へデータをコピーする関数です。 そのため、配列の準備や参照方法を曖昧にしたまま使うと、誤動作やエラーの原因になります。 代表的な失敗は次の通りです。
  • 配列サイズを意識せずに使う
  • 何本取得したのか分からないまま参照する
  • [0] が常に「最新確定足」だと思い込む
たとえば次のコードです。
double upper[];
CopyBuffer(bandsHandle, 1, 0, 1, upper);
Print(upper[0]);
これは環境によっては動くこともありますが、 常に安全とは言えません。初心者はまず、サイズを明示した方が安全です。
double upper[1];

if(CopyBuffer(bandsHandle, 1, 0, 1, upper) <= 0)
   return;

Print(upper[0]);
また、複数本取得する場合は、どのインデックスがどのバーかを明確に意識する必要があります。
double upper[3];
CopyBuffer(bandsHandle, 1, 0, 3, upper);

7.2 iBands のバッファ番号はどう対応していますか?

ボリンジャーバンドは3つのラインで構成されており、それぞれ次のバッファ番号に対応します。
バッファ番号 内容
0 中央線(Middle Band / 移動平均 / BASE_LINE)
1 上バンド(Upper Band / UPPER_BAND)
2 下バンド(Lower Band / LOWER_BAND)
CopyBuffer の第2引数にこの番号を指定することで、目的のラインを取得できます。

7.3 iBands はどこで作成するのが適切ですか?

通常は OnInit() 内で一度だけ作成するのが推奨されます。 OnTick() 内で毎回 iBands を作成すると、ティックごとにインジケータを生成することになり、 EAの処理が重くなったり、挙動が不安定になる可能性があります。

7.4 CopyBufferstart_pos は何を意味しますか?

start_pos は、どのバー位置からデータを取得するかを指定する値です。
start_pos 意味
0 現在進行中のバー
1 直近確定バー
2 その1本前のバー
リアルタイムの変動を含めたくない場合は、確定バー(1)を使用する方が安定します。

7.5 CopyBuffer が失敗するのはなぜですか?

主な原因は次の通りです。
  • インジケータハンドルが無効
  • バー履歴がまだ読み込まれていない
  • バッファ番号の指定ミス
  • インジケータ計算が完了していない
そのため、CopyBuffer の戻り値を必ず確認し、取得失敗時は処理を中断するようにするのが安全です。

7.6 ボリンジャーバンドに触れたら必ず反転しますか?

必ずしも反転するわけではありません。 ボリンジャーバンドは価格の変動幅(ボラティリティ)を示す指標であり、 トレンド方向そのものを保証する指標ではありません。 強いトレンドでは、価格がバンド沿いに動き続ける(バンドウォーク)こともあります。 そのため、EAでは次のような補助条件を組み合わせることが一般的です。
  • RSI
  • ATR
  • 移動平均トレンド
  • 上位足の方向

7.7 バンド幅はどのように計算しますか?

ボリンジャーバンドの幅は、上バンドと下バンドの差で計算できます。
double bandWidth = upper[0] - lower[0];
この値を利用すると、次のような判断が可能になります。
  • バンド幅が狭い → 相場が停滞している可能性
  • バンド幅が広い → 相場が活発な可能性
ただし、通貨ペアや価格桁数によって値のスケールが異なるため、 固定値の閾値は環境によって調整が必要です。

7.8 iBandsiCustom の違いは何ですか?

iBandsMetaTraderに標準搭載されているボリンジャーバンドインジケータを呼び出す関数です。 一方 iCustom は、自作または外部のカスタムインジケータを呼び出す関数です。 標準ボリンジャーバンドを使う場合は iBands の方がシンプルで扱いやすく、 カスタム計算ロジックを使う場合は iCustom を使用します。