English Deutsch
preview
トレンド強度の最適化:方向と強さに沿った取引戦略

トレンド強度の最適化:方向と強さに沿った取引戦略

MetaTrader 5トレーディング |
28 2
Eugene Mmene
Eugene Mmene

はじめに

本記事の目的は、適切な取引方向やトレンド方向の選択に困難を抱えるトレーダー、あるいは規律を確立し、トレンド方向に沿った取引のみに集中することで損失の回避・軽減を目指すトレーダーの課題に対処することです。また、エントリー機会を認識していながらも過度な分析や判断の迷いにより実行できず、最終的に理想的なトレンド方向や市場バイアスを特定できないまま機会を逃してしまうトレーダーにとっても有益です。さらに、本記事は初心者や発展段階のトレーダーにも適しており、日中、短期、長期を問わず、トレンドの方向性と強さを基にした取引判断の理解を支援します。  

多くの場合、トレンドの強さと方向に沿って取引をおこなうことが、同程度のスキルや経験を持つトレーダー同士の成果に大きな差を生む決定的な要因となります。トレンドに対してどのようにポジションを取るかによって、結果は大きく異なります。統計的にも、逆張り取引は短期的な値動きを捉えることはできるものの、その多くはトレンド方向への大きな動きに先立つ一時的な戻りに過ぎません。そのため、注意を怠ると大きな損失につながる可能性があります。一方で、トレンド方向に沿った取引は比較的寛容であり、エントリーが多少不利であっても、トレンドの継続を待つ忍耐力があれば、数百ドルから数千ドル規模の利益につながる可能性があります。 

私自身の経験から見ても、トレーダーは数多くの課題に直面します。実際、ほとんどのトレーダーはキャリアのどこかで似た、あるいはほぼ同一の問題に直面しますが、その結果に差が生まれるのは、それらの課題に対する解釈、対応、そして予測の仕方が異なるためです。その結果、スキルや経験、判断力が近いトレーダー同士であっても、最終的なパフォーマンスには大きな差が生じます。

その中でも、最も一般的かつ重要な課題の一つが、トレンドの方向と強さの判断です。本記事および本EAは、この課題に対処することを目的としています。これは初心者や発展段階のトレーダーにとって非常に大きな課題であり、場合によっては経験豊富なトレーダーにとっても依然として難しい問題です。私自身も発展途上のトレーダーであった頃に直面していました。本記事とEAを通じて、トレンドに整合した形で取引できるようになり、結果として短期的な逆張り取引を回避できるようになります。これにより、トレーダーはより自信を持って明確な判断のもとで取引を実行できるようになり、最終的にはトレンドの方向性や価格変動の流れを自然に把握できるようになります。この課題が解決されれば、残るのは適切なセットアップ、タイミング、そしてエントリーポジションの選択のみとなります。 

また、トレンド方向に基づいて分析、実行、管理された取引は、単に精度が高いだけでなく、より迅速に結果へ到達する傾向があります。さらにドローダウンも比較的小さく抑えられ、価格は目標水準へより速く到達しやすくなります。加えて、価格のスイングはより強力であるため、仮に一時的に含み損を抱えた場合でも、最終的にはトレンドの方向と強さに従って価格が再び動き、ドローダウンから回復する可能性が高くなります。

本記事では、トレンドの方向と強さに従ってのみ取引をおこない、忍耐強くポジションを維持できるトレーダー向けに設計されたEAについて詳しく解説します。このEAは逆張り取引を避け、頻繁にバイアスを変更することなく、テイクプロフィットに到達するか、あるいは全体のトレンドが転換するまでポジションを保持することを前提としています。また、このEAは日中取引や短期取引においても重要であり、トレンドに基づいた最も可能性の高い値動きに従うことで、成功率の向上に寄与します。

強い上昇トレンドを示す移動平均線



トレンドの強さと方向性に基づく取引の内省

本記事の主な目的は、トレンドの方向性と強さに沿った取引の重要性を強調することです。これは多くのトレーダー、特に経験の浅いトレーダーや、十分な経験を持ちながらも市場に深く関わっているトレーダーでさえ見落としがちな要素であり、最終的には大きな差を生む決定的な要因となる可能性があります。

実際のところ、価格は月足(MN)、週足(W1)、日足(D1)といった上位時間足における主要な価格水準から次の主要水準へと移動していきます。そして、その上位時間足における価格の進行方向こそが「トレンド」と呼ばれるものです。下位時間足の値動きは、その結果として生じる現象に過ぎません。これは多くのトレーダーが考えている認識とは逆です。一般的には下位時間足の動きがトレンドを形成し、それが上位時間足に影響を与えると考えられがちですが、実際にはその逆の構造であるという点が重要です。

この観点に立てば、トレンドの判断は上位時間足の価格変動、移動平均線、そして重要な価格構造を観察することで比較的容易におこなうことができます。最初に注目すべきは月足チャート(MN)であり、その後、観察や重要な水準のマーキングをおこなったうえで、順次下位時間足へと落とし込んでいくべきです。これらの重要水準や関心領域は、戦略によってさまざまな名称で呼ばれることがありますが、本質的には同じ概念を指しています。これらは非常に重要な価格帯として認識すべきであり、トレンドや価格の方向性をより正確に理解・解釈する助けとなります。また場合によっては、アセットの価格変動のスピードや強さを判断する要素としても機能します。

一部のトレーダーはこれらをオーダーブロックとして捉え、別のトレーダーはサポート・レジスタンスとして扱い、また別のトレーダーは需給ゾーン、あるいはリクイディティレイドとして認識するなど、さまざまな呼び方をします。しかし、こうした戦略や理論に共通している最も重要な点は、これらのポイントが非常に重要かつ有用な水準であり、価格が強く反応しやすい注目領域であるということです。また同時に、精度の高いプロフェッショナルトレーダーが理想的なセットアップを探す際に注視する領域でもあります。本記事が目指すのは、この現象を効果的に活用するエキスパートアドバイザー(EA)をどのように作成し、どのように運用するかを示すことにあります。

D1時間足で強気トレンドを示す移動平均線


トレンドの検出(週足、月足、日足)と方向性および強さの予測

MNチャートを開いた後、最初におこなうべきことは、前述した主要なポイント(反応エリア)に印を付けることです。これらは通常、過去数か月の高値や安値付近に位置しています。これらの主要な反応エリアは常に念頭に置く必要があります。というのも、価格は多くの場合ここで反応を示し、その月、あるいはその月の残り期間の値動きの方向性を決定づける可能性があるからです。そのため、MN時間足において価格が一つの重要水準から次の重要水準へと移動していることが確認できれば、それは月足レベルでのトレンド方向が確定したことを意味し、その月の取引はMN上の重要水準に向かう形で引き寄せられることになります。

これは、月足において最も近い反応エリアであるため、いわば「狙いやすい目標」と言えます。もう一つの注目点は移動平均線であり、これは価格がターゲットへ向かう際の強さやスピードを把握するために利用されます。そして最後の重要要素がプライスアクションです。これは価格の動きを決定づける非常に重要な要素であり、トレンドの急変やブレイクを察知する手がかりにもなります。移動平均線は明確なシグナルが出るまで時間がかかることがありますが、プライスアクションはより即時的かつ情報量が多く、特に理解しているトレーダーにとっては非常に有益です。

注意深いトレーダーはプライスアクションから、長期トレンドの開始時に共通して見られる動きを観察できます。たとえば、価格が重要水準に到達した後、直前の安値や高値を一気にブレイク(パージ)し、その後すぐに強い包み足やマーケットストラクチャーのシフトが発生するケースです。この現象は、より下位の時間足で発生することもあり、必ずしも同一時間足で起こる必要はありません。重要なのは、その構造が有効に機能することです。たとえば、週足の安値を一度下抜けた後に、強い陽線の包み足や構造転換が発生し、その後価格が急激に反対方向へ拡張する場合、それは新しいトレンドの開始を示している可能性があります。

この場合の基本的な考え方は、包み足や市場構造の変化が確定してクローズするまで待ち、それが有効であると確認できた時点で新しいトレンドを認識し、そのトレンド方向に沿って買いポジションまたは売りポジションを構築することです。すべての取引は現在のトレンドに従っておこなうべきであり、トレンド方向への取引は一般的に値動きが速く、価格構造もクリーンであり、ドローダウンも非常に小さくなります。そのため、トレンドが変化するまでは逆方向の取引は避けることが理想です。

もちろん、特に下位時間足では短期的なスイングや一時的な反転は発生しますが、それらは長期トレンドの全体像には大きな影響を与えません。トレンドの終焉や反転は、月末付近や先述した重要水準付近で発生することが多いです。同様の考え方は週足にも当てはまり、週足のトレンドや市場のナラティブ(方向性認識)を判断するために使用されます。

この明確で特徴的な構造が最後に現れる時間足が日足(D1)です。日足は、下位足と上位足の中間に位置する橋渡し的な時間足として機能するため、極めて重要かつ基礎的な時間軸であると考えられます。日足のみを用いることで、数日から数時間にわたる短期的な取引の枠組みを構築することも可能です。

また、この時間足では短期スイングと長期スイングの両方を比較的容易に識別でき、さらにナラティブやトレンドの把握もおこないやすくなります。そのためトレーダーはプライスアクション、トレンド、移動平均線に特に注目する必要があります。必要な情報の多くはこの時間足に集約されています。

また、サポート・レジスタンス、需給ゾーン、オーダーブロックといった概念も重要な観察対象となります。これらは名称が異なるだけで、本質的には同じ価格反応パターンを指しています。さらに、地政学的要因や資産を取り巻く環境によって、トレンドそのものが変化する場合もあります。

最後に最も重要なポイントとして、最適な成果を得るためには、複数の時間足、できれば月足、週足、日足のすべてが同一のバイアス、ナラティブ、トレンドで一致している局面を優先すべきです。W1、D1、MNがすべて同じ方向性を示している場合、それは最も取引しやすい局面であり、非常にスムーズな値動きと最小限のドローダウンで推移することが多くなります。 

以下では、このトレンド分析に基づいて取引判断をおこなうEAの設計および構築方法について詳しく解説します。 

弱気トレンドにおけるエントリーのための市場構造変化の例


MQL5におけるTrend King EAによる取引判断の自動化

この戦略を自動化し、説明して実装するために、以下を作成しました。

  • トレンドの方向性のみに沿った売買シグナルを分析・実行します。また、トレンドと逆方向のポジションは回避し、トレーリングストップロスおよび移動平均線を活用してトレンド判定を補助するトレンドフォロー型EA

取引判断プロセス

このEAの判断(トレンド検出、プライスアクション判定、取引実行)は、以下のロジックに基づいておこなわれます。

Trend King EAのソースコード

このEAは、全体のトレンド方向および強さに一致する可能性のある売買シグナルを検出し、トレンド方向のみでエントリー機会を待機します。トレンドと逆方向のポジションは回避されます。また、指数移動平均線(EMA)および単純移動平均線(SMA)を利用して全体的なトレンド方向を把握し、エントリーの判断に活用します。さらに、トレーリングストップロスロジックを用いて、価格が有利に動いた場合に損失を保護しながら利益を確保します。リスク管理として、1取引あたり資金の1%をリスクに設定しています。 

入力パラメータ:取引設定のカスタマイズ

このEAの入力パラメータにより、GBPJPY、GBPUSD、EURUSDの取引に合わせてコアコードを変更せずにEAの挙動を調整できます。LotSizeは0.1に設定されており、GBPペアの中程度のボラティリティ(1日100〜300 pips)を考慮した保守的なサイズです。LookbackBarsは3で、H1、H4、D1における直近高値/安値を特定する期間を定義し、応答性と信頼性のバランスを取る設計になっています。StopLossPipsは150、TakeProfitPipsは600に設定されており、GBPJPY、GBPUSD、EURUSDの典型的な値幅に合わせ、リスクリワード比1:4で流動性刈り取り後の強いトレンドを活用できるようになっています。TrailingStopPipsは100で、GBPJPYの急激な値動き中でも利益を確保します。EngulfingMinBodyRatioは0.3に設定されており、包み足の実体が前のローソク足に対して十分な大きさであることを確認し、弱いシグナルをフィルタリングします。

TradeTimeframeはH1、ConfirmationTimeframeはM15で、流動性刈り取りの検知および迅速なエントリー確認を可能にしています。MaxCandlesPostPurgeは3で、流動性刈り取り後の包み足シグナル検出の時間窓を制限し、遅すぎるエントリーを避けます。VolumeThresholdは1.0で、流動性確認のために出来高のスパイクを条件とし、GBPUSDのニュース相場で重要な役割を果たします。UseTrendFilterがtrueに設定され、SMAPeriodは50で、50期間のSMAを使用してより大きなトレンドに沿った取引をおこない、乱高下するGBP市場での誤ブレイクを減らすようになっています。

//+------------------------------------------------------------------+
//|                 TrendKingEA.mq5                                  |
//| Expert Advisor for MetaTrader 5                                  |
//| Description:Trades based on Trend strenght and direction, waits  |
//| for trade set ups on trend direction, with flexible execution.   |
//+------------------------------------------------------------------+
#property copyright "Eugene Mmene"
#property link "https://www.EMcapital.com"
#property version "1.06"
//--- Input parameters
input double LotSize = 0.1;                              // Lot size for trades
input int LookbackBars = 5;                              // Number of bars to check for highs/lows
input double StopLossPips = 30.0;                        // Stop loss in pips (adjusted for GOLD#)
input double TakeProfitPips = 90.0;                      // Take profit in pips (adjusted for GOLD#)
input double TrailingStopPips = 40.0;                    // Trailing stop in pips
input double BreakevenPips = 30.0;                       // Move to BE after 30 pips profit
input double EngulfingMinBodyRatio = 0.5;                // Min body ratio for engulfing candle
input ENUM_TIMEFRAMES TradeTimeframe = PERIOD_M15;       // Primary timeframe for trading
input ENUM_TIMEFRAMES ConfirmationTimeframe = PERIOD_M5; // Lower timeframe for engulfing
input ENUM_TIMEFRAMES TrendTimeframe = PERIOD_H1;        // Trend from H1 SMA
input int MaxCandlesPostPurge = 5;                       // Max H1 candles to wait for engulfing
input double VolumeThreshold = 1.2;                      // Volume multiplier for liquidity confirmation
input bool UseTrendFilter = true;                        // Use SMA trend filter
input int SMAPeriod = 50;                                // SMA period for trend filter

OnInit関数:堅牢な取引のためのセットアップと検証

OnInit関数は、EAがチャートに読み込まれた際に一度だけ実行され、GBPUSD、GBPJPY、EURUSDの取引に適した設定をおこないます。この関数はTradeTimeframe(H1、H4、D1)とConfirmationTimeframe(M15、M30)が戦略の多時間軸アプローチ構成と整合しているかを検証し、無効な入力は拒否してエラー発生を防ぎます。さらに、SymbolInfoDoubleを使用して通貨ペアごとの契約サイズを取得します。これはGBPペアでの正確なポジションサイズ計算に不可欠で、たとえばGBPJPYはJPYのスケールによりpip値が小さいため特に重要です。

また、高値と安値を保持するグローバル変数(lastHighH1、lastLowH1など)、ローソク足の時間、取引状況などは0またはfalseに初期化され、EAの状態をリセットします。契約サイズのチェックにより、EAは正しいロットサイズを計算できるようになり、特にGBPJPYのpip値の特性上、特に重要です。初期化が正常に完了すると、使用する時間足と契約サイズがログに出力され、取引準備が整ったことが確認できます。このセットアップにより、EAはEURUSD、GBPUSD、GBPJPYの特定市場環境に適応した堅牢な動作が可能となり、金などのよりボラティリティの高い資産とは異なり、比較的安定した取引が可能になります。

int OnInit()
{
   if(TradeTimeframe != PERIOD_M15 && TradeTimeframe != PERIOD_M30)
   {
      Print("Invalid trade timeframe. Use M15 or M30.");
      return(INIT_PARAMETERS_INCORRECT);
   }
   if(ConfirmationTimeframe != PERIOD_M5 && ConfirmationTimeframe != PERIOD_M15)
   {
      Print("Invalid confirmation timeframe. Use M5 or M15.");
      return(INIT_PARAMETERS_INCORRECT);
   }
  
   contractSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   if(contractSize == 0)
   {
      Print("Failed to get contract size for ", _Symbol);
      return(INIT_PARAMETERS_INCORRECT);
   }
  
   lastHigh = 0; lastLow = 0;
   lastCandleTime = 0;
   purgeDetected = false;
   lastPurgeTime = 0;
  
   Print("EA Initialized on ", EnumToString(TradeTimeframe), ", Confirmation TF: ", EnumToString(ConfirmationTimeframe), ", Contract Size: ", contractSize);
   return(INIT_SUCCEEDED);
}

IsNewCandle関数:新規ローソク足でのトリガーロジック 

IsNewCandle関数は、主要取引時間足(デフォルトはH1)で新しいローソク足が形成されたかを確認します。具体的には、現在のローソク足のタイムスタンプ(iTime)と最後に記録されたローソク足時間(lastCandleTime)を比較します。新しいローソク足が検出された場合、lastCandleTimeが更新され、関数はtrueを返します。これにより、OnTick内のメイン取引ロジックが実行されます。これにより、EAはH1足ごとに一度だけ取引条件を評価することができ、GBPUSDやGBPJPYでのボラティリティの高いローソク足内の値動きによる不要な処理負荷や重複チェックを防ぐことができます。新しいローソク足に焦点を当てることで、流動性刈り取りの検出や包み足パターンの判定に必要な完全なローソク足データに基づいた戦略を正確に実行でき、トレンド主導のGBPペア市場で重要な値動きを捉えることが可能です。この関数は軽量でありながら、EAの効率性と精度を維持するために不可欠です。

bool IsNewCandle()
{
   datetime currentCandleTime = iTime(_Symbol, TradeTimeframe, 0);
   if(currentCandleTime != lastCandleTime)
   {
      lastCandleTime = currentCandleTime;
      return true;
   }
   return false;
}

UpdateHighsLows関数:流動性刈り取りレベルの監視

UpdateHighsLows関数は、H1、H4、D1の各時間足において、過去LookbackBars(デフォルト3本)の最高値と最安値を追跡し、それらをグローバル変数(lastHighH1、lastLowH1など)に格納します。CopyRatesを用いて過去の価格データを取得し、ArraySetAsSeriesにより最新のローソク足が配列のインデックス0に来るよう設定されます。時間軸ごとに、最初のローソク足の高値/安値を初期値とし、ルックバック期間を順に確認することで極値を更新します。

この関数は、流動性刈り取りの検出において極めて重要です。たとえば、現在のH1足が過去の高値を上抜ける、または安値を下抜ける場合、それはEURUSD、GBPUSD、GBPJPYにおけるトレンド転換や継続の可能性を示唆します。多時間軸アプローチにより、GBPJPYのボラティリティの高い値動きで発生するストップ狩りなど、重要な流動性刈り取りを逃さず捉えることができます。また、CopyRatesの読み込みに失敗した場合はエラーログに記録され、EAの堅牢性が確保されます。この関数は、GBPペアの重要サポート/レジスタンスに敏感な特性を考慮した、流動性刈り取りに基づくエントリーロジックの基盤を形成します。

void UpdateHighsLows()
{
   // H1
   MqlRates ratesH1[];
   ArraySetAsSeries(ratesH1, true);
   if(CopyRates(_Symbol, PERIOD_H1, 1, LookbackBars, ratesH1) >= LookbackBars)
   {
      lastHighH1 = ratesH1[0].high;
      lastLowH1 = ratesH1[0].low;
      for(int i = 1; i < LookbackBars; i++)
      {
         if(ratesH1[i].high > lastHighH1) lastHighH1 = ratesH1[i].high;
         if(ratesH1[i].low < lastLowH1) lastLowH1 = ratesH1[i].low;
      }
   }
   else Print("Failed to load H1 rates");
   
   // H4
   MqlRates ratesH4[];
   ArraySetAsSeries(ratesH4, true);
   if(CopyRates(_Symbol, PERIOD_H4, 1, LookbackBars, ratesH4) >= LookbackBars)
   {
      lastHighH4 = ratesH4[0].high;
      lastLowH4 = ratesH4[0].low;
      for(int i = 1; i < LookbackBars; i++)
      {
         if(ratesH4[i].high > lastHighH4) lastHighH4 = ratesH4[i].high;
         if(ratesH4[i].low < lastLowH4) lastLowH4 = ratesH4[i].low;
      }
   }
   else Print("Failed to load H4 rates");
   
   // D1
   MqlRates ratesD1[];
   ArraySetAsSeries(ratesD1, true);
   if(CopyRates(_Symbol, PERIOD_D1, 1, LookbackBars, ratesD1) >= LookbackBars)
   {
      lastHighD1 = ratesD1[0].high;
      lastLowD1 = ratesD1[0].low;
      for(int i = 1; i < LookbackBars; i++)
      {
         if(ratesD1[i].high > lastHighD1) lastHighD1 = ratesD1[i].high;
         if(ratesD1[i].low < lastLowD1) lastLowD1 = ratesD1[i].low;
      }
   }
   else Print("Failed to load D1 rates");
}

IsVolumeSpike関数:取引流動性の検証

IsVolumeSpike関数は、取引セットアップが有効かを確認するために、現在のローソク足のティックボリュームが、過去LookbackBars(デフォルト3本)の平均ボリュームをVolumeThreshold(デフォルト1.0)倍以上かどうかをチェックします。CopyRatesを使用して取引時間足(H1)の直近ローソク足データを取得し、有効なローソク足(ボリュームが1以上のローソク足)を対象に平均ボリュームを計算します。有効なローソク足が存在しない場合はチェックをスキップし、デバッグ用に警告をログに出力します。EURUSD、GBPUSD、GBPJPYにおいては、高い取引量はニュース後のブレイクアウトや流動性刈り取りなどの重要な値動きに伴うことが多いため、このフィルタは流動性刈り取りの有効性を確認するうえで非常に重要です。関数は現在のボリュームと平均ボリュームをログに出力することで透明性を確保します。ボリューム確認をおこなうことで、EAは流動性の低いセットアップによる誤ったシグナルを避け、GBPペア、特にトレンド主導の市場であるGBPJPYにおける取引の精度と収益性を高めます。

bool IsVolumeSpike(long currentVolume)
{
   double avgVolume = 0;
   MqlRates rates[];
   ArraySetAsSeries(rates, true);
   if(CopyRates(_Symbol, TradeTimeframe, 1, LookbackBars, rates) < LookbackBars)
   {
      Print("Failed to load rates for volume check");
      return true;
   }
   
   int validBars = 0;
   for(int i = 0; i < LookbackBars; i++)
   {
      if(rates[i].tick_volume > 1)
      {
         avgVolume += rates[i].tick_volume;
         validBars++;
      }
   }
   if(validBars == 0)
   {
      Print("Warning: No valid volume data. Average volume is 0. Bypassing volume check.");
      return true;
   }
   avgVolume /= validBars;
   
   Print("Current volume: ", currentVolume, ", Average volume: ", avgVolume, ", Valid bars: ", validBars);
   return currentVolume >= VolumeThreshold * avgVolume;
}

IsBullishTrend関数:トレンドの整合性の確認

IsBullishTrend関数は、取引時間足(H1)における50期間の単純移動平均(SMA)を用いて、市場のトレンド方向を判定します。iMAでSMAハンドルを作成し、CopyBufferで最新のSMA値を取得した後、現在の終値(iClose)と比較します。価格がSMAより上にある場合、関数はtrueを返し、強気トレンドであることを示します。それ以外の場合は、弱気または中立のトレンドと判断されます。

UseTrendFilterが有効(デフォルトtrue)の場合、この関数は買い取引を強気条件下でのみ、売りを弱気条件下でのみ実行するよう制御します。これにより、EURUSD、GBPUSD、GBPJPYがロンドン/ニューヨーク時間帯に持続的トレンドに従う傾向に沿った取引が可能になります。SMAデータ取得の失敗はエラーログに記録され、信頼性が確保されます。このフィルタは、GBPペア市場における乱高下時の誤ブレイクを減らし、流動性刈り取り後の取引に先立って広い市場環境を確認することで、より安全で精度の高い取引を支援します。

bool IsBullishTrend()
{
   double sma[];
   ArraySetAsSeries(sma, true);
   int smaHandle = iMA(_Symbol, TradeTimeframe, SMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   if(CopyBuffer(smaHandle, 0, 0, 1, sma) < 1)
   {
      Print("Failed to load SMA data");
      return false;
   }
   double currentPrice = iClose(_Symbol, TradeTimeframe, 0);
   Print("Current price: ", currentPrice, ", SMA: ", sma[0]);
   return currentPrice > sma[0];
}

IsBullishEngulfingおよびIsBearishEngulfing関数:反転シグナルの確認

これらの関数は、流動性刈り取り後のエントリーを確認するための重要な反転パターンである、陽および陰の包み足を検出します。IsBullishEngulfingは、現在のローソク足が陽線(終値 > 始値)、直前のローソク足が陰線(終値 < 始値)であり、現在のローソク足が前のローソク足を包み込む(始値 ≤ 前の終値、終値 ≥ 前の始値)条件を満たすかどうかをチェックします。さらに、現在のローソク足の実体が前のローソク足の実体のEngulfingMinBodyRatio(0.3)以上であることを確認します。IsBearishEngulfingはこの逆のロジックを適用し、弱気のセットアップを判定します。EURUSD、GBPUSD、GBPJPYにおいては、M15やH1の流動性刈り取り後の包み足は、重要水準での流動性刈り取り後に特に強い反転やトレンド継続のシグナルとなることが多いです。

実体比率のチェックにより、GBPペアのボラティリティが高い時間帯における弱いパターンを除外し、信頼性の高いシグナルを抽出します。これらの関数は、直近3本のH1足およびM15足に適用され、どちらの時間足でもシグナルを捉える柔軟性を提供し、GBP市場のダイナミクスに対するEAの応答性を高めます。

bool IsBullishEngulfing(MqlRates &current, MqlRates &previous)
{
   double currentBody = MathAbs(current.close - current.open);
   double prevBody = MathAbs(previous.close - previous.open);
   
   if(current.close > current.open && 
      previous.close < previous.open && 
      current.open <= previous.close && 
      current.close >= previous.open && 
      currentBody >= EngulfingMinBodyRatio * prevBody)
   {
      return true;
   }
   return false;
}

bool IsBearishEngulfing(MqlRates &current, MqlRates &previous)
{
   double currentBody = MathAbs(current.close - current.open);
   double prevBody = MathAbs(previous.close - previous.open);
   
   if(current.close < current.open && 
      previous.close > previous.open && 
      current.open >= previous.close && 
      current.close <= previous.open && 
      currentBody >= EngulfingMinBodyRatio * prevBody)
   {
      return true;
   }
   return false;
}

PlaceTrade関数:成行注文の実行(SL/TP使用)

PlaceTrade関数は、有効なシグナル(流動性刈り取り + 包み足 + ボリューム + トレンド)が確認された際に、買いまたは売りの注文を実行します。この関数では、MqlTradeRequestを作成し、通貨ペア、固定のLotSize(0.1)、注文種別(買い/売り)、およびエントリープライスを設定します。ストップロスは150 pips、テイクプロフィットは600 pipsに設定されており、EURUSD、GBPUSD、GBPJPYのポイント値(_Point * 100)に合わせてpipスケーリングを考慮しています。ORDER_FILLING_IOC (Immediate or Cancel)により、GBPJPYのような急速な値動きが発生する市場でも迅速な約定が保証されます。

注文が成功した場合、取引内容がログに記録され、tradePlacedがtrueに設定され、同一シグナルでの重複エントリーを防ぎます。また、purgeDetectedはリセットされ、同じ流動性刈り取りで再エントリーされるのを防ぎます。注文が失敗した場合は、デバッグ用にエラーコードがログに出力されます。この関数により、あらかじめ定義されたリスクパラメータに基づく正確な取引が可能となり、GBPペアのトレンドフォロー市場における高確率セットアップを狙った収益性の最適化が可能になります。

void PlaceTrade(ENUM_ORDER_TYPE orderType, double price)
{
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = LotSize;
   request.type = orderType;
   request.price = price;
   request.sl = (orderType == ORDER_TYPE_BUY) ? price - StopLossPips * _Point * 100 : price + StopLossPips * _Point * 100;
   request.tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfitPips * _Point * 100 : price - TakeProfitPips * _Point * 100;
   request.type_filling = ORDER_FILLING_IOC;
   
   if(OrderSend(request, result))
   {
      Print("Trade placed successfully: ", orderType == ORDER_TYPE_BUY ? "BUY" : "SELL", " at ", price, " SL: ", request.sl, " TP: ", request.tp);
      tradePlaced = true;
      purgeDetected = false; // Reset purge after trade
   }
   else
   {
      Print("Trade failed: ", result.retcode);
   }
}

ManageTrailingStop関数:トレーリングストップによる利益保護

ManageTrailingStop関数は、価格が有利に動いた際に、保有ポジションのストップロスを動的に調整して利益を確保します。まず、PositionSelectを使用して指定された通貨ペアのポジションが存在するかを確認します。買いポジションの場合、現在のBid価格からTrailingStopPips (100 pips)を引いた位置に新しいストップロスを計算し、GBPUSD、EURUSD、GBPJPYのポイント値に合わせて調整します。新しいストップロスは、現在のストップロスよりも高く、かつ建値より上の場合のみ適用され、損益分岐点または利益を確保できるようにします。売りポジションの場合は、現在のアスク価格より上にストップロスを設定し、現在のストップロスより低い場合(または未設定の場合)かつ建値より下の場合に適用されます。

ストップロスの更新にはMqlTradeRequestとTRADE_ACTION_SLTPを使用し、テイクプロフィットは保持されます。このトレーリング機能は、GBPJPYのようなボラティリティの高い相場で非常に重要で、大きな値動きを捉えつつ利益を守ることが可能です。更新に失敗した場合はエラーログに記録され、透明性が確保されます。この関数により、GBPペアのトレンド主導市場で利益を失うリスクを低減し、収益性を向上させることができます。

void ManageTrailingStop()
{
   if(!PositionSelect(_Symbol)) return;
   
   double currentPrice = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? 
                         SymbolInfoDouble(_Symbol, SYMBOL_BID) : 
                         SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   double currentSL = PositionGetDouble(POSITION_SL);
   
   double newSL = 0;
   if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
   {
      newSL = currentPrice - TrailingStopPips * _Point * 100;
      if(newSL > currentSL && newSL > openPrice)
      {
         MqlTradeRequest request = {};
         MqlTradeResult result = {};
         request.action = TRADE_ACTION_SLTP;
         request.position = PositionGetInteger(POSITION_TICKET);
         request.symbol = _Symbol;
         request.sl = newSL;
         request.tp = PositionGetDouble(POSITION_TP);
         if(OrderSend(request, result))
            Print("Trailing stop updated for BUY: ", newSL);
         else
            Print("Failed to update trailing stop: ", result.retcode);
      }
   }
   else // POSITION_TYPE_SELL
   {
      newSL = currentPrice + TrailingStopPips * _Point * 100;
      if((newSL < currentSL || currentSL == 0) && newSL < openPrice)
      {
         MqlTradeRequest request = {};
         MqlTradeResult result = {};
         request.action = TRADE_ACTION_SLTP;
         request.position = PositionGetInteger(POSITION_TICKET);
         request.symbol = _Symbol;
         request.sl = newSL;
         request.tp = PositionGetDouble(POSITION_TP);
         if(OrderSend(request, result))
            Print("Trailing stop updated for SELL: ", newSL);
         else
            Print("Failed to update trailing stop: ", result.retcode);
      }
   }
}

OnTick関数:流動性刈り取りと包み足に基づく取引のコアロジック

OnTick関数はEAの主要な意思決定ハブであり、すべての価格ティックで実行されますが、IsNewCandleによって新しいH1ローソク足のタイミングでのみ処理されます。ポジションが開かれていない場合はtradePlacedをリセットし、1回の流動性刈り取りサイクルにつき1回だけ取引がおこなわれるようにします。保有ポジションに対してはManageTrailingStopでトレーリングストップが管理されます。H1足およびM15足のデータをCopyRatesで読み込み、現在のH1足を過去の高値/安値(UpdateHighsLowsで更新)と比較して流動性刈り取りを検出します。具体的には、H1/H4/D1の高値を上抜ける、あるいは安値を下抜ける場合に流動性刈り取りが発生したと判断します。この現象はEURUSD、GBPUSD、GBPJPYでの主要取引セッション中によく見られます。刈り取りが検出されるとpurgeDetectedがセットされ、lastPurgeTimeが3本分のH1ローソク足のウィンドウを追跡します。

ボリュームはIsVolumeSpikeで確認され、トレンドはIsBullishTrendでチェックされます(有効な場合)。包み足パターンはH1およびM15の両方で判定され、柔軟な確認が可能です。高値刈り取り後にH1またはM15で陽の包み足が形成され、ボリュームが高く、トレンドが強気であれば買い取引が発動されます。一方、安値刈り取り後に陰の包み足が形成され、ボリュームが高く、トレンドが弱気であれば売りが実行されます。詳細なログ出力によりデバッグの透明性が確保されます。このロジックは、多時間軸での流動性刈り取りと堅牢な確認シグナルを組み合わせることで、GBPペアのトレンドフォロー型市場における高確率取引を実現し、収益性の最適化を可能にしています。

void OnTick()
{
   // Check if a new candle has formed on the trade timeframe
   if(!IsNewCandle()) return;
   
   // Reset tradePlaced if no open positions
   if(!PositionSelect(_Symbol)) tradePlaced = false;
   
   // Manage trailing stop for open positions
   ManageTrailingStop();
   
   // Get current and previous candle data for trade timeframe
   MqlRates ratesH1[];
   ArraySetAsSeries(ratesH1, true);
   if(CopyRates(_Symbol, TradeTimeframe, 0, 4, ratesH1) < 4)
   {
      Print("Failed to load H1 rates data");
      return;
   }
   
   // Get candle data for confirmation timeframe (M15)
   MqlRates ratesM15[];
   ArraySetAsSeries(ratesM15, true);
   if(CopyRates(_Symbol, ConfirmationTimeframe, 0, 4, ratesM15) < 4)
   {
      Print("Failed to load M15 rates data");
      return;
   }
   
   // Current H1 candle (index 0)
   double currentOpenH1 = ratesH1[0].open;
   double currentCloseH1 = ratesH1[0].close;
   double currentHighH1 = ratesH1[0].high;
   double currentLowH1 = ratesH1[0].low;
   long currentVolumeH1 = ratesH1[0].tick_volume;
   datetime currentTimeH1 = ratesH1[0].time;
   
   // Update highs and lows for all timeframes
   UpdateHighsLows();
   
   // Check for purge (liquidity sweep) on any timeframe
   bool highPurgedH1 = (currentHighH1 > lastHighH1 && lastHighH1 > 0);
   bool highPurgedH4 = (currentHighH1 > lastHighH4 && lastHighH4 > 0);
   bool highPurgedD1 = (currentHighH1 > lastHighD1 && lastHighD1 > 0);
   bool lowPurgedH1 = (currentLowH1 < lastLowH1 && lastLowH1 > 0);
   bool lowPurgedH4 = (currentLowH1 < lastLowH4 && lastLowH4 > 0);
   bool lowPurgedD1 = (currentLowH1 < lastLowD1 && lastLowD1 > 0);
   bool highPurged = highPurgedH1 || highPurgedH4 || highPurgedD1;
   bool lowPurged = lowPurgedH1 || lowPurgedH4 || lowPurgedD1;
   
   // Update purge status
   if(highPurged || lowPurged)
   {
      purgeDetected = true;
      lastPurgeTime = currentTimeH1;
      highPurge = highPurged;
   }
   
   // Check if within the post-purge window
   bool withinPurgeWindow = false;
   if(purgeDetected)
   {
      int candlesSincePurge = iBarShift(_Symbol, TradeTimeframe, lastPurgeTime, true);
      withinPurgeWindow = candlesSincePurge <= MaxCandlesPostPurge;
      if(!withinPurgeWindow)
      {
         purgeDetected = false; // Reset if window expires
         Print("Purge window expired: ", candlesSincePurge, " candles since last purge");
      }
   }
   
   // Check volume for liquidity confirmation
   bool volumeConfirmed = IsVolumeSpike(currentVolumeH1);
   if(currentVolumeH1 <= 1) 
   {
      Print("Warning: Tick volume is ", currentVolumeH1, ". Possible data issue. Bypassing volume check.");
      volumeConfirmed = true;
   }
   
   // Check trend with SMA
   bool isBullishTrend = UseTrendFilter ? IsBullishTrend() : true;
   
   // Check for engulfing candles on H1 (current + previous 2 candles)
   bool bullishEngulfingH1 = false, bearishEngulfingH1 = false;
   for(int i = 0; i < 3; i++)
   {
      if(IsBullishEngulfing(ratesH1[i], ratesH1[i+1]))
         bullishEngulfingH1 = true;
      if(IsBearishEngulfing(ratesH1[i], ratesH1[i+1]))
         bearishEngulfingH1 = true;
   }
   
   // Check for engulfing candles on M15 (current + previous 2 candles)
   bool bullishEngulfingM15 = false, bearishEngulfingM15 = false;
   for(int i = 0; i < 3; i++)
   {
      if(IsBullishEngulfing(ratesM15[i], ratesM15[i+1]))
         bullishEngulfingM15 = true;
      if(IsBearishEngulfing(ratesM15[i], ratesM15[i+1]))
         bearishEngulfingM15 = true;
   }
   
   // Trade logic
   if(purgeDetected && withinPurgeWindow && !tradePlaced)
   {
      if(highPurge && (bullishEngulfingH1 || bullishEngulfingM15) && volumeConfirmed && isBullishTrend)
      {
         Print("Buy signal: High purged, bullish engulfing on ", bullishEngulfingH1 ? "H1" : "M15", ", volume confirmed, bullish trend");
         PlaceTrade(ORDER_TYPE_BUY, currentCloseH1);
      }
      else if(!highPurge && (bearishEngulfingH1 || bearishEngulfingM15) && volumeConfirmed && !isBullishTrend)
      {
         Print("Sell signal: Low purged, bearish engulfing on ", bearishEngulfingH1 ? "H1" : "M15", ", volume confirmed, bearish trend");
         PlaceTrade(ORDER_TYPE_SELL, currentCloseH1);
      }
   }
}

インストールとバックテスト:MetaEditorでコンパイルし、チャートに添付します。GBPUSDのバックテスト、H1(2025~2026年)、リスク1%。 


戦略テスト

Trending King EAの戦略テスト

この戦略は、そのコアロジックおよびトレンドフォロー型取引への高い適応性により、多くの通貨ペア、場合によってはほぼすべての通貨ペアにおいて有効に機能します。本戦略では、エントリーセットアップとして流動性パージの概念を採用しており、高ボラティリティ環境を活用する設計となっています。これらは多くの取引戦略において重要かつ有利な要素です。今回、この戦略はGBPUSDを対象に、2025年1月1日から2026年1月8日までの期間、60分足(H1)チャートで検証を行います。以下は、本戦略において選択したパラメータです。以下に、この戦略で使用するパラメータを示します。 

GBP/USD

入力設定

入力設定


ストラテジーテスターの結果

ストラテジーテスターで検証をおこなった結果、このEAがどのように機能し、市場をどのように分析し、どのようなパフォーマンスを示すかが明らかになりました。

Trending King EAのストラテジーテスター結果

残高/エクイティグラフ 

GBP/USD

テスト結果グラフ

バックテスト結果

GBP/USD

テスト結果


まとめ

本記事では、トレンドフォローに特化して設計されたMetaTrader 5のEAについて解説しました。このEAは、トレンドのスピードと勢いを活用しつつ、取引およびリスク管理の手法を組み合わせ、GOLDにおける高確率の取引セットアップを識別し、実行しつつ、リスクやエクスポージャー、人為的ミスを体系的に最小化するよう設計されています。また、同じ取引・リスク管理プロトコルを用いて適切な決済ポイントも管理します。

このEAは、プライスアクションに基づくエントリーおよびトレンド変化の検出を可能にする、非常にシンプルでありながら強力なトレンドフォロー型EAおよびコンセプトの一つです。堅牢で柔軟性の高いリスク・取引管理ロジックにより、ドローダウンや取引の損失を最小化しながら、EAが最適なパフォーマンスを発揮できるよう設計されています。 

このEAをGBPUSDでテストし、任意の時間足で効率的にエントリを検出できることを確認しました。しかし、エントリの検出はあくまで一部であり、EA内部には最適なエントリ検証ロジックが組み込まれており、特定の条件を満たした場合のみ取引が実行されます。取引が検証されて実行されると、取引およびリスク管理ロジックが即座に適用され、決済時まで適切な管理がおこなわれます。

このEA戦略を実装するには、下記の入力パラメータを設定することで望ましい結果を得られます。EAは、トレーダーが選択した時間足(M15~D1)で可能性のあるエントリをスキャンし、トレンドや移動平均、ATRによるトレーリングストップと整合するポイントを検出します。興味のあるトレーダーは、まずデモ口座でGBPUSDを用いてこのEAのバックテストをおこなうべきです。GBPUSD向けに設計されており、最適なパフォーマンスを発揮しますが、GBPJPY、EURUSD、GOLDにも適用可能です。このEAは、トレンドフォローに特化した取引に最適化されており、プロップファーム向けに、高確率のセットアップ、高度な売買ロジック、リスク管理およびトレーリングストップを統合することを目的として設計されています。

また、ユーザーには、定期的にパフォーマンスログを確認し、目標や資産クラス、リスク許容度に応じて設定や入力パラメータを調整することを推奨します。免責条項:このEAを使用する場合、まずデモ口座でテストし、トレンドフォローおよび取引手法を習得してから、実資金で取引するようにしてください。


結論

本記事では、トレーダーが直面する主な課題として、ナラティブ、バイアス、方向性およびトレンドの識別、リスク管理、取引管理、そしてドローダウンの回避を取り上げました。そのうえで、これらのプロセスを簡略化し、高確率の取引のみを実行できる可能性を高めるEAの設計方法について解説しました。また、トレンド方向に沿った取引のみに集中し、逆張りのアイデアやセットアップを排除することが、これらの課題解決に大きく寄与する点についても説明しています。  

多くのトレーダーは、トレンドフォロー型取引がパフォーマンスに与える大きな正の影響を十分に理解していない場合があります。しかし、これを適切なリスク管理および取引管理と組み合わせることで、結果は大きく変わり、平均的なトレーダーとトップレベルのトレーダーを分ける決定的な要因となります。本記事で提案するEAは、規律を維持する支援をおこない、トレーダーが自分の取引アイデアやポジションサイズ、セットアップを検証できるようにします。EAのエントリを直接使用しなくても、管理と検証が可能です。

自動化されたMQL5 EAは以下を提供します。

  • 取引対象資産のトレンド方向に一致した高確率の取引機会の提供
  • ニュース時のボラティリティから保護するため、ニュース前後の取引をブロック
  • 確認されたシグナルのみでの取引エントリ、動的SL/TP対応
  • 適応型リスク管理(連敗時のロット削減、連勝時のロット増加)
  • 継続的な戦略最適化のための取引ログ記録
  • トレンド方向のみに限定した厳格な取引ルールの適用
  • 感情による意思決定の排除
  • 自動取引管理(SL、TP、部分決済)

これらの機能により、高確率取引の一貫した実行と最適なリスク管理が可能となり、収益性の向上とパフォーマンス改善の可能性が高まります。

記事で参照されているすべてのコードは以下に添付されています。次の表では、この記事に付随するすべてのソースコードファイルについて説明します。

ファイル名 説明
Trending King EA.mq5 Trend King EAの完全なソースコードを含むファイル

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/19755

添付されたファイル |
Trending_King.mq5 (16.29 KB)
最後のコメント | ディスカッションに移動 (2)
Mustafa Nail Sertoglu
Mustafa Nail Sertoglu | 12 2月 2026 において 13:42

健康で安全でありますように。


多くのPRINT()と多くのログがある。

Eugene Mmene
Eugene Mmene | 12 2月 2026 において 13:56
Mustafa Nail Sertoglu #:

健康で安全でありますように


多くのPRINT()と多くのログがある。

ようこそ。
プライスアクション分析ツールキットの開発(第54回):EMAと平滑化された価格変動によるトレンドのフィルタリング プライスアクション分析ツールキットの開発(第54回):EMAと平滑化された価格変動によるトレンドのフィルタリング
取引の明確さとタイミングを向上させるために、平均足による平滑化とEMA20の高値および安値のバンド、さらにEMA50のトレンドフィルターを組み合わせた手法を解説します。これらのツールにより、トレーダーは真のモメンタムを見極め、ノイズを排除し、ボラティリティの高い局面やトレンド相場により適切に対応できます。
初心者からエキスパートへ:市場の不規則性への対処 初心者からエキスパートへ:市場の不規則性への対処
市場のルールは常に変化しており、かつて有効だった原則も、時間の経過とともにその効力を徐々に失っていきます。過去に機能していたものが、現在では一貫して機能しなくなることがあります。本記事では、このような市場の不確実性に対応するために、「確率レンジ(ゾーン)」という考え方に焦点を当てます。さらに、MQL5を用いて、特に値動きが不安定な相場環境でも機能するアルゴリズムの構築方法を解説していきます。ディスカッションにぜひご参加ください。
ラリー・ウィリアムズの『市場の秘密』(第6回):市場変動を利用したボラティリティブレイクアウトの測定 ラリー・ウィリアムズの『市場の秘密』(第6回):市場変動を利用したボラティリティブレイクアウトの測定
MQL5を用いてラリー・ウィリアムズのボラティリティブレイクアウト型エキスパートアドバイザーを設計および実装する方法を解説します。スイングレンジの測定、エントリーレベルの算出、リスクベースのポジションサイジング、さらに実際の市場データを用いたバックテストまでを網羅します。
MQL5入門(第34回):MQL5のAPIとWebRequest関数の習得(VIII) MQL5入門(第34回):MQL5のAPIとWebRequest関数の習得(VIII)
MetaTrader 5でインタラクティブなコントロールパネルを作成する方法を学びます。入力フィールド、アクションボタン、テキストを表示するためのラベルを追加する基本について説明します。プロジェクトベースのアプローチを用いて、ユーザーがメッセージを入力し、最終的にAPIからのサーバー応答を表示するパネルを設定する方法を学びます。