English Русский 中文 Español Deutsch Português
テクニカル分析におけるトーマス・デマーク

テクニカル分析におけるトーマス・デマーク

MetaTrader 4トレーディング | 5 5月 2016, 14:22
3 666 0
Ivan Morozov
Ivan Morozov

イントロダクション

テクニカル分析は、科学とアートの両方の側面から議論されてきました。この二重性の背後には、さまざまなトレーダーやアナリストのビューにあります。例えば、全く同じトレンドラインでも完全に異なるものとして描画することができます。このような不確実性は、精度が重要な商品取引では問題になります。これまでのトレンドラインでは、いくつかの引き方があり、トレーダーにはこの問題に直面していました。このような問題が原因で、トレンドラインと市場を分析することができず、正確な取引システムの構築が困難になります。適切に引かれなかったトレンドラインにより、極値・発散と収束に矛盾が生じます。:つまり、この多重度によって引き起こされるいくつか問題があります。

テクニカル分析は、これまでそのような多様性を受け入れてきました。たとえば、トーマス・デマークは、この問題に対する分析的なアプローチを見つけ、それを解決する方法を提案しました。「テクニカル分析の新しい科学」と呼ばれる彼の本の中で、現在の価格状況をより正確に分析する方法を解説しました。TDポイントとTDライン - この記事では、デマーク氏の2の調査結果をご紹介します。これは、トーマス・デマーク方式の本の唯一の内容ではありません。著書では、市場の周期性、エリオット波動などをより多くをカバーしています。

この資料も使い、3つの指標とトーマス・デマーク方式の考えに基づいて作成された2つのエキスパートアドバイザー説明します。この記事は、多くのトレーダー、特に為替初心者に有効だと考えられます。


1. TDポイント

トーマス・デマークの第一の発明は、トレンドラインを構築するための価格点を出すプロセスを簡素化します。日足チャートを 定義された日の翌日の最大値よりも高くなるロウソク足を見つけるために使いました。(この"定義された日"を今後TDポイントの決定に使われるロウソク足として使います。)この条件が満たされた場合、TDポイントが定義されたロウソク足の高値に基づいて、グラフ上に構築することができます。定義された日の安値が前と次の最小値よりも低い場合、TDポイントは定義されたロウソク足の上に付けることができます。

ブル型TDポイントベア型TDポイント

図1. ブル型とベア型のTDポイント

最初の図は、レベル1TDポイント(赤マーク)を示しています。図の通り、定義されたロウソク足の高値は、1つ前と1つ次のロウソク足の高値よりも大きいです。高値の値は、灰色の水平線として図に表示されています。2番目の図では、同様に、ベア型のTDポイントを示しています。どちらも同じ方法です。:定義されたロウソク足の安値が前と後のロウソク足の安値よりも低くなっています。

唯一のレベル1 TDポイントは上記と考えられます。これは、定義されたロウソク足の価格を前と後ろで比較されていることを意味します。レベル2TDポイントを構築するには、定義されたロウソク足の高値を、前2本と次2本のロウソク足と比較されなければなりません。同様に、同じことを、安値に適用します。

レベル2TDポイント

図2. レベル2TDポイントの例

上の図は、レベル2のTDポイントを示しています。定義されたロウソク足の最高価格が、前の2本ロウソク足より後の2本のロウソク足よりも著しく高いです。 

レベル40TDポイント

図3. レべル40TDポイント

定義されたロウソク足と比較されるべきである最大値と最小値の量に応じて、TDポイントが発生します。例えば、レベル3TDポイントは、1番目と2番目よりも低いレベルが同時にあることが条件です。トーマス・デマーク氏の著書では、レベル3ポイントまでカバーしています。

このような原理のインジケータは、すでに昔から存在しています。実際、ビル・ウィリアムズのフラクタルは、レベル2TDポイントにほかなりません。定義されたロウソク足の前に、2本のロウソク足があり、後にも2本のロウソク足があり、それぞれの安値より低く、高値より高い状態が、レベル2 TDポイントの定義です。


2. TDライン

単独のTDポイントは単に極値です。トレンドラインを構築するためには、2つのポイント(2つの最大値または2つの最小値)が必要になります。同時に、トーマス・デマークは、最も重要なものとして直近のポイントを使用します。

レベル1TDラインレベル2TDライン

図4. レベル1のTDライン/レベル2 TDライン。

左図は、2つのレベルと2つのTDライン(青線 - 最小値、緑線 - 最大値)を示しています。ライン・レベルは、このラインを構築するために使用されるポイントのレベルを指します。右図は、レベル3 TDラインを示しています。

トーマス・デマークは、直接的にTDラインにリンクされている3つの価格プロジェクタを開発しました。これについては、"追加情報"で簡潔に説明します。


3. インジケーターの作成

3.1. iTDDots

手動で、新しいロウソク足が更新されるたびに、新しい点と線を構築するのは非常に大変です。品質に影響を与えることなく、自動化することができれば最適です。TDポイントを構築するインジケーターを作成する処理について説明します。この例では、MQL4で行います。

まず、インジケーターのプランが終わりました。現在のロウソク足では、誤って構成される可能性があるので、インジケーターの計算に使いません。したがって、直前のロウソク足から考慮します。

インジケーター実行の計画:

  • チャート上に追加する場合、既存のヒストリーデータのすべてのTDポイントを作成します。そのレベルは、ユーザ設定です。
  • 新しいロウソク足を確認し、常に更新します。

インジケーターの主なタスクは、その極値に隣接するロウソク足に関連するn個の極値よりも高いロウソク足を決定することです。これが、必要とされる範囲内で、最大と最小のロウソク足の価格を決定する関数を書くことをオススメする理由です。ロウソク足を決定するため、更新されるたびにロウソク足をチェックする必要があります。

インジケータで使用されるロウソク足

図5. インジケータで使用されるロウソク足

 上図は、インジケーターによって計算されるロウソク足が番号付けされている例を示しています。これは、その算出方法を示しています。

さて、コーディングの方法を紹介します。

1つのロウソク足が同時に最大値と最小値のTDポイントを得る可能性があるので、インジケータはポイントを表示するために2つのバッファを持っている必要があります。そのため、プログラムは次のようになります。

#property indicator_chart_window        //チャートウィンドウにインジケータを表示
#property indicator_buffers 2           //2のバッファを使用
#property indicator_plots   2           //2つのバッファが表示
#property indicator_color1 clrGreen     //第一のバッファの標準色
#property indicator_type1   DRAW_ARROW  //第一のバッファの描画タイプ
#property indicator_width1 2            //第一のバッファを表示するための標準的な線の太さ
#property indicator_color2 clrBlue      //第2のバッファの標準色
#property indicator_type2   DRAW_ARROW  //第2のバッファに描画タイプ
#property indicator_width2 2            //第2のバッファを表示するための標準的な線の太さ

ユーザーは、チャートに追加するとき、インジケータのTDポイントのレベルを決定する必要があります。

input int Level = 1;

グローバルで宣言された以下の変数を操作に使用します。

bool new_candle = true;         
double  pdH,                    //定義された燭台の最高価格
        pdL,                    //定義された燭台の最低価格
        pricesH[],              //最大の価格を格納するための配列
        pricesL[];              //最小限の価格を格納するための配列
bool    DOTH,                   //ポイントを表示する(最大に基づいて、)
        DOTL;                   //ポイントを表示(最小に基づく)
double  UpDot[],                //ポイントのバッファアレイが最大値に基づいて描く
        DownDot[];              //ポイントのバッファ・アレイは、最小値に基づいて描く

Init() 関数は、下方に設けられています。:

 intOnInit()
  {
   ChartRedraw(0);                              //時間枠を切り替えたときに表示の問題を防止するのに必要
   SetIndexBuffer(0, UpDot);
   SetIndexBuffer(1, DownDot);
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   SetIndexArrow(0,159);                        //Wingdingsフォントからシンボルセット番号
   SetIndexArrow(1,159);
   SetIndexLabel(0, "TD " + Level + " High");   //これらの名前は、データウィンドウに表示されます
   SetIndexLabel(1, "TD " + Level + " Low");
   return(INIT_SUCCEEDED);
  }

必要なロウソク足の価格を得るために、以下に機能を作成しました:

void GetVariables(int start_candle, int level)
  {
   /*この機能では、インジケータは、ポイントを構築するためのロウソク足から情報を収集します. ここで使用されるすべての変数はすでにグローバルとして宣言されています*/
   pdH = iHigh(NULL, 0, start_candle + 1 + level);      //定義されたロウソク足の高値
   pdL = iLow(NULL, 0, start_candle + 1 + level);       //定義されたロウソク足の安値
   
   ArrayResize(pricesH, level * 2 + 1);                 //設定配列サイズ
   ArrayResize(pricesL, level * 2 + 1);                 //
   
   for (int i = level * 2; i >= 0; i--){                //配列内の必要なロウソク足のすべての価格(最大値と最小値)を収集
      pricesH[i] = iHigh(NULL, 0, start_candle + i + 1);
      pricesL[i] = iLow(NULL, 0, start_candle + i + 1);
  }

そして、最後に、最も興味深い - start() 関数のコードです。:

int start()
  {
   int i = Bars - IndicatorCounted();                   //同じ新しいローソク足が表示されるたびにカウントを回避するために必要
   for (; i >= 0; i--)
     {                                                  //TDポイントの構築に関連するすべてのアクティビティは、ここを取ります
      DOTH = true;
      DOTL = true;
      GetVariables(i, Level);                           //現在の価格値を取得
      
      for(int ii = 0; ii < ArraySize(pricesH); ii++)
        {                                              //この区間でのTDポイントがあるかどうかを決定
         if (pdH < pricesH[ii]) DOTH = false;
         if (pdL > pricesL[ii]) DOTL = false;
        }   
         
      if(DOTH) UpDot[i + Level + 1] = pdH;              //次のような場合
      if(DOTL) DownDot[i + Level + 1] = pdL;
      
      if(UpDot[i + Level + 1] ==  UpDot[i + Level + 2]) UpDot[i + Level + 2] = 0;       //ここで2つのロウソク足をカバーする
      if(DownDot[i + Level + 1] ==  DownDot[i + Level + 2]) DownDot[i + Level + 2] = 0; //その結果、同一の最小・最大価格を有し、TDポイントを構築します
     }                                                                                  //最後のロウソク足のペア
   return(0);
  }

これで、TDポイントを作成するインジケーターをコーディングする過程が分かりました。TDDotsインジケーターは下記のチャートです。最初のチャート Level=10 - 2番目のチャート=10これは、最初のグラフ上のすべてのTDポイントが最初のチャート上で、少なくとも、1つのロウソク足に囲まれているということを意味します。これらのチャートは、インジケータの動作を確認するためのものです。

すべてのレベル1 TDポイントすべてのレベル10のTDポイント

図6. インジケータ操作の例:レベル1 TDポイントとレベル10 TDポイントを作成します。


3.2. iTDライン

以前に述べたように、トーマス・デマーカはTDラインを描画するために、2つのポイントを使用していました。インジケーターでこのアプローチを自動化します。このインジケーターの目的は、設定された点を通る2本の直線を構築することです。問題は、それを構築する方法です。y= kx+ b:明らかに、線形関数を使用することができます。ラインが設定された点を厳密に通過するので、係数kおよびbが選択されなければなりません。

2点の座標は、それらを介して直線を構築します。以下の式を利用して、線形関数についてのkとbを見つけます。xで、グラフの右側からロウソク足の数、およびyをマークします。

k = (y2 - y1) / (x2 - x1),
b = (x2 * y1 - x1 * y2) / (x2 - x1),
ただし、x1 は- 最初のポイントのロウソク足の数
      ×2 - 2番目のポイントとロウソク足の数
      y1 - 最初のポイントの価格、
      y2 - 第2の点の価格.

kとbを知ることにより、TDライン上に位置する点の価格を得て、単純な線形方程式を解くことができます。 

インジケータコードが以下です。

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2

#property indicator_color1 clrGreen
#property indicator_color2 clrBlue

input int Level = 1;

double LU[], LD[];

//この変数は、計算を最小限にするために使用します。
datetime LastCount;

ラインのポイントのレベルの値で、一つの変数がインジケータに使用されます。これは、ユーザによって、TDDotsと同じ方法で設定されます。ラインのすべてのポイントの価格値が含まれている二つの配列です。LastCount変数は一度だけ、各ローソク足の計算を行うためにインジケータで使用されます。

瞬時にkとbの値を検出する関数がさらに提示されています。これは、部分的に説明します。

void GetBK(double &Ub, double &Uk, double &Db, double &Dk, int &EndUN, int &EndDN)
  {
   double TDU[];
   double TDD[];
   int TDU_n[];
   int TDD_n[];
   ArrayResize(TDU, 2, 2);
   ArrayResize(TDD, 2, 2);
   ArrayResize(TDU_n, 2, 2);
   ArrayResize(TDD_n, 2, 2);

この関数は、6つの値を返します。最初の4つの変数の代入は明確ですが、最後の二つの変数は少し複雑に見えます。ラインを表示するために役に立ちます。それらの各々は、現在のロウソク足から線の長さを表しています。

//最初からロウソク足の数とポイントの価格の値を受け取ります。
   int Ui = 0;
   int Di = 0;
   for(int i = 0;; i++)
     {
      double current_bar_U = iCustom(NULL, 0, "TDDots", Level, 0, i);
      double current_bar_D = iCustom(NULL, 0, "TDDots", Level, 1, i);
      
      if(current_bar_U > 0 && Ui < 2)
        {
         TDU[Ui] = current_bar_U;   //価格
         TDU_n[Ui] = i;             //数
         Ui++;
        }
      if(current_bar_D > 0 && Di < 2)
        {
         TDD[Di] = current_bar_D;
         TDD_n[Di] = i;
         Di++;
        }
      if(Ui == 2 && Di == 2) break;
     }

コードのこのパートは、2つの直近のTDポイントの値を受け取ります。価格は将来的に動作するように配列に保存されます。

   Ub = ( (TDU_n[0] * TDU[1]) - (TDU[0] * TDU_n[1]) ) / ( TDU_n[0] - TDU_n[1] );
   Uk = (TDU[0] - TDU[1]) / (TDU_n[0] - TDU_n[1]);
   
   Db = ( (TDD_n[0] * TDD[1]) - (TDD_n[1] * TDD[0]) ) / ( TDD_n[0] - TDD_n[1] );
   Dk = (TDD[0] - TDD[1]) / (TDD_n[0] - TDD_n[1]);   
   
   EndUN = TDU_n[1];
   EndDN = TDD_n[1];
  }

ロウソク足は、(右から左へ)時系列のように番号が付けられているので、ポイントの反対の値を使用する必要があります。言い換えると、x2は、上記の式中のx2と×1に置き換える必要があります。これは、外観です。:

b = (x1 * y2 - x2 * y1) / (x1 - x2),
k = (y1 - y2) / (x1 - x2),
ただし、x1 - 最初のポイントのロウソク足番号
      x2 - 第二の点のロウソク足の番号、
      y1 - 最初のポイントの価格
      y2 - 第2の点の価格.

これは、(Init)関数です。:

 intOnInit()
  {
   SetIndexBuffer(0, LU);
   SetIndexLabel(0, "TDLU");
   SetIndexBuffer(1, LD);
   SetIndexLabel(1, "TDLD");
      
   SetIndexEmptyValue(0, 0);
   SetIndexEmptyValue(1, 0);
   
   LastCount = iTime(NULL, 0, 1);
   
   return(INIT_SUCCEEDED);
  }

バッファは初期化され、この関数で名前が付けられます。また、新たなティックでラインの位置を計算するインジケーターは、以前のロウソク足のデータは、LastCount変数で記述されています。実際には、すべてのデータは、現在から区別して、書き込むことができます。

その後、start()関数を記述します:

int start()
  {
   //新しいロウソク足または最初の起動
   if(iTime(NULL, 0, 0) != LastCount)
     {
      double Ub, Uk, Db, Dk;
      int eUp, eDp;
      
      GetBK(Ub, Uk, Db, Dk, eUp, eDp);
      
      //古い値を削除
      for(int i = 0; i < IndicatorCounted(); i++)
        {
         LU[i] = 0;      
         LD[i] = 0;
        }
         
      //新しい値を構築
      for(i = 0; i <= eUp; i++)
        {
         LU[i] = Uk * i + Ub;
        }
         
      for(i = 0; i <= eDp; i++)
        {
         LD[i] = Dk * i + Db;
        }
         
      LastCount = iTime(NULL, 0, 0);
     }
      
   return 0;
  }

古い値から新しい値をクリアするため、前に描画が必要とされます。したがって、個別のループが関数の先頭に実装されています。さて、上記の式によれば、2行がビルドされ、LastCount変数が現在のロウソク足に再び実行してしまうことを回避するために、現在の日付が割り当てられます。

結果として、インジケータは、それに応じて動作します。

インジケータ動作例

図7. インジケータ操作の例:レベル5 TDポイントに基づいて構築されるTDライン。

この図を理解することは難しくありません。図7は、レベル=5の変数値とインジケーターの実行を示しています。


3.3水平線インジケータ

明らかに、チャートの水平レベルの価格を決定するためには、いくつかの方法があります。現在の価格に関する二つのレベルを構築する簡単な方法を示します。すでに記述したiTDDotsはインジケータの実行に使用されます。(下記参照p. 3.1).

これはシンプルです。:

  1. インジケータは、ユーザによって設定されたTDポイントのn個の値を取得します
  2. これらの点の平均価格値を算出します
  3. 水平線は、それに基づいて、チャート上に表示されます

しかし、TDポイントは、現在の価格から最後の点に配置する場合があります。ユーザによって導入される点の間の距離を減少させる変数は、この問題を解決するために実施されました。これはつまり、インジケータはある一定数の点を超えないように互いから離れているn個の極値間の平均値を求めることを意味します。

インジケータのコードを見てみましょう。

2つのバッファと3つの変数の値は、ユーザが入力する必要があります。

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_color1 clrGreen
#property indicator_type1   DRAW_LINE
#property indicator_width1 2
#property indicator_color2 clrBlue
#property indicator_type2   DRAW_LINE
#property indicator_width2 2

input int TDLevel = 1;       //ポイントのレベル
input int NumberOfDots = 3;  //ポイント数
input double Delta = 0.001;  //2点間の最大距離

double TDLU[], TDLD[];

2本の水平線は、このインジケーターで作成されます。これらは(TDLinesインジケータのトレンドライン以外)長期分析で値を保持することができるので、このような水平線などのグラフィックオブジェクトを、使用することにしました。しかし、水平レベルの値をインジケーターバッファに格納すると、将来的にこのインジケーターを使用することがはるかに容易になります。0のインデックスと現在のロウソク足にこれらの値を保存することにしたので、いつも他のプログラムからiCustomを取り組むことによって、簡単な方法となります。

 intOnInit()
  {
   SetIndexBuffer(0,TDLU);
   SetIndexBuffer(1,TDLD);
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   SetIndexLabel(0, "U HL");
   SetIndexLabel(1, "D HL");
   ObjectCreate(0, "U horizontal level", OBJ_HLINE, 0, iTime(NULL, 0, 0), 0);
   ObjectCreate(0, "D" horizontal level, OBJ_HLINE, 0, iTime(NULL, 0, 0), 0);
   return(INIT_SUCCEEDED);
  }

特定の水平レベルの価格を計算する関数は以下の通りです。

double GetLevelPrice(int ud,int n,double delta,int level)
  {
   /* ud - ラインタイプのインジケータ。0 - U, other value - D.
   n - ポイントの数。
   delta - 間の最大距離
   level - ポイントのレベル。*/

   //ポイントの価格を格納するための配列が用意されています
   double TDU[];
   double TDD[];
   ArrayResize(TDU,n,n);
   ArrayResize(TDD,n,n);
   ArrayInitialize(TDU,0);
   ArrayInitialize(TDD,0);
 
   //唯一の2つのデータバッファが存在し、ループは、二回動作します
   for(int Buffer=0; Buffer<2; Buffer++)
     {
      int N=0;
      int Fails=0;
      bool r=false;
      for(int i=0; r==false; i++)
        {
         double d=iCustom(NULL,0,"TDDots",level,Buffer,i);
         if(d>0)
           {
            if(N>0)
              {
               if(Buffer==0) double cp=TDU[N-1];
               else cp=TDD[N-1];
               if(MathAbs(d-cp)<=delta)
                 {
                  if(Buffer == 0)
                     TDU[N] = d;
                  else TDD[N]=d;
                  N++;
                 }
               //もし距離が長すぎる場合、エラー1になります。
               else
                 {
                  Fails++;
                 }
              }
            else
              {
               if(Buffer == 0)
                  TDU[N] = d;
               else TDD[N]=d;

               N++;
              }
           }
         //多くのエラーがある場合、ループは終了
         if(Fails>2 || N>n) r=true;
        }
     }
   
   //平均値を求める
   double ATDU = 0;
   double ATDD = 0;
   N=0;
   for(i=0; i<ArraySize(TDU); i++)
     {
      ATDU=ATDU+TDU[i];
      if(TDU[i]==0)
        {
         i=ArraySize(TDU);
        }
      else
        {
         N++;
        }
     }
   ATDU=ATDU/N;
   N=0;
   for(i=0; i<ArraySize(TDD); i++)
     {
      ATDD=ATDD+TDD[i];
      if(TDD[i]==0)
        {
         i=ArraySize(TDD);
        }
      else
        {
         N++;
        }
     }
   ATDD=ATDD/N;

   //関数が値を返す
   if(ud == 0) return ATDU;
   else return ATDD;
  }

 単に価格の値を取得し、すでに新しいティックで呼び出される関数内のオブジェクトを作成するため、割り当て作業が残っています:

void start()
  { 
   //直前のロウソク足のインジケータバッファの値を削除
   TDLD[1] = 0;
   TDLU[1] = 0;

   TDLD[0] = GetLevelPrice(1, TDLevel, Delta, NumberOfDots);
   TDLU[0] = GetLevelPrice(0, TDLevel, Delta, NumberOfDots);
   
   //オブジェクトが消えた場合
   if(ObjectFind("U horizontal level") < 0)
     {
      ObjectCreate(0, "U horizontal level", OBJ_HLINE, 0, iTime(NULL, 0, 0), 0);
     }
   if(ObjectFind("D horizontal level") < 0)
     {
      ObjectCreate(0, "D" horizontal level, OBJ_HLINE, 0, iTime(NULL, 0, 0), 0);
     }
   
   ObjectSetDouble(0, "U horizontal level", OBJPROP_PRICE, TDLU[0]);
   ObjectSetDouble(0, "D horizontal level", OBJPROP_PRICE, TDLD[0]);
  }

便宜上、インジケータオブジェクトを削除した後も削除する必要があります。

void OnDeinit(const int reason)
  {
   if(!ObjectDelete("U horizontal level")) Print(GetLastError());
   if(!ObjectDelete("D horizontal level")) Print(GetLastError());
  }

最終的に、作成されたインジケータは、ユーザに設定されたパラメータに基づいて自動的に水平線を構築します。

インジケータ動作例

図8. インジケータ動作例。 



4. 水平線インジケータによるエキスパートアドバイザー

どのインジケーターも、自動的に利益を獲得するために使用されるべきです。明らかに、この記事に記載されているエキスパートアドバイザーは、任意の市場にを持ちこむことはできません。その背後にある目的は異なっています。これは、動作のインジケーターを実証するだけでなく、一般的にはエキスパートアドバイザーの構造を示すためでもあります。

では、より具体的にしていきます。水平線インジケータを使用して、下記のシグナルに基づくエキスパートアドバイザーを作ることができます。

買いの条件:

  • 価格が上側の水平レベルを突破。
  • 価格が、上部の水平レベルの価格の値から増加

売る条件は、逆です:

  • 価格が下部の水平レベルを突破。
  • 価格が下部の水平レベルから減少。

これは、図に示すことができます。

買いシグナル売りシグナル

図9. 買いと売りの条件

エキスパートアドバイザーは1つだけポジションを開き、トレーリングストップでそれを追従します。すなわち、その起動時にユーザによって設定されたポイント数に応じて、ストップロスをシフトします。

イグジットはストップロスでのみ実行されます。

MQL4で開発されたExpert Advisorのコードを見てみましょう.
まず、事前にプログラムを実行するためにユーザが設定する変数を説明します。

input int MagicNumber = 88341;      //エキスパートアドバイザーは、このマジックナンバーで注文を開きます。
input int GL_TDLevel = 1;           //水平レベルインジケータで使用されるTDポイントのレベル
input int GL_NumberOfDots = 3;      //水平レベルインジケータで使用されるポイント数
input double S_ExtraPoints = 0.0001;//追加点の数上記の数値からのL
input double GL_Delta = 0.001;      //TDポイントの値は、水平レベルのインジケータによって考慮される距離
input int StopLoss = 50;            //ストップロスレベル
input double Lot = 0.01;            //ロットサイズ

TDラインが交差した場合は、次の関数がチェックされます。インジケータによって構築されたラインを越えたときにシグナルが毎回反応するのを避けるために、以前のロウソク足の最低価格を要求してチェックします。*このように、あるロウソク足にのみシグナルを取得する機会があります。この関数のコードです。

int GetSignal(string symbol,int TF,int TDLevel,int NumberOfDots,int Delta,double ExtraPoints)
  {
//レベルの価格値が上位のTDポイント上に構築
   double UL=iCustom(symbol,TF,"iglevels",GL_TDLevel,GL_NumberOfDots,GL_Delta,0,0)+ExtraPoints;
//...下のTDポイント
   double DL=iCustom(symbol,TF,"iglevels",GL_TDLevel,GL_NumberOfDots,GL_Delta,1,0)-ExtraPoints;

   if(Bid<DL && iLow(symbol,TF,1)>DL)
     {
      return 1;
     }
   else
     {
      if(Ask>UL && iHigh(symbol,TF,1)<UL)
        {
         return 0;
        }
      else
        {
         return -1;
        }
     }
  }

以下の変数は、Expert Advisorでの動作上、グローバルに宣言する必要があります:

int Signal = -1;          //現在のシグナル
datetime LastOrder;       //最後に実行した日. 1つのロウソク足に複数の注文を開くケースを回避するために必要

Init()関数は、新規注文を開くLastOrder変数に任意の最近の日付を割り当てる必要があります。

 intOnInit()
  {
   LastOrder = iTime(NULL, 0, 1);
   return(INIT_SUCCEEDED);
  }

最も重要なOnTick関数を以下に示します。

void OnTick()
  {
   bool order_is_open=false;
//オープンオーダーを検索
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS)) Print(GetLastError());

      if(OrderMagicNumber()==MagicNumber)
        {
         order_is_open=true;
         break;
        }
     }

//現在のシグナルを取得
   Signal=GetSignal(Symbol(),0,GL_TDLevel,GL_NumberOfDots,GL_Delta,S_ExtraPoints);

//ストップロスの大きさを計算
   double tsl=NormalizeDouble(StopLoss*MathPow(10,-Digits),Digits);


   if(order_is_open==true)
     {
      //ストップロスの価格の計算
      double p=NormalizeDouble(Ask-tsl,Digits);
      if(OrderType()==1) p=NormalizeDouble(Ask+tsl,Digits);

      if(OrderType()==0 && OrderStopLoss()<p)
        {
         if(!OrderModify(OrderTicket(),OrderOpenPrice(),p,0,0)) Print(GetLastError());
        }
      if(OrderType()==1 && OrderStopLoss()>p)
        {
         if(!OrderModify(OrderTicket(),OrderOpenPrice(),p,0,0)) Print(GetLastError());
        }
     }
//注文が存在しない場合
   if(order_is_open==false)
     {
      //現在のロウソク足でポジションを開いていない場合
      if(iTime(NULL,0,0)!=LastOrder)
        {
         //買い
         if(Signal==0)
           {
            if(!OrderSend(NULL,0,Lot,Ask,5,Ask-tsl,0,NULL,MagicNumber)) Print(GetLastError());
            LastOrder=iTime(NULL,0,0);
           }
         //売り
         if(Signal==1)
           {
            if(!OrderSend(NULL,1,Lot,Bid,5,Ask+tsl,0,NULL,MagicNumber)) Print(GetLastError());
            LastOrder=iTime(NULL,0,0);
           }
        }
     }
  }

これは、開いているオーダーの有無を確認するために使用され、もし存在する場合、エキスパートアドバイザーはストップロスを転送します。まだ注文がない場合、GetSignal関数により得られたシグナルに基づいて動作します。重要:プログラムの中で二つの実数値を比較する場合、あらかじめNormalizeDouble関数を使用します。

エキスパートアドバイザーは、それに応じて動作します。

エキスパートアドバイザー実行の例

図10. ストラテジーテスターでのエキスパートアドバイザー操作の例

図10は、損失と収益になることを示しています。利益が損失を超えています。これは、損失が限定され、トレーリングストップを伴っているためです。良い結果と残念な結果、両方の結果を示しています。しかし、これは実際のトレードで得られた結果ではないということに注意しなければなりません。エキスパートアドバイザーは、このタスクを処理することができます。


テスト結果

図11。テスト結果

このエキスパートアドバイザは、時々起こるトレンド補正でのマイナスを避け、特定の利益を達成するために、部分的な位置を追加することによって改善することができます。その場合、試算の保全に貢献し、損失または利益が発生する前にポジションを閉じます。ストップロスの大きさは、価格の動きに応じて変更しなければならないことに注意してください。


5。TDライン上の取引のエキスパートアドバイザー

このエキスパートアドバイザーは、取引システムの構築にTDラインを使用した例です。一般的に、TDラインは、トレンドラインです。これは、価格がTDラインと同じ方向に移動する場合、そのトレンドが変化する可能性があることを意味します。

エキスパートアドバイザーは、2つのシグナルのみで取引します:

売りシグナル      買いシグナル

図12。TDラインが使用するシグナル

ブル型のTDラインが壊れ、価格が通過したときに買いポジションが開かれます。さらに、ラインの価格の最も小さな値がロウソク足に一致したとき売りポジションです。

価格が弱気TDラインは突破した場合、売りポジションが開かれます。TDラインが上向き。

ポジションはトレーリングストップを伴います。決済はストップロスによってのみ行われます。

下記は、ユーザーが入力した変数です。:

input intLevel=1;  //TDラインレベル
input double Lot=0.01;//ロットサイズ
input int AddPips=3;//ポイントの追加番号
input int Magic=88342;//注文の魔法数
input int Stop=50//ポイント単位でのストップロス
input int Bars_To_Open_New_Order=2;//インターバルのバーで新規注文を開く

datetime LastBar;
datetime Trade_is_allowed;

古いオーダーから新しい注文までに時間を置く機能がエキスパートアドバイザーで使用されています。これは、頻繁なポジションを防ぐことができます。

このエキスパートアドバイザーは、OnInit関数のLastBarやTrade_is_allowedの変数に値を代入します。

 intOnInit()
  {
   LastBar=iTime(NULL,0,1);
   Trade_is_allowed=iTime(NULL,0,0);

   return(INIT_SUCCEEDED);
  }

シグナルを返すGetSignalの関数:

int GetSignal()
  {
//新しいロウソク足の場合
   if(LastBar!=iTime(NULL,0,0))
     {
      double DU = iCustom(NULL, 0, "itdlines", Level, 0, 0);
      double DD = iCustom(NULL, 0, "itdlines", Level, 1, 0);
      double DU1 = iCustom(NULL, 0, "itdlines", Level, 0, 1);
      double DD1 = iCustom(NULL, 0, "itdlines", Level, 1, 1);
     }

   double add_pips=NormalizeDouble(AddPips*MathPow(10,-Digits),Digits);

// U字ブレークスルー - >買い
   if(Ask>DU+add_pips && iLow(NULL,0,0)<Ask && DU<DU1)
     {
      return 0;
     }
   else
     {
      // Dラインブレークスルー - >売り
      if(Bid<DD-add_pips && iHigh(NULL,0,0)>Bid && DD>DD1)
        {
         return 1;
        }
      //ブレークスルーがない - > シグナルなし
      else
        {
         return -1;
        }
     }

   return -1;
  }

LastBar変数は新しいロウソク足を決定するために使用されます。これは一度だけ新しいローソク足が表示されたときに計算されているので、新しいティックでTDラインの最後の二つの点を計算回避するために必要とされます。この関数の返り値: 0 — 買い, 1 — 売り, -1 — シグナルなし

最後に、計算すべてを行うOnTick関数:

void OnTick()
  {
   int signal=GetSignal();
   bool order_is_open=false;

//オープンオーダーの検索
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS)) Print(GetLastError());

      //マジックナンバー
      if(OrderMagicNumber()==Magic)
        {
         order_is_open=true;
         i=OrdersTotal();
        }
     }

//ストップロスの大きさ
   double stop=Stop*MathPow(10,-Digits);
//注文がすでに開いている場合
   if(order_is_open==true)
     {
      //ストップロスの転送を確認

      //ストップロスの価格
      double order_stop=NormalizeDouble(OrderStopLoss(),Digits);

      //買い注文の場合
      if(OrderType()==0)
        {
         if(order_stop<NormalizeDouble(Ask-stop,Digits))
           {
            if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(Ask-stop,Digits),0,0))Print(GetLastError());
           }
        }
      //売り注文の場合
      if(OrderType()==1)
        {
         if(order_stop>NormalizeDouble(Bid+stop,Digits))
           {
            if(!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(Bid+stop,Digits),0,0))Print(GetLastError());
           }
        }
      Trade_is_allowed=iTime(NULL,0,0)+ChartPeriod(0)*60*Bars_To_Open_New_Order;
     }
//何もオーダーがない場合
   else
     {
      if(signal>=0 && iTime(NULL,0,0)>Trade_is_allowed)
        {
         if(signal==0)
           {
            if(!OrderSend(NULL,signal,Lot,Ask,5,Ask-stop,0,NULL,Magic)) Print(GetLastError());
           }
         if(signal==1)
           {
            if(!OrderSend(NULL,signal,Lot,Bid,5,Bid+stop,0,NULL,Magic)) Print(GetLastError());
           }

        }
     }
  }

まず、シグナルが算出され、オーダーはそのマジックナンバーでループして検索されます。(他のシステムとの任意の一致がないことを考慮して)すでにオーダーがあると、ストップロスを送信するかどうかがチェックします。注文が存在しない場合、シグナルに応じて新しいオーダーを取ります。しかし、現在のロウソク足の条件がTrade_is_allowed変数のデータよりも大きい場合のみです。

このエキスパートアドバイザーは、次のように取引します:

テスターの実行例

図13. TDラインエキスパートアドバイザーの動作例

値動きが速い場合にはシグナルのダマシが発生し、損失につながる可能性があります。エキスパートアドバイザーのテスト結果です。

テスト結果

図14. TDLineのテスト結果


結論

今回の目標は、トーマス・デマークが開発したTDポイントとTDラインを解説し、MQL4で実装することでした。この記事では、3つのインジケーターと2つのエキスパートアドバイザーを例としています。デマークの考えが論理的に取引システムに組み込まれていることを確認し、上手く利用することができます。  


このインジケータを使用するには、まず、itddots.mq4をインストールする必要があります。etdlines.mq4が動作にするには、itunes.mq4、および、eglevels.mq4を使用する必要があります。シャットダウンを引き起こす可能性があるので、必要なインジケーターの設定は非常に重要です。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1995

添付されたファイル |
eglevels.mq4 (7.22 KB)
etdlines.mq4 (7.92 KB)
iglevels.mq4 (9.15 KB)
itdlines.mq4 (6.57 KB)
itddots.mq4 (5.83 KB)
MQL5 でのアサーション MQL5 でのアサーション
この記事では、MQL5でのアサーションの利用について扱います。アサーションメカニズムとアサーションを実装するための一般的なガイダンスを2つの例として提供します。
グラフィカルインタフェースIV:マルチウィンドウモードと優先度のシステム(チャプター2) グラフィカルインタフェースIV:マルチウィンドウモードと優先度のシステム(チャプター2)
この章では、MQLアプリケーションでのマルチウィンドウインタフェースの作成の可能性をもたらすライブラリの実装を拡張します。また、グラフィカルオブジェクト上でのマウスの左クリックの優先順位のシステムを開発します。これは、要素がユーザのアクションに応答しない場合に発生する問題を回避するために必要です。
ファジーロジックの概要 ファジーロジックの概要
ファジーロジックは、数学的論理と集合論の境界を拡張します。この記事では、マムダニ型とスゲノ型モデルを使用して、2つのファジー推論システムを説明し、ファジー理論の基本的な原則を取り扱います。MQL5FuzzyNetライブラリを使用して、これら2つのシステムに基づいてファジーモデルの実装について説明します。
グラフィカルインタフェースIII:シンプルボタンと多機能ボタンのグループ(チャプター 2) グラフィカルインタフェースIII:シンプルボタンと多機能ボタンのグループ(チャプター 2)
シリーズの最初の章は、シンプルボタンと多機能ボタンについてでした。2番目の記事は、アプリケーション内でユーザーがセット(グループ)のうちオプションのいずれかを選択することができる際の要素の作成を可能にする相互接続されたボタンのグループに専念します。