English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
MQL5 Coobook: 일반적인 차트 이벤트 처리

MQL5 Coobook: 일반적인 차트 이벤트 처리

MetaTrader 5 | 3 9월 2021, 09:42
73 0
Denis Kirichenko
Denis Kirichenko

소개

제 글에서는 MQL5 개발자가 미리 정의한 일반적인(표준) 이벤트와 함께 OnChartEvent()를 사용하는 기능과 실습을 설명하고 싶습니다. MQL5 글 및 코드 기반에는 이미 이 핸들러를 사용하는 예가 포함되어 있습니다.

그러나 저의 목적은 이벤트 지향 프로그래밍(EOP)의 맥락에서 이 도구를 분석하는 것입니다. 저는 이 핸들러가 전자동 및 반자동 거래 시스템에 성공적으로 사용될 수 있다고 믿습니다.


1. "ChartEvent" 이벤트

그럼 먼저 어떤 이벤트인지 알아볼까요?

문서에 따르면 ChartEvent 이벤트는 특히 다음과 같은 경우 차트로 작업할 때 나타날 수 있습니다.

  • 차트 창에 포커스가 있을 때 키보드의 키를 누릅니다.
  • 그래픽 개체를 생성합니다.
  • 그래픽 개체를 삭제합니다.
  • 그래픽 개체를 클릭합니다.
  • 마우스로 그래픽 개체를 드래그합니다.
  • LabelEdit 그래픽 개체의 텍스트 필드에 있는 텍스트 편집을 완료합니다.

따라서 이 이벤트는 상호 작용을 가져오고 차트와 상호 작용할 수 있습니다. 또한 이러한 상호 작용은 수동 거래 및 일부 알고리즘 작업(자동 거래)의 결과일 수 있습니다.

MQL5 개발자는 ENUM_CHART_EVENT 열거형에 지정된 유형별로 ChartEvent 이벤트를 분류합니다.

이 목록에는 프로그래머에게 서비스를 제공하기 위한 숨겨진 예비 역할을 하는 다양한 사용자 정의 이벤트가 있다는 점에 유의하는 것이 중요합니다. MQL5 개발자는 사용자 지정 이벤트에 대해 65535개의 ID를 제공합니다.

사용자 정의 이벤트로 작업하기 위해 프로그래머의 필요에 따라 특수 생성기 함수 EventChartCustom()을 사용할 수 있습니다. 그러나 이 문서에서는 사용자 지정 이벤트를 고려하지 않습니다.


2. ChartEvent 핸들러 및 생성기

ChartEvent 이벤트의 모든 처리는 특수 핸들러 함수 OnChartEvent()에 의해 수행됩니다. 이것은 예를 들어 Trade 이벤트가 OnTrade() 함수에 의해 처리되고 OnInit() 함수 등에 의해 Init 이벤트가 처리되는 MQL5 언어 개념과 일치합니다.

OnChartEvent() 함수에는 다음 서명이 있습니다.

void OnChartEvent(const int id,         // event identifier  
                  const long& lparam,   // parameter of the event of type long
                  const double& dparam, // parameter of the event of type double
                  const string& sparam  // parameter of the event of type string
                  )

모든 입력 매개변수는 일정하며 핸들러가 호출될 때 유용한 정보를 전달합니다.

따라서 id 매개변수의 값은 핸들러를 호출한 특정 이벤트를 나타낼 수 있습니다. 다른 것들은 long, double 및 string 유형의 값을 가질 수 있습니다. 이 방법으로 이벤트에 대한 추가 정보를 얻을 수 있습니다.

나중에 우리는 지정된 매개변수의 값을 사용하여 진행 상황을 분석하는 예제를 만들 것입니다.

프로그래머가 구현해야 하는 ChartEvent 이벤트의 사용자 정의 부분은 EventChartCustom() 함수에 연결됩니다. 바로 이 기능이 이벤트를 생성할 수 있습니다. 함수 서명은 다음과 같습니다.

bool  EventChartCustom(long    chart_id,        // receiving chart identifier
                       ushort  custom_event_id, // event identifier
                       long    lparam,          // the long parameter
                       double  dparam,          // the double parameter
                       string  sparam           // the string parameter
                       )

실제로 생성기 함수는 이벤트를 생성하고 입력 매개변수 값이 있는 현재 차트를 포함한 모든 차트에 이벤트를 보낼 수 있습니다. 후자는 ushort, long, double, string 유형입니다.

OnChartEvent() 및 EventChartCustom() 함수는 함께 이벤트 지향 프로그래밍 이점의 좋은 예인 강력한 도구를 형성합니다.


3. 표준 이벤트 처리 템플릿

이제 차트 이벤트의 유형을 고려하고 각각에 대한 예를 제공하겠습니다. 각 이벤트에는 자체 전용 버전의 EventProcessor.mq5가 있으며 해당 코드에는 차트 이벤트 처리가 포함됩니다. MQL5에는 10개의 일반적인 이벤트가 있습니다.

그 중 3가지(마우스 이벤트, 그래픽 개체 생성 이벤트, 그래픽 개체 제거 이벤트)에 대해 차트를 준비해야 합니다. ChartSetInteger() 함수를 사용하여 수행할 수 있습니다. 차트가 지정된 이벤트에 응답할 수 있도록 합니다.

차트 이벤트 처리를 위한 일반적인 블록은 다음과 같습니다.

void OnChartEvent(const int id, 
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   string comment="Last event: ";

//--- select event on chart
   switch(id)
     {
      //--- 1
      case CHARTEVENT_KEYDOWN:
        {
         comment+="1) keystroke";
         break;
        }
      //--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         break;
        }
      //--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         break;
        }
      //--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         break;
        }
      //--- 5
      case CHARTEVENT_OBJECT_DELETE:
        {
         comment+="5) delete graphical object";
         break;
        }
      //--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         break;
        }
      //--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         break;
        }
      //--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         break;
        }
      //--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) finish editing text";
         break;
        }
      //--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         comment+="10) modify chart";
         break;
        }
     }
//---
   Comment(comment);
  }

각 경우에 선택한 이벤트를 설명하는 문자열을 추가했습니다. 결과적으로 주석 행에서 차트에서 발생한 마지막 이벤트를 볼 수 있습니다. 템플릿을 실행하고 차트로 다양한 조작을 수행하면 주석 행에 다른 레코드가 있을 수 있음을 알 수 있습니다.

분명히 이벤트 유형만 결정하는 Expert Advisor는 거의 사용되지 않습니다. 우리는 그 능력을 확장해야 합니다.


4. 표준 이벤트 처리 예


4.1. 키스트로크 이벤트

첫 번째 경우를 살펴보고 키보드의 버튼으로 작업하여 EA가 키 입력에 응답하도록 합시다. "위쪽 화살표"를 누르면 매수하고 "아래쪽 화살표"를 누르면 매도합니다. 그러면 이 경우는 다음과 같이 보일 것입니다.

//--- 1
      case CHARTEVENT_KEYDOWN:
        {
         //--- "up" arrow
         if(lparam==38)
            TryToBuy();

         //--- "down" arrow
         else if(lparam==40)
            TryToSell();

         comment+="1) keystroke";
         //---         
         break;
        }

TryToBuy() 및 TryToSell() 구현에 대한 자세한 내용은 첨부된 EA 소스 코드를 참조하십시오. 거래 매개변수(랏 크기, 손절매, 이익실현 등)는 입력 변수(InpLot, InpStopLoss, InpTakeProfit 등)로 지정됩니다.). lparam 매개변수는 누른 키의 코드를 가져옵니다.



EA의 업데이트된 버전은 EventProcessor1.mq5입니다.


4.2. 마우스 이벤트

이 유형의 이벤트는 CHART_EVENT_MOUSE_MOVE 속성이 차트에 지정된 경우에만 처리됩니다. 이러한 이유로 EA의 초기화 블록에는 다음과 같은 문자열이 포함됩니다.

//--- mouse move
bool is_mouse=false;
if(InpIsEventMouseMove)
   is_mouse=true;
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,is_mouse);

참고로 마우스를 사용하다보면 자연스럽게 마우스 이벤트가 자주 발생하게 됩니다. 이러한 이유로 이 이벤트의 처리를 비활성화할 수 있는 기회가 유용할 수 있습니다. 핸들러의 lparamdparam 매개변수는 그에 따라 좌표 X와 Y를 보고합니다.

우리는 만들어진 예를 논의할 것입니다. 오른쪽 경계에서 제로 바 이동이 있다고 가정해 보겠습니다. 시프트에서 오른쪽에 있는 화면 부분에 커서를 가져가면 매수 또는 매도를 제안하는 창이 나타납니다.

그러기 위해서는 먼저 시프트를 결정해야 합니다. 우리는 퍼센트 단위로 오른쪽 경계에서 제로 바 이동의 크기를 결정하기 위한 입력 변수를 도입할 것입니다(InpChartShiftSize).

그림 1 거래 작업 창

그림 1 거래 작업 창

시프트를 활성화하는 함수를 사용하고 크기 ChartShiftSet() 및 ChartShiftSizeSet()를 결정합니다. 그런 다음 커서의 X 좌표가 이전에 경계에서 왼쪽에 있었고 오른쪽으로 이동했는지 식별합니다. 그렇다면 매수/매도를 제안하는 창이 나타납니다(그림 1).

설정 대상을 구현하는 코드는 다음과 같습니다.

//--- 2
      case CHARTEVENT_MOUSE_MOVE:
        {
         comment+="2) mouse";
         //--- if a mouse event is processed
         if(InpIsEventMouseMove)
           {
            long static last_mouse_x;

            //--- enable shift
            if(ChartShiftSet(true))
               //--- set shift size 
               if(ChartShiftSizeSet(InpChartShiftSize))
                 {
                  //--- chart width
                  int chart_width=ChartWidthInPixels();

                  //--- calculate X coordinate of shift border
                  int chart_shift_x=(int)(chart_width-chart_width*InpChartShiftSize/100.);

                  //--- border crossing condition
                  if(lparam>chart_shift_x && last_mouse_x<chart_shift_x)
                    {
                     int res=MessageBox("Yes: buy / No: sell","Trade operation",MB_YESNO);
                     //--- buy
                     if(res==IDYES)
                        TryToBuy();
                     //--- sell
                     else if(res==IDNO)
                        TryToSell();
                    }

                  //--- store mouse X coordinate
                  last_mouse_x=lparam;
                 }
           }

         //---
         break;
        }

매수 및 판매는 이전에 생성된 거래 기능에 의해 수행됩니다. EA의 업데이트된 버전의 이름은 EventProcessor2.mq5입니다.


4.3. 그래픽 개체 생성 이벤트

이 유형의 이벤트는 차트에 개체가 생성될 때 생성됩니다. 마우스 이벤트와 유사하게 이 유형은 CHART_EVENT_OBJECT_CREATE 속성으로 처리할 수 있는 권한을 받아야 합니다. 새로운 그래픽 개체의 모양에 응답하려면 초기화 블록에서 한 번만 지정하면 됩니다.

//--- object create
bool is_obj_create=false;
if(InpIsEventObjectCreate)
   is_obj_create=true;
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,is_obj_create);

핸들러의 하나의 매개변수에만 정보가 포함될 것입니다. 생성된 그래픽 개체의 이름을 담고 있는 문자열 매개변수 sparam입니다. 우리는 그 개체를 이름으로 찾아 처리하고 다음에 무엇을 할지 결정할 수 있습니다.

다음은 간단한 예입니다. 차트에 수평선을 그리고 로봇이 차트에 반영된 모든 바의 최고 가격에 배치하도록 하고 다른 두 개의 선을 그립니다. 하단 라인은 최소 가격에 배치되고 세 번째 라인은 둘 다에서 같은 거리에 있는 처음 두 라인 사이에 위치합니다.

작업 구현을 위한 코드:

//--- 3
      case CHARTEVENT_OBJECT_CREATE:
        {
         comment+="3) create graphical object";
         //--- if graphical object creation event is processed
         if(InpIsEventObjectCreate)
           {
            //--- capture creation of horizontal line
            int all_hor_lines=ObjectsTotal(0,0,OBJ_HLINE);

            //--- if this is the only line
            if(all_hor_lines==1)
              {
               string hor_line_name1=sparam;

               //--- calculate levels
               int visible_bars_num=ChartVisibleBars();

               //--- arrays for high and low prices
               double highs[],lows[];
               //---
               int copied=CopyHigh(_Symbol,_Period,0,visible_bars_num-1,highs);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy highs!");
                  return;
                 }
               copied=CopyLow(_Symbol,_Period,0,visible_bars_num-1,lows);
               if(copied!=visible_bars_num-1)
                 {
                  Print("Failed to copy lows!");
                  return;
                 }
               //--- high and low prices
               double ch_high_pr,ch_low_pr,ch_mid_pr;
               //---
               ch_high_pr=NormalizeDouble(highs[ArrayMaximum(highs)],_Digits);
               ch_low_pr=NormalizeDouble(lows[ArrayMinimum(lows)],_Digits);
               ch_mid_pr=NormalizeDouble((ch_high_pr+ch_low_pr)/2.,_Digits);

               //--- place created line on high
               if(ObjectFind(0,hor_line_name1)>-1)
                  if(!ObjectMove(0,hor_line_name1,0,0,ch_high_pr))
                    {
                     Print("Failed to move!");
                     return;
                    }
               //--- create line on low
               string hor_line_name2="Hor_line_min";
               //---
               if(!ObjectCreate(0,hor_line_name2,OBJ_HLINE,0,0,ch_low_pr))
                 {
                  Print("Failed to create the 2nd horizontal line!");
                  return;
                 }
               //--- create line between high and low 
               string hor_line_name3="Hor_line_mid";
               //---
               if(!ObjectCreate(0,hor_line_name3,OBJ_HLINE,0,0,ch_mid_pr))
                 {
                  Print("Failed to create the 3rd horizontal line!");
                  return;
                 }
              }
           }
         break;
        }

EA의 업데이트된 버전 이름은 EventProcessor3.mq5입니다.

그림 2. 그래픽 개체 생성 이벤트 처리 결과

그림. 2. 그래픽 개체 생성
이벤트 처리 결과

절차를 완료한 후 다음과 같은 사진을 받았습니다(그림 2). 따라서 통합된 기능은 EA가 그래픽 개체 생성에 반응한 다음 그에 따라 작업할 수 있는 기능을 제공합니다.


4.4. 속성 대화 상자를 통한 그래픽 개체의 속성 변경 이벤트

이 이벤트 유형은 이전 유형과 부분적으로 유사합니다. 속성 대화 상자를 통해 그래픽 개체의 속성 중 하나가 변경될 때 트리거됩니다. 이 도구는 예를 들어 동일한 유형의 개체의 그래픽 속성을 동기화하는 데 유용할 수 있습니다.

차트에 있는 여러 개체를 상상해 보십시오. 트레이더는 일반적으로 차트에 다양한 선을 가지고 있습니다. 이 줄은 삭제되지 않고 한동안 보이지 않게 해야 합니다. 우리는 이 작업에 대한 해결책을 찾을 것입니다. 변경된 선은 탈색이 가능하며, 다른 그래픽 오브젝트에도 동일하게 적용할 수 있습니다. 그러면 코드는 다음과 같을 수 있습니다.

//--- 4
      case CHARTEVENT_OBJECT_CHANGE:
        {
         comment+="4) change object properties via properties dialog";
         //---
         string curr_obj_name=sparam;
         //--- find the changed object
         if(ObjectFind(0,curr_obj_name)>-1)
           {
            //--- get object color
            color curr_obj_color=(color)ObjectGetInteger(0,curr_obj_name,OBJPROP_COLOR);
            //--- total number of objects on chart
            int all_other_objects=ObjectsTotal(0);
            //--- find other objects
            for(int obj_idx=0;obj_idx<all_other_objects;obj_idx++)
              {
               string other_obj_name=ObjectName(0,obj_idx);
               if(StringCompare(curr_obj_name,other_obj_name)!=0)
                  if(!ObjectSetInteger(0,other_obj_name,OBJPROP_COLOR,curr_obj_color))
                    {
                     Print("Failed to change the object color!");
                     return;
                    }
              }
            //--- redraw chart
            ChartRedraw();
           }
         //---
         break;

차트에 일련의 라인이 있다고 가정해 보겠습니다(그림 3).

그림 3. 멀티 컬러 다이나믹 라인

그림 3. 멀티 컬러 다이나믹 라인

선의 색상을 변경하려고 하거나 정확하게는 속성 대화 상자에서 색상을 제거하면(그림 4) 차트에 라인이 표시되지 않습니다. 동시에 그래픽 개체는 여전히 존재합니다.

그림 4. 선 색상 변경

그림 4. 선 색상 변경

EA의 업데이트된 버전은 EventProcessor4.mq5입니다.


4.5. 그래픽 개체 삭제 이벤트

이 이벤트 유형의 이름에서 알 수 있듯이 차트에서 개체를 삭제할 때 나타납니다. 그룹의 마지막 이벤트로 처리를 위해 직접 선행 권한이 필요합니다. CHART_EVENT_OBJECT_DELETE 속성을 ​​통해 수행할 수 있습니다.

//--- object delete
   bool is_obj_delete=false;
   if(InpIsEventObjectDelete)
      is_obj_delete=true;
   ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,is_obj_delete);

여기에 또 다른 가상의 예가 있습니다. EA가 첨부된 차트에는 다양한 유형의 그래픽 개체 집합이 있습니다. 특정 유형의 개체만 삭제해야 한다고 가정해 보겠습니다. 예를 들어 수직선(그림 5).

그림 5. 5개의 수직선 및 기타 선

그림 5. 5개의 수직선 및 기타 선

하나의 수직만 제거하면 Expert가 나머지를 제거합니다(그림 6).

그림 6. 남은 줄

그림 6. 남은 줄

"Expert" 레지스터에 다음 항목이 표시됩니다.

NS      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines before removing: 4
MD      0       10:31:17.937    EventProcessor5 (EURUSD.e,W1)   Vertical lines removed from the chart: 4
QJ      0       10:31:18.078    EventProcessor5 (EURUSD.e,W1)   Vertical lines after removing: 0

중요한 측면을 언급해야 합니다. 개체가 제거되면 해당 속성에 액세스할 수 없습니다. 이는 개체에 대해 사전에 필요한 데이터를 검색하지 않으면 제거된 후 액세스할 수 없음을 의미합니다. 따라서 제거된 개체의 유형을 찾아야 하는 경우 개체 자체가 제거되기 전에 저장해야 합니다. MQL5 개발자가 터미널에서 사용할 수 있는 차트의 히스토리를 생성할 것을 제안합니다. 그러면 제거된 개체의 속성을 참조할 수 있습니다.

Expert EventProcessor5.mq5의 마지막 버전을 호출합니다.


4.6. 차트를 마우스로 클릭하는 이벤트

이 이벤트는 차트를 마우스 왼쪽 버튼으로 클릭하면 생성됩니다. 차트를 마우스 오른쪽 버튼으로 클릭하면 상황에 맞는 메뉴가 열리고 가운데 버튼을 클릭하면 십자형이 나타납니다. 핸들러의 lparamdparam 매개변수는 그에 따라 좌표 X와 Y를 보고합니다.

다음의 간단한 작업이 예제로 사용됩니다. 마우스 클릭이 일어나는 지점에 '매수' 화살표가 그려지도록 배열해야 합니다. 개체 '화살표'에는 앵커 포인트가 하나만 있습니다. 결과적으로 좌표 X와 Y를 기준점의 시간 값과 가격 값으로 한 번만 변환하면 됩니다.

위의 예에 대한 코드:

//--- 6
      case CHARTEVENT_CLICK:
        {
         comment+="6) mouse click on chart";
         //--- object counter 
         static uint sign_obj_cnt;
         string buy_sign_name="buy_sign_"+IntegerToString(sign_obj_cnt+1);
         //--- coordinates 
         int mouse_x=(int)lparam;
         int mouse_y=(int)dparam;
         //--- time and price
         datetime obj_time;
         double obj_price;
         int sub_window;
         //--- convert the X and Y coordinates to the time and price values
         if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
           {
            //--- create object
            if(!ObjectCreate(0,buy_sign_name,OBJ_ARROW_BUY,0,obj_time,obj_price))
              {
               Print("Failed to create buy sign!");
               return;
              }
            //--- redraw chart
            ChartRedraw();
            //--- increase object counter
            sign_obj_cnt++;
           }
         //---
         break;
        }

Expert의 현재 버전 이름은 EventProcessor6.mq5입니다.


4.7. 그래픽 개체를 마우스로 클릭하는 이벤트

이 유형의 차트 이벤트는 그래픽 개체에서 마우스 클릭이 발생한다는 사실만 이전 이벤트와 다릅니다. 문자열 매개변수 sparam에는 클릭한 개체의 이름이 포함됩니다. 이전 예에서 우리는 '매수' 화살표를 만들었습니다. 이 유형의 개체를 클릭하면 '판매' 화살표로 바뀌도록 만들겠습니다.

이 핸들러 블록의 코드는 다음과 같습니다.

//--- 7
      case CHARTEVENT_OBJECT_CLICK:
        {
         comment+="7) mouse click on graphical object";
         //---
         string sign_name=sparam;

         //--- delete buy arrow
         if(ObjectDelete(0,sign_name))
           {
            //--- redraw chart
            ChartRedraw();
            //---
            static uint sign_obj_cnt;
            string sell_sign_name="sell_sign_"+IntegerToString(sign_obj_cnt+1);

            //--- coordinates 
            int mouse_x=(int)lparam;
            int mouse_y=(int)dparam;
            //--- time and price
            datetime obj_time;
            double obj_price;
            int sub_window;
            //--- convert the X and Y coordinates to the time and price values
            if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price))
              {
               //--- create object
               if(!ObjectCreate(0,sell_sign_name,OBJ_ARROW_SELL,0,obj_time,obj_price))
                 {
                  Print("Failed to create sell sign!");
                  return;
                 }
               //--- redraw chart
               ChartRedraw();
               //--- increase object counter
               sign_obj_cnt++;
              }
           }
         //---
         break;
        }

이 예에서는 마우스 클릭 처리의 경우를 그대로 유지했습니다. EA를 실행하고 마우스 왼쪽 버튼을 세 번 클릭하고 세 개의 화살표를 매수했습니다(그림 7). 나는 그들의 위치를 ​​노란색으로 강조 표시했습니다.

그림 7. '매수' 화살표

그림 7. '매수' 화살표

이제 각 '매수' 화살표를 클릭하면 다음 그림이 표시됩니다(그림 8).

그림 8. '매수' 및 '매도' 화살표

그림 8. '매수' 및 '매도' 화살표

'매도' 화살표는 계획대로 나왔지만 '매수' 화살표는 나타나도록 설계되지 않았습니다. 내가 '매수' 화살표의 이름을 노란색으로 강조 표시한 차트의 개체 목록을 가져오는 데는 이유가 있습니다.

EA가 4, 5, 6번째 '매수' 화살표를 만든 것을 쉽게 알 수 있습니다. 왜 그런 일이 일어났습니까? 개체에 대한 첫 번째 클릭이 두 개의 이벤트를 트리거했기 때문에 발생했습니다. 첫 번째는 개체에 대한 실제 클릭이고 두 번째는 차트 클릭입니다. 마지막 이벤트는 '매수' 화살표를 생성합니다. 여기서 차트를 클릭하는 두 번째 이벤트의 처리를 방지하는 메커니즘을 추가해야 할 필요성이 발생합니다. 제 시간에 대한 통제가 그러한 메커니즘이 될 수 있다고 생각합니다.

전역 변수 gLastTime을 추가해 보겠습니다. '매수' 화살표 생성 시간을 쉽게 제어할 수 있습니다. '판매' 화살표가 생성된 후 간단한 클릭 핸들러가 250ms 미만 동안 호출되면 이 호출이 전달됩니다.

차트를 다시 그리기 전에 개체 클릭을 처리하는 블록에 아래 문자열을 추가해야 합니다.

//--- store the moment of creation
gLastTime=GetTickCount();

차트 클릭 처리 블록에 시간 확인을 추가해야 합니다.

uint lastTime=GetTickCount();
if((lastTime-gLastTime)>250)
  {
   //--- click handling
  }

다시 '매수' 유형의 차트에 세 개의 화살표를 생성해 보겠습니다(그림 9).

그림 9. '매수' 화살표

그림 9. '매수' 화살표

우리는 작은 크기에도 불구하고 클릭하려고 노력할 것입니다. 화살표는 클릭 시 '매도' 형태로 바뀌었다(그림 10).

그림 10. '판매' 화살표

그림 10. '판매' 화살표

이전 버전과 유사하게 새 버전의 이름을 EventProcessor7.mq5.으로 지정합니다.


4.8. 마우스로 그래픽 개체를 이동하는 이벤트

이 이벤트는 개체가 차트 영역 내에서 이동할 때 발생합니다. 핸들러는 문자열 매개변수 sparam 형식으로 이동된 개체의 이름을 수신합니다.

여기 또 다른 예가 있습니다. 장중 거래자는 특정 시간 간격 내에서 거래하는 경우가 많습니다. 수직선은 시간 간격의 한계가 됩니다. 그림은 대략 그림 11과 같습니다. 관심 구간이 강조 표시됩니다.

그림 11. 시간 간격의 한계

그림 11. 시간 간격의 한계

시간 간격은 수동으로 변경할 수 있습니다. 그러면 반자동 기계는 그러한 변화에 반응해야 합니다.

전역 수준에서 우리는 gTimeLimit1_name과 gTimeLimit2_name이라는 두 개의 수직의 이름을 설명하는 변수를 생성할 것입니다. 또한 차트에서 비거래 시간을 어둡게 하는 직사각형 이름에 대한 몇 가지 변수를 만들어야 합니다. 앵커 포인트에 대한 전역 변수도 생성해야 합니다. 두 개의 직사각형이 있으므로 4개의 점이 있습니다.

CHARTEVENT_OBJECT_DRAG 처리기의 경우 코드:

//--- 8
      case CHARTEVENT_OBJECT_DRAG:
        {
         comment+="8) move graphical object with mouse";
         string curr_obj_name=sparam;
         //--- if one of the vertical lines is moved
         if(!StringCompare(curr_obj_name,gTimeLimit1_name) || 
            !StringCompare(curr_obj_name,gTimeLimit2_name))
           {
            //--- the time coordinate of vertical lines
            datetime time_limit1=0;
            datetime time_limit2=0;
            //--- find the first vertical line
            if(ObjectFind(0,gTimeLimit1_name)>-1)
               time_limit1=(datetime)ObjectGetInteger(0,gTimeLimit1_name,OBJPROP_TIME);
            //--- find the second vertical line
            if(ObjectFind(0,gTimeLimit2_name)>-1)
               time_limit2=(datetime)ObjectGetInteger(0,gTimeLimit2_name,OBJPROP_TIME);

            //--- if vertical lines are found
            if(time_limit1>0 && time_limit2>0)
               if(time_limit1<time_limit2)
                 {
                  //--- update properties of rectangles
                  datetime start_time=time_limit1;
                  datetime finish_time=time_limit2;
                  //---
                  if(RefreshRecPoints(start_time,finish_time))
                    {
                     //---
                     if(!ObjectMove(0,gRectLimit1_name,0,gRec1_time1,gRec1_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit1_name,1,gRec1_time2,gRec1_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                     //---
                     if(!ObjectMove(0,gRectLimit2_name,0,gRec2_time1,gRec2_pr1))
                       {
                        Print("Failed to move the 1st point!");
                        return;
                       }
                     if(!ObjectMove(0,gRectLimit2_name,1,gRec2_time2,gRec2_pr2))
                       {
                        Print("Failed to move the 2nd point!");
                        return;
                       }
                    }
                 }
           }
         //---
         break;
        }

이 코드에는 사용자 정의 함수 RefreshRecPoints()가 포함되어 있습니다. 두 개의 직사각형에 대한 앵커 포인트 값 업데이트를 처리합니다. EA 초기화 블록은 그래픽 개체 생성에 대한 정보를 제공할 수 있습니다. 업데이트된 버전의 이름은 EventProcessor8.mq5입니다.


4.9. 텍스트 입력란의 텍스트 수정 종료 이벤트

이 이벤트 유형은 고도로 전문화된 특성을 가지며 데이터 입력 필드의 텍스트를 편집할 때 나타납니다. 매개변수 sparam에는 작업한 개체의 이름이 포함됩니다.

다음은 고려해야 할 예입니다. 데이터 입력 필드에 실행하려는 거래 작업을 입력합니다. 매수와 판매의 두 가지 작업만 수행하십시오. 입력 필드에 '매수'라는 단어를 입력하면 EA가 자산을 매수하고 '판매'를 입력하면 자산이 판매됩니다. 우리는 이 필드가 대소문자를 구분하지 않도록 배열할 것입니다. 즉, 'buy'와 'sell'을 입력할 수 있습니다. 텍스트와 입력 필드는 판매 시 빨간색, 매수 시 파란색으로 표시됩니다(그림 12).

그림 12. 텍스트 필드를 통해 매수

그림 12. 텍스트 필드를 통해 매수

CHARTEVENT_OBJECT_ENDEDIT의 경우 코드:

//--- 9
      case CHARTEVENT_OBJECT_ENDEDIT:
        {
         comment+="9) end of editing a text in the data entry field";
         //---
         string curr_obj_name=sparam;
         //--- if specified text field is being edited
         if(!StringCompare(curr_obj_name,gEdit_name))
           {
            //--- get object description
            string obj_text=NULL;
            if(ObjectGetString(0,curr_obj_name,OBJPROP_TEXT,0,obj_text))
              {
               //--- check value
               if(!StringCompare(obj_text,"Buy",false))
                 {
                  if(TryToBuy())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrBlue);
                 }
               else if(!StringCompare(obj_text,"Sell",false))
                 {
                  if(TryToSell())
                     //--- set text color
                     ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrRed);
                 }
               else
                 {
                  //--- set text color
                  ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrGray);
                 }
               //--- redraw chart
               ChartRedraw();
              }
           }
         //---
         break;
        }

EA의 업데이트된 버전은 EventProcessor9.mq5입니다. 소스 파일에서 텍스트 필드를 생성하는 블록을 찾을 수 있습니다.


4.10. 차트 수정 이벤트

이 글에서 고려할 마지막 이벤트는 차트 설정 변경과 관련이 있습니다. 이것은 이 시점에서 차트의 개체가 아니라 차트 자체를 다루기 때문에 특이한 이벤트입니다. 개발자들은 이 이벤트가 차트의 크기가 변경되거나 새로운 설정이 도입될 때 발생한다고 말합니다.

여기 또 다른 예가 있습니다. 일부 차트 설정을 변경하는 것이 금지되어 있다고 가정해 보겠습니다. 그러면 제한된 설정을 변경하려는 모든 시도가 무시됩니다. 실제로 EA는 단순히 이전 값을 반환합니다. 차트의 다음 매개변수를 수정해 보겠습니다.

  • 디스플레이 그리드;
  • 차트 표시 유형;
  • 배경색.

이 경우의 코드:

//--- 10
      case CHARTEVENT_CHART_CHANGE:
        {
         //--- current height and width of the chart         
         int curr_ch_height=ChartHeightInPixelsGet();
         int curr_ch_width=ChartWidthInPixels();
         //--- if chart height and width have not changed
         if(gChartHeight==curr_ch_height && gChartWidth==curr_ch_width)
           {
            //--- fix the properties:
            //--- display grid
            if(!ChartShowGridSet(InpToShowGrid))
              {
               Print("Failed to show grid!");
               return;
              }
            //--- type of chart display
            if(!ChartModeSet(InpMode))
              {
               Print("Failed to set mode!");
               return;
              }
            //--- background color
            if(!ChartBackColorSet(InpBackColor))
              {
               Print("Failed to set background сolor!");
               return;
              }
           }
         //--- store window dimensions
         else
           {
            gChartHeight=curr_ch_height;
            gChartWidth=curr_ch_width;
           }
         //---
         comment+="10) modify chart";
         //---
         break;
        }

마지막 버전의 이름은 EventProcessor10.mq5입니다.


결론

이 글에서는 MetaTrader 5의 일반적인 차트 이벤트의 다양성을 설명하려고 했습니다. 이러한 이벤트 처리 예제가 MQL5에서 코딩을 시작하는 프로그래머에게 유용하기를 바랍니다.

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

파일 첨부됨 |
code_en.zip (19.59 KB)
계산을 위해 OpenCL을 설치하고 사용하는 방법 계산을 위해 OpenCL을 설치하고 사용하는 방법
MQL5가 OpenCL에 대한 기본 지원을 제공하기 시작한 지 1년이 넘었습니다. 그러나 Expert Advisors, 지표 또는 스크립트에서 병렬 컴퓨팅 사용의 진정한 가치를 본 사용자는 많지 않습니다. 이 문서는 MetaTrader 5 거래 터미널에서 이 기술을 사용할 수 있도록 컴퓨터에 OpenCL을 설치하고 설정하는 데 도움이 됩니다.
MQL5 클라우드 네트워크: 아직도 계산 중입니까? MQL5 클라우드 네트워크: 아직도 계산 중입니까?
MQL5 클라우드 네트워크가 출시된 지 곧 1년 반이 됩니다. 이 최첨단 이벤트는 알고리즘 거래의 새로운 시대를 열었습니다. 이제 몇 번의 클릭으로 거래자는 거래 전략의 최적화를 위해 수백 수천 개의 컴퓨팅 코어를 마음대로 사용할 수 있습니다.
또 다른 MQL5 OOP 클래스 또 다른 MQL5 OOP 클래스
이 글은 이론적인 거래 아이디어를 구상하는 것부터 그 아이디어를 경험적 세계에서 현실로 만드는 MQL5 EA를 프로그래밍하는 것에 이르기까지 처음부터 객체 지향 Expert Advisor를 구축하는 방법을 보여줍니다. 행동으로 배우는 것은 IMHO 성공을 위한 확실한 접근 방식입니다. 그래서 저는 여러분이 Forex 로봇을 최종적으로 코딩하기 위해 아이디어를 주문하는 방법을 볼 수 있도록 실용적인 예를 보여주고 있습니다. 저의 목표는 또한 당신이 OO 원칙을 준수하도록 초대하는 것입니다.
포인트 앤 피겨 차트 지표 포인트 앤 피겨 차트 지표
현재 시장 상황에 대한 정보를 제공하는 차트 유형이 많이 있습니다. Point and Figure 차트와 같은 많은 것들은 먼 과거의 유산입니다. 이 글에서는 실시간 지표를 사용한 점 및 그림 차트의 예를 설명합니다.