EURUSDが上がっているのを見て、

「これはユーロが強いのか、それとも単にドルが弱いだけなのか」と迷ったことはないでしょうか。

既刊の通貨強弱メーターインジケーターの記事では、

8通貨の強弱をパネルに表示してこの疑問に答えましたが、

この記事ではそのロジックを「表示するだけ」から一歩進めて、

強弱の「差」が一定以上あるときだけ自動でエントリーするEAに発展させます。

この記事で分かること

・既刊インジケーターの通貨強弱計算ロジックを発注条件に転用する方法

・表示中の通貨ペアを基準通貨・決済通貨に分解する方法

・強弱差のしきい値をエントリー条件に使う考え方

・新しいバー判定・損切り必須・ポジション重複防止を備えた実際に動くコード全文

設計思想: なぜ通貨強弱の「差」を発注条件に使うのか

まず、通貨強弱の「差」に注目する理由を整理します。

既刊インジケーターとの関係

既刊記事では、7つの主要通貨ペアの変化率から、

主要8通貨(USD/EUR/GBP/JPY/AUD/NZD/CAD/CHF)の、

強弱を計算し、

パネルに一覧表示しました。

この記事では、同じ計算ロジックをそのまま使い、表示ではなく発注条件の判定に転用します。

1つの通貨ペアだけでは分からないこと

EURUSDが上がっていても、それがEURの強さなのかUSDの弱さなのかは、

EURUSD単体のチャートだけでは判断できません。

「差」を使う理由

補足

・通貨強弱メーターは「今どの通貨が強いか」を示すだけで、エントリーの判断は人間が行う

・本記事では、表示中の通貨ペアの基準通貨・決済通貨の強弱の差を数値化し

・その差がしきい値を超えたときだけ自動でエントリーする設計にする

通貨強弱の計算ロジック

既刊インジケーターのPercentChange関数を、そのまま使います。

PercentChangeで変化率を取る

double PercentChange(string symbol)
  {
   double past = iClose(symbol, 0, InpLookbackBars);
   double now  = iClose(symbol, 0, 0);
   if(past == 0)
      return(0); //履歴未取得時の保険(ゼロ除算防止)

   return((now - past) / past * 100.0);
  }

InpLookbackBars本前の終値と、直近の終値を比較した変化率(%)を返します。

USDは7ペアの平均、他7通貨は対USDペアそのまま

void GetStrengthValues(double &values[])
  {
   double chgEURUSD = PercentChange("EURUSD");
   double chgGBPUSD = PercentChange("GBPUSD");
   double chgAUDUSD = PercentChange("AUDUSD");
   double chgNZDUSD = PercentChange("NZDUSD");
   double chgUSDJPY = PercentChange("USDJPY");
   double chgUSDCAD = PercentChange("USDCAD");
   double chgUSDCHF = PercentChange("USDCHF");

   values[0] = (-chgEURUSD - chgGBPUSD - chgAUDUSD - chgNZDUSD
               + chgUSDJPY + chgUSDCAD + chgUSDCHF) / 7.0; //USD
   values[1] = chgEURUSD;  //EUR
   values[2] = chgGBPUSD;  //GBP
   values[3] = chgAUDUSD;  //AUD
   values[4] = chgNZDUSD;  //NZD
   values[5] = -chgUSDJPY; //JPY
   values[6] = -chgUSDCAD; //CAD
   values[7] = -chgUSDCHF; //CHF
  }

既刊インジケーターと同じ考え方で、

USDが分母側(USDJPY等)にあるペアは符号を反転させています。

通貨コードから強弱配列のインデックスを探す

string CcyNames[8] = {"USD","EUR","GBP","AUD","NZD","JPY","CAD","CHF"};

int CurrencyIndex(string code)
  {
   for(int i = 0; i < 8; i++)
      if(CcyNames[i] == code)
         return(i);
   return(-1);
  }

対応していない通貨コードの場合は-1を返し、

発注条件の側でこのエラー値を必ずチェックします。

発注条件: 強弱差がしきい値を超えたら順張り

通貨強弱の計算ができたら、実際の発注条件を組み立てます。

表示中の通貨ペアをbase/quoteに分解する

string baseCode  = StringSubstr(_Symbol, 0, 3);
string quoteCode = StringSubstr(_Symbol, 3, 3);

EURUSDなら、baseCodeは”EUR”、quoteCodeは”USD”になります。

diff = base強さ – quote強さ

baseの強さからquoteの強さを引いた値をdiffとします。

diffが大きく正の値なら「baseが強くquoteが弱い」状態、

負の値なら逆の状態と判断できます。

InpThresholdの考え方

実践アドバイス

・InpThresholdを0に近づけるほどエントリー頻度が増える

・増えるほど、わずかな差でのダマシも増える

・まずは既定値0.3前後から試し、通貨ペアや時間足にあわせて調整する

新しいバー判定と損切り・ポジション重複防止

発注条件が整っても、資金管理の基本設計を省略しないようにします。

IsNewBar()で1バー1回に絞る

datetime LastBarTime = 0;

bool IsNewBar()
  {
   datetime t = Time[0];
   if(t == LastBarTime)
      return(false);
   LastBarTime = t;
   return(true);
  }

強弱差はティックごとに細かく変動するため、この判定が無いと、

同じバーの中で何度も発注を試みてしまいます。

固定pipsの損切り

double PipSize()
  {
   if(Digits == 3 || Digits == 5)
      return(Point * 10);
   return(Point);
  }

4桁(2桁)・5桁(3桁)どちらのブローカーでも、

同じpips数で損切り幅を指定できるようにしています。

OrdersTotalループでの重複防止

int GetMyTicket()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(OrderTicket());
     }
   return(-1);
  }

同じ通貨ペア・同じマジックナンバーのポジションがすでにある場合は、

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

実際に動くコード全体

通貨強弱の計算から発注まで、実際にMetaEditorでコンパイルできるEAです。

//+------------------------------------------------------------------+
//|                              CurrencyStrengthFilterEA.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    InpLookbackBars = 20;        //強弱を計算する期間(本数)
input double InpThreshold    = 0.3;       //エントリーする強弱差のしきい値(%)
input double InpLots         = 0.1;       //発注ロット数
input int    InpStopLossPips = 30;        //損切り(pips)
input int    InpMagic        = 20261025;  //マジックナンバー

string   Symbols7[7] = {"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDJPY","USDCAD","USDCHF"};
string   CcyNames[8]  = {"USD","EUR","GBP","AUD","NZD","JPY","CAD","CHF"};
datetime LastBarTime  = 0;

int OnInit()
  {
   for(int i = 0; i < 7; i++)
      SymbolSelect(Symbols7[i], true); //Market Watchに追加(iCloseの0返り対策)
   return(INIT_SUCCEEDED);
  }

double PipSize()
  {
   if(Digits == 3 || Digits == 5)
      return(Point * 10);
   return(Point);
  }

bool IsNewBar()
  {
   datetime t = Time[0];
   if(t == LastBarTime)
      return(false);
   LastBarTime = t;
   return(true);
  }

double PercentChange(string symbol)
  {
   double past = iClose(symbol, 0, InpLookbackBars);
   double now  = iClose(symbol, 0, 0);
   if(past == 0)
      return(0);
   return((now - past) / past * 100.0);
  }

void GetStrengthValues(double &values[])
  {
   double chgEURUSD = PercentChange("EURUSD");
   double chgGBPUSD = PercentChange("GBPUSD");
   double chgAUDUSD = PercentChange("AUDUSD");
   double chgNZDUSD = PercentChange("NZDUSD");
   double chgUSDJPY = PercentChange("USDJPY");
   double chgUSDCAD = PercentChange("USDCAD");
   double chgUSDCHF = PercentChange("USDCHF");

   values[0] = (-chgEURUSD - chgGBPUSD - chgAUDUSD - chgNZDUSD
               + chgUSDJPY + chgUSDCAD + chgUSDCHF) / 7.0;
   values[1] = chgEURUSD;
   values[2] = chgGBPUSD;
   values[3] = chgAUDUSD;
   values[4] = chgNZDUSD;
   values[5] = -chgUSDJPY;
   values[6] = -chgUSDCAD;
   values[7] = -chgUSDCHF;
  }

int CurrencyIndex(string code)
  {
   for(int i = 0; i < 8; i++)
      if(CcyNames[i] == code)
         return(i);
   return(-1);
  }

int GetMyTicket()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderSymbol() == _Symbol && OrderMagicNumber() == InpMagic)
         return(OrderTicket());
     }
   return(-1);
  }

void CheckStrengthEntry()
  {
   if(GetMyTicket() >= 0)
      return;

   string baseCode  = StringSubstr(_Symbol, 0, 3);
   string quoteCode = StringSubstr(_Symbol, 3, 3);

   int baseIdx  = CurrencyIndex(baseCode);
   int quoteIdx = CurrencyIndex(quoteCode);

   if(baseIdx < 0 || quoteIdx < 0)
     {
      Print("対応していない通貨コードのため判定をスキップしました: ", _Symbol);
      return;
     }

   double values[8];
   GetStrengthValues(values);

   double diff    = values[baseIdx] - values[quoteIdx];
   double sl_pips = InpStopLossPips * PipSize();

   if(diff > InpThreshold)
     {
      double sl = Ask - sl_pips;
      int result = OrderSend(_Symbol, OP_BUY, InpLots, Ask, 3, sl, 0,
                             "CcyStrength Buy", InpMagic, 0, clrBlue);
      if(result < 0)
         Print("買い注文に失敗しました。エラーコード=", GetLastError());
      return;
     }

   if(diff < -InpThreshold)
     {
      double sl = Bid + sl_pips;
      int result = OrderSend(_Symbol, OP_SELL, InpLots, Bid, 3, sl, 0,
                             "CcyStrength Sell", InpMagic, 0, clrRed);
      if(result < 0)
         Print("売り注文に失敗しました。エラーコード=", GetLastError());
      return;
     }
  }

void OnTick()
  {
   if(!IsNewBar())
      return;
   CheckStrengthEntry();
  }

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

  1. MetaEditorで新規Expert Advisor「CurrencyStrengthFilterEA」を作成し、上のコードを貼り付ける
  2. F7キーでコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  3. デモ口座でEURUSD等のチャートにドラッグ&ドロップで適用する
  4. ストラテジーテスターで、強弱差がInpThresholdを超えた瞬間にだけ発注される様子を確認する

よくあるエラーと注意点

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

ブローカーのシンボルサフィックスでズレる

注意

・ブローカーによっては通貨ペア名の末尾に.aや.pro等のサフィックスが付く

・この場合、_SymbolをそのままStringSubstrに渡すと、

base/quoteの切り出しがずれる

・サフィックス付きの環境では、先にサフィックスを取り除く処理を追加する必要がある

対応していない通貨コードではスキップされる

CcyNames配列に無い通貨コード(例: トルコリラ等)の通貨ペアで動かすと、

CurrencyIndex()が-1を返し、

Printでログを出したうえでエントリーをスキップする設計になっています。

InpThresholdを小さくしすぎるとオーバートレードになる

強弱差は常に揺れ動いているため、しきい値を極端に小さくすると、

新しいバーが来るたびに発注を繰り返すオーバートレード状態になりやすい点に注意してください。

MQL4とMQL5の違い

このロジックをMQL5に移植する場合の違いを確認します。

iCloseの引数構成が変わる

MQL4のiClose(symbol, timeframe, shift)は、

MQL5には同名関数がなく、

CopyCloseで配列を取得してからインデックスで参照する設計になります。

発注はCTradeクラスに変わる

OrderSendの代わりに、

CTradeクラスのBuy()/Sell()メソッドを使う設計になります。

通貨強弱の計算ロジック自体は、MQL5でもほぼそのまま応用できます。

よくある質問

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

既刊の通貨強弱メーターと同時に使えますか?

使えます。

このEAは独自にPercentChangeを計算しているため、

既刊インジケーターをチャートに表示しながら、同時にEAを動かすことができます。

7ペア以外の通貨ペアでも使えますか?

基準通貨・決済通貨の両方がCcyNames配列の8通貨に含まれていれば使えます。

例えばEURGBPやEURJPYのようなクロスペアでも、

baseCode・quoteCodeがそれぞれEUR/GBP、

EUR/JPYとなるため動作します。

InpThresholdの推奨値はどれくらいですか?

まずは既定値0.3前後から試すことを推奨します。

通貨ペアや時間足、InpLookbackBarsの長さによって、

強弱差の出やすさが変わるため、バックテストで調整してください。

【MQL4】通貨強弱の差が一定以上のときだけ順張りエントリーするEAの作り方(通貨強弱メーターの考え方を発注条件に):まとめ

EURUSDが上がっていても、それがEURの強さかUSDの弱さかは、

その通貨ペア単体では分かりません。

既刊インジケーターと同じ計算ロジックで8通貨の強弱を数値化し、

表示中の通貨ペアの基準通貨・決済通貨の強弱差がしきい値を超えたときだけ、

新しいバー判定・損切り必須・重複エントリー防止を備えた、

エントリーを行う設計にまで落とし込みました。

関連記事