English Русский Deutsch
preview
プライスアクション分析ツールキットの開発(第63回):MQL5での上昇・下降ウェッジ検出の自動化

プライスアクション分析ツールキットの開発(第63回):MQL5での上昇・下降ウェッジ検出の自動化

MetaTrader 5 |
19 0
Christian Benjamin
Christian Benjamin

内容


はじめに

チャートを開いたとき、まずは構造を探して全体像をつかもうとするものです。よく知られたパターンは、期待値を形成し、リスクを管理し、高確率なエントリーに備えるための指針となります。上昇ウェッジと下降ウェッジは、その中でも最も多く取引されているプライスアクション構造の一つです。これらは、しばしば値動きの拡大に先行する圧縮形成を示します。

しかし、課題はウェッジが存在することを知っていることではありません。課題は、適切なウェッジ構造を一貫して客観的に識別することです。特にチャート分析を学び始めたばかりのトレーダーにとって、正しいウェッジ構造を認識することは難しい場合があります。また、経験豊富な分析者であっても、トレンドラインを引き、調整し、検証するために多くの時間を費やすことがあり、ときには有効な形成を見逃してしまうこともあります。主観的なパターン認識は、判断の遅れ、不一致、そしてバイアスを生み出します。

この問題に対応するため、本稿では、チャート上で上昇ウェッジおよび下降ウェッジ形成を自動的に検出し、構築するMQL5インジケーターを紹介します。このシステムは、ピボットポイントを識別し、傾きの収束を検証し、構造的な重複を防止するとともに、ブレイクアウトまたは失敗条件を監視します。これにより、幾何学的な考え方を、構造化されたアルゴリズムとして実装します。

本記事では、以下の流れで段階的に解説していきます。

  • まず、上昇ウェッジと下降ウェッジの構造的特徴について確認します。
  • 次に、その理論を実践的なMQL5実装へと変換します。
  • 続いて、テストを通じてシステムの動作を検証します。
  • 最後に、システムの洞察と実践的な考慮事項についてまとめます。

それではまず、ウェッジ形成がどのように発展するのか、そしてなぜプライスアクション分析において重要なのかを理解することから始めます。


上昇ウェッジと下降ウェッジの構造的特徴

ウェッジとは、2本の収束するトレンドラインによって定義される価格形成であり、市場の値動きを徐々に狭まる範囲内に収める構造です。水平的なレンジ形成とは異なり、ウェッジは方向性を伴う圧縮を示します。価格は、上昇ウェッジでは高値・安値の切り上がりが続き、下降ウェッジでは高値・安値の切り下がりが続きます。しかし、2つの境界線の間における値動きの速度は時間の経過とともに縮小していきます。この構造を定義する重要な特徴は、単に2本のラインが存在することではありません。重要なのは、構造が示す測定可能な収束です。この収束は、モメンタムの低下と圧力の蓄積を示し、多くの場合、明確なブレイクアウトまたは構造的な失敗に先行します。

この形成をどのようにアルゴリズムロジックへ変換できるかを理解するため、その構造要素を段階的に確認します。

1. 価格圧縮と収束するトレンドライン

ウェッジは、制御された収縮局面で形成されます。連続する各スイングは、徐々に接近していく2本のラインの内側に収まります。

  • 上側の境界線は、レジスタンス圧力を表します。
  • 下側の境界線は、サポート圧力を表します。

価格がこれらの境界線の間で変動するにつれて、両者の垂直方向の距離は縮小していきます。この圧縮は、ボラティリティの低下と市場構造の引き締まりを反映しています。狭まるレンジはランダムに発生するものではなく、拡大する力を徐々に失っていく方向性のある値動きの中で形成されます。ウェッジと平行チャネルを区別する要素は、この収束そのものです。チャネルでは、境界線間の距離は一定に保たれます。一方、ウェッジではその距離は一定ではありません。

上図は上昇ウェッジを示しており、高値と安値の切り上げを伴う方向性のある圧縮と、上側および下側境界線の収束を表しています。

2. ピボット構造とタッチ検証

ウェッジの信頼性は、検証された構造的な基準点に依存します。これらの基準点とは、上側および下側の境界線を定義するスイングハイとスイングロー、つまりピボットポイントです。有効なウェッジには、それぞれの境界線に対して複数回の確認された接触が必要です。十分な接触がなければ、その構造は推測的なものにとどまります。追加される各ピボットは、価格が収束する制約条件を尊重していることを確認するため、構造的な正当性を高めます。

この要件により、任意のトレンドライン描画を防ぎ、客観的な形成条件を適用できます。ウェッジは2つのポイントだけで判断されるものではありません。繰り返される構造的な相互作用によって確認されるものです。

3. 傾きの方向とウェッジ分類

ウェッジは、境界線の方向性を示す傾きによって分類されます。

上昇ウェッジでは:

  • 両方のトレンドラインが上向きに傾きます。
  • 下側の境界線は、上側の境界線より速い速度で上昇します。
  • 下側から収束が発生します。

下降ウェッジでは:

  • 両方のトレンドラインが下向きに傾きます。
  • 上側の境界線は、下側の境界線より速い速度で下降します。
  • 上側から収束が発生します。

分類は、2つの境界線の相対的な傾きを比較することで決定されます。収束は、傾きの差によって将来的なある地点で予測ラインが交差するとき、数学的に明確になります。この交差点は一般的にアペックス(頂点)と呼ばれます。この傾きの関係こそが、視覚的なパターンを測定可能な幾何学構造へと変換する要素です。

4. ブレイクアウトと失敗の挙動

圧縮(コンプレッション)が臨界段階に達すると、価格は最終的にパターンをブレイクし、その構造が決着します。

  • 上昇ウェッジは通常、下方向へブレイクします。


  • 下降ウェッジは通常、上方向へブレイクします。

しかし、市場は必ずしも期待どおりに動くわけではありません。価格が反対方向へブレイクした場合、そのウェッジは構造的に無効となります。この結果はノイズではなく、オーダーフローのダイナミクスの変化を反映しています。そのため、形成後の価格の挙動を監視することが重要です。ウェッジは、識別された時点では未完成です。その有効性は、価格がその境界線にどのように反応するかによって決まります。



MQL5での実装

ウェッジ形成の構造理論を説明したところで、次のステップは、そのロジックを堅牢で実運用に適したMQL5実装へ変換することです。目的は、単に収束するトレンドラインを描画することではありません。重要なスイングポイントを特定し、境界線の収束を数学的に検証し、インテリジェントな重複検出によって構造上の競合を防止し、さらに価格の推移に応じてブレイクアウトと失敗を継続的に監視する、リペイントしない検出エンジンを構築することです。実装は、設定入力、ピボット検出、ウェッジ認識、カプセル化されたパターン管理、可視化、およびイベント駆動型実行フローという相互に関連するレイヤーで構成されています。

このシステムは、主要なピボットポイント、ウェッジの傾き、およびブレイクアウトがチャート上に明確に反映されるよう設計されており、トレード判断のための直感的な手がかりを提供します。一方で、その基盤となるモジュール構造とリペイントしないロジックにより、コードの堅牢性、効率性、および保守性を維持します。

入力と設定

実装は、検出感度と視覚的な表示の両方を制御するために、論理的なグループに分けられた明確な入力セクションから始まります。これらのパラメータは、アルゴリズムが市場構造をどの程度厳密に解釈するか、および検出された形成をチャート上でどのように描画するかを決定します。

//+------------------------------------------------------------------+
//| Input parameters for Wedge Pattern indicator                     |
//+------------------------------------------------------------------+
input group "Pattern Detection Rules"
input int    PivotLeft           = 5;             // Pivot Left
input int    PivotRight          = 5;             // Pivot Right
input int    MinTouches          = 3;             // Min. Touches per Line

input group "Visual Design"
input color  RisingColor         = clrRed;        // Rising Wedge (Bearish)
input color  FallingColor        = clrLime;       // Falling Wedge (Bullish)
input int    MaxWedges           = 20;            // Max wedges displayed (oldest removed)
input bool   ExtendLines         = true;          // Extend wedge lines
input int    LineExtensionBars   = 30;            // Bars to extend (if ExtendLines=true)
input ENUM_LINE_STYLE LineStyle  = STYLE_SOLID;   // Line style for wedge lines
input int    LineWidth           = 1;             // Line width (1-5)
input bool   ShowLabels          = true;          // Show pattern labels
input int    LabelFontSize       = 8;             // Label font size
input bool   LabelWithBackground = false;         // Add background rectangle to labels
input color  LabelBgColor        = clrBlack;      // Label background color
input double LabelBgOpacity      = 0.7;           // Background opacity (0.0-1.0)

最初のグループであるPattern Detection Rulesには、PivotLeft、PivotRight、およびMinTouchesが含まれます。ピボット関連のパラメータは、候補となるローソク足がスイングハイまたはスイングローとして認識されるかどうかを判断する際に、その左右で評価するバーの本数を定義します。これらの値を大きくすると、より明確なスイングが求められるため、より強固で保守的なピボットが生成されます。一方、値を小さくすると応答性は向上しますが、その代償としてノイズが増える可能性があります。MinTouchesパラメータは、ウェッジが有効と見なされる前に、両方の境界線上で最小数のピボットポイントを要求することで構造的な検証をおこない、弱い形成や形成途中の形成が受け入れられることを防ぎます。

2番目のグループであるVisual Designは、チャートの描画とオブジェクトの動作を制御します。RisingColorとFallingColorは、弱気の上昇ウェッジと強気の下降ウェッジを区別します。MaxWedgesは、表示する過去の形成数を制限し、最も古い構造を自動的に削除することでチャートの煩雑化を防ぎます。ExtendLinesとLineExtensionBarsは、境界線を将来のバーへ延長するかどうか、およびどこまで延長するかを定義します。さらに、線の太さ、線種、ラベルの表示、フォントサイズ、不透明度を調整可能な背景矩形などの追加スタイル設定により、視認性とチャートの外観を調整できます。これらの設定オプションにより、コアとなる検出ロジックを変更することなく、システムを柔軟に調整できます。

ピボットポイントの検出と構造確認

設定が完了すると、検出処理は構造的に意味のあるスイングポイントを抽出することから始まります。ウェッジは、生の価格変動ではなく、明確なピボットデータに基づいて構築されます。このため、実装では、各ピボットのバーインデックス、タイムスタンプ、および価格をカプセル化する専用のPivotクラスを導入します。

//+------------------------------------------------------------------+
//| Pivot point class                                                |
//+------------------------------------------------------------------+
class Pivot : public CObject
  {
public:
   int      index;
   datetime time;
   double   price;

   Pivot(int idx,datetime t,double p) : index(idx),time(t),price(p) {}
  };

このオブジェクト指向アプローチにより、データの格納、メモリ管理、および後続の構造参照が簡素化されます。ヘルパー関数IsPivotHigh()とIsPivotLow()は、PivotLeftおよびPivotRightで定義された範囲内の隣接するバーと高値または安値を比較することで、各候補バーを評価します。 十分な数の周囲のバーが形成された後にのみピボットを確定することで、このインジケータは、意味のあるスイングハイとスイングローのみをウェッジ境界の定義に使用します。このアプローチは、サポートとレジスタンスが機能している価格帯を明確にし、検出ロジックにおける過去データの不安定性を防ぎながら、信頼性の高いシグナルを生成します。

//+------------------------------------------------------------------+
//| Check if bar at idx is a pivot high                              |
//+------------------------------------------------------------------+
bool IsPivotHigh(int idx,const double &high[],int left,int right)
  {
   if(idx-left<0) return(false);
   double val=high[idx];
   for(int i=idx-left; i<=idx+right; i++)
     {
      if(i==idx) continue;
      if(i>=ArraySize(high)) return(false);
      if(high[i]>=val) return(false);
     }
   return(true);
  }

//+------------------------------------------------------------------+
//| Check if bar at idx is a pivot low                               |
//+------------------------------------------------------------------+
bool IsPivotLow(int idx,const double &low[],int left,int right)
  {
   if(idx-left<0) return(false);
   double val=low[idx];
   for(int i=idx-left; i<=idx+right; i++)
     {
      if(i==idx) continue;
      if(i>=ArraySize(low)) return(false);
      if(low[i]<=val) return(false);
     }
   return(true);
  }

ピボットハイは、評価ウィンドウ内のすべての周囲の高値よりもそのバーの高値が高い場合にのみ確定されます。一方、ピボットローは、すべての周囲の安値よりも低い場合にのみ確定されます。重要なのは、ピボットは即座には確定されないという点です。アルゴリズムは、必要な数の右側のバーが形成された後にのみ候補インデックスを評価することで、確定を遅らせます。この段階的な確定メカニズムにより、ピボットはリペイントせず、構造的な整合性が維持されるとともに、検出されたパターンにおける過去データの不安定性が防止されます。初回の履歴スキャン時と、その後のOnCalculate()内での更新時のいずれにおいても、確定したピボットは、自動メモリ管理機能を備えた動的なCArrayObjコンテナに格納されます。このフィルタリング段階により、生の価格データは安定した市場構造の表現へと変換され、境界線を構築するための信頼性の高い基準点となります。

ウェッジパターンの認識と幾何学的検証

十分な数のピボットポイントが確定すると、次のステップは、それらの配置がウェッジに特徴的な収束構造を形成しているかどうかを判断することです。検出は、新しいピボットが追加されるたびに、TryDetectWedge関数によって直ちに実行されます。 境界線の傾きと収束性によって、その構造が上昇ウェッジであるか下降ウェッジであるかが判定されます。理論上のアペックス(頂点)を投影し、重複する形成や、すでに交差している形成を除外することで、このシステムは、コード内で正確な幾何学的検証を維持しながら、明確で実用的なパターンのみをチャート上に表示します。

//+------------------------------------------------------------------+
//| Try to detect a new wedge pattern from recent pivots             |
//+------------------------------------------------------------------+
void TryDetectWedge(int currentBar,const datetime &time[],const double &close[])
  {
   int nHighs=pivotHighs.Total();
   int nLows=pivotLows.Total();
   if(nHighs<MinTouches || nLows<MinTouches) return;

   Pivot *p1h=dynamic_cast<Pivot*>(pivotHighs.At(nHighs-MinTouches));
   Pivot *pNh=dynamic_cast<Pivot*>(pivotHighs.At(nHighs-1));
   Pivot *p1l=dynamic_cast<Pivot*>(pivotLows.At(nLows-MinTouches));
   Pivot *pNl=dynamic_cast<Pivot*>(pivotLows.At(nLows-1));

   if(!p1h || !pNh || !p1l || !pNl) return;

   double upperSlope=(pNh.price-p1h.price)/(pNh.index-p1h.index+1e-10);
   double lowerSlope=(pNl.price-p1l.price)/(pNl.index-p1l.index+1e-10);

   int wedgeType=0;
   if(upperSlope>0 && lowerSlope>0 && lowerSlope>upperSlope) wedgeType=1;
   if(upperSlope<0 && lowerSlope<0 && upperSlope<lowerSlope) wedgeType=2;
   if(wedgeType==0) return;

   double apexX=(p1l.price-p1h.price+upperSlope*p1h.index-lowerSlope*p1l.index)/(upperSlope-lowerSlope+1e-10);
   if((int)MathRound(apexX)<=currentBar) return;

   bool isRising=(wedgeType==1);
   Wedge *w=new Wedge(isRising,p1h.index,p1h.time,p1h.price,pNh.index,pNh.time,pNh.price,
                      p1l.index,p1l.time,p1l.price,pNl.index,pNl.time,pNl.price,
                      upperSlope,lowerSlope,currentBar);

   if(OverlapsExistingWedge(w))
     {
      delete w;
      return;
     }

   w.Draw();
   wedges.Add(w);
   PruneOldWedges();
  }

この中核となるロジックでは、必要なタッチ数の範囲内にある最も古いピボットポイントと最新のピボットポイントを取得します。これらのポイントが、ウェッジの上側および下側の境界線候補を定義します。各境界線の傾きは、対応するピボットの組の間で直接計算され、各トレンドラインの角度と方向を数値的に表します。この処理により、アルゴリズムは視覚的な近似に頼ることなく、収束を数学的に評価できます。分類は厳密に傾きに基づいておこなわれます。上昇ウェッジは、両方の境界線の傾きが正であり、下側の境界線の傾きが上側の境界線よりも急である場合に識別されます。一方、下降ウェッジは、両方の傾きが負であり、上側の境界線が下側の境界線よりも急な角度で下降している場合に識別されます。

幾何学的検証では、理論上のアペックス(2本のトレンドラインの交点)も投影し、このアペックスが現在のバーより先に位置する場合にのみ形成を受け入れます。平行なトレンドラインや、すでに交差している構造は自動的に除外されます。新しいウェッジを受け入れる前に、TryDetectWedge()はOverlapsExistingWedge()を呼び出し、この関数はさらにOverlapsWith()を使用して、既存のすべてのアクティブなウェッジに対してバー単位で正確な重複判定をおこないます。新しいウェッジオブジェクトを生成する前にこの判定を実行することで、システムはチャート上の構造的一貫性を維持し、複数の競合するパターンが発生することを防ぎます。

ウェッジ構造と検出エンジン

形成がTryDetectWedge()内のすべての幾何学的検証および重複判定に合格すると、システムはそれを正式なWedgeオブジェクトとして生成します。Wedgeクラスは、両方の境界線の始点および終点となるピボット、事前計算された傾き、ウェッジの種類(上昇または下降)、形成バー、および実行時の状態フラグを含む、必要なすべての情報をカプセル化します。オブジェクト名は、ピボットインデックスと形成時刻に基づいて一意に生成されるため、各ウェッジは固有の識別子を持ち、複数の形成が短時間に連続して出現した場合でも、チャート上でオブジェクト名が衝突することはありません。生成されたウェッジは、新たに管理対象のCArrayObjコンテナへ追加され、そのライフサイクルが管理されます。

//+------------------------------------------------------------------+
//| Main Wedge pattern class                                         |
//+------------------------------------------------------------------+
class Wedge : public CObject
  {
public:
   bool      isRising;
   int       upperStartIdx,upperEndIdx;
   double    upperStartPrice,upperEndPrice;
   int       lowerStartIdx,lowerEndIdx;
   double    lowerStartPrice,lowerEndPrice;
   double    upperSlope,lowerSlope;
   int       formationBar;
   bool      isBroken,isFailed;

   string    upperLineName,lowerLineName;
   string    labelName,labelBgName;

   double UpperPriceAt(int barIdx) const;
   double LowerPriceAt(int barIdx) const;

   void Draw(void);
   void Update(int currentBar,datetime currentTime,double currentClose);
   void Delete(void);
  };

これにより、各形成が追跡され、チャート上に描画されるとともに、価格の推移に応じて更新され、検出ロジックと可視化とのリアルタイムな連携が維持されます。

可視化、オブジェクト識別、および動的な状態監視

ウェッジが検証され、Wedgeオブジェクトとして生成されると、システムはその可視化と継続的な監視に重点を置きます。各Wedgeオブジェクトは、幾何学的なデータだけでなく、その視覚的な識別情報と状態もカプセル化しています。Draw()メソッドは、設定された色、線幅、線種、およびオプションの前方延長を使用して、スタイル設定された上側および下側の境界トレンドラインを作成し、各ウェッジをチャート上に描画します。 上下の境界線はスタイル設定され、必要に応じて前方へ延長されるため、ウェッジの構造を一目で把握できる明確な視覚的ガイドとなります。一方で、コードはオブジェクトの生成とスタイル設定を動的に管理します。

//+------------------------------------------------------------------+
//| Draw wedge trendlines and optional label                         |
//+------------------------------------------------------------------+
void Wedge::Draw(void)
  {
   color clr=isRising?RisingColor:FallingColor;
   
   //--- Upper trend line
   if(ExtendLines)
     {
      int upperExtIdx=upperEndIdx+LineExtensionBars;
      datetime upperExtTime=upperEndTime+PeriodSeconds(PERIOD_CURRENT)*LineExtensionBars;
      double upperExtPrice=UpperPriceAt(upperExtIdx);
      ObjectCreate(0,upperLineName,OBJ_TREND,0,upperStartTime,upperStartPrice,upperExtTime,upperExtPrice);
     }
   else
      ObjectCreate(0,upperLineName,OBJ_TREND,0,upperStartTime,upperStartPrice,upperEndTime,upperEndPrice);

   ObjectSetInteger(0,upperLineName,OBJPROP_COLOR,clr);
   ObjectSetInteger(0,upperLineName,OBJPROP_WIDTH,LineWidth);
   ObjectSetInteger(0,upperLineName,OBJPROP_STYLE,LineStyle);
   ObjectSetInteger(0,upperLineName,OBJPROP_RAY_RIGHT,false);

   //--- Lower trend line (identical logic) + label with formation date and optional background rectangle
  }

形成ラベルには、ウェッジの種類と日付が表示されます。また、チャートが混雑している場合の視認性を向上させるために、半透明の背景矩形を追加することもできます。動的な状態はUpdate()メソッドによって監視され、新しいバーが形成されるたびに、UpperPriceAt()およびLowerPriceAt()の投影ヘルパーを使用して境界線との相互作用を評価します。ブレイクアウトの検出には、小さなボラティリティバッファを組み込み、ノイズやスプレッドを除外します。 ブレイクアウトおよび失敗は、境界線の外側で価格が明確に終値を付けた場合にのみマークされるため、チャート上で意味のあるシグナルとなります。一方で、この更新メカニズムはアクティブなウェッジのみを効率的に評価します。

//+------------------------------------------------------------------+
//| Update wedge status - check for breakout or failure              |
//+------------------------------------------------------------------+
void Wedge::Update(int currentBar,datetime currentTime,double currentClose)
  {
   if(isBroken || isFailed) return;

   double upperNow=UpperPriceAt(currentBar);
   double lowerNow=LowerPriceAt(currentBar);

   bool upperBreak=currentClose>upperNow+Point()*3;
   bool lowerBreak=currentClose<lowerNow-Point()*3;

   if((isRising && lowerBreak) || (!isRising && upperBreak))
     {
      isBroken=true;
      //--- Update label to BREAKOUT
     }
   else if((isRising && upperBreak) || (!isRising && lowerBreak) || upperNow<=lowerNow)
     {
      isFailed=true;
      //--- Update label to FAILED
     }
  }

Draw()、Update()、およびPruneOldWedges()の各メカニズムを組み合わせることで、構造検出と直感的なリアルタイムチャート解釈を結びつける、堅牢な可視化および監視レイヤーが構築されます。ウェッジが不要になった場合、そのDelete()メソッドによって、関連付けられたすべてのチャートオブジェクトが確実に削除されます。

//+------------------------------------------------------------------+
//| Remove oldest wedges when limit is exceeded                      |
//+------------------------------------------------------------------+
void PruneOldWedges(void)
  {
   while(wedges.Total()>MaxWedges)
     {
      Wedge *oldest=dynamic_cast<Wedge*>(wedges.At(0));
      if(oldest) oldest.Delete();
      wedges.Delete(0);
     }
  }

イベント駆動型実行フロー

ウェッジ検出システムは、MQL5のイベント駆動型フレームワーク内で完全に動作するよう設計されており、効率性と信頼性を高めるためにプラットフォームのライフサイクル関数を活用しています。初期化はOnInit()関数内でおこなわれ、ピボットとウェッジ用のCArrayObjコンテナが、自動メモリ管理を有効にした状態で作成されます。この設定により、オブジェクトはメモリリークを発生させることなく、安全に生成および削除されます。インジケータがチャートから削除されると、OnDeinit()関数が呼び出され、すべてのウェッジ関連チャートオブジェクトのクリーンアップと確保されたメモリの解放がおこなわれ、チャートはクリーンな状態に戻ります。

主な処理は OnCalculate() 内で実行されます。最初の実行サイクルでは、価格系列全体のヒストリカルスキャンが実行され、IsPivotHigh()およびIsPivotLow()を使用して初期ピボットポイントが検出され、さらにTryDetectWedge()によって条件を満たすウェッジが識別されます。 増分的な評価により、新しいバーが形成されるたびに即座に検出と状態更新が実行され、パフォーマンスを維持しながら、チャート上でウェッジの進展をリアルタイムかつ信頼性の高い形で確認できます。

//+------------------------------------------------------------------+
//| Main indicator calculation function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[])
  {
   ArraySetAsSeries(time,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(close,false);

   if(prev_calculated==0)
     {
      ObjectsDeleteAll(0,"WEDGE_");
      pivotHighs.Clear();
      pivotLows.Clear();
      wedges.Clear();

      int startBar=PivotRight;
      int endBar=rates_total-PivotRight-1;

      for(int i=startBar; i<=endBar; i++)
        {
         bool newPivot=false;
         if(IsPivotHigh(i,high,PivotLeft,PivotRight))
           {
            pivotHighs.Add(new Pivot(i,time[i],high[i]));
            newPivot=true;
           }
         if(IsPivotLow(i,low,PivotLeft,PivotRight))
           {
            pivotLows.Add(new Pivot(i,time[i],low[i]));
            newPivot=true;
           }
         if(newPivot) TryDetectWedge(i,time,close);
        }
     }

   int start=(prev_calculated>0)?prev_calculated-1:0;
   for(int i=start; i<rates_total; i++)
     {
      int possibleIdx=i-PivotRight;
      if(possibleIdx<0) continue;

      bool newPivot=false;
      if(IsPivotHigh(possibleIdx,high,PivotLeft,PivotRight))
        {
         pivotHighs.Add(new Pivot(possibleIdx,time[possibleIdx],high[possibleIdx]));
         newPivot=true;
        }
      if(IsPivotLow(possibleIdx,low,PivotLeft,PivotRight))
        {
         pivotLows.Add(new Pivot(possibleIdx,time[possibleIdx],low[possibleIdx]));
         newPivot=true;
        }
      if(newPivot) TryDetectWedge(possibleIdx,time,close);
     }

   if(rates_total>0)
     {
      int currentBar=rates_total-1;
      for(int j=0; j<wedges.Total(); j++)
        {
         Wedge *w=dynamic_cast<Wedge*>(wedges.At(j));
         if(w) w.Update(currentBar,time[currentBar],close[currentBar]);
        }
     }

   PruneOldWedges();
   return(rates_total);
  }

その後の更新では、システムは新たに確定したバーのみを評価するため、計算効率が大幅に向上します。新たに確定したピボットは、直ちにウェッジ検出ロジックを実行します。同時に、既存のすべてのウェッジは、それぞれのUpdate()メソッドを通じて最新の終値で更新され、ブレイクアウトまたは無効化条件をリアルタイムで評価できます。この増分処理によるアプローチは、不要な再計算を回避しながら、形成中のパターンに対してタイムリーな視覚的フィードバックを提供します。PruneOldWedges()は、各更新後に適用され、最適なパフォーマンスとチャートの明瞭性を維持します。

実装の要約

このMQL5実装は、理論的なウェッジ構造を、数学的に検証された収束に基づく、規律あるリペイントしない検出エンジンへ変換します。IsPivotHigh()およびIsPivotLow()によって重要なピボットポイントを抽出し、TryDetectWedge()内で境界線の傾きを計算し、アペックスの交点を投影し、OverlapsWith()によって幾何学的な重複による競合を防止し、さらにUpdate()によって方向性を持つブレイクアウト状態を動的に管理することで、このシステムはリアルタイム市場環境において構造的整合性を維持します。Draw()、PruneOldWedges()、およびOnInit()/OnDeinit()内での制御されたライフサイクル管理を備えたオブジェクト指向設計に加え、設定可能なパラメータにより、このインジケータは分析面で堅牢であり、より広範なトレードフレームワークへ統合可能な拡張性を備えています。


検証および動作分析

このセクションでは、ウェッジパターンインジケータの実際のパフォーマンスと堅牢性を評価するために使用したテストおよび検証プロセスについて説明します。ここでは、さまざまな取引条件、時間足、および市場レジームに最適化するために、入力パラメータを調整します。

このインジケータは、2026年初頭の開発および最適化フェーズにおいて、徹底的に検証されました。テストでは、選択した過去の期間の分析と、ライブチャート上での広範なリアルタイムフォワードテストを組み合わせました。EURUSD、GBPUSD、USDJPY、AUDUSD、およびゴールド(XAUUSD)を含む主要な銘柄を使用し、M15からH4までの時間足で、ボラティリティの高い市場環境とトレンド市場環境の両方における動作を評価しました。

以下の設定を主要なベースラインとして使用しました。

//+------------------------------------------------------------------+
//| Default parameters used during validation                        |
//+------------------------------------------------------------------+
input group "Pattern Detection Rules"
input int PivotLeft   = 5;   // Pivot Left
input int PivotRight  = 5;   // Pivot Right
input int MinTouches  = 3;   // Min. Touches per Line

input group "Visual Design"
input color RisingColor  = clrRed;     // Rising Wedge (Bearish)
input color FallingColor = clrLime;    // Falling Wedge (Bullish)
input int   MaxWedges    = 20;         // Max wedges displayed (oldest removed)
input bool  ExtendLines  = true;       // Extend wedge lines

リアルタイムチャートの例では、インジケータの動作が明確に示されています。

  • 信頼性の高い検出と分類:システムは、有効な上昇ウェッジおよび下降ウェッジを一貫して検出し、傾きの比較に基づいて強気構造と弱気構造を正しく区別します。
  • タイムリーなブレイクアウトフィードバック:方向性を考慮するUpdate()メソッドは、ブレイクアウトと失敗を正確にマークし、明確なラベル(「BREAKOUT」または「FAILED」)を表示することで、トレーダーが迅速に対応できるよう支援します。
  • チャートの整理:重複防止ロジック(OverlapsWith()およびOverlapsExistingWedge())により、複数の候補パターンが出現した場合でも、チャートが乱雑になることを効果的に防ぎます。

以下の画像は、EURUSD M30における典型的なライブ例を示しており、複数のウェッジ検出と、その後のブレイクアウト結果を確認できます。

以下のアニメーションは、EURUSD M30上でウェッジエンジンがリアルタイムで動作している様子を示しています。この例では、内部的な仕組みではなく、観察可能な動作に焦点を当てています。

いくつかの重要な特徴が確認できます。

  1. ウェッジ形成は、構造が成熟した後にのみ表示される
  2. 検出されたパターンは、一度確定されると安定して維持される
  3. ブレイクアウトの結果は、決着時点ですぐにマークされる

シーケンス全体を通じて、複数のウェッジ形成がそれぞれ独立して発展し、解決されます。あるものは方向性を伴う拡大によって完成し、また別のものはフォロースルーに至る前に無効化されます。それぞれの結果は、構造の帰結が確定した瞬間に明確にラベル表示されるため、手動で再分析することなく即座に解釈できます。この記録は、パターンのライフサイクル管理も示しています。価格が新しい構造フェーズへ移行すると、以前のウェッジは不要な表示を残さずに正常に終了し、継続的なボラティリティ環境においてもチャートの明瞭性が維持されます。重要なのは、この例が示すように、システムはブレイクアウトを予測しているのではなく、境界条件が明確に満たされた後にのみ反応するという点です。これにより、視覚的なシグナルは推測に基づく予測ではなく、実際の構造的イベントに対応したものになります。

したがって、このアニメーションは、価格が変化するライブ環境下においても、エンジンが決定論的に動作し、安定性、明瞭性、および応答性を維持していることを実践的に確認するものです。

ライブデモンストレーションは、この実装が単なる理論上のものではなく、動的な市場環境において一貫して機能し、価格の変化に応じて構造的整合性を維持しながら、実用的なフィードバックを提供することを示しています。



結論

本記事では、単純な視覚的パターン描画を大きく超える、構造的に規律化されたリペイントしないウェッジ検出エンジンをMQL5で設計・実装しました。このシステムは、確定したピボット構造を識別し、境界線の収束を数学的に検証し、インテリジェントなフィルタリングによって構造的な重複を防止し、さらにクリーンなオブジェクト指向ライフサイクルフレームワーク内でブレイクアウトおよび失敗条件を監視します。

カプセル化されたPivotおよびWedgeクラス、動的なCArrayObj管理、厳格な確定ルールなど、意図的なアーキテクチャ設計を通じて、このインジケータはライブ市場環境において決定論的な動作を維持します。複数の銘柄および時間足でのテストにより、安定した検出、タイムリーな構造解決、および投影バイアスのない一貫したチャートの明瞭性が確認されました。この実装は、単独で意思決定をおこなうエンジンとして使用するものではなく、より広範なトレードフレームワーク内での構造分析コンポーネントとして利用することが最適です。トレーダーには、自身の市場環境でその動作を検証し、既存の戦略、リスクモデル、および確認ツールと組み合わせて統合することで、プライスアクション分析の文脈理解を向上させることが推奨されます。

これにより、ウェッジ形成は、主観的な視覚パターンから、規律あるトレード手法を補完できる、状態を踏まえて扱える客観的な構造へと発展します。

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

添付されたファイル |
WedgePattern.mq5 (19.94 KB)
ダイナミックマルチペアEAの形成(第7回):リアルタイムトレードフィルタリングのためのクロスペア相関マッピング ダイナミックマルチペアEAの形成(第7回):リアルタイムトレードフィルタリングのためのクロスペア相関マッピング
このパートでは、複数銘柄型エキスパートアドバイザー(EA)にリアルタイム相関行列を統合し、冗長な取引やリスクが積み重なるポジションを防ぐ仕組みを構築します。複数ペア間の相互関係を動的に測定することで、EAは既存エクスポージャーと競合するエントリーをフィルタリングし、ポートフォリオ全体のバランスを改善します。その結果、システミックリスクを低減し、より質の高いトレード判断を実現します。
取引規律をコードに組み込む(第2回):MQL5で口座全体の全取引に対応する日次取引制限エンフォーサーを構築する 取引規律をコードに組み込む(第2回):MQL5で口座全体の全取引に対応する日次取引制限エンフォーサーを構築する
取引ルールを遵守できるようにするため、1日の取引制限を強制するシステムを開発しました。このシステムは、口座全体で実行されたすべての取引を監視し、設定された制限に到達すると自動的に介入して、それ以降の取引活動を防止します。制御機能をプラットフォームに直接組み込むことで、市場からのプレッシャーが高まった状況でも、規律を維持できるようにします。
MQL5標準ライブラリエクスプローラー(第9回):ALGLIBによる多発するMAクロスオーバーシグナルのフィルタ処理 MQL5標準ライブラリエクスプローラー(第9回):ALGLIBによる多発するMAクロスオーバーシグナルのフィルタ処理
横ばいの価格変動中、トレーダーは複数の移動平均クロスオーバーによって過剰なシグナルに直面します。今回は、ALGLIBがどのように生の価格データを前処理し、フィルタ処理済みのクロスオーバー系列を生成するのかについて説明します。また、これらのレイヤーは発生時にアラートを生成することもできます。数学ライブラリをMQL5プログラムでどう活用できるのかを一緒に見ていきましょう。
MQL5取引ツールのアクセシビリティ課題を克服する(第2回):Pythonのテキスト読み上げエンジンでEAを音声対応にする MQL5取引ツールのアクセシビリティ課題を克服する(第2回):Pythonのテキスト読み上げエンジンでEAを音声対応にする
テキスト読み上げ(TTS)技術を使用し、PythonとMQL5を連携させてエキスパートアドバイザー(EA)を音声対応にする方法について説明します。この記事を読み終える頃には、動的な市場情報を音声で伝えるEAの実装例を手にすることができます。TTSの活用方法、WebRequest関数の使い方、そしてPythonライブラリがMQL5言語とどのように統合され、実際に音声を活用できるトレードツールを構築できるかを理解できます。