Williams%Rの-80ライン・-20ラインの意味は知っていても、

それを「いつエントリーするか」という自動判定に

落とし込めずにいないでしょうか。

売られすぎ・買われすぎの水準に達しただけで即エントリーすると、

強いトレンド中はダマシで何度も逆行してしまいます。

この記事では、水準に達した後の「戻り」を確認してから

エントリーするWilliams%R逆張りEAの設計を、

損切り設定・ポジション重複防止まで含めて解説します。

この記事で分かること
・iWPRの引数と戻り値の見方
・-80/-20ラインへの到達だけでなく『戻り』を確認する設計
・ポジション重複を防ぐ書き方
・実際に動くEAのコード全体

Williams%Rとは何か

まず、シグナルの元になるWilliams%Rの基本を確認します。

iWPRのシグネチャと戻り値の見方

double iWPR(
   string symbol,
   int    timeframe,
   int    period,
   int    shift
);

戻り値はdouble型で、

`-100`(売られすぎの極限)から`0`(買われすぎの極限)の範囲で動きます。

-80/-20ラインの意味(売られすぎ・買われすぎ)

一般的に、`-80`を下回ると「売られすぎ」、

`-20`を上回ると「買われすぎ」と判断されます。

マイナス表記のため、数値の大小関係が直感と逆になりやすい点に注意してください。

RSIとの違い(スケールと感度)

RSIが`0`〜`100`のプラス表記であるのに対し、

Williams%Rは`-100`〜`0`のマイナス表記です。

計算に使う期間内の高値・安値の位置関係を直接見るため、

RSIよりも反応が速く、水準到達の頻度が多くなる傾向があります。

補足
・計算方法自体はストキャスティクスの%Rに近い考え方です
・反応が速い分、トレンド相場ではダマシも増えやすい指標です
・この記事では『戻り確認』を挟むことでダマシを減らします

逆張りエントリーのロジック設計

水準への到達だけで即エントリーせず、一手間加える設計にします。

売られすぎからの反発を検知する条件

bool BuySignal()
  {
   double wpr1 = iWPR(_Symbol, 0, InpPeriod, 1);
   double wpr2 = iWPR(_Symbol, 0, InpPeriod, 2);
   return(wpr2 <= InpOversold && wpr1 > InpOversold);
  }

1本前が`-80`以下(売られすぎ)で、

直近足がそこから戻ってきた瞬間だけを買いシグナルにします。

買われすぎからの反落を検知する条件

bool SellSignal()
  {
   double wpr1 = iWPR(_Symbol, 0, InpPeriod, 1);
   double wpr2 = iWPR(_Symbol, 0, InpPeriod, 2);
   return(wpr2 >= InpOverbought && wpr1 < InpOverbought);
  }

買いシグナルとは逆に、`-20`以上から

下回った瞬間だけを売りシグナルにします。

ダマシを減らすための「戻り確認」の一手間

到達した瞬間ではなく「水準をまたいだ瞬間」を条件にすることで、

水準に張り付いたまま動かない(強いトレンド継続)相場での

無駄なシグナル連発をある程度減らせます。

損切り・利確とポジション重複の防止

シグナルが出ても、それだけでは安全な発注になりません。

OrderSendでの発注とストップ設定

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

double sl = Ask - InpStopLossPips * point;
double tp = Ask + InpTakeProfitPips * point;
OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, tp, "WPR-Reversal", 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です。

//+------------------------------------------------------------------+
//|                                       WprReversalEA.mq4            |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property strict

input int    InpPeriod         = 14;
input double InpOversold       = -80.0;
input double InpOverbought     = -20.0;
input double InpLots           = 0.1;
input int    InpStopLossPips   = 300;
input int    InpTakeProfitPips = 450;
input int    InpMagic          = 20261001;

bool BuySignal()
  {
   double wpr1 = iWPR(_Symbol, 0, InpPeriod, 1);
   double wpr2 = iWPR(_Symbol, 0, InpPeriod, 2);
   return(wpr2 <= InpOversold && wpr1 > InpOversold);
  }

bool SellSignal()
  {
   double wpr1 = iWPR(_Symbol, 0, InpPeriod, 1);
   double wpr2 = iWPR(_Symbol, 0, InpPeriod, 2);
   return(wpr2 >= InpOverbought && wpr1 < InpOverbought);
  }

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,
                             "WPR-Reversal", 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,
                             "WPR-Reversal", InpMagic, 0, clrRed);
      if(ticket < 0)
         Print("売り発注に失敗しました。エラーコード: ", GetLastError());
     }
  }

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

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

よくあるエラーと注意点

実際に運用する前に確認しておきたい注意点をまとめます。

シグナルが出すぎて逆張りし続けてしまう

注意
・強いトレンド相場では水準の到達と戻りを繰り返しやすくなります
・逆張りポジションが連続して損切りになりやすい局面です
・既刊のADX・効率比系の記事と組み合わせたフィルターの追加を推奨します

MQL4とMQL5の違い

MQL4の`iWPR()`は、この記事のように値を直接返します。

MQL5の`iWPR()`はハンドルを返す方式に変わっており、

`CopyBuffer()`で値を取得する必要があります。

よくある質問

Williams%R逆張りEAについて、よく検索される疑問に回答します。

-80/-20以外の数値に変えてもよいですか?

はい、`InpOversold`・`InpOverbought`は入力パラメータのため、

通貨ペアや時間足に合わせて自由に調整できます。

数値を浅くするほどシグナル回数は増え、ダマシも増える傾向があります。

なぜ到達した瞬間ではなく戻りを待つのですか?

到達した瞬間にエントリーすると、

そこからさらに水準の外側へ進むダマシを

そのまま受け止めることになりやすいためです。

戻りを待つことで、反発の初動に近いタイミングを狙えます。

他のオシレーターと同時に使ってもよいですか?

問題ありません。

既刊のCCI逆張りEA・DeMarkerフィルターEAの記事と同様、

複数の条件を`&&`で組み合わせるフィルター設計は、

このEAにもそのまま応用できます。

【MQL】Williams%R(iWPR)の逆張りシグナルでエントリーするEAの作り方:まとめ

Williams%Rの-80/-20ラインは、

到達した瞬間ではなく「そこからの戻り」を条件にすることで、

ダマシをある程度減らしたシグナルに変えられます。

損切り・利確の必須設定と、

ポジション重複防止のチェックを組み合わせれば、

最低限の安全策を備えたシンプルな逆張りEAになります。

関連記事