既刊iBWMFIインジケーターの記事では、

Green/Fade/Fake/Squatという4色で、

値動きと出来高の「伴い」を判定する設計を解説しました。

この記事ではその判定結果を発注の起点には使わず、

移動平均のゴールデンクロス・デッドクロスという別の発注条件に、

Fake・Squat(伴いの無い警戒パターン)のときは、

エントリーを見送るフィルターとして組み込むEAを作ります。

この記事で分かること
・既刊インジケーターの4色判定をEAのフィルターとして関数化する方法
・移動平均クロスという発注条件とフィルターを組み合わせる設計
・Fake/Squatのときだけエントリーを見送る理由
・実際に動くEAのコード全体

設計思想: なぜクロス判定そのものではなくフィルターに使うのか

まず、既刊インジケーターの4色判定を、そのまま発注条件にしない理由を整理します。

既刊iBWMFIインジケーターのおさらい

既刊インジケーターは、

1本前のバーとのBWMFI・出来高の増減を比較し、

Green(伴いのある上昇)・Fade(伴いのある下降)・

Fake(出来高が減っているのに動いた警戒)・

Squat(出来高が増えているのに動かない拮抗)の4色に分類していました。

4色は方向を示さない、信頼度の指標である

補足
・BWMFIは(High-Low)÷Volumeで、常に正の値になる
・そのため4色は「上がるか下がるか」を示していない
・示しているのは「その動きに参加者の裏付けがあるか」という信頼度
・既刊記事のFAQでも「EAのフィルターに使える」と予告していた

方向を示さない指標を、方向を決める発注条件として単体で使うのは筋が悪く、

既にあるトレンド判定の信頼度を補強するフィルターとして使う方が自然です。

ベースの発注条件に移動平均クロスを選んだ理由

このサイトには既にMACD・ストキャスティクス・ボリンジャーバンドなど、

複数のクロス判定型EAがありますが、

最も基本的な2本の移動平均クロス(ゴールデンクロス・デッドクロス)は、

このiBWMFIフィルターの土台として分かりやすいため採用しました。

移動平均クロス+iBWMFIフィルターの判定ロジック

発注の起点となるクロス判定と、フィルターとなる4色判定を、それぞれ用意します。

ゴールデンクロス・デッドクロスの判定

double fastNow  = iMA(_Symbol, 0, InpFastMA, 0, MODE_SMA, PRICE_CLOSE, 1);
double slowNow  = iMA(_Symbol, 0, InpSlowMA, 0, MODE_SMA, PRICE_CLOSE, 1);
double fastPrev = iMA(_Symbol, 0, InpFastMA, 0, MODE_SMA, PRICE_CLOSE, 2);
double slowPrev = iMA(_Symbol, 0, InpSlowMA, 0, MODE_SMA, PRICE_CLOSE, 2);

bool goldenCross = (fastPrev <= slowPrev && fastNow > slowNow);
bool deadCross   = (fastPrev >= slowPrev && fastNow < slowNow);

確定済みの1本前・2本前のバーを比較し、

短期線が長期線を上下に抜けた瞬間だけを検知します。

iBWMFIの4色判定を関数化する

既刊インジケーターのOnCalculate内にあった判定部分を、

EA用の関数として切り出します。

enum ENUM_BWMFI_PATTERN
  {
   BWMFI_GREEN,
   BWMFI_FADE,
   BWMFI_FAKE,
   BWMFI_SQUAT
  };

ENUM_BWMFI_PATTERN GetBwmfiPattern(int shift)
  {
   double curMfi  = iBWMFI(NULL, 0, shift);
   double prevMfi = iBWMFI(NULL, 0, shift + 1);
   double curVol  = (double)iVolume(NULL, 0, shift);
   double prevVol = (double)iVolume(NULL, 0, shift + 1);

   bool mfiUp = (curMfi > prevMfi);
   bool volUp = (curVol > prevVol);

   if(mfiUp && volUp)   return(BWMFI_GREEN);
   if(!mfiUp && !volUp) return(BWMFI_FADE);
   if(mfiUp && !volUp)  return(BWMFI_FAKE);
   return(BWMFI_SQUAT);
  }

インジケーター版はバッファへ値を書き込んでいましたが、

EA版は4色のうちどれに該当するかをENUM値として返すだけにしています。

Fake/Squatのときはエントリーを見送るフィルター

bool IsReliableMove()
  {
   ENUM_BWMFI_PATTERN pattern = GetBwmfiPattern(1);
   return(pattern == BWMFI_GREEN || pattern == BWMFI_FADE);
  }
注意
・GreenとFadeは「出来高の裏付けがある動き」としてエントリーを許可する
・FakeとSquatは「裏付けの無い動き」として、クロスが出てもエントリーを見送る
・4色はあくまで経験則的な分類であり、見送った後に相場が動くこともある

既刊インジケーターのFAQで予告されていた「EAのフィルターに使える」という内容を、

この関数で実装しています。

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

クロス判定とフィルターを組み合わせ、安全策も合わせて実装します。

買い・売りの発注条件

bool reliable   = IsReliableMove();
bool buySignal  = (goldenCross && reliable);
bool sellSignal = (deadCross   && reliable);

クロスが発生し、かつ4色判定がGreenかFadeのときだけ発注対象にします。

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

`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の全体です。

//+------------------------------------------------------------------+
//|                                   BWMFIFilterEA.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

enum ENUM_BWMFI_PATTERN
  {
   BWMFI_GREEN,
   BWMFI_FADE,
   BWMFI_FAKE,
   BWMFI_SQUAT
  };

input int    InpFastMA         = 10;       //短期移動平均の期間
input int    InpSlowMA         = 30;       //長期移動平均の期間
input double InpLots           = 0.1;      //発注ロット数
input int    InpStopLossPips   = 300;      //損切り(pips)
input int    InpTakeProfitPips = 600;      //利確(pips)
input int    InpMagic          = 20261113; //マジックナンバー

datetime lastBarTime = 0;

ENUM_BWMFI_PATTERN GetBwmfiPattern(int shift)
  {
   double curMfi  = iBWMFI(NULL, 0, shift);
   double prevMfi = iBWMFI(NULL, 0, shift + 1);
   double curVol  = (double)iVolume(NULL, 0, shift);
   double prevVol = (double)iVolume(NULL, 0, shift + 1);

   bool mfiUp = (curMfi > prevMfi);
   bool volUp = (curVol > prevVol);

   if(mfiUp && volUp)   return(BWMFI_GREEN);
   if(!mfiUp && !volUp) return(BWMFI_FADE);
   if(mfiUp && !volUp)  return(BWMFI_FAKE);
   return(BWMFI_SQUAT);
  }

bool IsReliableMove()
  {
   ENUM_BWMFI_PATTERN pattern = GetBwmfiPattern(1);
   return(pattern == BWMFI_GREEN || pattern == BWMFI_FADE);
  }

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(Time[0] == lastBarTime)
      return;
   lastBarTime = Time[0];

   int needed = MathMax(InpFastMA, InpSlowMA) + 5;
   if(Bars < needed)
      return;

   double fastNow  = iMA(_Symbol, 0, InpFastMA, 0, MODE_SMA, PRICE_CLOSE, 1);
   double slowNow  = iMA(_Symbol, 0, InpSlowMA, 0, MODE_SMA, PRICE_CLOSE, 1);
   double fastPrev = iMA(_Symbol, 0, InpFastMA, 0, MODE_SMA, PRICE_CLOSE, 2);
   double slowPrev = iMA(_Symbol, 0, InpSlowMA, 0, MODE_SMA, PRICE_CLOSE, 2);

   bool goldenCross = (fastPrev <= slowPrev && fastNow > slowNow);
   bool deadCross   = (fastPrev >= slowPrev && fastNow < slowNow);

   bool reliable   = IsReliableMove();
   bool buySignal  = (goldenCross && reliable);
   bool sellSignal = (deadCross   && reliable);

   if(HasOpenPosition())
      return;

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

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

ゴールデンクロス・デッドクロスが発生し、

かつiBWMFIがGreenかFadeのときだけ、新規エントリーが発生します。

MetaEditorでのコンパイル・バックテスト手順

実際に動かすまでの手順です。

  1. MetaEditorで新規Expert Advisor「BWMFIFilterEA」を作成し、上のコードを貼り付ける
  2. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  3. ストラテジーテスターでこのEAを選択し、任意の通貨ペア・期間でバックテストを実行する
  4. 「結果」タブで、クロス発生時にFake/Squatだったバーが見送られていることを、既刊iBWMFIインジケーターを同時に表示して目視確認する

よくあるエラーと注意点

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

iVolumeがFXでは実出来高ではない

注意
・MT4のiVolumeはティックボリューム(約定件数相当)であり、実際の売買量ではない
・ブローカーによってティックの刻み方が異なるため、同じ通貨ペアでも値が変わる
・あくまで補助的な参考情報として扱う

短期線・長期線の期間を近づけすぎる

InpFastMAとInpSlowMAの差が小さいと、

クロスの発生頻度が増えすぎて、

フィルターの有無に関わらずノイズの多いエントリーになりがちです。

既刊iGator幅フィルターEAと混同する

既刊igator-width-filter-breakout-ea-mt4.mdは、

価格のブレイクアウトをアリゲーターの幅でフィルターする設計でしたが、

本EAは移動平均クロスをiBWMFIの4色でフィルターする設計であり、

ベースの発注条件・フィルターの指標ともに異なります。

既刊のフィルター系EAとの使い分け

似た「フィルター付きEA」の記事が複数あるため、使い分けを整理します。

記事 ベースの発注条件 フィルター
本記事(iBWMFIフィルターEA) 移動平均クロス 出来高の裏付け(4色判定)
既刊iGator幅フィルターEA 価格のブレイクアウト アリゲーターの口の広がり
既刊ATRボラティリティフィルターEA 個別記事のベース条件 値動きの大きさ

よくある質問

iBWMFIフィルターEAについて、よくある疑問に回答します。

Fake/Squatのときに見送るのはなぜですか?

Fakeは出来高が減っているのに値幅が広がっている状態、

Squatは出来高が増えているのに値幅が広がらない状態で、

いずれも「価格の動きに参加者の裏付けが伴っていない」警戒パターンだからです。

GreenとFadeを両方許可するのはなぜですか?

Greenは上昇方向、Fadeは下降方向の「伴いのある動き」を示すため、

クロスの方向を問わず、どちらも裏付けのある状態として許可しています。

フィルターを外した場合との比較はできますか?

IsReliableMove()の呼び出し部分をtrueに置き換えれば、

フィルター無しの単純な移動平均クロスEAとして動作するため、

バックテストで有無の差を比較できます。

【MQL4】iBWMFIの4色判定をEAのフィルターに使う作り方(Fake/Squatのときはエントリーを見送る設計):まとめ

この記事では、既刊iBWMFIインジケーターの4色判定を発注の起点にせず、

移動平均クロスという発注条件に、

出来高の裏付けがあるかどうかのフィルターとして組み込むEAを解説しました。

BWMFIが方向を示さない指標であることを踏まえ、

Green/Fadeのときだけクロスを許可し、

Fake/Squatのときは見送るという設計にしています。

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

IsReliableMove()の呼び出しを外すだけで、

フィルター無し版との比較もできる構成にしています。

関連記事