English Русский
preview
MQL5入門(第22回):5-0ハーモニックパターンを用いたエキスパートアドバイザーの構築

MQL5入門(第22回):5-0ハーモニックパターンを用いたエキスパートアドバイザーの構築

MetaTrader 5トレーディングシステム |
41 2
Israel Pelumi Abioye
Israel Pelumi Abioye

はじめに

連載「MQL5入門」の第22回へようこそ。前回の記事では、ガートレーフォーメーションなどのハーモニックパターンをMQL5で自動検出する方法を取り上げました。今回の続編では、もう1つの興味深い、しかし比較的出現頻度の低い構造である5-0ハーモニックパターンに焦点を当てます。このパターンは、ほとんどのハーモニックセットアップがリトレースメントから始まるのに対し、強い逆トレンドの動きから始まるという点で際立っています。その後に構造化された調整が続き、トレーダーにとって価値のある取引機会を提供します。

本記事では、エキスパートアドバイザー(EA)内で5-0パターンを自動的に認識し、プログラムによって検出する方法を学びます。5-0構造を構成する主要な転換点(O、X、A、B、C、D)をどのように特定するか、専用のフィボナッチ比率をどのように計算し検証するか、そしてそのパターンをチャート上に視覚的に表現する方法を解説します。この記事を読み終える頃には、5-0パターンの背後にあるテクニカルな考え方を、プライスアクションを自動解析できる実用的なMQL5コードへと落とし込む方法を理解できるようになるでしょう。

 

5-0ハーモニックパターン

5-0ハーモニックパターンは、通常、顕著かつ持続的な価格変動の後に出現する反転フォーメーションです。純粋な反転型セットアップというよりも、継続から反転へ移行するパターンと捉えられており、トレンドの方向が転換する可能性を示唆します。 このパターンは、6つの主要ポイント(O、X、A、B、C、D)によって構成され、そこから4つのレッグ(XA、AB、BC、CD)が形成されます。5-0パターンは、その独特な起点と構造によって、他のハーモニックパターンと明確に区別されます。多くのハーモニックパターンがスイングハイまたはスイングローから始まるのに対し、5-0パターンは調整的な動きから始まる点が特徴です。この動きは、直前のトレンドやパターンが完了した後に発生することが多く、新たな推進波の始まりを捉えるのではなく、逆トレンドの動きが枯渇する局面を捉えることを目的としています。この点が、5-0パターンを際立たせる要因となっています。

強気の5-0パターンは、チャート上で明確なスイングハイを形成する点Oから始まります。市場はこのレベルから下落し、パターンの最初の重要な弱気レッグとなるXを形成します。その後のXからAへの動きは、この下落に対する調整的なリトレースメントを表します。このリトレースメントには明確なフィボナッチ比率の指定はありませんが、この初期構造においては弱気トレンドが依然として継続していることを示すために、AはOよりも下に位置している必要があります。

Aが確立された後、市場はさらに下落してBを形成します。Bは、XAに対する113%から161.8%のフィボナッチエクステンションの範囲内に位置します。このレッグは、現在の下落トレンドが疲弊段階に入っていることを示す場合が多く見られます。その後、市場はBから反転上昇してCを形成し、これは通常、ABに対する161.8%から224%の水準に達します。この動きは、パターン内における非常に力強い調整反応を示しています。 構造は、再び市場が押し戻されるDで完成します。Dは、BCに対して50%から55%のリトレースメントとなることが推奨されます。このリトレースメントゾーンが、潜在的な買いエリアとして注目されます。

図1:強気5-0パターン

Oは、チャート上で明確なスイングローを形成し、弱気の5-0パターンを開始します。市場がこの点から上昇してXを形成することで、パターンの最初の強気レッグが確立されます。続くXからAへの動きは調整的なリトレースメントですが、このレッグには厳密なフィボナッチリトレースメントの指定は必要ありません。ただし、現時点で全体のトレンドが依然として強気であることを示すために、AはOよりも上に位置している必要があります。

Aが形成された後、価格が再び上昇してBを作ります。Bは、XAに対する113%から161.8%のフィボナッチエクステンションの範囲内に位置する必要があります。この水準は、強気トレンドが限界に達していることを示す場合が多く見られます。その後、市場は反転下落してCを形成します。Cは、パターン内で重要な調整局面を表し、ABに対する161.8%から224%の範囲に達することが想定されます。 構造は、価格が再び上昇してDに到達した時点で完成します。Dは、BCに対して50%から55%のリトレースメントとなることが推奨されます。このリトレースメント領域が、潜在的な売りポイントとして機能します。

図3:弱気5-0パターン


OXABの識別

5-0パターンの意味と主要な比率原則を理解したところで、次のステップはそれをMQL5でプログラムとして実装することです。これは、ローソク足データを取得および更新し、スイングポイントを正確に特定し、O、X、A、B、C、Dから成る候補シーケンスを構築し、各レッグをパターンの比率要件に従って検証し、検証済みパターンをチャート上に表示することを意味します。

実装では、明確な手順に従います。まず直近のバーを配列にコピーし、信頼性の高いスイング検出手法を用いて重要なピボット点を特定します。その後、これらのピボットを順に処理し、OX、XA、AB、BCの各レッグ候補を構築します。次に、フィボナッチのエクステンションおよびリトレースメント条件を使用して、B、C、Dが有効であるかを検証します。すべての条件が満たされた場合、検出ロジックを取引実行処理に接続し、視覚的な確認のためにパターンと三角形をチャート上に描画します。 本記事では強気の5-0ハーモニックパターンの検出を主な対象としますが、方向をわずかに調整することで、同じ考え方と検出手順を弱気の5-0パターンにも適用できる点に注意してください。

5-0パターン検出アルゴリズムの最初の工程は、ローソク足データをコピーし、OXAB構造を特定することです。MQL5に用意されているCopy系関数を使用し、始値、終値、高値、安値、時間を含む直近の市場データを取得します。これらの配列により、プログラムは過去の価格変動へアクセスでき、重要なスイングハイとスイングローを特定するための基盤が整います。

データが取得された後、プログラムはスイング検出ロジックを用いて、プライスアクションにおける転換点候補を特定します。EAはこれらのスイングポイントを使用して、5-0パターンの基礎となるO、X、A、Bの候補を決定します。Oは大きなスイングハイを表し、Xはスイングローを表します。続いて、AはOより低い戻り高値として形成され、BはXAに対するフィボナッチエクステンション範囲内、すなわち113%から161.8%の間まで拡張されます。これら最初の4点を正確に検出することは、その後にCとDが確認された際に、パターンが正当な強気の5-0セットアップへ進展できるかを判断する上で極めて重要です。

例:
input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;

datetime time_bar;
int bars_check = 400;
int total_symbol_bars;

double open[];
double close[];
double low[];
double high[];
datetime time[];

int z = 4;

double O;
datetime O_time;
string O_line;
string O_letter;

double X;
datetime X_time;
string X_letter;

double A;
datetime A_time;
string A_letter;

double B;
datetime B_time;
string B_line;
string B_letter;

double C;
datetime C_time;
string C_line;
string C_letter;

double D;
datetime D_time;
string D_line;
string D_letter;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---


//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   total_symbol_bars = Bars(_Symbol, timeframe);
   time_bar = iTime(_Symbol, timeframe, 0);
   CopyOpen(_Symbol, timeframe, time_bar, bars_check, open);
   CopyClose(_Symbol, timeframe, time_bar, bars_check, close);
   CopyLow(_Symbol, timeframe, time_bar, bars_check, low);
   CopyHigh(_Symbol, timeframe, time_bar, bars_check, high);
   CopyTime(_Symbol, timeframe, time_bar, bars_check, time);

  }

//+------------------------------------------------------------------+
//| FUNCTION FOR SWING LOW                                           |
//+------------------------------------------------------------------+
bool IsSwingLow(const double &low_price[], int index, int lookback)
  {
   for(int i = 1; i <= lookback; i++)
     {
      if(low_price[index] > low_price[index - i] || low_price[index] > low_price[index + i])
         return false;
     }
   return true;
  }

//+------------------------------------------------------------------+
//| FUNCTION FOR SWING HIGH                                          |
//+------------------------------------------------------------------+
bool IsSwingHigh(const double &high_price[], int index, int lookback)
  {
   for(int i = 1; i <= lookback; i++)
     {
      if(high_price[index] < high_price[index - i] || high_price[index] < high_price[index + i])
         return false; // If the current high is not the highest, return false.
     }
   return true;
  }

説明

input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;

ここでは、EAが解析対象とするチャートの時間足を指定します。デフォルトでは現在表示されているチャートの時間足を使用しますが、基本コードを変更することなく、M15、H1、D1など他の時間足でEAをテストできるよう、トレーダーが簡単に変更できる設計になっています。 

ローソク足データとチャート全体の情報を管理するために、いくつかのグローバル変数が宣言されます。

datetime time_bar;
int bars_check = 400;
int total_symbol_bars;

double open[];
double close[];
double low[];
double high[];
datetime time[];

これらの変数は、市場データをまとめて保持するために使用されます。EAが解析対象とするバー数はbars_check変数で指定されており、この例では直近400本のローソク足を参照します。その後、該当するローソク足データがチャートから配列へ読み込まれます。これらのデータ配列は、スイングハイおよびスイングローを特定するための価格履歴を提供するため、非常に重要な役割を果たします。

基本的なデータ格納用コンテナを宣言した後、プログラムは5-0パターンにおける各重要な点の詳細を保持するための複数の変数を定義します。

double O;
datetime O_time;
string O_line;
string O_letter;

double X;
datetime X_time;
string X_letter;

double A;
datetime A_time;
string A_letter;

double B;
datetime B_time;
string B_line;
string B_letter;

double C;
datetime C_time;
string C_line;
string C_letter;

double D;
datetime D_time;
string D_line;
string D_letter;

各スイングポイントには、固有の変数群が割り当てられています。たとえば、O_timeはOが発生した時間を記録し、OはOの価格を保持します。Oをラベル付けしたり、チャート上に視覚的なマーカーを描画するには、O_lineやO_letter変数を使用します。スイングポイントごとに同じ構造が繰り返されます。すべてのレッグが検証された時に5-0パターン全体を描画できるのは、この構造により各点の座標を記録できるためです。

スイングローを特定するために、IsSwingLow関数はあるインデックスのローが周囲のローよりも低いかどうかを確認します。lookbackパラメータは、現在のローソク足の前後で比較するローソク足の本数を調整します。対象ローソク足のローが周囲のローの中で最も低い場合、そのスイングローは有効とみなされます。OやXの基点を作る可能性のある転換点を見つけるために、スイングローは不可欠です。指定されたlookback範囲内では、IsSwingHigh関数により、あるローソク足の高値が周囲の高値よりも高いかどうかも確認されます。

市場データの管理とスイングポイントの特定の基本的枠組みが整った後、次のステップはOXAB構造を特定することです。強気の5-0ハーモニックパターンの波に対応する顕著なスイングハイとスイングローを見つけるには、過去のローソク足データを検索する必要があります。Xはより低いスイングローとして認識され、Oは顕著なスイングハイとして認識されます。その後、BはXAのフィボナッチエクステンション範囲である113%から161.8%の間でXを超える位置に形成され、AはOより下の戻り高値として形成されることが求められます。

例:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   total_symbol_bars = Bars(_Symbol, timeframe);
   time_bar = iTime(_Symbol, timeframe, 0);
   CopyOpen(_Symbol, timeframe, time_bar, bars_check, open);
   CopyClose(_Symbol, timeframe, time_bar, bars_check, close);
   CopyLow(_Symbol, timeframe, time_bar, bars_check, low);
   CopyHigh(_Symbol, timeframe, time_bar, bars_check, high);
   CopyTime(_Symbol, timeframe, time_bar, bars_check, time);

   if(total_symbol_bars >= bars_check)
     {

      for(int i = z ; i < bars_check - z; i++)
        {
         if(IsSwingHigh(high, i, z))
           {

            for(int j = i; j < bars_check - z; j++)
              {

               if(IsSwingLow(low, j, z) && low[j] < high[i])
                 {

                  X = low[j];
                  X_time = time[j];
                  X_letter = StringFormat("X  %d",j);

                  for(int a = j; a >= i; a--)
                    {
                     if(IsSwingHigh(high, a, z) && high[a] > X)
                       {

                        O = high[a];
                        O_time = time[a];
                        O_letter = StringFormat("0  %d",a);

                        for(int k = j; k < bars_check - z; k++)
                          {

                           if(IsSwingHigh(high, k, z) && high[k] > X)
                             {

                              A = high[k];
                              A_time = time[k];
                              A_letter = StringFormat("A  %d",k);

                              for(int l = k; l < bars_check - z; l++)
                                {

                                 if(IsSwingLow(low, l, z) && low[l] < X)
                                   {
                                    B = low[l];
                                    B_time = time[l];
                                    B_letter = StringFormat("B  %d",l);

                                    break;
                                   }
                                }

                              break;
                             }
                          }

                        break;
                       }
                    }

                  break;
                 }
              }
           }
        }
     }
  }

説明

プログラムは、まず解析対象となるバーが十分にあるかを確認することから始めます。全体のバー数が解析に必要な本数より少ない場合、検索は開始されません。これは、本棚に本が十分に揃っているかを確認してから順番を探すのと似ています。本が足りない状態で探し始めると、結論に飛びついてしまい、パターン全体を見逃してしまう可能性があります。

次に、チャート上で最初のスイングハイを探します。特定の位置のバーが局所的な高値かどうかを判断するために、外側のループが各バーをIsSwingHigh()関数でチェックします。この条件を満たすバーは、5-0構造の候補開始点となります。

スイングハイを特定した後、Xとして使えるスイングローを探します。これは、高値からバーを順にスキャンし、その高値よりも低い位置にあるスイングローを見つけるループで実行されます。条件が満たされると、そのバーの安値、時間、チャート表示用ラベルがX変数に格納されます。本棚の例で言えば、高い本の少し下にある小さな本を次の候補としてマークするイメージです。

次に、Xを検出した後、正しいOを見つけるためにXから逆方向に移動します。Xより上の最高峰を探すために、Xと初期の高値の間を逆順にスキャンします。価格、時間、ラベルを記録し、最初に見つかったピークがOとなります。逆順に検索するのは、OがXより前の直近の高値であることを保証するためです。

OとXが特定された後、アルゴリズムは次にAを見つけます。Xを超える次のスイングハイを探し、それをAとしてマークします。Aは、初期の下落後に形成される新しいピークとして、パターン内の新たな上昇局面の開始を示します。これは、本棚の例で短い本の後にやや高い本を見つけるように、シリーズが予想された交互のパターンで形成され続けていることを示しています。

次のステップはBの特定です。Aの後、Xを下回るスイングローを見つけるためにコードは順方向にスキャンを続けます。この条件を満たすバーの価格、時間、ラベルはBとして記録されます。コードはBをOXABシーケンスの最後の点としてマークし、これ以上の安値は探索しません。これで、5-0パターンの初期構造を特徴付ける4点のセットが完成します。本棚の例で言えば、前の短い本よりさらに低い小さな本を見つけたことに相当します。

このシーケンスの内側のループでは、条件を満たした時点でbreakコマンドを使用して終了します。これにより、同じ領域から重複するセットが多数生成されるのを防ぎ、検出を的確かつ効率的におこなえます。高さと順序のルールに従った正しい本の積み上げが完成したら、そのセクションのスキャンを停止し、次のセクションに進みます。ネストされたループ処理の後、プログラムは最初の4つの重要な点、O、X、A、Bと、それぞれの時間とラベルを正確に特定して保存します。

前述したように、スイングハイ「A」はOXのリトレースメントであり、Xより高く、Oより低くなる必要があります。またスイングローOはXより高い必要があります。しかし、Aについては特定のフィボナッチ比率は必要ありません。BはXAのフィボナッチエクステンション113%から161.8%の範囲に入る必要があります。アルゴリズムがこれらの条件を確認した後、チャート上にオブジェクトを作成して、パターンの形成を視覚的に識別・表現することが求められます。

例:

input ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT;
input double b_xa_max = 161.8; // MAX B EXTENSION LEVEL FOR XA
input double b_xa_min = 113.0; // MIN B EXTENSION LEVEL FOR XA
double fib_ext_b_161;
double fib_ext_b_113;
string fib_xa_ext_obj;
string fib_xa_ext_lvl;

string ox_line;
string xa_line;
string ab_line;
ulong chart_id = ChartID();
for(int l = k; l < bars_check - z; l++)
  {

   if(IsSwingLow(low, l, z) && low[l] < X)
     {

      B = low[l];
      B_time = time[l];
      B_letter = StringFormat("B  %d",l);

      fib_ext_b_113 =  MathAbs((((A - X) / 100) * (b_xa_min - 100)) - X);
      fib_ext_b_161 =   MathAbs((((A - X) / 100) * (b_xa_max - 100)) - X);

      if(X < O && A > X && A < O && B <= fib_ext_b_113 && B >= fib_ext_b_161)
        {

         ObjectCreate(chart_id,O_letter,OBJ_TEXT,0,O_time,O);
         ObjectSetString(chart_id,O_letter,OBJPROP_TEXT,"0");
         ObjectSetInteger(chart_id,O_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,X_letter,OBJ_TEXT,0,X_time,X);
         ObjectSetString(chart_id,X_letter,OBJPROP_TEXT,"X");
         ObjectSetInteger(chart_id,X_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,A_letter,OBJ_TEXT,0,A_time,A);
         ObjectSetString(chart_id,A_letter,OBJPROP_TEXT,"A");
         ObjectSetInteger(chart_id,A_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,B_letter,OBJ_TEXT,0,B_time,B);
         ObjectSetString(chart_id,B_letter,OBJPROP_TEXT,"B");
         ObjectSetInteger(chart_id,B_letter,OBJPROP_COLOR,clrBlue);

         ox_line = StringFormat("0X Line  %d",i);
         xa_line = StringFormat("XA Line  %d",i);
         ab_line = StringFormat("AB Line  %d",i);

         ObjectCreate(chart_id,ox_line,OBJ_TREND,0, O_time, O,X_time,X);
         ObjectSetInteger(chart_id,ox_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,xa_line,OBJ_TREND,0, X_time, X,A_time,A);
         ObjectSetInteger(chart_id,xa_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,ab_line,OBJ_TREND,0, A_time, A,B_time,B);
         ObjectSetInteger(chart_id,ab_line,OBJPROP_COLOR,clrBlue);

         fib_xa_ext_obj = StringFormat("XA Expansion  %d",i);
         ObjectCreate(chart_id,fib_xa_ext_obj,OBJ_EXPANSION,0,A_time,A,X_time,X,A_time,A);
         ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_COLOR,clrBlue);
         for(int i = 0; i <= 2; i++)
           {

            ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);

           }

         fib_xa_ext_lvl = StringFormat("XA Expansion Levels %d",i);

         ObjectCreate(chart_id,fib_xa_ext_lvl,OBJ_RECTANGLE,0,X_time,fib_ext_b_113,B_time,fib_ext_b_161);
         ObjectSetInteger(chart_id,fib_xa_ext_lvl,OBJPROP_COLOR,clrBlue);

        }

      break;
     }
  }

出力

図3:OXAB

説明

コードはまず、いくつかの入力変数を宣言します。プログラムは、適用されるチャートと同じ時間足を自動的に使用します。次に、XAのフィボナッチエクステンション範囲を2つの入力で表します。パターンが有効であるためには、Bはこれらの値で定義された範囲内に収まる必要があります。

計算された値やオブジェクト名は、その後、複数の変数に格納されます。XAの113%および161.8%に対応する計算済みフィボナッチエクステンション価格は、変数fib_ext_b_113およびfib_ext_b_161に保持されます。チャート上に描画して検出されたパターンを示す各種グラフィカルコンポーネントは、変数fib_xa_ext_obj、fib_xa_ext_lvl、ox_line、xa_line、ab_lineを使用して命名されます。すべての描画が適切なチャートウィンドウで行われるよう、変数chart_idでアクティブなチャートのIDを取得します。

これらの変数を宣言した後、プログラムはAとXの間の数学的関係を利用してフィボナッチエクステンションレベルを計算します。XAの113%および161.8%の拡張に対応する価格を決定します。本棚の例で、XとAの間の距離を測ることを考えると理解しやすいでしょう。最初のXAは基準距離(100%)を表し、その先の拡張が113%および161.8%として表されます。Bがこの許容範囲内に収まることが、計算されたレベルに基づいてパターンの有効性を保証します。

次のコード行では、5-0パターンに必要なすべての幾何学的およびフィボナッチ関係が満たされているかを確認する条件文が導入されます。XがOより下にあるかを判定することで、弱気から強気への価格構造を維持します。さらに、AがXから上方にリトレースしつつOを超えないことを確認して、正当なリトレースメントゾーン内にあるかを検証します。最後に、BがXAの113%から161.8%の範囲内に収まっていることを確認します。これが許容されるフィボナッチエクステンション範囲です。

アルゴリズムは、これらの条件がすべて満たされた後に、検出された構造をチャート上に描画します。まず、重要なスイング位置(O、X、A、B)をテキストオブジェクトで命名します。各テキストには青色を設定し、視認性を高めます。これにより、トレーダーはパターンの基本構造を容易に認識できるようになります。

次に、これらの位置にラベルを付けた後、OX、XA、ABをトレンドラインで接続します。5-0パターンの基礎となる価格スイングの動きが、各ラインによって視覚的に表現されます。それぞれのラインには「OX Line」や「XA Line」といった名称が付けられ、チャート上の各要素が明確かつ識別しやすくなります。

その後、XA間にフィボナッチエクステンションツールを使って、潜在的な拡張ゾーンを視覚的に表示します。このエクスパンションは、価格がXAをどれだけ超えたかを示すことで、Bの正当性をトレーダーに明示します。 最後に、113%から161.8%の拡張レベル間を強調するために矩形オブジェクトを描画します。この矩形は、Bの想定形成領域を明確に示すハイライト部分として機能します。Bはこの範囲内に収まる場合、トレーダーがチャート上で5-0パターンの適切な拡張ゾーンを視覚的に確認するのに役立ちます。


Cの特定

O、X、A、Bが正しく特定された後、CとDを見つけることで5-0パターンの構造が完成します。これら2つの点は、検出されたセットアップが正当なハーモニック形成へ発展するかどうかを決定するため、非常に重要です。 価格の反応に応じて、CはABからの拡張またはリトレースメントとして形成されます。弱気の5-0パターンの場合、CはABの161.8%から224%のフィボナッチエクステンションの範囲内に位置することが想定されます。これは、Bに到達した後、価格がABの終点をABの距離の約1.618倍から2.24倍まで超えて移動することを意味します。

別の言い方をすると、ABを棚の一部と考えてください。新しい本(C)を棚のBより少し先に置くイメージです。Bに近すぎず(161.8%未満)、遠すぎず(224%超過)に配置されるのが理想です。この範囲は、市場がハーモニックバランスを保ちながら十分に拡張したことを示すゾーンであり、Cが到達するのに最適な場所となります。

Cが特定された後、構造はBCのリトレースメントとしてDを決定することで完成します。取引の確認やアラートロジックを適用する前に、弱気の5-0セットアップを検証するためには、CとDの両方が正しく整列している必要があります。これにより、パターンのハーモニックな対称性が保持されます。

例:

input double c_ab_max = 224.0; // MAX C EXTENSION LEVEL FOR AB
input double c_ab_min = 161.8; // MIN C EXTENSION LEVEL FOR AB
double fib_ext_c_161;
double fib_ext_c_224;
string fib_ab_ext_obj;
string fib_ab_ext_lvl;
string bc_line;

if(total_symbol_bars >= bars_check)
  {
   for(int i = z ; i < bars_check - z; i++)
     {
      if(IsSwingHigh(high, i, z))
        {
         for(int j = i; j < bars_check - z; j++)
           {
            if(IsSwingLow(low, j, z) && low[j] < high[i])
              {
               X = low[j];
               X_time = time[j];
               X_letter = StringFormat("X  %d",j);

               for(int a = j; a >= i; a--)
                 {
                  if(IsSwingHigh(high, a, z) && high[a] > X)
                    {
                     O = high[a];
                     O_time = time[a];
                     O_letter = StringFormat("0  %d",a);

                     for(int k = j; k < bars_check - z; k++)
                       {

                        if(IsSwingHigh(high, k, z) && high[k] > X)
                          {
                           A = high[k];
                           A_time = time[k];
                           A_letter = StringFormat("A  %d",k);

                           for(int l = k; l < bars_check - z; l++)
                             {

                              if(IsSwingLow(low, l, z) && low[l] < X)
                                {
                                 B = low[l];
                                 B_time = time[l];
                                 B_letter = StringFormat("B  %d",l);

                                 for(int m = l; m < bars_check - z; m++)
                                   {

                                    if(IsSwingHigh(high, m, z) && high[m] > A)
                                      {

                                       C = high[m];
                                       C_time = time[m];
                                       C_letter = StringFormat("C  %d",m);

                                       fib_ext_b_113 =  MathAbs((((A - X) / 100) * (b_xa_min - 100)) - X);
                                       fib_ext_b_161 =   MathAbs((((A - X) / 100) * (b_xa_max - 100)) - X);

                                       fib_ext_c_161 = MathAbs((((A - B) / 100) * (c_ab_min - 100)) + A);
                                       fib_ext_c_224 =    MathAbs((((A - B) / 100) * (c_ab_max - 100)) + A);

                                       if(X < O && A > X && A < O && B <= fib_ext_b_113 && B >= fib_ext_b_161 && C >= fib_ext_c_161 && C <= fib_ext_c_224)
                                         {
                                          ObjectCreate(chart_id,O_letter,OBJ_TEXT,0,O_time,O);
                                          ObjectSetString(chart_id,O_letter,OBJPROP_TEXT,"0");
                                          ObjectSetInteger(chart_id,O_letter,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,X_letter,OBJ_TEXT,0,X_time,X);
                                          ObjectSetString(chart_id,X_letter,OBJPROP_TEXT,"X");
                                          ObjectSetInteger(chart_id,X_letter,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,A_letter,OBJ_TEXT,0,A_time,A);
                                          ObjectSetString(chart_id,A_letter,OBJPROP_TEXT,"A");
                                          ObjectSetInteger(chart_id,A_letter,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,B_letter,OBJ_TEXT,0,B_time,B);
                                          ObjectSetString(chart_id,B_letter,OBJPROP_TEXT,"B");
                                          ObjectSetInteger(chart_id,B_letter,OBJPROP_COLOR,clrBlue);

                                          ox_line = StringFormat("0X Line  %d",i);
                                          xa_line = StringFormat("XA Line  %d",i);
                                          ab_line = StringFormat("AB Line  %d",i);

                                          ObjectCreate(chart_id,ox_line,OBJ_TREND,0, O_time, O,X_time,X);
                                          ObjectSetInteger(chart_id,ox_line,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,xa_line,OBJ_TREND,0, X_time, X,A_time,A);
                                          ObjectSetInteger(chart_id,xa_line,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,ab_line,OBJ_TREND,0, A_time, A,B_time,B);
                                          ObjectSetInteger(chart_id,ab_line,OBJPROP_COLOR,clrBlue);

                                          fib_xa_ext_obj = StringFormat("XA Expansion  %d",i);
                                          ObjectCreate(chart_id,fib_xa_ext_obj,OBJ_EXPANSION,0,A_time,A,X_time,X,A_time,A);
                                          ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_COLOR,clrBlue);
                                          for(int i = 0; i <= 2; i++)
                                            {
                                             ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
                                            }

                                          fib_xa_ext_lvl = StringFormat("XA Expansion Levels %d",i);

                                          ObjectCreate(chart_id,fib_xa_ext_lvl,OBJ_RECTANGLE,0,X_time,fib_ext_b_113,B_time,fib_ext_b_161);
                                          ObjectSetInteger(chart_id,fib_xa_ext_lvl,OBJPROP_COLOR,clrBlue);

                                          ObjectCreate(chart_id,C_letter,OBJ_TEXT,0,C_time,C);
                                          ObjectSetString(chart_id,C_letter,OBJPROP_TEXT,"C");
                                          ObjectSetInteger(chart_id,C_letter,OBJPROP_COLOR,clrBlue);

                                          bc_line = StringFormat("BC Line  %d",i);
                                          ObjectCreate(chart_id,bc_line,OBJ_TREND,0, B_time, B,C_time,C);
                                          ObjectSetInteger(chart_id,bc_line,OBJPROP_COLOR,clrBlue);

                                          fib_ab_ext_obj = StringFormat("AB Expansion  %d",i);
                                          ObjectCreate(chart_id,fib_ab_ext_obj,OBJ_EXPANSION,0,B_time,B,A_time,A,B_time,B);
                                          ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_COLOR,clrBlue);
                                          for(int i = 0; i <= 2; i++)
                                            {

                                             ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);

                                            }

                                          fib_ab_ext_lvl = StringFormat("AB Expansion Levels %d",i);

                                          ObjectCreate(chart_id,fib_ab_ext_lvl,OBJ_RECTANGLE,0,A_time,fib_ext_c_161,C_time,fib_ext_c_224);
                                          ObjectSetInteger(chart_id,fib_ab_ext_lvl,OBJPROP_COLOR,clrBlue);

                                         }

                                       break;
                                      }
                                   }
                                 break;
                                }
                             }
                           break;
                          }
                       }
                     break;
                    }
                 }
               break;
              }
           }
        }
     }
  }

出力

図4:C

説明

CがABの距離を大きく超えすぎないように、ABの最大許容フィボナッチエクステンションレベルは224%に設定されています。CがBに近すぎて形成されないように、最小フィボナッチエクステンションレベルも161.8%に設定されています。Cが到達することが想定される正当な価格ゾーンは、これら2つのレベルを組み合わせることで定義されます。さらに、計算や表示のための複数の変数が準備されています。これらの変数は、BとCを結ぶトレンドラインを作成し、計算済みフィボナッチエクステンションレベルを保存し、チャート上のフィボナッチエクステンションとその視覚表示を制御することで、パターン構造をより明確にします。

プログラムは、Cの条件を満たす可能性のあるスイングハイを検出した際に、価格、時間、ラベルを参照用として記録します。その後、Bの正当な範囲を確認し、Cの想定価格ゾーンを特定するために、フィボナッチエクステンションレベルを再計算します。この計算により、AとBの差に応じてCが理想的に出現すべき161.8%および224%の拡張閾値が決定されます。この手順により、EAは検出されたスイングが5-0パターンの許容範囲内にあるかどうかを確認できます。

次に条件文を使用して、すべてのパターン点が正しく整列しているかを判定します。AはXより高く、Oより低いこと、BはXAの113%から161.8%の範囲内にあること、CはABの161.8%から224%のフィボナッチエクステンション内にあること、そしてXがOより低いことを確認します。これらすべての幾何学的およびフィボナッチの条件が満たされた場合、強気の5-0パターンの可能性として正当なOXABC構造が確認されます。

この条件が満たされると、EAはチャート上にパターンをグラフィカルに表示します。まずCのテキストラベルを作成し、BとCを結ぶラインを描きます。さらに、矩形オブジェクトとフィボナッチエクステンションオブジェクトを追加してCの拡張ゾーンを表示します。矩形は、CがABに対してどこに位置するかを正確に示し、161.8%から224%の範囲をハイライトします。

 

Dの識別

Dは強気の5-0ハーモニックパターンにおける最後の波であり、パターン全体を完成させます。O、X、A、B、Cを特定し、検証した後、正しいフィボナッチリトレースメント範囲内でDを見つけることが最後のステップです。Dはパターンの完成ゾーンであり、トレーダーが強気の反転を期待する可能性のある領域を示す場合が多いです。

強気の5-0セットアップが正当であると判断するには、DはBCの50%から55%のフィボナッチリトレースメントの範囲内で形成される必要があります。このリトレースメントゾーンは、パターンの構造を成立させるハーモニックバランスを提供します。言い換えると、DはBCの動きのほぼ半分を戻す形で形成されることが望ましく、Cからの下方修正がそろそろ終了する可能性を示しています。

例:

input double d_bc_max = 55.0; // MAX D RETRACEMENT LEVEL FOR BC
input double d_bc_min = 50.0; // MIN D RETRACEMENT LEVEL FOR BC
double fib_ret_d_50;
double fib_ret_d_55;
string fib_bc_ret_lvl;
string cd_line;
for(int n = m; n < bars_check - z; n++)
  {
   if(IsSwingLow(low, n, z) && low[n] < C)
     {

      D = low[n];
      D_time = time[n];
      D_letter = StringFormat("D  %d",l);
      cd_line = StringFormat("CD %d",i);

      fib_ext_b_113 =  MathAbs((((A - X) / 100) * (b_xa_min - 100)) - X);
      fib_ext_b_161 =   MathAbs((((A - X) / 100) * (b_xa_max - 100)) - X);

      fib_ext_c_161 = MathAbs((((A - B) / 100) * (c_ab_min - 100)) + A);
      fib_ext_c_224 =    MathAbs((((A - B) / 100) * (c_ab_max - 100)) + A);

      fib_ret_d_50 = C - ((d_bc_min / 100) * (C - B));
      fib_ret_d_55 = C - ((d_bc_max / 100) * (C - B));

      if(X < O && A > X && A < O && B <= fib_ext_b_113 && B >= fib_ext_b_161 && C >= fib_ext_c_161 && C <= fib_ext_c_224 && D <= fib_ret_d_50 && D >= fib_ret_d_55)
        {
         ObjectCreate(chart_id,O_letter,OBJ_TEXT,0,O_time,O);
         ObjectSetString(chart_id,O_letter,OBJPROP_TEXT,"0");
         ObjectSetInteger(chart_id,O_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,X_letter,OBJ_TEXT,0,X_time,X);
         ObjectSetString(chart_id,X_letter,OBJPROP_TEXT,"X");
         ObjectSetInteger(chart_id,X_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,A_letter,OBJ_TEXT,0,A_time,A);
         ObjectSetString(chart_id,A_letter,OBJPROP_TEXT,"A");
         ObjectSetInteger(chart_id,A_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,B_letter,OBJ_TEXT,0,B_time,B);
         ObjectSetString(chart_id,B_letter,OBJPROP_TEXT,"B");
         ObjectSetInteger(chart_id,B_letter,OBJPROP_COLOR,clrBlue);

         ox_line = StringFormat("0X Line  %d",i);
         xa_line = StringFormat("XA Line  %d",i);
         ab_line = StringFormat("AB Line  %d",i);

         ObjectCreate(chart_id,ox_line,OBJ_TREND,0, O_time, O,X_time,X);
         ObjectSetInteger(chart_id,ox_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,xa_line,OBJ_TREND,0, X_time, X,A_time,A);
         ObjectSetInteger(chart_id,xa_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,ab_line,OBJ_TREND,0, A_time, A,B_time,B);
         ObjectSetInteger(chart_id,ab_line,OBJPROP_COLOR,clrBlue);

         fib_xa_ext_obj = StringFormat("XA Expansion  %d",i);
         ObjectCreate(chart_id,fib_xa_ext_obj,OBJ_EXPANSION,0,A_time,A,X_time,X,A_time,A);
         ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_COLOR,clrBlue);
         for(int i = 0; i <= 2; i++)
           {
            ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
           }
         fib_xa_ext_lvl = StringFormat("XA Expansion Levels %d",i);

         ObjectCreate(chart_id,fib_xa_ext_lvl,OBJ_RECTANGLE,0,X_time,fib_ext_b_113,B_time,fib_ext_b_161);
         ObjectSetInteger(chart_id,fib_xa_ext_lvl,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,C_letter,OBJ_TEXT,0,C_time,C);
         ObjectSetString(chart_id,C_letter,OBJPROP_TEXT,"C");
         ObjectSetInteger(chart_id,C_letter,OBJPROP_COLOR,clrBlue);

         bc_line = StringFormat("BC Line  %d",i);
         ObjectCreate(chart_id,bc_line,OBJ_TREND,0, B_time, B,C_time,C);
         ObjectSetInteger(chart_id,bc_line,OBJPROP_COLOR,clrBlue);

         fib_ab_ext_obj = StringFormat("AB Expansion  %d",i);
         ObjectCreate(chart_id,fib_ab_ext_obj,OBJ_EXPANSION,0,B_time,B,A_time,A,B_time,B);
         ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_COLOR,clrBlue);
         for(int i = 0; i <= 2; i++)
           {

            ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);

           }

         fib_ab_ext_lvl = StringFormat("AB Expansion Levels %d",i);

         ObjectCreate(chart_id,fib_ab_ext_lvl,OBJ_RECTANGLE,0,A_time,fib_ext_c_161,C_time,fib_ext_c_224);
         ObjectSetInteger(chart_id,fib_ab_ext_lvl,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,D_letter,OBJ_TEXT,0,D_time,D);
         ObjectSetString(chart_id,D_letter,OBJPROP_TEXT,"D");
         ObjectSetInteger(chart_id,D_letter,OBJPROP_COLOR,clrBlue);

         cd_line = StringFormat("CD Line  %d",i);
         ObjectCreate(chart_id,cd_line,OBJ_TREND,0, C_time, C,D_time,D);
         ObjectSetInteger(chart_id,cd_line,OBJPROP_COLOR,clrBlue);

         fib_bc_ret_lvl = StringFormat("BC RETRACEMENT Levels %d",i);

         ObjectCreate(chart_id,fib_bc_ret_lvl,OBJ_RECTANGLE,0,B_time,fib_ret_d_50,D_time,fib_ret_d_55);
         ObjectSetInteger(chart_id,fib_bc_ret_lvl,OBJPROP_COLOR,clrBlue);

        }

      break;
     }
  }

出力

図5:D

説明

fib_ret_d_50とfib_ret_d_55は、Dが形成される可能性のある正確なリトレースメントレベルを決定するために使用される2つの変数です。計算は、CとBの差にリトレースメント割合の小数表現を掛け、結果をCから引くことでおこないます。これにより、Dのリトレースメントゾーンを示す価格レベルが得られます。この計算式により、Dが予想されるフィボナッチリトレースメント範囲内に正しく配置されることが保証されます。

リトレースメントレベルが決定された後、プログラムは5-0パターン全体が必要なハーモニック条件を満たしているかを判定します。状況に応じて、DはBCの50%から55%のリトレースメント範囲内、BとCはXAの113%から161.8%の範囲内、CはABの161.8%から224%の範囲内、そしてXはOより低いことを確認します。これらすべての関係が満たされた場合にのみ、構造は正当な5-0パターンとみなされます。

条件が確認された後、プログラムはチャート上にパターンを視覚的に表示します。Dの位置には「D」と記したテキストラベルを作成します。次に、CとDを結ぶラインを描画してCDを示すことで、パターンの最後の部分を明確に表示します。さらに、Dの可能な完成ゾーンを視覚的に示すために、50%から55%のリトレースメント領域を強調する矩形を作成します。これにより、トレーダーはリアルタイムで潜在的な反転や完成ポイントを簡単に確認できます。

次のステップは、特定された各点が対応するレッグ内の実際のスイングを正確に示しているかを検証することです。わずかな価格変動でもパターン全体の構造を歪め、誤ったシグナルを発生させる可能性があるため、高値や安値を単に記録するだけでは不十分です。正確性を保つために、各スイングポイントを確認する明確な指針を設ける必要があります。

OからXの間では、Oを起点として最高値でなければなりません。これにより、単なる小さな価格上昇ではなく、真のスイング高値が最初の下落レッグ(OX)の開始点であることが保証されます。XからAの間では、Xが最も低い安値である必要があります。これにより、XAが一時的な下落ではなく、真のスイングローから始まることが示されます。

同様に、ABが正当なスイングハイを反映するためには、AがAとBの間で最高値である必要があります。BCは、BがBとCの間で最も低い安値である場合、主要な谷からリトレースされなければなりません。CDが真のスイングハイから始まることを保証するためには、CがCとDの間で最高値である必要があります。

例:
int c_d_bars;
int c_highest_index;
double c_d_hh;
datetime c_d_hh_t;

int b_c_bars;
int b_lowest_index;
double b_c_ll;
datetime b_c_ll_t;

int a_b_bars;
int a_highest_index;
double a_b_hh;
datetime a_b_hh_t;

int x_a_bars;
int x_lowest_index;
double x_a_ll;
datetime x_a_ll_t;

int o_x_bars;
int o_highest_index;
double o_x_hh;
datetime o_x_hh_t;
for(int n = m; n < bars_check - z; n++)
  {
   if(IsSwingLow(low, n, z) && low[n] < C)
     {

      D = low[n];
      D_time = time[n];
      D_letter = StringFormat("D  %d",l);
      cd_line = StringFormat("CD %d",i);

      c_d_bars = Bars(_Symbol,PERIOD_CURRENT,C_time,D_time);
      c_highest_index = ArrayMaximum(high,m,c_d_bars);
      c_d_hh = high[c_highest_index];
      c_d_hh_t = time[c_highest_index];

      b_c_bars = Bars(_Symbol,PERIOD_CURRENT,B_time,c_d_hh_t);
      b_lowest_index = ArrayMinimum(low,l,b_c_bars);
      b_c_ll = low[b_lowest_index];
      b_c_ll_t = time[b_lowest_index];

      a_b_bars = Bars(_Symbol,PERIOD_CURRENT,A_time,b_c_ll_t);
      a_highest_index = ArrayMaximum(high,k,a_b_bars);
      a_b_hh = high[a_highest_index];
      a_b_hh_t = time[a_highest_index];

      x_a_bars = Bars(_Symbol,PERIOD_CURRENT,X_time,a_b_hh_t);
      x_lowest_index = ArrayMinimum(low,j,x_a_bars);
      x_a_ll = low[x_lowest_index];
      x_a_ll_t = time[x_lowest_index];

      o_x_bars = Bars(_Symbol,PERIOD_CURRENT,O_time,x_a_ll_t);
      o_highest_index = ArrayMaximum(high,a,o_x_bars);
      o_x_hh = high[o_highest_index];
      o_x_hh_t = time[o_highest_index];

      fib_ext_b_113 =  MathAbs((((a_b_hh - x_a_ll) / 100) * (b_xa_min - 100)) - x_a_ll);
      fib_ext_b_161 =   MathAbs((((a_b_hh - x_a_ll) / 100) * (b_xa_max - 100)) - x_a_ll);

      fib_ext_c_161 = MathAbs((((a_b_hh - b_c_ll) / 100) * (c_ab_min - 100)) + a_b_hh);
      fib_ext_c_224 =    MathAbs((((a_b_hh - b_c_ll) / 100) * (c_ab_max - 100)) + a_b_hh);

      fib_ret_d_50 = c_d_hh - ((d_bc_min / 100) * (c_d_hh - b_c_ll));
      fib_ret_d_55 = c_d_hh - ((d_bc_max / 100) * (c_d_hh - b_c_ll));

      if(x_a_ll < o_x_hh && a_b_hh > x_a_ll && a_b_hh < o_x_hh && b_c_ll <= fib_ext_b_113 && b_c_ll >= fib_ext_b_161 && c_d_hh >= fib_ext_c_161 && c_d_hh <= fib_ext_c_224 && D <= fib_ret_d_50 && D >= fib_ret_d_55)
        {
         ObjectCreate(chart_id,O_letter,OBJ_TEXT,0,o_x_hh_t,o_x_hh);
         ObjectSetString(chart_id,O_letter,OBJPROP_TEXT,"0");
         ObjectSetInteger(chart_id,O_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,X_letter,OBJ_TEXT,0,x_a_ll_t,x_a_ll);
         ObjectSetString(chart_id,X_letter,OBJPROP_TEXT,"X");
         ObjectSetInteger(chart_id,X_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,A_letter,OBJ_TEXT,0,a_b_hh_t,a_b_hh);
         ObjectSetString(chart_id,A_letter,OBJPROP_TEXT,"A");
         ObjectSetInteger(chart_id,A_letter,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,B_letter,OBJ_TEXT,0,b_c_ll_t,b_c_ll);
         ObjectSetString(chart_id,B_letter,OBJPROP_TEXT,"B");
         ObjectSetInteger(chart_id,B_letter,OBJPROP_COLOR,clrBlue);

         ox_line = StringFormat("0X Line  %d",i);
         xa_line = StringFormat("XA Line  %d",i);
         ab_line = StringFormat("AB Line  %d",i);

         ObjectCreate(chart_id,ox_line,OBJ_TREND,0, o_x_hh_t, o_x_hh,x_a_ll_t,x_a_ll);
         ObjectSetInteger(chart_id,ox_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,xa_line,OBJ_TREND,0, x_a_ll_t, x_a_ll,a_b_hh_t,a_b_hh);
         ObjectSetInteger(chart_id,xa_line,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,ab_line,OBJ_TREND,0, a_b_hh_t, a_b_hh,b_c_ll_t,b_c_ll);
         ObjectSetInteger(chart_id,ab_line,OBJPROP_COLOR,clrBlue);

         fib_xa_ext_obj = StringFormat("XA Expansion  %d",i);
         ObjectCreate(chart_id,fib_xa_ext_obj,OBJ_EXPANSION,0,a_b_hh_t,a_b_hh,x_a_ll_t,x_a_ll,a_b_hh_t,a_b_hh);
         ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_COLOR,clrBlue);
         for(int i = 0; i <= 2; i++)
           {
            ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
           }

         fib_xa_ext_lvl = StringFormat("XA Expansion Levels %d",i);

         ObjectCreate(chart_id,fib_xa_ext_lvl,OBJ_RECTANGLE,0,x_a_ll_t,fib_ext_b_113,b_c_ll_t,fib_ext_b_161);
         ObjectSetInteger(chart_id,fib_xa_ext_lvl,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,C_letter,OBJ_TEXT,0,c_d_hh_t,c_d_hh);
         ObjectSetString(chart_id,C_letter,OBJPROP_TEXT,"C");
         ObjectSetInteger(chart_id,C_letter,OBJPROP_COLOR,clrBlue);

         bc_line = StringFormat("BC Line  %d",i);
         ObjectCreate(chart_id,bc_line,OBJ_TREND,0, b_c_ll_t, b_c_ll,c_d_hh_t,c_d_hh);
         ObjectSetInteger(chart_id,bc_line,OBJPROP_COLOR,clrBlue);

         fib_ab_ext_obj = StringFormat("AB Expansion  %d",i);
         ObjectCreate(chart_id,fib_ab_ext_obj,OBJ_EXPANSION,0,b_c_ll_t,b_c_ll,a_b_hh_t,a_b_hh,b_c_ll_t,b_c_ll);
         ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_COLOR,clrBlue);
         for(int i = 0; i <= 2; i++)
           {
            ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
           }

         fib_ab_ext_lvl = StringFormat("AB Expansion Levels %d",i);

         ObjectCreate(chart_id,fib_ab_ext_lvl,OBJ_RECTANGLE,0,a_b_hh_t,fib_ext_c_161,c_d_hh_t,fib_ext_c_224);
         ObjectSetInteger(chart_id,fib_ab_ext_lvl,OBJPROP_COLOR,clrBlue);

         ObjectCreate(chart_id,D_letter,OBJ_TEXT,0,D_time,D);
         ObjectSetString(chart_id,D_letter,OBJPROP_TEXT,"D");
         ObjectSetInteger(chart_id,D_letter,OBJPROP_COLOR,clrBlue);

         cd_line = StringFormat("CD Line  %d",i);
         ObjectCreate(chart_id,cd_line,OBJ_TREND,0, C_time, C,D_time,D);
         ObjectSetInteger(chart_id,cd_line,OBJPROP_COLOR,clrBlue);

         fib_bc_ret_lvl = StringFormat("BC RETRACEMENT Levels %d",i);

         ObjectCreate(chart_id,fib_bc_ret_lvl,OBJ_RECTANGLE,0,b_c_ll_t,fib_ret_d_50,D_time,fib_ret_d_55);
         ObjectSetInteger(chart_id,fib_bc_ret_lvl,OBJPROP_COLOR,clrBlue);

        }
      break;
     }
  }

説明

すべての点が市場のスイングを正確に表すことを保証するために、残りのレッグについても同じ検証手順が使用されます。アルゴリズムはXAにおいてXとAの間で最も低い安値を求め、Xがスイングローであることを確認します。また、OXレッグではOからXの間で最高値を求めることで、Oがパターン開始時の支配的なスイングハイであることを保証します。このように各点を評価する方法により、パターン構造は安定かつ信頼性の高いものとなり、誤ったスイングによる識別の精度低下を防ぐことができます。

プログラムは、各支配的スイングポイントを検証した後、最近確認された高値と安値が後続の計算に反映されていることを確認します。これにより、フィボナッチエクステンションおよびリトレースメントレベルをより正確に再計算でき、各レッグの比率が実際の市場変動に対応していることが保証されます。この再調整が完了した後、ソフトウェアは強気の5-0パターン内のすべての点が正しい順序と連結を保持しているかを確認します。すべての幾何学的およびフィボナッチの条件が満たされた場合、チャート上に正当な5-0構造が形成されたことが確認されます。


取引の執行

強気の5-0ハーモニックパターンが正しく特定されたことを確認した後、次のステップはこの構造に基づいて取引を実行することです。このセットアップでは、価格がDに到達したときにエントリーします。Dはパターンの潜在的完成点および強気の反転ゾーンを示しています。MQL5では、現在の価格がD付近にあるかを確認し、ロットサイズ、ストップロス、テイクプロフィットなどの事前定義されたパラメータで買い注文を開くことで実装できます。

例:

#include <Trade/Trade.mqh>
CTrade trade;
input double lot_size = 0.6;
datetime time_price[];
double ask_price;
double take_p;
datetime last_trade_time = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   ArraySetAsSeries(time_price,true);

//---
   return(INIT_SUCCEEDED);
  }
CopyTime(_Symbol, timeframe, 0, 2, time_price);
ask_price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
datetime current_bar_time = iTime(_Symbol,timeframe,0);
if(x_a_ll < o_x_hh && a_b_hh > x_a_ll && a_b_hh < o_x_hh && b_c_ll <= fib_ext_b_113 && b_c_ll >= fib_ext_b_161 && c_d_hh >= fib_ext_c_161 && c_d_hh <= fib_ext_c_224 && D <= fib_ret_d_50 && D >= fib_ret_d_55)
  {

   ObjectCreate(chart_id,O_letter,OBJ_TEXT,0,o_x_hh_t,o_x_hh);
   ObjectSetString(chart_id,O_letter,OBJPROP_TEXT,"0");
   ObjectSetInteger(chart_id,O_letter,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,X_letter,OBJ_TEXT,0,x_a_ll_t,x_a_ll);
   ObjectSetString(chart_id,X_letter,OBJPROP_TEXT,"X");
   ObjectSetInteger(chart_id,X_letter,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,A_letter,OBJ_TEXT,0,a_b_hh_t,a_b_hh);
   ObjectSetString(chart_id,A_letter,OBJPROP_TEXT,"A");
   ObjectSetInteger(chart_id,A_letter,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,B_letter,OBJ_TEXT,0,b_c_ll_t,b_c_ll);
   ObjectSetString(chart_id,B_letter,OBJPROP_TEXT,"B");
   ObjectSetInteger(chart_id,B_letter,OBJPROP_COLOR,clrBlue);

   ox_line = StringFormat("0X Line  %d",i);
   xa_line = StringFormat("XA Line  %d",i);
   ab_line = StringFormat("AB Line  %d",i);

   ObjectCreate(chart_id,ox_line,OBJ_TREND,0, o_x_hh_t, o_x_hh,x_a_ll_t,x_a_ll);
   ObjectSetInteger(chart_id,ox_line,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,xa_line,OBJ_TREND,0, x_a_ll_t, x_a_ll,a_b_hh_t,a_b_hh);
   ObjectSetInteger(chart_id,xa_line,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,ab_line,OBJ_TREND,0, a_b_hh_t, a_b_hh,b_c_ll_t,b_c_ll);
   ObjectSetInteger(chart_id,ab_line,OBJPROP_COLOR,clrBlue);

   fib_xa_ext_obj = StringFormat("XA Expansion  %d",i);
   ObjectCreate(chart_id,fib_xa_ext_obj,OBJ_EXPANSION,0,a_b_hh_t,a_b_hh,x_a_ll_t,x_a_ll,a_b_hh_t,a_b_hh);
   ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_COLOR,clrBlue);
   for(int i = 0; i <= 2; i++)
     {
      ObjectSetInteger(chart_id,fib_xa_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
     }

   fib_xa_ext_lvl = StringFormat("XA Expansion Levels %d",i);

   ObjectCreate(chart_id,fib_xa_ext_lvl,OBJ_RECTANGLE,0,x_a_ll_t,fib_ext_b_113,b_c_ll_t,fib_ext_b_161);
   ObjectSetInteger(chart_id,fib_xa_ext_lvl,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,C_letter,OBJ_TEXT,0,c_d_hh_t,c_d_hh);
   ObjectSetString(chart_id,C_letter,OBJPROP_TEXT,"C");
   ObjectSetInteger(chart_id,C_letter,OBJPROP_COLOR,clrBlue);

   bc_line = StringFormat("BC Line  %d",i);
   ObjectCreate(chart_id,bc_line,OBJ_TREND,0, b_c_ll_t, b_c_ll,c_d_hh_t,c_d_hh);
   ObjectSetInteger(chart_id,bc_line,OBJPROP_COLOR,clrBlue);

   fib_ab_ext_obj = StringFormat("AB Expansion  %d",i);
   ObjectCreate(chart_id,fib_ab_ext_obj,OBJ_EXPANSION,0,b_c_ll_t,b_c_ll,a_b_hh_t,a_b_hh,b_c_ll_t,b_c_ll);
   ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_COLOR,clrBlue);
   for(int i = 0; i <= 2; i++)
     {
      ObjectSetInteger(chart_id,fib_ab_ext_obj,OBJPROP_LEVELCOLOR,i,clrBlue);
     }

   fib_ab_ext_lvl = StringFormat("AB Expansion Levels %d",i);

   ObjectCreate(chart_id,fib_ab_ext_lvl,OBJ_RECTANGLE,0,a_b_hh_t,fib_ext_c_161,c_d_hh_t,fib_ext_c_224);
   ObjectSetInteger(chart_id,fib_ab_ext_lvl,OBJPROP_COLOR,clrBlue);

   ObjectCreate(chart_id,D_letter,OBJ_TEXT,0,D_time,D);
   ObjectSetString(chart_id,D_letter,OBJPROP_TEXT,"D");
   ObjectSetInteger(chart_id,D_letter,OBJPROP_COLOR,clrBlue);

   cd_line = StringFormat("CD Line  %d",i);
   ObjectCreate(chart_id,cd_line,OBJ_TREND,0, c_d_hh_t, c_d_hh,D_time,D);
   ObjectSetInteger(chart_id,cd_line,OBJPROP_COLOR,clrBlue);

   fib_bc_ret_lvl = StringFormat("BC RETRACEMENT Levels %d",i);

   ObjectCreate(chart_id,fib_bc_ret_lvl,OBJ_RECTANGLE,0,b_c_ll_t,fib_ret_d_50,D_time,fib_ret_d_55);
   ObjectSetInteger(chart_id,fib_bc_ret_lvl,OBJPROP_COLOR,clrBlue);

   if(time[n+z] == time_price[1] && close[n+z] > D && current_bar_time != last_trade_time)
     {
      take_p = ask_price + (MathAbs(ask_price - D) * 3);

      trade.Buy(lot_size,_Symbol,ask_price,D,take_p);

      last_trade_time = current_bar_time;

     }
  }

出力

図6:取引執行

説明

強気の5-0ハーモニックパターンが確認された後、取引の実行はソフトウェアのこの部分で処理されます。MQL5の取引ライブラリをインポートする最初の行、#include <Trade/Trade.mqh>により、ブローカーに注文を送信するために必要なCTradeクラスが利用可能になります。そのクラスのインスタンスを作成した後、「CTrade trade;」の行により、プログラムは買い注文や売り注文などの取引操作を実行できるようになります。各取引は、入力変数「lot_size = 0.6」で定義された通り、0.6ロットで実行されます。

取引の実行を管理し、重複エントリーを防ぐために、プログラムはいくつかの変数を定義しています。Ask_priceは現在の市場のAsk価格を保存し、take_pはテイクプロフィットの目標を決定するために使用され、last_trade_timeは直近取引時刻を記録し、配列time_price[]はローソク足の時間を追跡します。MQL5の時系列データの扱いに合わせるため、time_price配列は最新から最古の順に初期化されます。ソフトウェアは各ティックで最新のローソク足の時間と市場価格を取得します。

取引を開くかどうかを判断するためには、現在のローソク足の時間が最も最近コピーされた時間と一致すること、終値がDより上であること、そして同じローソク足で取引が実行されていないことが条件として確認されます。これらの条件が満たされた場合、同じバー内での複数エントリーを避けるため、プログラムは買い注文を実行し、現在のAsk価格とDの差の3倍の距離をテイクプロフィット目標に設定し、取引時刻を記録します。


結論

本記事では、5-0ハーモニックパターンを検出して取引するEAの作り方を説明しました。各スイングポイントの特定と検証、パターン構造の確認、自動売買の実行、トレンドラインやラベルなどのグラフィカルオブジェクトを用いたチャート上でのパターン表示方法について解説しました。これで、高度なチャートパターンについてのシリーズは最終回となります。次回の記事では、MQL5の新しい側面が紹介されます。

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

添付されたファイル |
最後のコメント | ディスカッションに移動 (2)
kimo161
kimo161 | 24 12月 2025 において 15:10

エリオット・ウェーブ?


そう、エリオット波だ。ウィリアム・オッカムが反対しているんだ。

Silk Road Trading LLC
Ryan L Johnson | 24 12月 2025 において 16:32
kimo161 #:

エリオットが手を振る?


そう、エリオット波だ。ウィリアム・オッカムが反対しているんだ。

もっとニュアンスが違う。5-0パターン(商標状況と文書検索)を含むハーモニックパターンは、エリオット波動が発明された後に発明されました。エリオット波動はサイクルの9度の波動に基づいているのに対し、5-0パターンはフィボナッチ比率に基づいている。両パターンをチャートに適用した場合、多少の重複が生じ、混乱を招く可能性があります。
プライスアクション分析ツールキットの開発(第45回):MQL5で動的水準分析パネルを作成する プライスアクション分析ツールキットの開発(第45回):MQL5で動的水準分析パネルを作成する
この記事では、ワンクリックで任意の価格水準をテストできる強力なMQL5ツールについて説明します。テストしたい価格を入力して分析ボタンを押すと、EAは過去のデータを瞬時にスキャンし、チャート上でその水準に触れた箇所やブレイクアウトをハイライト表示します。また、統計情報を整理されたダッシュボードに表示し、価格がその水準にどの程度反応したか、ブレイクしたか、サポートとして機能したか、レジスタンスとして働いたかを一目で確認できます。以下では、詳細な手順について解説します。
機械学習の限界を克服する(第5回):時系列交差検証の簡単な概要 機械学習の限界を克服する(第5回):時系列交差検証の簡単な概要
本連載では、機械学習を活用した取引戦略を実運用に展開する際に、アルゴリズムトレーダーが直面する課題について考察します。私たちのコミュニティには、より深い技術的理解を必要とするがゆえに、見過ごされがちな課題がいくつも存在します。本日の議論は、機械学習における交差検証の盲点を検討するための足がかりとなるものです。交差検証はしばしば定型的な手順として扱われますが、不注意に実施すると、誤解を招く、あるいは最適とは言えない結果を容易に生み出してしまいます。本記事では、その隠れた盲点をより深く考察する準備として、時系列交差検証の基本を簡単に振り返ります。
MQL5入門(第23回):オープニングレンジブレイクアウト戦略の自動化 MQL5入門(第23回):オープニングレンジブレイクアウト戦略の自動化
この記事では、MQL5でオープニングレンジブレイクアウト(ORB)エキスパートアドバイザー(EA)を作成する方法を解説します。EAが市場の初期レンジからのブレイクアウトをどのように検知し、それに応じてポジションを建てるかを説明します。また、建てるポジションの数を制御したり、指定した時間で自動的に取引を停止する方法についても学べます。
初心者からエキスパートへ:市場期間同期化ツール 初心者からエキスパートへ:市場期間同期化ツール
本ディスカッションでは、上位時間足から下位時間足への同期をおこなうツールを紹介します。このツールは、上位時間足の期間にまたがる市場パターンを分析する際の課題を解決することを目的としています。MetaTrader 5に標準搭載されている期間マーカーは、制限が多く柔軟性に欠けるため、非標準の時間足には対応しにくいことがあります。そこで私たちは、MQL5言語を活用して、下位時間足のチャート上で上位時間足の構造を動的かつ視覚的に表示できるインジケーターを開発しました。このツールは、詳細な市場分析に非常に役立ちます。その機能や実装方法について詳しく知りたい方は、ぜひディスカッションにご参加ください。