보조지표 게시글

모든 시간 프레임의 현재 추세를 한눈에 - MetaTrader 4용 지표

첨부파일
15620.zip (2.17 KB, 다운로드 0회)

안녕하세요, 트레이더 여러분! 오늘은 MetaTrader 4에서 모든 시간 프레임의 현재 추세를 한눈에 볼 수 있는 그래픽 지표에 대해 소개해 드리려고 합니다.

이 지표는 기울기 방향 추세 지표를 기반으로 하며, 이미 여러 형태로 공개된 바 있습니다. 하지만 이번에 소개할 지표는 모든 시간 프레임을 한 개의 그래픽 패널에서 동시에 보여주는 유일한 버전입니다.

더 많은 결과를 보고 싶다면 이곳를 클릭해 보세요.

저는 이 지표를 활용하여 모든 시간 프레임을 보여주는 그래픽 패널로 만들었으며, 원래 코드에서 몇 가지 소소한 수정도 진행했습니다. 그 중 하나는 부드럽게 하는 데 사용되는 두 번째 이동 평균 방법을 선택할 수 있도록 한 것입니다. 원래 코드는 두 번째 계산에 선형 가중 평균을 사용했지만, 저의 버전은 사용자가 부드러움의 방법을 선택할 수 있도록 했습니다. 두 가지 계산 모두 선형 가중 평균을 사용할 경우, 지표가 너무 민감해져서 현재 추세에 대해 잘못된 신호를 줄 수 있습니다. 반면에, 단순 평균을 두 번째 평균 방법으로 사용하면 가격이 나아가는 방향을 더 잘 나타내는 추세를 얻을 수 있습니다.

또 다른 변경 사항은 추세의 방향(상승, 하락 또는 보합)뿐만 아니라 그 값도 확인할 수 있게 한 것입니다. 이 내용을 다루는 또 다른 글도 곧 발행할 예정이니 기대해 주세요!

SlopeDirection 

자, 그럼 코드에 대해 간단히 살펴볼까요? 먼저 사용할 객체 이름을 정의합니다. 객체 이름을 인용부호로 묶을 때마다 프로그램에서 공간을 할당하기 때문에, 한 번 정의해 두면 코드에서 공간을 한 번만 사용하게 됩니다.

// 추세 방향 정의
#define     UPTREND           1
#define     DOWNTREND         -1
#define     FLATTREND         0

// 객체 정의
#define     TrendPanel        "TrendPanel"
#define     InfoLine1         "InfoLine1"
#define     InfoLine2         "InfoLine2"
#define     TrendLabel        "추세:  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() 함수는 패널과 그 안의 객체를 생성하는 함수를 호출합니다. 또한 추세를 계산하는 데 사용하는 바(bar)의 수에 대해 간단한 체크를 진행합니다. 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[] 배열을 통해 각 시간 프레임을 반복하면서 각 시간 프레임의 추세 방향에 따라 추세 화살표를 설정합니다. 만약 추세가 보합이라면, 보합이 아닌 첫 번째 방향을 찾아 그 방향의 색깔로 측면 화살표를 표시합니다.

OnInit()의 Create_Panel() 함수는 화면 왼쪽 하단에 고정된 객체를 생성하며 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)