ホーム テクニカル指標 投稿

全時間軸のトレンドを一目で確認できるMetaTrader 4用インジケーター

添付ファイル
15620.zip (2.17 KB, ダウンロード 0回)

こんにちは、トレーダーの皆さん!今日は、全ての時間軸のトレンドを一目で確認できるインジケーターについてお話しします。このインジケーターは、スロープ・ディレクション・トレンド(Slope Direction Trend)を元にしたグラフィカルな表示が特徴です。

これまでにも同様のインジケーターは存在しましたが、全ての時間軸を一つのグラフィカルパネルに表示するものはありませんでした。興味のある方は、こちらから検索してみてください

私はこのインジケーターを改良し、全時間軸を表示するグラフィカルパネルを作成しました。主な変更点は、スムージングに使用する移動平均法を選択できるようにしたことです。元のコードではリニアウェイテッドが使用されていましたが、ユーザーがスムージングの方法を選べるようにしました。リニアウェイテッドで両方の計算を行うと、インジケーターが過剰に反応し、トレンドの誤った読みを与える可能性があります。シンプルな移動平均を使用することで、価格の動きにより合致したトレンドが得られます。

さらに、トレンドの方向(上昇、下降、フラット)だけでなく、その値も取得できるようにしました。この詳細については、別の記事で「ダブルスロープディレクションインジケーターを使用してEAを作成する方法」を紹介する予定ですので、お楽しみに!

スロープディレクション 

さて、ここでコードを見てみましょう。最初に、使用するオブジェクト名を定義します。このルールは、コードを効率的にするために非常に有用です。オブジェクト名をクォートの中に入れるたびに、プログラム内にそのためのスペースが割り当てられます。したがって、一度定義しておくことで、コード内のスペースを一度だけ消費します。

// トレンド方向の定義
#define     UPTREND           1
#define     DOWNTREND         -1
#define     FLATTREND         0

// オブジェクトの定義
#define     TrendPanel        "TrendPanel"
#define     InfoLine1         "InfoLine1"
#define     InfoLine2         "InfoLine2"
#define     TrendLabel        "Trend:  M1  M5  M15  M30  H1  H4  D1  W1  MN"
#define     TrendUp           "\233"
#define     TrendDown         "\234"
#define     TrendFlat         "\232"
#define     TrendUnknown      "\251"
#define     StatObjectError   "%s(%d) '%s' の作成に失敗しました。エラー = %d"

次に、9つの時間枠ごとのピクセル位置の配列と、時間枠の配列を定義します。これらはグローバル変数として定義されます。

// グローバル変数の定義
int      TrendPosition[] = { 44, 64, 88, 114, 136, 156, 174, 194, 216 };
int      TrendPeriods[] = { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1 };

私たちのインジケーターのOnInit()関数は、パネルとその中のオブジェクトを作成する関数を呼び出します。また、トレンドを計算するために使用されるバーの数をチェックします。3未満のバーは、あまり意味がありませんので。

//+------------------------------------------------------------------+
//| カスタムインジケーター初期化関数 |
//+------------------------------------------------------------------+
int   OnInit()
{
   // インジケーターパネルのオブジェクトを作成
   if(Create_Panel() && BarCount >= 3)
      return(INIT_SUCCEEDED);
   else
      return(INIT_FAILED);
}

GetTrend()関数がどのように動作するかの詳細には触れませんが、このサイトにはすでに良いドキュメントがあります。ここでは、グラフィカルなDisplayTrend()関数を見てみましょう。

//+------------------------------------------------------------------+
//| すべての時間軸の現在のトレンドを表示 |
//+------------------------------------------------------------------+
void  DisplayTrend(void)
{
   int      i, cntr, Trend, LastTrend;
   string   str;
   
   for(i=1; i<10; i++)
   {
      str = "Trend" + DoubleToStr(i, 0);
      Trend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method);
      if(Trend == FLATTREND)
      {
         // フラットの場合、最後のトレンド方向を探す
         cntr = 1;
         do 
         { 
            LastTrend = (int)GetTrend(TrendPeriods[i-1], BarCount, Method, false, cntr++);
         } while(LastTrend == Trend);
         ObjectSetText(str, TrendFlat, 8, "WingDings", (LastTrend == UPTREND ? Green : Red));
         ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 6);
      }
      else
      {
         ObjectSetText(str, (Trend == UPTREND ? TrendUp : TrendDown), 8, "WingDings", (Trend == UPTREND ? Green : Red));
         ObjectSetInteger(0, str, OBJPROP_YDISTANCE, 5 + (Trend == UPTREND ? 1 : -1));
      }
   }
}

基本的に、TrendPeriods[]配列をループして、各時間枠のトレンド方向に応じてトレンド矢印を設定します。トレンドがフラットの場合は、フラットでない最初の方向を探り、その方向の色でサイド矢印を表示します。

Create_Panel()関数は、OnInit()内で画面の左下にアンカーを付けてオブジェクトを作成します。TrendPosition[]を使用して矢印を適切な位置に配置します。

//+------------------------------------------------------------------+
//| 画面の左下にトレンドパネルを作成 |
//+------------------------------------------------------------------+
bool  Create_Panel(void)
{
   int      i;
   string   str;
   
   // トレンドインジケータウィンドウを作成
   if(ObjectCreate(TrendPanel, OBJ_RECTANGLE_LABEL, 0, 0, 0))
   {
      ObjectSetInteger(0, TrendPanel, OBJPROP_XDISTANCE, 1);
      ObjectSetInteger(0, TrendPanel, OBJPROP_YDISTANCE, 29);
      ObjectSetInteger(0, TrendPanel, OBJPROP_XSIZE, 240);
      ObjectSetInteger(0, TrendPanel, OBJPROP_YSIZE, 26);
      ObjectSetInteger(0, TrendPanel, OBJPROP_BGCOLOR, White);
      ObjectSetInteger(0, TrendPanel, OBJPROP_BORDER_TYPE, 0);
      ObjectSetInteger(0, TrendPanel, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSetInteger(0, TrendPanel, OBJPROP_COLOR, Red);
      ObjectSetInteger(0, TrendPanel, OBJPROP_STYLE, STYLE_SOLID);
      ObjectSetInteger(0, TrendPanel, OBJPROP_WIDTH, 2);
      ObjectSetInteger(0, TrendPanel, OBJPROP_BACK, false);
      ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, TrendPanel, OBJPROP_SELECTED, false);
      ObjectSetInteger(0, TrendPanel, OBJPROP_HIDDEN, true);
      ObjectSetString(0, TrendPanel, OBJPROP_TOOLTIP, "\n");
   }
   else
   { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, TrendPanel, GetLastError()); return(false); }

   if(ObjectCreate(InfoLine1, OBJ_LABEL, 0, 0, 0))
   {
      ObjectSet(InfoLine1, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSet(InfoLine1, OBJPROP_XDISTANCE, 6);
      ObjectSet(InfoLine1, OBJPROP_YDISTANCE, 15);
      ObjectSetInteger(0, InfoLine1, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, InfoLine1, OBJPROP_HIDDEN, true);
      ObjectSetString(0, InfoLine1, OBJPROP_TOOLTIP, "\n");
      ObjectSetText(InfoLine1, TrendLabel, 8, "Arial", Black);
   }
   else
   { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine1, GetLastError()); return(false); }
   
   if(ObjectCreate(InfoLine2, OBJ_LABEL, 0, 0, 0))
   {
      ObjectSet(InfoLine2, OBJPROP_CORNER, CORNER_LEFT_LOWER);
      ObjectSet(InfoLine2, OBJPROP_XDISTANCE, 6);
      ObjectSet(InfoLine2, OBJPROP_YDISTANCE, 5);
      ObjectSetInteger(0, InfoLine2, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, InfoLine2, OBJPROP_HIDDEN, true);
      ObjectSetString(0, InfoLine2, OBJPROP_TOOLTIP, "\n");
      ObjectSetText(InfoLine2, " " + DoubleToStr(BarCount, 0) + " / " + DoubleToStr(Method, 0), 8, "Arial", Black);
   }
   else
   { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, InfoLine2, GetLastError()); return(false); }

   // トレンドオブジェクトを作成し、現在のトレンドを表示    
   for(i=1; i<10; i++)
   {
      str = "Trend" + DoubleToStr(i, 0);
      if(ObjectCreate(str, OBJ_LABEL, 0, 0, 0))
      {
         ObjectSet(str, OBJPROP_CORNER, CORNER_LEFT_LOWER);
         ObjectSet(str, OBJPROP_XDISTANCE, TrendPosition[i-1]);
         ObjectSet(str, OBJPROP_YDISTANCE, 5);
         ObjectSetInteger(0, str, OBJPROP_SELECTABLE, false);
         ObjectSetInteger(0, str, OBJPROP_HIDDEN, true);
         ObjectSetString(0, str, OBJPROP_TOOLTIP, "\n");
      }
      else
      { PrintFormat(StatObjectError, __FUNCTION__, __LINE__, str, GetLastError()); return(false); }
   }

   // 現在のトレンドを表示
   DisplayTrend();
      
   // すべて正常
   return(true);
}

この関数は、すべてのオブジェクトの作成が成功した場合はTRUEを返し、エラーが発生した場合はFALSEを返します。インジケーターは、EXPERTタブにエラーコードとエラーが発生した行番号を表示します。

新しいティックを受信するたびに、トレンドインジケーターを更新する必要があります。これは、start()関数内でDisplayTrend()を呼び出すことで行います。

//+------------------------------------------------------------------+
//| カスタムインジケーター処理関数 |
//+------------------------------------------------------------------+
int   start()
{
   // すべての時間枠の現在のトレンドを表示
   DisplayTrend();   

   return(0);
}

最後に、インジケーターを閉じる際に作成されたすべてのオブジェクトを削除します。

//+------------------------------------------------------------------+
//| デイニシャライゼーション関数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // インジケーターのオブジェクトを削除
   if(ObjectFind(TrendPanel) >= 0) ObjectDelete(TrendPanel);
   if(ObjectFind(InfoLine1) >= 0) ObjectDelete(InfoLine1);
   if(ObjectFind(InfoLine2) >= 0) ObjectDelete(InfoLine2);
   for(int i=1; i<10; i++)
      if(ObjectFind("Trend"+DoubleToStr(i, 0)) >= 0) ObjectDelete("Trend"+DoubleToStr(i, 0));
}

これで、画面の左下に現在のトレンドを表示する素晴らしいインジケーターパネルが完成しました。

楽しんでください!


関連記事

コメント (0)