English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
가격 히스토그램 (시장 프로필) 및 MQL5에서 구현

가격 히스토그램 (시장 프로필) 및 MQL5에서 구현

MetaTrader 5 | 5 7월 2021, 12:59
81 0
Dmitry Voronkov
Dmitry Voronkov

"시장 프로필은 시장의 맥락에서 이러한 내부 논리를 제공하려고 합니다.
가격만으로 시작하는 분석 방법입니다
구문없이
단어처럼 참가자에게 정보를 전달하지 않습니다.또는 문맥은 의미가 없을 수 있습니다. 볼륨은 직접 표현의 필수 부분입니다.
시장의 언어를 이해하고 시장의 언어를 이해합니다."
로빈 메시

소개

오래 전 잡지 구독을 통해 러시아 저널 "Valutny Spekulant"(현재 "Active Trader"라고 함)에서 "시장 프로필 및 시장 언어 이해"(2002 년 10 월) 기사를 발견했습니다. 원본 기사는 "기술 분석의 새로운 생각: 마스터의 거래 모델"에 게재되었습니다.

시장 프로필은 정말 뛰어난 사상가인 Peter Steidlmayer가 개발했습니다. 그는 시장의 자연스러운 표현 (볼륨)을 발견하고 읽을 수 있는 방식 (종형 곡선)으로 구성하여 시장에서 생성된 객관적인 정보를 시장 참여자가 액세스 할 수 있도록 했습니다. Steidlmayer는 완전히 다른 모델 세트로 이어지는 "수평" 및 "수직" 시장 움직임에 대한 정보의 대체 표현을 사용할 것을 제안했습니다. 그는 시장의 근본적인 맥박이나 균형과 불균형의 순환이라는 근본적인 패턴이 있다고 가정했습니다.

Market Profile은 수직적 시장을 통한 수평적 시장 움직임을 측정합니다. 이것을 '불평형'을 통해 '평형'이라고합시다. 이 관계는 시장의 기본 구성 원칙입니다. 트레이더의 전체 거래 스타일은 시장이 있는 균형 / 불균형 주기의 어느 부분에 있는지에 따라 변경 될 수 있습니다. 시장 프로필은 시장이 균형에서 불균형으로 이동하는 시기와 이동의 크기를 결정할 수 있습니다.

Market Profile의 두 가지 기본 개념은 다음과 같습니다.

  1. 시장은 경매이고 수요와 공급이 어느 정도 같은 가격대 방향으로 움직입니다.
  2. 시장에는 수평적 활동과 수직적 활동의 두 단계가 있습니다. 시장은 공급과 수요가 같지 않거나 불균형에 있을 때 수직으로 움직이고, 균형이나 균형에 있을 때 수평으로 움직입니다.

아래 차트의 시장 프로필을 사용하여 표시된 균형 시장은 차트의 방향으로 인해 90도 회전된 거의 완벽한 종 모양의 곡선을 형성하는 경향이 있습니다.

 

그림 1. 균형 시장의 시장 프로필

추세, 비 균형 시장도 종 모양의 곡선을 형성하지만 그 중심은 위아래로 이동합니다. 가격 움직임과 시장 참여자의 신뢰에 따라 두 개의 종을 형성하는 다른 구성도 가능합니다.

그림 2. 불균형 (추세) 시장의 시장 프로필

일일 프로필 모양을 사용하여 시장의 균형/불균형 수준을 결정하는 것이 유용할 수 있습니다. 다양한 시장 참여자 간의 변화를 이해하는 데 출발점을 제공하기 때문입니다.

균형에서 불균형으로의 전환이 임박했을 때 가장 큰 혜택을 주는 거래 기회가 나타납니다. 또한 해당 거래 기회를 식별하고 해당 변화의 잠재적 규모를 정확하게 추정 할 수 있다면 해당 거래의 품질과 필요한 시간을 추정 할 수 있습니다.

이 기사에서는 가격과 시간 사이의 현실성을 기반으로 하는 소위 가격 히스토그램인 시장 프로필의 단순화된 버전을 그리는 코드를 고려할 것입니다.

이 도구를 사용하는 방법론의 예는 http://www.enthios.com/에서 찾을 수 있습니다. 여기에서 트레이더 그룹은 1998 년부터 가격 히스토그램을 연구했습니다. Enthios Universal 전략과 그 사용 예도 거기에서 찾을 수 있습니다.

1. 가격 히스토그램

가격 히스토그램은 매우 신뢰할 수 있는 도구입니다. 약간 직관적이지만 매우 효과적입니다. 가격 히스토그램은 단순히 시장에서 "가장 편리한" 거래 지점을 보여줍니다. 이는 시장이 미리 방향을 바꿀 수 있는 지점을 보여주기 때문에 선행 인디케이터입니다. 이동 평균이나 오실레이터와 같은 인디케이터는 저항과 지지의 정확한 지점을 지정할 수 없으며 시장이 과매 수인지 과매도인지 여부만 보여줄 수 있습니다.

일반적으로 가격 히스토그램 (또는 시장 프로필)은 30 분 동안 적용됩니다. 하루 동안의 시장 활동을 연구하는 가격 차트. 저는 5 분을 선호합니다. 주식 시장 차트 및 15-30 분. FOREX 용 차트.

2. 제어 지점

위의 그림에서 최대 시간 동안 시장이 거래된 수준을 볼 수 있습니다. 히스토그램에서 가장 긴 선으로 윤곽이 그려져 있습니다. 이를 통제 지점 또는 POC라고 합니다. 때때로 그림에서 볼 수 있듯이 히스토그램에는 두 개의 상단이 있으며 그 중 하나는 약간 더 낮습니다. 이 경우 인디케이터에 POC가 하나만 표시되는 것을 볼 수 있지만 실제로는 둘 중 두 개가 있으므로 이를 고려해야 합니다.

또한 히스토그램에서 범위의 백분율 수준은 보조 POC 수준이라고 하는 추가 수준을 만듭니다.

그림 3. 통제 지점

POC는 무엇을 보여줍니까? 대부분의 트레이더가 기억하는 가격. 더 긴 시장이 이 가격으로 거래되고, 더 긴 시장이 그것을 기억합니다.

심리적으로 POC는 매력의 중심 역할을 합니다.

다음 차트는 며칠 전에 일어난 일을 보여줍니다. 가격 히스토그램의 힘을 잘 보여줍니다.

Fig 4. 통제 지점은 절대적인 것이 아닙니다. 그것은 무역의 범위를 보여줍니다

통제 지점은 절대적인 것이 아닙니다. 거래 범위를 나타냅니다. 따라서 거래자는 시장이 POC에 접근할 때 행동할 준비가 되어 있어야 합니다. 과거 관찰을 사용하여 주문을 최적화 하는 데 도움이 됩니다.

그림 4를 살펴봅시다. 2009년 12월 29일의 POC 가격은 68.87입니다. 히스토그램과 POC 라인이 없어도 시장이 거의 하루 종일 68.82 ~ 68.96 범위 내에 있었던 것은 분명합니다. 시장은 하루가 끝나고 POC 아래 5 포인트에서 마감되었습니다. 이튿날 격차를 줄인 채 시장 개방을 일으켰습니다.

시장이 상승할지 하락할지 예측할 수 없다는 것을 이해하는 것이 중요합니다. 시장이 POC 라인과 히스토그램 라인의 최대 누적으로 돌아갈 것이라고 가정 할 수 있습니다. 그러나 가격이 POC에 닿으면 어떻게 될까요? 땅에 떨어지는 탄성 물체에서 일어나는 것과 똑같은 일이 다시 뛰어 오를 것입니다. 테니스 공이 라켓으로 뒤로 치는 것처럼 빠르게 발생하면 가격은 매우 빠르게 초기 수준으로 돌아갑니다.

2009년 12월 30일 개장 후 우리는 그것이 격차임을 확인하고 시장이 전날의 POC에 닿았다가 곧 공개 가격으로 돌아와 최소값을 업데이트 했습니다.

POC는 절대적으로 정확하지 않습니다 (경험이 있는 거래자는 가격이 최대, 최소 또는 집중 범위에 도달 할 때 명확한 저항 수준이 없다는 것을 알고 있음). 이 시점에서 일어나는 일은 시장 참여자에 따라 다릅니다. 집단적 욕구 (예: 뉴스 간행물)가 일치하면 시장은 POC를 통과하지만 드물고 거래 시스템을 개발하는 데 사용할 수 있습니다.

2009년 12월 31일의 시장 행동이 동일하다는 점에 유의하십시오. 가격이 POC에 닿자 구매자는 판매자에게 양보했습니다.

3. Virgin Point of Control

Virgin POC (Virgin Point of Control)는 다음 날 가격에 도달하지 못한 수준입니다.

논리는 간단합니다. 위에서 설명한 것처럼 POC는 시장의 매력 포인트입니다. 가격이 POC에서 멀어짐에 따라 매력의 힘이 증가합니다. 가격이 Virgin POC에서 멀어질수록 이 수준으로 돌아오면 리바운스가 발생하고 가격 반전도 발생할 가능성이 커집니다.

그림 5. 이전 및 현재 Virgin POC

그림 5에서 지원 및 저항 수준이었던 이전 Virgin POC는 원으로 표시됩니다. 작동중인 Virgin POC에는 가격 값이 표시되어 있습니다.

가격이 Virgin POC에 영향을 미치면 "virgin"이 아닙니다. 심리적으로 시장은 더 이상 이를 상당한 수준의 지원이나 저항으로 보지 않습니다. 트레이더는 초기에 POC를 형성한 가격 수준을 여전히 볼 수 있지만 단순한 가격 누적으로 볼 수 있습니다.

가격 수준에 대한 자세한 내용은 Eric Naiman의 "Master-trading : The X-Files"책 (4장, "가격 수준은 기준선")에서 확인할 수 있습니다.

4. MQL5의 가격 히스토그램 구현

저의 첫 번째 Price Histogram 버전은 2006년에 나타났으며 개인용으로 MetaTrader4의 MQL4로 작성되었습니다. 이 인디케이터를 개발하는 동안 몇 가지 문제가 발생했습니다. 여기에 몇 가지 문제가 있습니다.

    1. M1은 말할 것도없고 M5의 역사상 매우 짧은 마디 수;
    2. 공휴일을 고려하여 하루만 복귀, 금요일 장 마감 시간 확인, CFD 장터 개장 시간 확인 등 역사 작업을위한 특수 기능 개발 필요;
    3. 기간 변경 및 결과적으로 터미널 지연시 인디케이터 재 계산.

    따라서 МetaТrader5 및 MQL5의 베타 테스트가 시작되었을 때 MQL5로 변환하기로 결정했습니다.

    사람들이 "첫 번째 팬케이크는 항상 조금 까다 롭다"고 말했듯이 나는 그것을 인디케이터로 구현하려고 노력했습니다.

    좋은 점부터 시작하겠습니다. 모든 기호에 대한 분 따옴표의 긴 역사의 존재, 모든 시간 범위에서 특정 기간 동안 과거 데이터를 얻을 수 있는 가능성과 같은 것들 말이죠.

    이제 그 이유를 설명하겠습니다. MQL5 인디케이터의 기능을 고려하지 않았습니다.

      1. 인디케이터의 런타임이 중요합니다.
      2. 기간 변경 후 인디케이터 작업의 특징.

      Calculate 이벤트 핸들러에 해당하는 함수 OnCalculate()의 실행에는 중요한 런타임이 있습니다. 따라서 분 바 히스토리를 이용한 260 일 (연간) 처리에는 최대 수 분까지 오랜 시간이 소요된다. 물론 인디케이터를 차트에 붙인 후 계산을 한꺼번에 수행한다면 우리는 그것을 받아들일 수 있습니다. 그러나 이것은 기간 변경의 경우가 아닙니다. 인디케이터가 다른 시간대로 전환되면 인디케이터의 이전 사본이 폐기되고 새 인디케이터가 생성됩니다. 그렇기 때문에 기간이 변경된 후 동일한 수준을 다시 계산해야 하고 많은 시간이 소요됩니다.

      하지만 무엇을 해야 할지 모르겠다면 "먼저 문서를 읽으십시오". 저희의 경우 MQL5 문서입니다. 해결책은 매우 간단했습니다. 이 인디케이터를 거래하지 않는 Expert Advisor로 구현하는 것입니다.

      Expert Advisor의 장점은 다음과 같습니다.

        1. OnTick의 Init 이벤트 핸들러에는 처리 시간이 중요하지 않습니다 ();
        2. 핸들러 OnDeinit (const int reason)의 매개 변수를 얻을 가능성.

        Expert Advisors는 다음과 같은 인디케이터와 다릅니다. 시간 프레임 변경 후 Expert Advisor는 REASON_CHARTCHANGE 이유 매개 변수를 사용하여 DeInit 이벤트를 생성하기만 하면 메모리에서 Expert Advisor를 언로드하지 않고 전역 변수의 다음 값을 제공합니다. 우리의 경우 새로운 거래일을 위해 Expert Advisor를 첨부하고 매개 변수를 변경하고 새로운 데이터가 나타난 후 모든 계산을 한 번에 수행 할 수 있습니다.

        나중에 필요한 몇 가지 정의를 소개하겠습니다.

        객체 지향 프로그래밍 (OOP) - 기본 개념이 객체와 클래스의 개념인 프로그래밍 스타일입니다.

        객체는 지정된 상태와 동작을 가진 가상 공간의 엔티티입니다. 속성 값 (속성이라고 함)과 작업 (메소드라고 함)이 있습니다.

        OOP에서 Class는 특수 추상 데이터 유형으로 구성을 통해 특징 지어집니다. 클래스은 OOP의 핵심 개념입니다. 클래스는 다른 추상 데이터 유형과 다릅니다. 클래스의 데이터 정의에는 데이터 처리 (인터페이스)의 클래스 메소드도 포함되어 있습니다.

        프로그래밍에는 알고리즘, 인수 설명 및 진행할 입력 매개 변수의 순서 및 반환 값을 포함하여 프로그램의 일부에서 수행 할 수있는 가능한 계산 목록을 의미하는 소프트웨어 인터페이스 개념이 있습니다. 추상 데이터 유형 인터페이스는 이러한 목록의 형식화된 설명을 위해 개발되었습니다. 알고리즘 자체와 이러한 모든 계산을 수행할 코드는 지정되지 않고 인터페이스 구현으로 호출됩니다.

        클래스 생성은 필드와 메소드로 일부 구조를 생성하는 것입니다. 전체 클래스는 클래스 인스턴스인 객체 생성을 위한 템플릿으로 간주할 수 있습니다. 클래스 인스턴스는 동일한 템플릿을 사용하여 생성되므로 동일한 필드와 메소드를 갖습니다.

        시작해봅시다...

        소스 코드는 4 개의 파일에 있습니다. 기본 파일은 PriceHistogram.mq5이고 다른 파일은 ClassExpert.mqh, ClassPriceHistogram.mqhClassProgressBar.mqh 입니다. 확장자가 .mqh 인 파일에는 클래스의 설명과 메소드가 포함됩니다. 모든 파일은 동일한 디렉토리에 있어야 합니다. 내 디렉토리는 \MQL5\Experts\PriceHistogram입니다

        4.1. PriceHistogram.mq5

        소스 코드의 첫 번째 문장은 다음과 같습니다.

        #include "ClassExpert.mqh"

        #include 컴파일러 지시문은 지정된 파일의 텍스트를 포함합니다. 우리의 경우 CExpert 클래스에 대한 설명입니다 (아래에서 논의 됨).

        다음은 Expert Advisor의 매개 변수인 입력 변수 블록입니다.

        // The block input parameters
        input int         DayTheHistogram   = 10;          // Days for histogram
        input int         DaysForCalculation= 500;         // Days for calculation(-1 all)
        input uint        RangePercent      = 70;          // Percent range
        input color       InnerRange        =Indigo;       // Inner range
        input color       OuterRange        =Magenta;      // Outer range
        input color       ControlPoint      =Orange;       // Point of Control
        input bool        ShowValue         =true;         // Show Values
        

        그 후 ExtExpert 변수 (CExpert 클래스 유형)가 선언됩니다.

        다음은 MQL5 프로그램에있는 표준 이벤트 핸들러입니다. 이벤트 핸들러는 CExpert 클래스의 해당 메소드를 호출합니다.

        CExpert를 실행하기 전에 몇 가지 작업을 수행하는 유일한 메소드가 있습니다 - OnInit() 메소드.
        int OnInit()
          {
        //---
        // We check for symbol synchronization before the start of calculations
           int err=0;
           while(!(bool)SeriesInfoInteger(Symbol(),0,SERIES_SYNCRONIZED) && err<AMOUNT_OF_ATTEMPTS)
             {
              Sleep(500);
              err++;
             }
        // CExpert class initialization
           ExtExpert.RangePercent=RangePercent;
           ExtExpert.InnerRange=InnerRange;
           ExtExpert.OuterRange=OuterRange;
           ExtExpert.ControlPoint=ControlPoint;
           ExtExpert.ShowValue=ShowValue;
           ExtExpert.DaysForCalculation=DaysForCalculation;
           ExtExpert.DayTheHistogram=DayTheHistogram;
           ExtExpert.Init();
           return(0);
          }
        

        Expert Advisor의 첫 번째 버전을 작성하고 실행할 때 클라이언트 터미널을 다시 시작하거나 기호가 변경된 후 오류로 종료되는 이유를 이해하는 데 약간의 어려움이 있습니다. 그리고 클라이언트 단말기의 연결이 끊어졌거나 심볼을 오랫동안 사용하지 않았을 때 발생합니다.

        개발자가 MetaEditor5에 디버거를 추가 한 것이 좋습니다. MetaEditor4에서 변수 값을 확인하는 데 사용되는 Print() 및 Comment() 명령을 많이 기억합니다. Editor5 개발자에게 감사드립니다.

        제 경우에는 모든 것이 쉬웠습니다. 전문가는 서버에 연결하고 기록 데이터를 업데이트하기 전에 시작합니다. 이 문제를 해결하기 위해 데이터가 동기화되었는지 여부를보고하는 SeriesInfoInteger (Symbol(), 0, SERIES_SYNCRONIZED)와 연결이 없는 경우 () 동안 주기를 사용해야했습니다. 카운터 변수 err을 사용합니다.

        데이터가 동기화되거나 연결이 없는 카운터로 인해 주기가 완료되면 전문가 클래스 CExpert의 입력 매개 변수를 전달하고 클래스 초기화 메소드 Init ()를 호출합니다.

        보시다시피 MQL5의 클래스 개념 덕분에 PriceHistogram.mq5 파일이 간단한 템플릿으로 변환되었으며 모든 추가 처리는 ClassExpert.mqh 파일에 선언된 CExpert 클래스에 있습니다.

        4.2. ClassExpert.mqh

        그 설명을 고려해 봅시다.

        //+------------------------------------------------------------------+
        //|   Class CExpert                                                  |
        //|   Class description                                              |
        //+------------------------------------------------------------------+
        class CExpert
          {
        public:
           int               DaysForCalculation; // Days to calculate (-1 for all)
           int               DayTheHistogram;    // Days for Histogram 
           int               RangePercent;       // Percent range
           color             InnerRange;         // Internal range color
           color             OuterRange;         // Outer range color
           color             ControlPoint;       // Point of Control (POC) Color
           bool              ShowValue;          // Show value
        

        공개 섹션은 열려 있고 외부 변수에서 액세스할 수 있습니다. 변수 이름은 PriceHistogram.mq5에 설명 된 입력 매개 변수 섹션의 이름과 일치합니다. 입력 매개 변수가 전역이므로 필요하지 않습니다. 그러나 이 경우 - 좋은 번식 규칙에 대한 찬사이므로 클래스 내에서 외부 변수를 사용하지 않는 것이 바람직합니다.

        private:
           CList             list_object;        // The dynamic list of CObject class instances
           string            name_symbol;        // Symbol name
           int               count_bars;         // Number of daily bars
           bool              event_on;           // Flag of events processing
        

        비공개 섹션은 외부에서 닫혀 있으며 클래스 내에서만 액세스 할 수 있습니다. 표준 클래스인 CList 유형의 list_object 변수를 간략하게 설명하고 싶습니다. 그리고 그건 바로 표준 MQL5 라이브러리이죠. CList 클래스는 CObject 클래스 그리고 그 계승자의 인스턴스 목록이 있는 동적 클래스입니다. CObject 클래스의 상속인 인 CPriceHistogram 클래스 요소에 대한 참조 저장소에 이 목록을 사용할 것입니다. 아래에서 자세히 살펴 보겠습니다. CList 클래스 설명은 List.mqh에 있으며 컴파일러 지시문 #include <Arrays\List.mqh>를 사용하여 포함합니다.

        public:
           // Class constructor
                             CExpert();
           // Class destructor
                            ~CExpert(){Deinit(REASON_CHARTCLOSE);}
           // Initialization method
           bool              Init();
           // Deinitialization method
           void              Deinit(const int reason);
           // Method of OnTick processing
           void              OnTick();
           // Method of OnChartEvent() event processing
           void              OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
           // Method of OnTimer() event processing
           void              OnTimer();
        };

        다음은 공용 메소드 섹션입니다. 짐작했듯이 이러한 메소드 (함수)는 클래스 외부에서 사용할 수 있습니다.

        마지막으로 세미콜론이 있는 중괄호가 클래스 설명을 완료합니다.

        클래스 메소드를 자세히 살펴보겠습니다.

        클래스 생성자는 객체가 생성될 때 호출되는 특수 블록입니다. 생성자는 메소드와 유사하지만 특정 유형의 반환된 데이터가 명시적으로 지정되지 않은 메소드와 다릅니다.

        MQL5 언어에서 생성자는 입력 매개 변수를 가질 수 없으며 각 클래스에는 생성자가 하나만 있어야 합니다. 우리의 경우 생성자는 변수의 기본 초기화입니다.

        소멸자는 객체 초기화 해제 (예: 여유 메모리)에 사용되는 특수 클래스 메소드입니다. 우리의 경우 메소드는 Deinit (REASON_CHARTCLOSE)로 호출됩니다.

        Init()는 클래스 초기화를 위한 메소드입니다. 이것은 CExpert 클래스의 가장 중요한 방법입니다. 히스토그램 객체의 생성이 그곳에서 수행되었습니다. 자세한 내용은 의견을 참조하십시오. 그러나 저는 그 점을 고려하고자 합니다.

        첫 번째는 일일 가격 히스토그램을 작성하기 위해 진행할 날짜의 오픈 타임 데이터가 필요합니다. 여기서는 시계열 작업의 기능에 대해 이야기하고 당신의 관심을 끌고 싶습니다. 다른 시간대의 데이터 요청에는 시간이 필요했기 때문에 Bars() 및 CopyTime() 함수와 시계열 작업을 위한 다른 함수가 항상 첫 번째 호출에서 원하는 데이터를 반환하는 것은 아닙니다.

        그래서 이 함수를 do (...) while () 루프에 넣어야 했지만 유한하게 만들기 위해 counter 변수를 사용했습니다.

         int err=0;
         do
           {
            // Calculate the number of days which available from the history
            count_bars=Bars(NULL,PERIOD_D1);
            if(DaysForCalculation+1<count_bars)
               count=DaysForCalculation+1;
            else
               count=count_bars;
            if(DaysForCalculation<=0) count=count_bars;
            rates_total=CopyTime(NULL,PERIOD_D1,0,count,day_time_open);
            Sleep(1);
            err++;
           }
         while(rates_total<=0 && err<AMOUNT_OF_ATTEMPTS);
         if(err>=AMOUNT_OF_ATTEMPTS)
           {
           Print("There is no accessible history PERIOD_D1");
           name_symbol=NULL;
           return(false);
           }

        둘째, MetaTrader 5의 분 이력은 사용 가능한 날짜와 동일하므로 진행하는 데 많은 시간이 소요될 수 있으므로 계산 프로세스를 시각화할 필요가 있습니다. 이러한 목적으로 CProgressBar 클래스 (#include "ClassProgressBar.mqh")가 개발되었습니다. 차트 창에 진행률 표시 줄을 만들고 계산 프로세스 중에 업데이트 합니다.

         // We create the progress bar on the char to shot the loading process
         CProgressBar   *progress=new CProgressBar;
         progress.Create(0,"Loading",0,150,20);
         progress.Text("Calculation:");
         progress.Maximum=rates_total; 

        세 번째, 주기적으로 "new" 진술을 사용하여 CPriceHistogram 객체를 만들고 메소드를 사용하여 구성하고 Init()를 호출하여 초기화합니다. 성공하면 list_object 목록에 추가하고, overwise delete 진술을 사용하여 hist_obj를 삭제합니다. CPriceHistogram 클래스 설명이 추가로 제공되며 코드의 주석을 참조하십시오.

         // In this cycle there is creation of object CPriceHistogram
         // its initialization and addition to the list of objects
         for(int i=0;i<rates_total;i++)
           {
            CPriceHistogram  *hist_obj=new CPriceHistogram();
            //         hist_obj.StepHistigram(step);
            // We set the flag to show text labels
            hist_obj.ShowLevel(ShowValue);
            // We set POCs colour
            hist_obj.ColorPOCs(ControlPoint);
            // We set colour for inner range
            hist_obj.ColorInner(InnerRange);
            // We set colour for outer range
            hist_obj.ColorOuter(OuterRange);
            // We set the percent range
            hist_obj.RangePercent(RangePercent);
            //  hist_obj.ShowSecondaryPOCs((i>=rates_total-DayTheHistogram),PeriodSeconds(PERIOD_D1));
            if(hist_obj.Init(day_time_open[i],day_time_open[i]+PeriodSeconds(PERIOD_D1),(i>=rates_total-DayTheHistogram)))
               list_object.Add(hist_obj);
            else
               delete hist_obj; // Delete object if there was an error
            progress.Value(i);
           }; 

        OnTick()은 심볼에 대한 새 틱을 받을 때 호출되는 메소드입니다. count_bars 변수에 저장된 일 수 값을 Bars (Symbol (), PERIOD_D1)에서 반환한 일일 바 수와 비교하고 같지 않으면 클래스 초기화를 위해 Init () 메소드를 강제로 호출하여 지웁니다. list_object 목록과 변수를 NULL name_symbol로 변경합니다. 일수가 변경되지 않은 경우 루프는 CPriceHistogram list_object 클래스에 저장된 모든 개체를 통과하고 Virgin («virgin ") 인 사용자를 위해 Redraw () 메소드를 실행합니다.

        Deinit()는 클래스 초기화 해제를 위한 메소드입니다. REASON_PARAMETERS (입력 매개 변수가 사용자에 의해 변경됨)의 경우 list_object 목록을 지우고 name_symbol 변수를 NULL로 설정합니다. 다른 경우에는 전문가가 아무 작업도하지 않지만 추가하려면 댓글을 읽어보세요.

        OnEvent()는 클라이언트 단말기의 이벤트 처리를 위한 메소드입니다. 사용자가 차트로 작업 할 때 클라이언트 터미널에 의해 이벤트가 생성됩니다. 세부 사항은 MQL5 언어 문서에서 찾을 수 있습니다. 이 Expert Advisor에서는 차트 이벤트 CHARTEVENT_OBJECT_CLICK이 사용되었습니다. 히스토그램 요소를 클릭하면 보조 POC 수준이 표시되고 히스토그램 색상이 반전됩니다.

        OnTimer (void)는 타이머 이벤트 처리를 위한 메소드입니다. 내 프로그램에서는 사용되지 않지만 타이머 동작 (예: 시간 표시)을 추가하려면 여기에 있습니다. 사용하기 전에 클래스 생성자에 다음 줄을 추가해야 합니다.

        EventSetTimer(time in seconds);

        그리고 소멸자에 대한 다음 줄:

        EventKillTimer(); 

        Deinit (REASON_CHARTCLOSE) 메소드를 호출하기 전에.

        iCPriceHistogram 클래스 메소드를 시연하기 위해 생성된 CExpert 클래스를 고려했습니다.

        4.3. ClassPriceHistogram.mqh
        //+------------------------------------------------------------------+
        //|   Class CPriceHistogram                                          |
        //|   Class description                                              |
        //+------------------------------------------------------------------+
        class CPriceHistogram : public CObject
          {
        private:
           // Class variables
           double            high_day,low_day;
           bool              Init_passed;      // Flag if the initialization has passed or not
           CChartObjectTrend *POCLine;
           CChartObjectTrend *SecondTopPOCLine,*SecondBottomPOCLine;
           CChartObjectText  *POCLable;
           CList             ListHistogramInner; // list for inner lines storage 
           CList             ListHistogramOuter; // list for outer lines storage
           bool              show_level;         // to show values of level
           bool              virgin;             // is it virgin
           bool              show_second_poc;    // show secondary POC levels
           double            second_poc_top;     // value of the top secondary POC level
           double            second_poc_bottom;  // value of the bottom secondary POC level
           double            poc_value;          // POC level value
           color             poc_color;          // color of POC level
           datetime          poc_start_time;
           datetime          poc_end_time;
           bool              show_histogram;     // show histogram  
           color             inner_color;        // inner color of the histogram
           color             outer_color;        // outer color of the histogram
           uint              range_percent;      // percent range
           datetime          time_start;         // start time for construction
           datetime          time_end;           // final time of construction
        public:
           // Class constructor
                             CPriceHistogram();
           // Class destructor
                            ~CPriceHistogram(){Delete();}
           // Class initialization
           bool              Init(datetime time_open,datetime time_close,bool showhistogram);
           // To level value
           void              ShowLevel(bool show){show_level=show; if(Init_passed) RefreshPOCs();}
           bool              ShowLevel(){return(show_level);}
           // To show histogram
           void              ShowHistogram(bool show);
           bool              ShowHistogram(){return(show_histogram);}
           // To show Secondary POC levels
           void              ShowSecondaryPOCs(bool show){show_second_poc=show;if(Init_passed)RefreshPOCs();}
           bool              ShowSecondaryPOCs(){return(show_second_poc);}
           // To set color of POC levels
           void              ColorPOCs(color col){poc_color=col; if(Init_passed)RefreshPOCs();}
           color             ColorPOCs(){return(poc_color);}
           // To set internal colour of histogram
           void              ColorInner(color col);
           color             ColorInner(){return(inner_color);}
           // To set outer colour of histogram
           void              ColorOuter(color col);
           color             ColorOuter(){return(outer_color);}
           // To set percent range
           void              RangePercent(uint percent){range_percent=percent; if(Init_passed)calculationPOCs();}
           uint              RangePercent(){return(range_percent);}
           // Returns value of virginity of POC level
           bool              VirginPOCs(){return(virgin);}
           // Returns starting time of histogram construction
           datetime          GetStartDateTime(){return(time_start);}
           // Updating of POC levels
           bool              RefreshPOCs();
        private:
           // Calculations of the histogram and POC levels
           bool              calculationPOCs();
           // Class delete
           void              Delete();
          }; 

        클래스 설명에서 클래스 변수와 메소드에 대한 주석을 제공하려고 했습니다. 그들 중 일부를 자세히 고려해 봅시다.

        //+------------------------------------------------------------------+
        //|   Class initialization                                           |
        //+------------------------------------------------------------------+
        bool CPriceHistogram::Init(datetime time_open,datetime time_close,bool showhistogram) 

        이 방법은 세 가지 입력 매개 변수 (건물 개장, 건설 마감 시간 및 히스토그램 구성을 나타내는 플래그 또는 POC 수준만)를 사용합니다.

        내 예제 (클래스 CExpert)에서 입력 매개 변수는 개장일과 다음 날 개장 시간에 전달됩니다. day_time_open [i] + PeriodSeconds (PERIOD_D1). 그러나 이 클래스를 사용할 때, 예를 들어 유럽, 미국 세션의 시간 또는 주, 월의 간격 크기 등을 묻는 것을 막을 수 있는 것은 없습니다.

        //+---------------------------------------------------------------------------------------+
        //|   Calculations of the histogram and POCs levels                                       |
        //+---------------------------------------------------------------------------------------+
        bool CPriceHistogram::calculationPOCs() 

        이 방법은 모든 수준의 기원과 그 구성의 계산이며 외부에서 접근 할 수 없는 폐쇄형 개인 방법입니다.

        // We get the data from time_start to time_end
           int err=0;
           do
             {
              //--- for each bar we are copying the open time
              rates_time=CopyTime(NULL,PERIOD_M1,time_start,time_end,iTime);
              if(rates_time<0)
                 PrintErrorOnCopyFunction("CopyTime",_Symbol,PERIOD_M1,GetLastError());
        
              //--- for each bar we are copying the High prices
              rates_high=CopyHigh(NULL,PERIOD_M1,time_start,time_end,iHigh);
              if(rates_high<0)
                 PrintErrorOnCopyFunction("CopyHigh",_Symbol,PERIOD_M1,GetLastError());
        
              //--- for each bar we are copying the Low prices
              rates_total=CopyLow(NULL,PERIOD_M1,time_start,time_end,iLow);
              if(rates_total<0)
                 PrintErrorOnCopyFunction("CopyLow",_Symbol,PERIOD_M1,GetLastError());
        
              err++;
             }
           while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS&&!IsStopped());
           if(err>=AMOUNT_OF_ATTEMPTS)
             {
              return(false);
             }
           poc_start_time=iTime[0];
           high_day=iHigh[ArrayMaximum(iHigh,0,WHOLE_ARRAY)];
           low_day=iLow[ArrayMinimum(iLow,0,WHOLE_ARRAY)];
           int count=int((high_day-low_day)/_Point)+1;
        // Count of duration of a finding of the price at each level
           int ThicknessOfLevel[];    // create an array for count of ticks
           ArrayResize(ThicknessOfLevel,count);
           ArrayInitialize(ThicknessOfLevel,0);
           for(int i=0;i<rates_total;i++)
             {
              double C=iLow[i];
              while(C<iHigh[i])
                {
                 int Index=int((C-low_day)/_Point);
                 ThicknessOfLevel[Index]++;
                 C+=_Point;
                }
             }
           int MaxLevel=ArrayMaximum(ThicknessOfLevel,0,count);
           poc_value=low_day+_Point*MaxLevel;

        먼저 특정 기간 (iTime [], iHigh [], iLow []) 동안의 분 바 기록 데이터를 가져옵니다. 그런 다음 iHigh[] i 및 Low[]의 최대 및 최소 요소를 찾습니다. 그런 다음 최소에서 최대까지 포인트 수 (개수)를 계산하고 ThicknessOfLevel 요소를 사용하여 ThicknessOfLevel 배열을 예약합니다. 주기에서 우리는 낮음에서 높음으로 매분 캔들을 살펴보고 이 가격 수준에서 기간 존재에 대한 데이터를 추가합니다. 그런 다음 ThicknessOfLevel 배열의 최대 요소를 찾으면 가격이 가장 긴 수준이 됩니다. 이것이 POC 수준입니다.

        // Search for the secondary POCs
           int range_min=ThicknessOfLevel[MaxLevel]-ThicknessOfLevel[MaxLevel]*range_percent/100;
           int DownLine=0;
           int UpLine=0;
           for(int i=0;i<count;i++)
             {
              if(ThicknessOfLevel[i]>=range_min)
                {
                 DownLine=i;
                 break;
                }
             }
           for(int i=count-1;i>0;i--)
             {
              if(ThicknessOfLevel[i]>=range_min)
                {
                 UpLine=i;
                 break;
                }
             }
           if(DownLine==0)
              DownLine=MaxLevel;
           if(UpLine==0)
              UpLine=MaxLevel;
           second_poc_top=low_day+_Point*UpLine;
           second_poc_bottom=low_day+_Point*DownLine;
        

        다음 단계는 보조 POC 수준을 찾는 것입니다. 다이어그램이 나뉘어져 있음을 기억하십시오. 히스토그램은 내부 및 외부 (다른 색상으로 표시됨)의 두 범위로 나뉘며 크기 범위는 이 수준에서 가격의 시간 비율로 정의됩니다. 내부 경계의 범위는 Secondary POC 수준입니다.

        Secondary POC - Borders 퍼센트 범위를 찾은 후 히스토그램 구성을 진행합니다.

        // Histogram formation 
           if(show_histogram)
             {
              datetime Delta=(iTime[rates_total-1]-iTime[0]-PeriodSeconds(PERIOD_H1))/ThicknessOfLevel[MaxLevel];
              int step=1;
              
              if(count>100)
                 step=count/100// Calculate the step of the histogram (100 lines as max)
        
              ListHistogramInner.Clear();
              ListHistogramOuter.Clear();
              for(int i=0;i<count;i+=step)
                {
                 string name=TimeToString(time_start)+" "+IntegerToString(i);
                 double StartY= low_day+_Point*i;
                 datetime EndX= iTime[0]+(ThicknessOfLevel[i])*Delta;
        
                 CChartObjectTrend *obj=new CChartObjectTrend();
                 obj.Create(0,name,0,poc_start_time,StartY,EndX,StartY);
                 obj.Background(true);
                 if(i>=DownLine && i<=UpLine)
                   {
                    obj.Color(inner_color);
                    ListHistogramInner.Add(obj);
                   }
                 else
                   {
                    obj.Color(outer_color);
                    ListHistogramOuter.Add(obj);
                   }
                }
             }
        
        

        터미널의 부하를 줄이기 위해 각 히스토그램에 대해 최대 100 줄을 화면에 표시한다는 점을 언급해야 합니다. 히스토그램의 라인은 CList 클래스에 이미 알려진 개체인 ListHistogramInner ListHistogramOuter와 두 개의 목록에 저장됩니다. 그러나 이러한 포인터는 CChartObjectTrend 객체의 표준 클래스에 저장됩니다. 왜 두 개의 목록이 제목에서 추측 할 수 있는지, 색상 히스토그램을 변경할 수 있다고 생각합니다.

        // We receive data beginning from the final time of the histogram till current time
           err=0;
           do
             {
              rates_time=CopyTime(NULL,PERIOD_M1,time_end,last_tick.time,iTime);
              rates_high=CopyHigh(NULL,PERIOD_M1,time_end,last_tick.time,iHigh);
              rates_total=CopyLow(NULL,PERIOD_M1,time_end,last_tick.time,iLow);
              err++;
             }
           while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS);
        // If there isn't history, the present day, level is virgin, we hoist the colours
           if(rates_time==0)
             {
              virgin=true;
             }
           else
        // Otherwise we check history
             {
              for(index=0;index<rates_total;index++)
                 if(poc_value<iHigh[index] && poc_value>iLow[index]) break;
        
              if(index<rates_total)   // If level has crossed
                 poc_end_time=iTime[index];
              else
                 virgin=true;
             }
           if(POCLine==NULL)
             {     
              POCLine=new CChartObjectTrend();
              POCLine.Create(0,TimeToString(time_start)+" POC ",0,poc_start_time,poc_value,0,0);
             }
           POCLine.Color(poc_color);
           RefreshPOCs();

        필요한 모든 방법으로 CPriceHistogram을 디자인하려고했는데 불충분한 경우 직접 추가 할 수 있습니다. 제가 도와 드리겠습니다.

        요약

        가격 히스토그램은 신뢰할 수 있지만 직관적인 도구이므로 사용하려면 확인 신호가 필요합니다.

        관심을 가져주셔서 감사합니다. 저는 모든 질문에 답할 준비가 되어 있습니다.

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

        데이터 교환 방법: 10 분 안에 MQL5 용 DLL 데이터 교환 방법: 10 분 안에 MQL5 용 DLL
        이제 많은 개발자가 간단한 DLL을 작성하는 방법과 다른 시스템 바인딩의 특수 기능이 무엇인지 기억하지 못합니다. 몇 가지 예제를 사용하여 간단한 DLL 생성의 전체 프로세스를 10 분 안에 보여주고 바인딩 구현에 대한 몇 가지 기술적인 세부 사항을 논의하려고 합니다. 다양한 유형의 변수 (숫자, 배열, 문자열 등)를 교환하는 예제와 함께 Visual Studio에서 DLL을 만드는 단계별 프로세스를 보여 드리겠습니다. 게다가 사용자 지정 DLL의 충돌로부터 클라이언트 터미널을 보호하는 방법을 설명합니다.
        초보자를 위한 간편 스타트 가이드 초보자를 위한 간편 스타트 가이드
        여러분, 안녕하세요! 엑스퍼트 어드바이저 생성 방식이나 인디케이터 활용법을 쉽고 빠르게 이해할 수 있도록 돕고자 이번 글을 씁니다. 이 글은 초보자를 대상으로 하며 복잡하거나 난해한 예제는 포함하지 않습니다.
        인디케이터 데이터 교환: 쉬워요! 인디케이터 데이터 교환: 쉬워요!
        차트에 추가된 인디케이터 데이터에 액세스가 가능한 동시에, 데이터 복사가 불필요하고, 필요한 경우 최소한의 수정만을 거쳐 기존의 코드를 사용할 수 있으며, MQL 코드가 선호되는 환경을 제공하고 싶습니다. 물론 DLL을 사용하긴 하겠지만 C++ 문자열을 이용할 겁니다. 이 글은 다른 MQL 프로그램에서 MetaTrader 터미널로 인디케이터 버퍼를 가져올 수 있도록 하는 편리한 개발 환경 구축 방법을 설명하고 있습니다.
        매매 전략 다목적 엑스퍼트 어드바이저 매매 전략 다목적 엑스퍼트 어드바이저
        이 글은 대기 주문을 활용하는 전략 및 해당 전략 개발에 사용되는 Metalanguage, 그리고 그 Metalanguage를 기반으로 작동하는 다목적 엑스퍼트 어드바이저에 대한 설명입니다.