English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기

표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기

MetaTrader 5 | 5 7월 2021, 17:01
65 0
Dmitriy Skub
Dmitriy Skub

소개

이 작업의 주요 목적은 MetaTrader 5 클라이언트 터미널의 차트에 임의의 텍스트 정보를 출력하기 위한 사용자 친화적이고 확장 가능한 도구를 개발하는 것이었습니다. 예를 들어, Expert Advisor의 현재 설정 또는 지정된 간격 동안의 작업 결과, 트레이더가 사용하는 테이블, 가격 값 또는 지표 값 테이블 또는 거래 Expert Advisor의 로그로 표시됩니다. 이 모든 정보는 이 라이브러리를 사용하는 EA 또는 인디케이터 작업 중에 차트에 동적으로 표시 될 수 있습니다.

라이브러리 개발의 기초로 MetaTrader 5 클라이언트 터미널의 표준 라이브러리 클래스 모음이 사용되었습니다. 먼저 이러한 클래스를 고려한 다음 작업을 수행하도록 확장합니다.


그래픽 객체를 위한 표준 클래스

관심있는 클래스 세트는 IncludeInclude\ChartObjects 폴더에 있습니다.

다음 파일입니다.

  • Object.mqh - 그래픽 객체와 관련된 다른 모든 클래스를 만들기 위한 CObject 기본 클래스를 포함합니다.
  • ChartObject.mqh - 또한 CObject에서 파생된 CChartObject 클래스를 포함합니다. 그리고 이 클래스는 기능과 그래픽 객체 일반 데이터 및 방법의 캡슐화를 확장합니다.
  • ChartObjectsTxtControls.mqh - 텍스트를 포함하는 차트에 다양한 그래픽 개체를 표시하기 위한 여러 클래스를 포함합니다. (CChartObjectText 기본 클래스 및 그 하위 클래스: CChartObjectLabel, CChartObjectEdit, and CChartObjectButton.

이 클래스를 더 자세히 고려해봅시다.


CObject:: 기본 클래스

수업 설명은 짧으므로 여기에서 보여드리겠습니다.

class CObject
{
protected:
   CObject          *m_prev;
   CObject          *m_next;

public:
                     CObject();

   CObject          *Prev()                { return(m_prev); }
   void              Prev(CObject *node)   { m_prev=node;    }
   CObject          *Next()                { return(m_next); }
   void              Next(CObject *node)   { m_next=node;    }

   virtual bool      Save(int file_handle) { return(true);   }
   virtual bool      Load(int file_handle) { return(true);   }

   virtual int       Type() const          { return(0);      }

protected:
   virtual int       Compare(const CObject *node,int mode=0) const { return(0); }
};

//+------------------------------------------------------------------+
void CObject::CObject()
{
   m_prev=NULL;
   m_next=NULL;
}

보시다시피 이 클래스에는 범용 데이터 및 메소드만 포함되며 차트의 출력과 직접 관련이 없습니다.

그러나 매우 중요한 속성이 있습니다. 단순 연결 및 이중 연결 목록을 만드는 데 사용할 수 있습니다. CObject::m_prevCObject::m_next CObject *의 데이터 필드에서 제공하는 이러한 기능 읽기/쓰기 유형 및 방법. CObject::m_prev 필드는 이전 목록 요소를 참조하고 CObject::m_next - 다음 것. 목록 구성에 대한 자세한 내용은 추가로 제공됩니다.

또한 CObject* 유형의 두 개체를 비교하는 방법인 CObject:: Compare 방법이 있습니다. 그리고 이는 목록 요소를 정렬 할 때 사용할 수 있습니다. 파일의 데이터 필드를 저장/계산할 수있는 두 가지 유용한 방법이 더 있습니다. 이것들은 CObject::SaveCObject:: Load 메소드입니다. 원하는 기능을 얻으려면 이러한 메소드를 하위 클래스에서 오버로드해야 합니다.

CObject::Type 은 객체 유형 식별 방법입니다. 이 메소드는 다른 유형의 개체를 포함하는 목록을 조작할 때 유용합니다.

CObject 클래스 (및 해당 인스턴스)에는 다음과 같은 기능이 있습니다.

  • 목록 내에서 인접한 요소와 관련된 위치 식별.
  • 개체 유형 식별.
  • 객체 데이터를 저장하고 로드하는 방법입니다.
  • 지정된 개체와 비교하는 방법입니다.with the specified objects.

위에서 설명한 대부분의 메소드는 가상이며 기본 클래스에서 구현되지 않습니다. 기본 클래스에는 물리적 의미가 있는 실제 속성이 없습니다. OOP에서 평소처럼 기능은 하위 클래스에서 구현되어야 합니다.


CChartObject: 그래픽 개체의 기본 클래스

The CChartObjectCObject 클래스의 자손입니다.

이름에서 이것은 추상적인 그래픽 객체를 설명하는 클래스임을 알 수 있습니다. 그럼에도 불구하고 이 추상 객체에는 이미 이러한 속성을 사용하는 몇 가지 물리적 속성과 방법이 포함되어 있습니다. 이러한 속성은 MetaTrader5의 모든 그래픽 개체에 공통적이므로 이 클래스에 배치하는 것이 논리적입니다.

더 자세히 고려해봅시다. 다음 데이터를 사용하여 그래픽 개체를 차트 창에 연결합니다.

protected:
  long       m_chart_id;    // identifier of the chart, which contains 
                               // specified graphic object (0 - current chart)
  int        m_window;      // number of chart sub-window (0 - main window)
  string     m_name;        // unique name of the object on the chart
  int        m_num_points;  // number of points for anchoring the object

실제 그래픽 객체의 속성을 지정하거나 읽기 전에 객체 (클래스 인스턴스)와 접촉해야 합니다. 이는 CChartObject::Attach 메소드에 의해 수행됩니다. 하위 클래스에서는 차트에 그래픽 개체를 만든 직후에 호출됩니다.

bool CChartObject::Attach(long chart_id,string name,int window,int points)
{
  if(ObjectFind(chart_id,name)<0)
  {
    return(false);
  }

  if(chart_id==0) chart_id=ChartID();

  m_chart_id  =chart_id;
  m_window    =window;
  m_name      =name;
  m_num_points=points;

  return(true);
}

먼저 실제 그래픽 객체의 존재를 확인합니다. 존재하는 경우 해당 속성은 CChartObject 클래스 개체의 내부 필드에 저장됩니다. 그런 다음 그래픽 객체 속성 (색상, 위치 등)을 읽고 수정할 수 있습니다.

그래픽 객체 속성의 저장/읽기 방법은 이미 CChartObject::SaveCChartObject::Load방법에 구현되어 있습니다. 저장/읽기의 상위 메소드는 자체 메소드보다 먼저 하위 클래스에서 먼저 호출되어야 합니다.

CChartObject 클래스 (및 해당 인스턴스)에는 기본 속성과 비교하여 다음과 같은 새로운 속성이 있습니다.

  • 클래스 인스턴스를 사용하여 차트에 실제 그래픽 개체를 첨부합니다.
  • 모든 그래픽스 객체의 공통 속성 읽기 및 수정.
  • 차트에서 그래픽 개체 삭제.
  • 차트에서 그래픽 개체의 움직임.


CChartObjectText: 텍스트 그래픽 객체를 위한 클래스

이제 ChartObjectsTxtControls.mqh 파일을 살펴보겠습니다. 여기에서는 텍스트를 포함하는 다양한 그래픽 개체를 차트에 출력하기 위해 개발된 클래스에 대한 설명을 찾을 수 있습니다. 기본 기능을 고려해보겠습니다.

이들의 기본 클래스는 CChartObjectText 클래스입니다. 차트의 텍스트 출력과 관련된 속성 및 메소드를 캡슐화합니다.

다음은 수업 설명입니다.

class CChartObjectText : public CChartObject
{
public:
   double            Angle() const;
   bool              Angle(double angle);
   string            Font() const;
   bool              Font(string font);
   int               FontSize() const;
   bool              FontSize(int size);
   ENUM_ANCHOR_POINT  Anchor() const;
   bool              Anchor(ENUM_ANCHOR_POINT anchor);

   bool              Create(long chart_id,string name,int window,datetime time,double price);

   virtual int       Type() const { return(OBJ_TEXT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

CChartObject와 비교하여, 텍스트 그래픽 개체의 속성을 읽고 수정하는 데 메소드 (차트의 텍스트 방향 각도, 텍스트의 글꼴 이름, 글꼴 크기 및 그래픽 목표의 좌표)를 포함합니다. 새로운 메소드가 CChartObjectText:: Create로 등장하여 차트에 OBJ_TEXT 유형의 실제 그래픽 개체를 만들 수 있습니다.

구현:

bool CChartObjectText::Create(long chart_id,string name,int window,datetime time,double price)
{
  bool result = ObjectCreate( chart_id, name, OBJ_TEXT, window, time, price );
  if(result)
  {
    result &= Attach(chart_id, name, window, 1 );
  }

  return(result);
}

그래픽 개체를 성공적으로 생성 한 경우 (ObjectCreate 메소드가 true를 반환 함) CChartObject:: Attach 메소드가 호출되며, 이는 앞서 살펴보았습니다.

따라서 상위 클래스와 비교하여 CChartObjectText에는 새로운 기능이 포함되어 있습니다.

  • 텍스트 그래픽 개체의 속성 읽기 및 수정.
  • 차트에 OBJ_TEXT 유형의 실제 그래픽 개체를 만듭니다.


CChartObjectLabel: 텍스트 레이블" 그래픽 개체에 대한 클래스

표준 클래스 계층 구조의 다음 클래스는 CChartObjectLabel 클래스입니다. 차트에 OBJ_LABEL 유형 (텍스트 레이블)의 그래픽 개체를 생성할 수 있습니다.

다음은 이 클래스에 대한 설명입니다.

class CChartObjectLabel : public CChartObjectText
{
public:
   int               X_Distance() const;
   bool              X_Distance(int X);
   int               Y_Distance() const;
   bool              Y_Distance(int Y);
   int               X_Size() const;
   int               Y_Size() const;
   ENUM_BASE_CORNER  Corner() const;
   bool              Corner(ENUM_BASE_CORNER corner);

   bool              Time(datetime time) { return(false);  }
   bool              Price(double price) { return(false);  }

   bool              Create(long chart_id,string name,int window,int X,int Y);

   virtual int       Type() const        { return(OBJ_LABEL); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

여기서는 OBJ_TEXT 유형의 그래픽 개체와 OBJ_LABEL 유형의 개체 간의 차이점을 확인해야 합니다.

첫 번째는 가격 차트 (가격-시간 좌표) 또는 하위 창의 차트에 바인딩하는 것입니다. 두 번째는 창 또는 차트의 하위 창 (픽셀)의 차트 좌표에 바인딩하는 것입니다.

따라서 OBJ_TEXT 유형의 개체는 스크롤 할 때 차트와 함께 이동하고 OBJ_LABEL 유형의 개체는 스크롤 할 때 고정된 상태로 유지됩니다. 따라서 taks에 따라 특정 유형의 그래픽 텍스트 개체를 선택해야 합니다.

상위 클래스와 비교하여 CChartObjectLabel 클래스에는 다음과 같은 특징이 있습니다.

  • 차트 좌표는 그래픽 개체를 찾을 때 사용됩니다.
  • 앵커 모서리를 읽고 수정할 수 있습니다. 실제로 이것은 그래프 창의 네 모서리 중 하나에 좌표의 시작을 할당합니다.
  • 클라이언트 터미널의 차트에 OBJ_LABEL 유형의 실제 그래픽 개체를 생성합니다.


CChartObjectEdit: a Class for "입력 필드" 그래픽 개체에 대한 클래스

계층 구조의 다음 클래스는 CChartObjectEdit 클래스입니다. OBJ_EDIT 유형 (입력 필드)의 그래픽 객체를 생성하기 위한 클래스입니다.

이 유형의 객체는 차트 좌표 (픽셀)를 사용하여 OBJ_LABEL 유형의 객체와 동일한 방식으로 바인딩됩니다. 표준 클래스와 동일한 CChartObjectLabel 클래스에서 파생하는 것이 논리적입니다.

class CChartObjectEdit : public CChartObjectLabel
{
public:
   bool              X_Size(int X);
   bool              Y_Size(int Y);
   color             BackColor() const;
   bool              BackColor(color new_color);
   bool              ReadOnly() const;
   bool              ReadOnly(bool flag);

   bool              Angle(double angle) { return(false);    }

   bool              Create(long chart_id,string name,int window,int X,int Y,int sizeX,int sizeY);

   virtual int       Type() const        { return(OBJ_EDIT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

텍스트 레이블에서 OBJ_EDIT 유형의 입력 필드 간의 차이점은 다음과 같습니다.

  • 입력 필드에는 차트의 그래픽 개체 크기를 제한하는 너비 및 높이 속성 (화면 픽셀로 지정됨)이 있습니다. 전체 텍스트를 볼 수 있도록 텍스트 레이블의 크기가 자동으로 조정됩니다.
  • 텍스트 수정을 활성화/비활성화하는 방법이 있습니다 - CChartObjectEdit:: ReadOnly.
  • 그래픽 객체가 차지하는 영역의 배경색을 변경하는 메소드가 추가되었습니다.
  • 개체가 표시되는 각도를 변경할 수 없습니다. 입력 필드는 가로 방향으로만 표시 할 수 있습니다.
  • 차트에 OBJ_EDIT 유형의 실제 그래픽 개체를 만들 수 있습니다.


CChartObjectButton: "Button" 그래픽 객체에 대한 클래스

텍스트 그래픽 개체 계층 구조의 또 다른 클래스는 CChartObjectButton 클래스입니다. 이 개체를 버튼이라고 하며, 눌러진 버튼의 형태로 차트에 컨트롤 요소를 생성하도록 개발되었습니다. 이 클래스는 CChartObjectEdit 클래스의 자손이며 그 기능을 상속합니다.

class CChartObjectButton : public CChartObjectEdit
{
public:
  bool             State() const;
  bool             State(bool state);

  virtual int       Type() const { return(OBJ_BUTTON); }

  virtual bool      Save(int file_handle);
  virtual bool      Load(int file_handle);
};

OBJ_BUTTON 유형의 버튼과 입력 필드의 차이점은 다음과 같습니다.

  • Windows 대화 상자에서 사용되는 것과 유사한 눌려진 버튼처럼 보입니다.
  • 버튼 상태 (눌림/누름) 읽기/수정을 위한 새로운 메소드가 있습니다-CChartObjectButton::State.
  • 차트에 OBJ_BUTTON 유형의 실제 그래픽 개체를 만들 수 있습니다.


그래픽 텍스트 개체에 대한 표준 클래스의 전체 구조

표준 라이브러리 클래스의 구조(계층)는 다음과 같이 요약할 수 있습니다.

표준 클래스의 전체 구조

그림 1. 표준 클래스의 전체 구조

CObject 클래스는 다른 표준 클래스의 기본 클래스입니다. 예를 들어 CList 클래스는 목록과 다른 클래스를 처리합니다.


표준 라이브러리 클래스의 기능 확장

차트에 텍스트 그래픽 개체를 생성하기 위해 개발된 표준 클래스의 계층 구조에 대해 간략하게 설명했습니다. 이제 새 클래스로 이 계층을 확장해보겠습니다. 우선 구현에 필요한 기능을 결정해야 합니다. 요구 사항을 공식화합시다. 텍스트 정보의 출력을 다루기 때문에 이 정보를 다음과 같은 구조화된 형식으로 제공하는 것이 논리적입니다.

표제 정보 텍스트


이러한 텍스트 정보 표현 구조는 대부분의 간단한 경우에 적합합니다.

예를 들어 기호 매개 변수의 표시기는 다음과 같을 수 있습니다.

텍스트 정보의 구조화된 디스플레이의 예

그림 2. 텍스트 정보의 구조화된 디스플레이의 예

위에서 제안한 구조의 6개의 정보 필드를 사용합니다. 구조의 일부 요소가 없을 수 있습니다. 예를 들어 그림 2에서는 맨 위 필드의 타일이 표시되지 않습니다. 다른 필드에는 제목과 텍스트가 포함됩니다. 이 표시기는 이 기사에 첨부된 PricelInfo.mq5 파일에서 찾을 수 있습니다.


그래픽 개체의 위치

두 번째로 고려해야 할 사항은 그래픽 텍스트 개체를 차트에 배치하는 방법입니다. 화면 픽셀에서 좌표를 지정하는 채택된 방법을 사용하면 차트의 임의 위치에 개체를 배치 할 수 있습니다.

화면의 모든 좌표를 계산해야 하기 때문에 차트의 여러 위치에 여러 텍스트 개체를 수용해야 하는 경우 실제로 불편합니다. 또한 차트 크기를 변경하는 경우 화면에서 개체의 상대 포지션이 변경되지 않았는지 확인하기 위해 모든 픽셀 좌표를 다시 계산해야 합니다.

차트 창을 같은 크기의 직사각형 (필드)으로 추적하고 각 직사각형에 수평 및 수직 좌표를 할당하면 화면 해상도와 독립적인 범용 위치 지정 시스템을 얻을 수 있습니다.

그래픽 텍스트 객체를 생성 할 때 사용자는 수직 및 수평 방향의 최대 필드 수와 매개 변수와 같은 필드의 객체 좌표를 설정할 수 있습니다. 적절한 클래스에 포함된 기능은 화면 해상도를 변경할 때 그래픽 개체의 좌표를 자동으로 조정합니다. 이러한 방식으로 좌표가 한 번 지정되고 추가 조정이 필요하지 않습니다.


고유한 개체 이름 자동 생성

해결해야 할 다음 질문은 그래픽 텍스트 개체 이름의 자동 생성입니다. 생성 방법에 대한 주요 요구 사항은 주어진 창 내에서 고유한 이름을 얻는 것입니다. 이렇게 하면 중복되지 않은 이름을 발명할 필요없이 화면에서 충분한 수의 개체를 찾을 수 있습니다.

이름 (필드로 구성된 문자열)을 생성하기 위해 다음과 같은 방법을 제안합니다.

날짜 시간
밀리 초 수


날짜와 시간을 포함하는 문자열 부분을 가져오려면 다음 호출을 사용하십시오.

TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);

밀리 초 수를 얻으려면 다음 호출을 사용하십시오.

DoubleToString(GetTickCount(), 0);

하지만 시간을 밀리 초 이내로 측정하더라도 GetTickCount () 함수를 두 번 이상 연속 호출하면 동일한 값을 얻을 수 있습니다. 이는 운영 체제 및 프로세서의 내부 타이머의 불연속성 제한 때문입니다. 따라서 이러한 상황을 감지하기 위한 추가 조치가 필요합니다.

제안된 방법은 다음과 같은 기능으로 구현됩니다.

string GetUniqName()
{
  static uint prev_count = 0;

  uint count = GetTickCount();
  while(1)
  {
    if(prev_count == UINT_MAX)
    {
      prev_count = 0;
    }
    if(count <= prev_count)
    {
      prev_count++;
      count = prev_count;
    }
    else
    {
      prev_count = count;
    }

//  Verify that there is no object already existing with such a name:
    string name = TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" "+DoubleToString(count, 0);
    if(ObjectFind(0, name) < 0)
    {
      return(name);
    }
  }

  return(NULL);
}

이 방법의 한계: 초당 4294967295 (UINT_MAX)의 고유 이름 생성. 분명히 이것은 실제로 충분할 것입니다. 혹시라도 동일한 이름을 가진 그래픽 개체의 존재에 대한 추가 확인이 있습니다.


정보 구조의 제목 표시 - 클래스 TTitleDisplay

터미널 화면에 제목을 표시하는 클래스는 다음과 같습니다.

class TTitleDisplay : public CChartObjectLabel
{
protected:
  long    chart_id;
  int     sub_window;
  long    chart_width;       // width of the chart in pixels
  long    chart_height;      // height of the chart graph in pixels
  long    chart_width_step;  // step of the coordinates grid in the horizontal direction
  long    chart_height_step; // step of the coordinates grid in the vertical direction
  int     columns_number;    // number of columns
  int     lines_number;      // number of lines
  int     curr_column;
  int     curr_row;

protected:
  void    SetParams(long chart_id, int window, int cols, int lines);// specify the object's parameters

protected:
  string  GetUniqName();    // get a unique name
  bool    Create(long chart_id, int window, int cols, int lines, int col, int row);
  void    RecalcAndRedraw();// recount the coordinates and re-draw

        
public:
  void    TTitleDisplay();  // constructor
  void    ~TTitleDisplay(); // destructor
};

그래픽 텍스트 개체를 만드는 기본 방법:

bool Create(long chart_id, int window, int _cols, int _lines, int _col, int _row);

입력 매개 변수 할당은 다음과 같습니다.

  • chart_id - window identifier (0 - main window);
  • window - 하위 창의 번호 (0 - 기본);
  • cols - 가로로 그래픽 텍스트 개체의 최대 수 (열 수);
  • lines - 세로로 그래픽 텍스트 개체의 최대 수 (행 수);
  • col - 그래픽 객체의 수평 좌표 (0에서 cols - 1까지 다양함);
  • row - 그래픽 객체의 수직 좌표 (0에서 lines - 1 까지 다양함),;

TTitleDisplay::SetParams 메소드는 화면의 위치와 관련된 개체의 매개 변수를 계산합니다.

구현은 다음과 같습니다.

void TTitleDisplay::SetParams(long _chart_id, int _window, int _cols, int _lines)
{
  this.chart_id = _chart_id;
  this.sub_window = _window;
  this.columns_number = _cols;
  this.lines_number = _lines;

//  Specify the size of the window in pixels:
  this.chart_width = GetSystemMetrics(SM_CXFULLSCREEN);
  this.chart_height = GetSystemMetrics(SM_CYFULLSCREEN);

//  Calculate the step of the coordinates grid:
  this.chart_width_step = this.chart_width/_cols;
  this.chart_height_step = this.chart_height/_lines;
}

여기서는 GetSystemMetrics WinAPI 함수 호출을 사용하여 현재 디스플레이 설정을 얻었습니다. 이 함수는 user32.dll Windows 시스템 라이브러리에서 가져옵니다.

정보 텍스트 TFieldDisplay를 만드는 클래스도 비슷하게 구성됩니다. 자세한 내용은 이 기사에 첨부된 TextDisplay.mqh 라이브러리에서 찾을 수 있습니다.


CList 클래스: 목록의 개체 조작

이제 계획을 실현하는데 필요한 또 다른 표준 클래스를 고려해보겠습니다. 이 클래스를 사용하면 개체를 목록으로 그룹화 할 수 있습니다. Include\Arrays\List.mqh 파일에 있습니다. 이 파일은 이 기사의 앞부분에서 고려한 CObject 기본 클래스의 자손인 표준 CList 클래스의 설명과 구현을 제공합니다. 여기에는 목록의 개체를 조작하기 위한 일련의 메소드가 포함되어 있습니다 (목록에 추가, 목록에서 제거, 목록의 임의 요소에 액세스, 목록 지우기).

기본 방법을 고려해 보겠습니다.

  • 목록에 추가:
   int Add(CObject *new_node);
   int Insert(CObject *new_node,int index);

목록에 새 항목을 추가하는 방법은 두 가지입니다. 첫 번째 CList::Add를 사용하면 새 요소 new_node를 목록 끝에 추가할 수 있습니다. 두 번째 CList::Insert를 사용하면 새 요소 new_node 를 임의의 위치에 삽입 할 수 있습니다 (index에 의해 지정됨). )이 목록에 있습니다.

  • 목록에서 제거:
   bool  Delete(int index);

CList::Delete 메소드를 사용하면 지정된 색인이 있는 요소를 목록에서 제거할 수 있습니다. 한편, 목록에서 항목을 제거하는 것 외에도 CObject 유형의 요소가 차지하는 메모리가 해제되고 유형 CObject의 요소가 차지하는 메모리가 해제됩니다. 즉, 개체가 "물리적으로" 삭제됩니다.

  • 목록의 임의 요소에 대한 액세스:
   int       IndexOf(CObject* node);
   CObject*  GetNodeAtIndex(int index);
   CObject*  GetFirstNode();
   CObject*  GetPrevNode();
   CObject*  GetNextNode();
   CObject*  GetLastNode();

CList:: IndexOf 메소드는 목록에있는 특정 요소의 인덱스를 반환합니다. 인덱스 번호 매기기는 0부터 시작합니다. 첫 번째 요소의 인덱스는 0입니다. 이 메소드는 요소의 포인터로 인덱스를 반환하는 역 연산을 수행합니다. 요소가 목록에 없으면 -1을 반환합니다.

목록을 탐색하기위한 네 가지 추가 메소드 CList:: GetFirstNode 는 이전 요소인 CList:: GetNextNode 를 반환합니다. 다음 항목을 반환하고 CList:: GetLastNode는 목록의 마지막 요소를 반환합니다.

  • 목록 지우기:
   void  Clear();

CList::Clear 메소드를 사용하면 목록에서 모든 요소를 ​​제거할 수 있으며 개체가 차지하는 메모리를 해제할 수도 있습니다.

이것들은 CList 클래스의 기본 메소드이며 나머지는 MQL5 참조에 설명되어 있습니다.


TableDisplay Class: 차트에 텍스트를 표시하기 위한 테이블 만들기

그래서 우리는 계획의 실현에 필요한 모든 것을 가지고 있습니다. 다음은 임의 크기의 테이블에서 텍스트 그래픽 개체를 구성 할 수있는 간단한 클래스입니다.

class TableDisplay : public CList
{
protected:
  long  chart_id;
  int   sub_window;

public:
  void  SetParams(long _chart_id, int _window, ENUM_BASE_CORNER _corner = CORNER_LEFT_UPPER);
  int   AddTitleObject(int _cols, int _lines, int _col, int _row, 
                      string _title, color _color, string _fontname = "Arial", int _fontsize = 8);
  int   AddFieldObject(int _cols, int _lines, int _col, int _row, 
                          color _color, string _fontname = "Arial", int _fontsize = 8);
  bool  SetColor(int _index, color _color);
  bool  SetFont(int _index, string _fontname, int _fontsize);
  bool  SetText(int _index, string _text);

public:
  void  TableDisplay();
  void  ~TableDisplay();
};

그래픽 개체를 테이블에 추가하기 전에 매개 변수 (문자 식별자, 하위 창 색인 및 앵커 포인트)를 설정해야 합니다. 이는 TableDisplay:: SetParams 메소드를 호출하여 수행됩니다. 그런 다음 원하는 수의 제목과 텍스트 필드를 테이블에 추가할 수 있습니다.

우리가 개발 한 라이브러리의 전체 텍스트는이 기사에 첨부된 TextDisplay.mqh 파일에서 찾을 수 있습니다.


3. Market Watch 생성의 예

여러 기호의 값을 표시기 형태로 표시하기 위한 표를 생성하는 예를 살펴 보겠습니다.

대략 다음과 같아야 합니다.

스크린 테이블의 예

Рисунок 3. 스크린 테이블의 예

  • 1 단계 - 라이브러리 포함 (인디케이터의 소스 코드에):
#include  <TextDisplay.mqh>
  • 2 단계 - 제목의 이름과 좌표로 배열 만들기:
#define  NUMBER  8
//---------------------------------------------------------------------
string  names[NUMBER]   = {"EURUSD", "GBPUSD", "AUDUSD", "NZDUSD", "USDCHF", "USDCAD", "USDJPY", "EURJPY"};
int     coord_y[NUMBER] = {2,        3,        4,        5,        6,      7,        8,       9};
좌표는 0부터 시작됩니다.
  • 3 단계 - 표시된 모든 텍스트 개체를 저장하기 위해 TableDisplay 유형의 테이블 개체를 만듭니다.
TableDisplay  Table1;
  • 4 단계 - 개체 제목 및 개체 정보 필드를 테이블에 추가합니다.
int OnInit()
{
//  Creating a table
  Table1.SetParams(0, 0);

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 3, coord_y[i], Yellow);
  }

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddTitleObject(40, 40, 1, coord_y[i], names[i]+":", White);
  }

  ChartRedraw(0);
  EventSetTimer(1);

  return(0);
}

OnInit 이벤트 핸들러에서하는 것이 가장 좋습니다. 먼저 >TableDisplay:: AddFieldObject 메소드를 사용하여 정보 필드를 추가합니다. 그런 다음 TableDisplay:: AddTitleObject 메소드를 사용하여 제목을 추가합니다.

추가는 두 가지 이유로 별도의 주기로 구현됩니다. 첫째, 일반적으로 제목의 수가 정보 필드의 수와 일치하지 않을 수 있으며, 둘째, 업데이트된 정보 필드에 대한 액세스는 한 행에 인덱싱될 때(이 경우 0부터 값 NUMBER - 1까지) 보다 쉽게 구성할 수 있습니다.

  • 5 단계 - 코드를 추가하여 동적 정보 업데이트:

이 경우 동적 정보 업데이트는 Timer 이벤트 핸들러에 의해 구성됩니다. 이 이벤트의 OnTimer 핸들러는 주어진 상품에 대한 가격 값을 수신하고 차트에 이러한 값을 표시해야 합니다.

이 텍스트는 다음과 같습니다.

//---------------------------------------------------------------------
double    rates[NUMBER];
datetime  times[NUMBER];
MqlTick   tick;
//---------------------------------------------------------------------
// OnTimer event handler
//---------------------------------------------------------------------
void OnTimer()
{
  for(int i=0; i<NUMBER; i++)
  {
//  Obtain the price values:
    ResetLastError();
    if(SymbolInfoTick(names[i], tick) != true)
    {
      Table1.SetText(i,"Err "+DoubleToString(GetLastError(),0));
      Table1.SetColor(i,Yellow);
      continue;
    }

    if(tick.time>times[i])
    {
       Table1.SetText(i, DoubleToString(tick.bid, (int)(SymbolInfoInteger(names[i], SYMBOL_DIGITS))));

       if(tick.bid>rates[i])
       {
         Table1.SetColor(i, Lime);
       }
       else if(tick.bid<rates[i])
       {
         Table1.SetColor(i, Red);
       }
       else
       {
         Table1.SetColor(i, Yellow);
       }
       rates[i] = tick.bid;
       times[i] = tick.time;
    }
  }

  ChartRedraw(0);
}

주기가 시작될 때 지정된 기기에 대한 틱 데이터를 읽은 다음 데이터의 관련성을 확인합니다. 틱 시간이 이전과 변경된 경우 데이터가 관련이 없다고 간주합니다. 또한 이전 틱과 관련하여 견적의 가치를 분석합니다.

현재 가격이 이전 가격보다 큰 경우 정보 필드에 녹색을 지정합니다. 적으면 빨간색보다 같고 같으면 노란색입니다. 주기가 끝날 때 OnTimer 이벤트 핸들러 호출시 분석을 위해 가격의 현재 값과 틱 시간이 저장됩니다.

일반적으로 동적 정보를 업데이트하는 코드는 작업에 따라 다릅니다. 기본적으로 사용자는 코드의 이 부분만 구현하면 됩니다. 그림 2에서 가격 오른쪽에 스프레드를 추가하기로 결정했다고 가정합니다. 이것이 어떻게 수행 될 수 있는지 봅시다.

필요한 것은 테이블에 데이터 필드를 추가하는 것입니다.

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 5, coord_y[i], Yellow);
  }

스프레드 값을 업데이트하는 코드를 OnTimer 이벤트 핸들러에 포함합니다.

  Table1.SetText(i+NUMBER, DoubleToString((tick.ask-tick.bid)/SymbolInfoDouble(names[i], SYMBOL_POINT), 0));

결과적으로 다음과 같은 그림을 얻습니다.

스프레드가 있는 가격

그림 4. 스프레드가 있는 가격

스프레드의 인덱스 필드는 값 NUMBER (i가 0 인 경우)에서 시작합니다.

  • 6 단계 - 생성된 개체 제거:
void OnDeinit(const int _reason)
{
  EventKillTimer();

//  Removing the elements of display:
  Table1.Clear();
}

여기서 타이머와 테이블이 지워집니다. 한편, 모든 개체도 메모리에서 해제됩니다.

이 표시기의 전체 텍스트는 이 기사에 첨부된 PriceList.mq5 파일에서 찾을 수 있습니다. 첨부 파일에는 스프레드를 표시하는 표시기의 "개선된" 버전이 포함되어 있습니다. 제목 색상 및 차트 내의 테이블 위치 지정을 위한 여러 외부 매개 변수가 있습니다.


결론

첨부된 MarketWatch.mq5 (및 포함된 MarketWatch.mqh)에는 거래 상품의 기본 매개 변수를 요약 테이블 형식으로 표시하기 위한 표시기가 포함되어 있습니다. 각 기호에 대해 그림 2와 유사한 정보가 표시됩니다.

또한 지정된 시간 간격 동안 가격 변동 비율을 표시합니다. 기호 집합 (16 개 이하) 및 시간 간격은 세미콜론으로 구분된 요소가있는 문자열로 지정됩니다. 이 지표의 작업 결과는 그림 5에 나와 있습니다.

시장 검토 지표

그림 5. Market Watch Indicator

MetaTrader 5 클라이언트 터미널의 차트에 텍스트 정보를 표시하는 한 가지 방법을 고려했습니다.

클라이언트 터미널과 함께 제공되는 표준 라이브러리 클래스를 사용하여 2차원 테이블 형식으로 텍스트 정보를 표현하는 새로운 기능을 상당히 쉽고 빠르게 개발할 수있었습니다. MQL5 언어의 객체 지향 접근 방식은 매우 강력합니다.


MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/179

파일 첨부됨 |
marketwatch.mq5 (11.51 KB)
priceinfo.mq5 (8.76 KB)
pricelist.mq5 (7.29 KB)
textdisplay.mqh (15.54 KB)
marketwatch.mqh (9.48 KB)
추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈 추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈
이 문서는 가장 단순한 클래스와 단일 유형 클래스로 압축된 평균화의 전통적이고 특이한 알고리즘에 대해 설명합니다. 거의 모든 지표 개발에서 보편적으로 사용하기 위한 것입니다. 제안된 클래스가 사용자 지정 및 기술 지표의 '대량' 호출에 대한 좋은 대안이 되기를 바랍니다.
퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예 퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예
이 글은 금융 시장 분석을위한 fuzzy logic 개념의 실제 적용에 전념합니다. Envelopes 인디케이터를 기반으로 두 가지 퍼지 규칙을 기반으로 신호를 생성하는 인디케이터의 예를 제안합니다. 개발된 인디케이터는 여러 인디케이터 버퍼를 사용함: 계산용 버퍼 7 개, 차트 디스플레이 용 버퍼 5 개, 색상 버퍼 2 개.
스펙트럼 분석기 구축 스펙트럼 분석기 구축
이 글은 독자들이 MQL5 언어의 그래픽 객체를 사용하는 가능한 변형에 대해 알게 하기 위한 것입니다. 그래픽 개체를 사용하여 간단한 스펙트럼 분석기를 관리하는 패널을 구현하는 표시기를 분석합니다. 이 기사는 MQL5의 기본 사항에 대해 잘 알고 있는 독자를 대상으로 합니다.
MQL5 마법사: 프로그래밍 없이 Expert Advisor 만들기 MQL5 마법사: 프로그래밍 없이 Expert Advisor 만들기
프로그래밍에 시간을 낭비하지 않고 거래 전략을 시도하고 싶습니까? MQL5 마법사에서 거래 신호 유형을 선택하고 추적 포지션 및 자금 관리 모듈을 추가하면 작업이 완료됩니다! 고유한 모듈 구현을 생성하거나 작업 서비스를 통해 주문하고 새 모듈을 기존 모듈과 결합합니다.