既刊記事で作ったバンドウォーク検知インジケーターは、矢印が出たことに自分で気づいて、

自分で発注するという、表示専用の設計でした。

では、その判定ロジックをそのままEAの発注条件に組み込んでしまえば、

矢印に気づく手間すらなくせるのではないでしょうか。

この記事では、バンドウォークの判定ロジックを発注条件に転用し、

損切り必須・ポジション重複防止を備えたトレンドフォローEAに仕立てる方法を解説します。

この記事で分かること

・既刊インジケーターの判定ロジックをEA化する考え方

・バンドウォーク確定の瞬間をエントリー条件にする設計

・損切り必須

・ポジション重複防止の書き方

・実際に動くEAのコード全体

バンドウォークをエントリー条件にする考え方

まず、インジケーターとEAで判定ロジックをどう使い分けるかを整理します。

既刊インジケーターとの関係(表示専用から発注条件へ)

既刊のバンドウォーク検知インジケーターは、終値が何本連続でバンドの外側にあるかを判定し、

確定した瞬間に矢印を出す設計でした。

本記事は、この判定関数をそのままEAのOnTick()内に移し、

矢印の代わりに発注を実行させます。

バンドウォークは「乗る」設計、終わり際は別途判断が必要

補足

・このEAは『歩き始めた瞬間』にエントリーする順張り設計

・『いつ歩き終わるか』は判定していない

・利確

・トレーリングストップの設定で手仕舞いのタイミングを補う必要がある

順張りEAとしての位置づけ

既刊のCCI逆張りEA・Williams%R逆張りEA等とは逆方向の発想で、

トレンドが続く方向へ乗っていく、順張り型のEAです。

iBands関数とバンドウォーク判定関数

発注条件の土台になる判定ロジックを確認します。

iBandsのシグネチャ

double iBands(
   string symbol,
   int    timeframe,
   int    period,
   double deviation,
   int    bands_shift,
   int    applied_price,
   int    mode,
   int    shift
);

modeにMODE_UPPER(1)を指定すると上部バンド、

MODE_LOWER(2)を指定すると下部バンドの値が取得できます。

IsWalkingUp/IsWalkingDown関数(既刊インジケーターと同じロジック)

bool IsWalkingUp(int shift, int bars)
  {
   for(int j = 0; j < bars; j++)
     {
      double upper = iBands(NULL, 0, InpBandPeriod, InpBandDeviation,
                             0, PRICE_CLOSE, MODE_UPPER, shift + j);
      if(Close[shift + j] <= upper)
         return(false);
     }
   return(true);
  }

bool IsWalkingDown(int shift, int bars)
  {
   for(int j = 0; j < bars; j++)
     {
      double lower = iBands(NULL, 0, InpBandPeriod, InpBandDeviation,
                             0, PRICE_CLOSE, MODE_LOWER, shift + j);
      if(Close[shift + j] >= lower)
         return(false);
     }
   return(true);
  }

既刊インジケーターと同じ、shiftからshift+bars-1まで、

全ての終値がバンド外にあるかを確認する関数です。

確定済みの1本前の足で判定する理由

注意

・形成中の0番目の足を基準に判定すると、終値が変化し続けて誤判定になる

・このEAは常に1本前(shift=1)を基準にエントリーを判定する

・リペイント(後からサインが変わる現象)を避けるための設計

発注条件・損切り・ポジション重複の防止

判定だけでは発注にならないため、安全策を組み込みます。

バンドウォーク確定の瞬間を検知する

bool BuySignal()
  {
   return(IsWalkingUp(1, InpWalkBars) && !IsWalkingUp(2, InpWalkBars));
  }

bool SellSignal()
  {
   return(IsWalkingDown(1, InpWalkBars) && !IsWalkingDown(2, InpWalkBars));
  }

1本前が確定していて、2本前はまだ確定していなかった場合だけを、

エントリーのシグナルにします。

損切り・利確を必ず指定する

double sl = Ask - InpStopLossPips * point;
double tp = Ask + InpTakeProfitPips * point;
OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp, "BBWalk", InpMagic, 0, clrBlue);

損切り(sl)・利確(tp)を発注時点で必ず指定し、未設定のまま放置しません。

ポジション重複を防ぐチェック

bool HasOpenPosition()
  {
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
         OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(true);
     }
   return(false);
  }

同じマジックナンバー・同じ通貨ペアでポジションが既にあるかを確認し、

あれば新規エントリーをスキップします。

実際に動くバンドウォークEAのコード全体

ここまでの要素をまとめた、EAの全体です。

//+------------------------------------------------------------------+
//|                                       BollingerBandWalkEA.mq4     |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict

input int    InpBandPeriod     = 20;   //ボリンジャーバンドの期間
input double InpBandDeviation  = 2.0;  //標準偏差の倍率(σ)
input int    InpWalkBars       = 3;    //バンドウォークと判定する連続本数
input double InpLots           = 0.1;  //発注ロット数
input int    InpStopLossPips   = 300;  //損切り(pips)
input int    InpTakeProfitPips = 600;  //利確(pips)
input int    InpMagic          = 20261017; //マジックナンバー

bool IsWalkingUp(int shift, int bars)
  {
   for(int j = 0; j < bars; j++)
     {
      double upper = iBands(NULL, 0, InpBandPeriod, InpBandDeviation,
                             0, PRICE_CLOSE, MODE_UPPER, shift + j);
      if(Close[shift + j] <= upper)
         return(false);
     }
   return(true);
  }

bool IsWalkingDown(int shift, int bars)
  {
   for(int j = 0; j < bars; j++)
     {
      double lower = iBands(NULL, 0, InpBandPeriod, InpBandDeviation,
                             0, PRICE_CLOSE, MODE_LOWER, shift + j);
      if(Close[shift + j] >= lower)
         return(false);
     }
   return(true);
  }

bool BuySignal()
  {
   return(IsWalkingUp(1, InpWalkBars) && !IsWalkingUp(2, InpWalkBars));
  }

bool SellSignal()
  {
   return(IsWalkingDown(1, InpWalkBars) && !IsWalkingDown(2, InpWalkBars));
  }

bool HasOpenPosition()
  {
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&
         OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(true);
     }
   return(false);
  }

void OnTick()
  {
   if(HasOpenPosition())
      return;

   double point = _Point;
   if(_Digits == 3 || _Digits == 5)
      point *= 10;

   if(BuySignal())
     {
      double sl = Ask - InpStopLossPips * point;
      double tp = Ask + InpTakeProfitPips * point;
      int ticket = OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp,
                             "BBWalk", InpMagic, 0, clrBlue);
      if(ticket < 0)
         Print("買い発注に失敗しました。エラーコード: ", GetLastError());
     }
   else if(SellSignal())
     {
      double sl = Bid + InpStopLossPips * point;
      double tp = Bid - InpTakeProfitPips * point;
      int ticket = OrderSend(_Symbol, OP_SELL, InpLots, Bid, 3, sl, tp,
                             "BBWalk", InpMagic, 0, clrRed);
      if(ticket < 0)
         Print("売り発注に失敗しました。エラーコード: ", GetLastError());
     }
  }

MetaEditorでのコンパイル・実行手順

  1. MetaEditorで新規Expert Advisor「BollingerBandWalkEA」を作成し、上のコードを貼り付けてコンパイルする
  2. ストラテジーテスターでこのEAを選択し、任意の通貨ペア・期間でバックテストを実行する
  3. 「結果」タブで、バンドウォーク確定直後にエントリーが発生していることを確認する
  4. デモ口座のチャートに適用し、ログに発注記録が出ることを確認する

よくあるエラーと注意点

実際に運用する前に、確認しておきたい点です。

レンジ相場でエントリーと損切りを繰り返す

注意

・バンドウォークはレンジ相場ではほぼ発生しないが、発生直後に失速する「ダマシ」はある

・既刊の効率比

・ADX系インジケーターと組み合わせたフィルターの追加を推奨する

・InpWalkBarsを増やすとダマシは減るが、エントリーは遅くなる

利確に達する前にトレンドが終わってしまう

固定pipsの利確(InpTakeProfitPips)では、

トレンドが利確ラインに届く前に終わることがあります。

トレーリングストップへの変更も検討してください。

既刊インジケーターのサインとEAの発注タイミングが一致しない

判定ロジック自体は同じですが、インジケーターはチャート表示用の計算、EAは発注用の計算と、

実行されるタイミング(ティックごと)が異なるため、

表示上の矢印とごくわずかにタイミングがずれる場合があります。

このEAの使いどころと限界

得意な場面と、単独では対応しきれない場面を整理します。

強いトレンドの初動に強い

スクイーズ(バンド幅の収縮)の後に発生するバンドウォークであれば、

トレンドの初動を捉えやすくなります。

手仕舞いのロジックは別途必要

このEAは「乗る」ことに特化しており、「いつ降りるか」は固定の利確・損切りに任せています。

より精緻な手仕舞いをしたい場合は、

終値がバンドの内側に戻った時点で決済する関数を追加してください。

よくある質問

バンドウォークEAについて、よく検索される疑問に回答します。

既刊インジケーターと同時に使う必要がありますか?

必須ではありません。

このEAは判定ロジックを内部に持っているため単独で動作しますが、

目視で経過を確認したい場合は既刊インジケーターを併用してください。

InpWalkBarsは何本にすべきですか?

既刊インジケーターと同じく3本を初期値にしていますが、

通貨ペアや時間足によって最適値は変わるため、バックテストで調整することをおすすめします。

逆張りEAと同時に動かしても大丈夫ですか?

マジックナンバーを別の値にしておけば、

既刊のCCI逆張りEA等と同じ口座で同時に動かすこと自体は可能です。

ただし、同じ通貨ペアで逆方向のEAを動かすと、

意図がぶつかる場面があるため注意してください。

【MQL4】ボリンジャーバンドの「バンドウォーク」でトレンドフォローするEAの作り方(損切り必須・ポジション重複防止つき):まとめ

この記事では、既刊インジケーターのバンドウォーク判定ロジックを、

そのままEAの発注条件に転用する方法を解説しました。

損切り必須・ポジション重複防止という最低限の安全策を備えつつ、

手仕舞いのロジックは今後の改善点として残しています。

関連記事