English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Guia Prático MQL5: Processamento de Eventos Típicos do Gráfico

Guia Prático MQL5: Processamento de Eventos Típicos do Gráfico

MetaTrader 5Exemplos | 27 outubro 2014, 09:02
2 941 0
Denis Kirichenko
Denis Kirichenko

Introdução

Em meu artigo eu gostaria de descrever as capacidades e o aspecto prático de usar o OnChartEvent() com eventos típicos (padrão) pré-definidos pelos desenvolvedores em MQL5. Os artigos em MQL5 e a Base de Código já contêm exemplos de como usar esse manipulador.

No entanto, meu objetivo é analisar este instrumento no contexto da programação orientada a eventos (EOP). Eu acredito que esse manipulador pode ser utilizado com sucesso tanto para sistemas de negociação totalmente automatizados quanto para os semi-automáticos.


1. Evento "ChartEvent"

Bem, para começar, vamos esclarecer o que representa um evento como esse.

De acordo com a documentação, o evento ChartEvent pode aparecer quando se trabalha com um gráfico, em especial, nos seguintes casos:

  • pressionar uma tecla do teclado quando uma janela do gráfico está em foco.
  • criar um objeto gráfico.
  • remover um objeto gráfico.
  • clicar em um objeto gráfico.
  • arrastar um objeto gráfico com um mouse.
  • terminar de editar um texto do campo de texto de um objeto gráfico LabelEdit.

Assim, este evento traz interatividade e permite interagir com um gráfico. Além disso, essa interação pode ser resultado de uma negociação manual, bem como de algumas operações algorítmicas (negociação automatizada).

Os desenvolvedores em MQL5 classificam o evento ChartEvent por tipos especificados na enumeração ENUM_CHART_EVENT.

É importante notar que esta lista tem uma série de eventos definidos pelo usuário, que funcionam como uma reserva oculta para servir ao programador. Os desenvolvedores do MQL5 fornecem 65.535 IDs de eventos personalizados.

Para trabalhar com eventos personalizados, há uma função geradora especial chamada EventChartCustom() que está disponível para suprir as necessidades do programador. No entanto, este artigo não leva em conta os eventos personalizados.


2. Manipulador e Gerador do ChartEvent

Todo o processamento do evento ChartEvent é feito por uma função especial do manipulador OnChartEvent(). Isto é consistente com o conceito da linguagem MQL5, onde por exemplo o evento Trade é tratado pela função OnTrade(), o evento Init é tratado pela função OnInit(), etc.

A função OnChartEvent() possui o seguinte cabeçalho:

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
                  )

Todos os parâmetros de entrada são constantes, e quando o manipulador é chamado, eles transmitem alguma informação útil.

Assim, o valor do parâmetro id pode revelar qual evento em particular que chamou o manipulador. Outros podem ter valores do tipo long, double e string. Desta forma, é possível obter informações adicionais sobre o evento.

Mais tarde, vamos criar um exemplo onde os valores dos parâmetros especificados serão usados ​​para analisar o que está acontecendo.

A parte personalizada do evento ChartEvent, que depende do programador para implementar, está vinculada a função EventChartCustom(). Na verdade, é ela que pode gerar este evento. O cabeçalho da função é o seguinte:

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
                       )

Na verdade, a função geradora pode criar um evento e enviá-lo para qualquer gráfico, incluindo o atual com todos os valores dos parâmetros de entrada. Estes últimos são do tipo: ushort, long, double, string.

As funções OnChartEvent() e EventChartCustom() funcionando em conjunto formam uma poderosa ferramenta, sendo um bom exemplo dos benefícios da programação orientada a eventos (EOP).


3. Modelo de Processamento de Eventos Padrão

Agora levarei em conta os tipos de eventos do gráfico e dar um exemplo para cada um deles. Cada evento terá sua própria versão dedicada do EventProcessor.mq5 e seu código conterá o processamento de um evento do gráfico. Existem 10 eventos típicos em MQL5.

Para três deles (evento do mouse, evento da criação de objetos gráficos, evento de remoção de objetos gráficos), será necessário preparar o gráfico. Isso pode ser feito usando a função ChartSetInteger(). Ele permite ao gráfico responder os eventos indicados.

Um bloco típico para o processamento de eventos do gráfico poderia ter o seguinte aspecto:

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);
  }

Em cada caso, eu adicionei uma string descrevendo o evento selecionado. Como resultado, na linha de comentário é possível ver o último evento que aconteceu no gráfico. Se você executar o modelo e executar várias manipulações com o gráfico, você irá notar que a linha de comentário poderá ter registros diferentes.

Obviamente, há pouco uso de tal Expert Advisor que apenas determina o tipo de evento. Precisamos expandir suas capacidades e adicionar novos recursos ao código.


4. Exemplos do Processamento de Eventos Padrão


4.1. Evento do Teclado

Vamos tomar o primeiro caso e trabalhar com as teclas do teclado, para que o nosso EA responda a teclas pressionadas. Vamos deixar para comprar quando pressionamos a tecla "seta para cima", e vender quando pressionamos a tecla "seta para baixo". Neste caso, parte do código ficará da seguinte forma:

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

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

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

Veja o código-fonte do EA em anexo para mais detalhes sobre a implematação das funções TryToBuy() e TryToSell(). Os parâmetros de negociação (tamanho do lote, Stop Loss, Take Profit, etc.) são especificados como variáveis ​​de entrada (InpLot, InpStopLoss, InpTakeProfit, Etc.). Deve-se também mencionar que o parâmetro lparam obtém o código da tecla pressionada.



A versão atualizada do EA é chamada EventProcessor1.mq5.


4.2. Evento do Mouse

Este tipo de evento será tratado apenas se a propriedade CHART_EVENT_MOUSE_MOVE for especificada para o gráfico. Por essa razão, o bloco de inicialização do EA contém tais strings:

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

Deve-se notar que, se você usar o mouse, então, naturalmente, o evento do mouse, muitas vezes, entrará em ação. Por essa razão, um meio para desabilitar o processamento deste evento pode ser útil. Os parâmetros lparam e dparam do manipulador relatam as coordenadas X e Y, respectivamente.

Nós estaremos discutindo um exemplo inventado. Vamos supor que há um deslocamento da barra zero a partir do limite da direita. Ao colocar o cursor do mouse sobre a área à direita do deslocamento, aparecerá uma janela sugerindo uma compra ou venda.

Para fazer isso primeiro temos que determinar a mudança. Nós vamos criar uma variável de entrada para determinar o tamanho do deslocamento da barra zero a partir do limite da direita em porcentagem (InpChartShiftSize).

Fig.1 Janela de uma operação de negócio

Fig.1 Janela de uma operação de negócio

Nós vamos usar as funções ChartShiftSet()() e ChartShiftSizeSet() que habilitam o deslocamento e determinam o seu tamanho. Em seguida, devemos identificar se a coordenada X do cursor se encontrava previamente à esquerda do limite e se ela se moveu para a direita. Se ele sim, então uma janela sugerindo compra/venda aparecerá (Fig.1).

O código de implementação para estabelecer um objetivo é o seguinte:

//--- 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;
        }

A compra e venda é feita pelas funções de negociação criadas anteriormente. A versão atualizada do EA será nomeado para EventProcessor2.mq5.


4.3. Evento de Criação do Objeto Gráfico

Este tipo de evento é gerado quando um objeto é criado em um gráfico. Semelhante ao evento do mouse, este tipo tem que receber uma autorização para o manuseio com a propriedade CHART_EVENT_OBJECT_CREATE. Ele precisa ser especificado apenas uma vez no bloco de inicialização para responder ao aparecimento de um novo objeto gráfico.

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

Apenas um parâmetro de manipulador irá conter as informações. Ele é um parâmetro de string sparam que contém o nome do objecto gráfico criado. Podemos encontrar esse objeto pelo nome, lidar com ele e então decidir o que fazer a seguir.

Aqui está um simples exemplo. Nós vamos desenhar uma linha horizontal no gráfico e deixar o robô colocá-la ao preço máximo de todas as barras visíveis do gráfico e desenhar outras duas linhas. A linha inferior será colocada ao preço mínimo e a terceira linha será entre as duas primeiras, equidistantes uma da outra.

Segue o código para a implementação da tarefa:

//--- 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;
        }

O nome da versão atualizada do EA é EventProcessor3.mq5.

Fig. 2. Resultado do processamento do evento de criação do objeto gráfico

Fig. 2. Resultado do processamento do evento de criação do objeto gráfico

Depois de terminado o processo, eu recebi a seguinte imagem (Fig. 2). Assim, as funções integradas fornece ao EA a capacidade de reagir a criação de um objeto gráfico e, em seguida, agir sobre ela.


4.4. Evento de Alteração das Propriedades de um Objeto Gráfico Através da Caixa de Diálogo Propriedades

Este tipo de evento é parcialmente semelhante ao anterior. Ela é acionado quando uma das propriedades do objeto gráfico é alterado através da caixa de diálogo propriedades. Esta ferramenta pode ser útil, por exemplo, para a sincronização de propriedades gráficas de objetos do mesmo tipo.

Imagine um número de alguns objetos em um gráfico. Geralmente, um trader possui várias linhas em um gráfico. Estas linhas devem ser feitas de forma invisível por algum tempo sem ser excluída. Nós vamos encontrar uma solução para esta tarefa. A linha alterada pode ser descolorida e o mesmo pode ser feito para outros objetos gráficos. Assim, o código pode ser o seguinte:

//--- 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;

Vamos supor que há um conjunto de linhas no gráfico (Figura 3).

Fig.3. Linhas dinâmicas multi-coloridas

Fig.3. Linhas dinâmicas multi-coloridas

Se tentarmos mudar a cor de qualquer uma das linhas, ou para ser mais preciso, descolorir ela (Fig.4) na caixa de diálogo Propriedades, então não haverá linhas visíveis no gráfico. Ao mesmo tempo, os objetos gráficos ainda estarão presentes.

Fig.4. Alterando a cor de uma linha

Fig.4. Alterando a cor de uma linha

A versão atualizada do EA é chamado de EventProcessor4.mq5.


4.5. Evento de Remoção do Objeto Gráfico

Como o nome deste tipo de evento indica, ele aparece na exclusão de um objeto a partir do gráfico. Ele é o último evento do grupo, que exige uma autorização prévia para o seu manuseio. Isso pode ser feito por meio da propriedade 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);

Aqui está outro exemplo hipotético. No gráfico onde o EA está ligado, há um conjunto de objetos gráficos de diferentes tipos. Vamos supor que temos de excluir os objetos de apenas um tipo em particular. Por exemplo, as linhas verticais (Fig.5).

Fig.5. Cinco verticais e outras linhas

Fig.5. Cinco verticais e outras linhas

Temos de remover apenas uma linha vertical que o restante o Expert irá remover (fig.6).

Fig.6. Linhas restantes

Fig.6. Linhas restantes

As entradas a seguir irá aparecer no registo "Experts":

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

Um aspecto importante deve ser mencionado. Uma vez que um objeto é removido, não há mais acesso às suas propriedades. Isso significa que, se não recuperarmos os dados necessários sobre o objeto antes, então, ele não estará mais acessível depois de ser removido. Portanto, se temos de descobrir o tipo do objeto removido, devemos guardá-lo antes que o próprio objeto seja removido. Eu tenho uma sugestão para os desenvolvedores em MQL5 para criar um histórico do gráfico disponível no terminal. Isso irá nos deixar referir às propriedades dos objetos removidos.

Chamaremos a última versão do Expert de EventProcessor5.mq5.


4.6. Evento de Clique do Mouse sobre o Gráfico

Este evento será gerado se o gráfico receber um clique com o botão esquerdo do mouse. O Botão direito do mouse sobre o gráfico irá abrir um menu de contexto, e clicando com o botão do meio trará uma mira. Os parâmetros lparam e dparam do manipulador relatam as coordenadas X e Y, respectivamente.

A seguinte simples tarefa irá servir de exemplo. Precisamos providenciar que uma seta "buy" seja desenhada no ponto onde o clique do mouse ocorre. O objeto "arrow" possui apenas um ponto de ancoragem. Consequentemente, é necessário apenas uma transformação das coordenadas X e Y para os valores de tempo e de preço do ponto de ancoragem.

Aqui está o código para este exemplo:

//--- 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;
        }

A versão atual do Expert será chamado de EventProcessor6.mq5.


4.7. Evento de Clique do Mouse em um Objeto Gráfico

Este tipo de eventos gráfico difere do anterior apenas pelo fato do clique do mouse acontecer sobre um objeto gráfico. O parâmetro string sparam conterá o nome do objeto clicado. No exemplo anterior, nós criamos a seta "comprar". Vamos fazer com que o clique sobre um objeto deste tipo transforme-o em uma seta de "vender".

O código deste bloco do manipulador pode ter o seguinte aspecto:

//--- 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;
        }

Para o propósito deste exemplo eu mantive o caso da manipulação do clique do mouse intocado. Ao iniciar o EA, eu cliquei com o botão esquerdo do mouse três vezes e obtive três setas de compra (Fig.7). Eu destaquei a sua localização em amarelo.

Fig.7. setas de "Compra"

Fig.7. setas de "Compra"

Se agora clicarmos em cada seta "comprar", iremos receber a seguinte imagem (Fig.8).

Fig.8. setas "comprar" e "vender"

Fig.8. setas "comprar" e "vender"

As setas "Vender" apareceram como planejado, mas as setas "comprar" não foram projetados para aparecer. Há uma razão pela qual eu estou trazendo uma lista de objetos no gráfico onde eu destaquei os nomes das setas "Comprar" de amarelo.

É fácil de perceber que o EA criou a 4ª, 5ª e 6ª setas "comprar". Por que isso aconteceu? Isso aconteceu porque o primeiro clique sobre o objeto acionou dois eventos: o primeiro foi o clique real sobre o objeto e o segundo - um clique no gráfico. O último evento gera a criação de uma seta "comprar". Aqui surge a necessidade de adicionar um mecanismo que irá impedir o processamento do segundo evento, que é um clique no gráfico. Me parece que o controle sobre o tempo pode ser um mecanismo desse tipo.

Vamos adicionar uma variável global gLastTime. Ela irá facilitar o controle sobre o tempo da criação da seta "comprar". Se um simples manipulador de clique for chamado por menos de 250ms após a seta "vender" ser criada, então esta chamada é para ser rejeitada.

Antes do gráfico ser redesenhado, a string abaixo será adicionada ao bloco de processamento do clique sobre o objeto:

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

A verificação do tempo deve ser adicionada ao bloco de manipulação do clique no gráfico.

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

Vamos criar três setas do tipo "comprar" no gráfico novamente (Fig.9).

Fig.9. setas de "Compra"

Fig.9. setas de "Compra"

Apesar de seu pequeno tamanho, vamos tentar clicar sobre elas. As setas se transformaram do tipo "vender" em cima do clique (Fig.10).

Fig.10. setas "vender"

Fig.10. setas "vender"

Semelhante aos anteriores, vamos nomear a nova versão de EventProcessor7.mq5.


4.8. Evento de Deslocamento de um objeto gráfico com o mouse

Este evento ocorre quando um objeto se move dentro de uma área do gráfico. O manipulador recebe o nome do objeto movido sob a forma de um parâmetro de string sparam.

Aqui está outro exemplo. Traders que operam no intra-day, muitas vezes negociam dentro de um determinado intervalo de tempo. As linhas verticais serão os limites desse intervalo de tempo. A imagem será semelhante a Fig.11. O intervalo de interesse está realçado.

Fig.11. Os limites de um intervalo de tempo

Fig.11. Os limites de um intervalo de tempo

O intervalo de tempo pode ser alterado manualmente. Então, o nosso Expert semi-automático terá que reagir a essa mudança.

Em nível global vamos criar variáveis ​​que descrevem os nomes das duas verticais - gTimeLimit1_name e gTimeLimit2_name. Nós também precisamos criar um par de variáveis ​​para os nomes dos retângulos, que escurecem o tempo que não é negociado no gráfico. As variáveis ​​globais para pontos de ancoragem também terão de ser criados. Uma vez que temos dois retângulos, teremos quatro pontos.

O código do manipulador é 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;
        }

Este código contém uma função personalizada RefreshRecPoints(). Ele está lidando com a atualização dos valores dos pontos de ancoragem para dois retângulos. O bloco de inicialização do EA pode fornecer informações sobre como criar objetos gráficos. A versão atualizada será chamada de EventProcessor8.mq5.


4.9. Fim da Edição de um Texto no Campo de Texto Evento

Este tipo de evento tem uma natureza altamente especializada e aparece quando o texto no campo de entrada de dados está sendo editado. O parâmetro sparam contém o nome do objeto trabalhado.

Aqui está um exemplo a considerar. No campo de entrada de dados, nós devemos introduzir a operação de negociação que está prestes a ser executada. Vamos deixar apenas duas operações - compra e venda. Se digitarmos a palavra "Buy" no campo de entrada, então o EA irá comprar um ativo e se digitarmos "Sell", o ativo será vendido. Nós vamos providenciar para que este campo não diferencie maiúsculas e minúsculas, ou seja, podemos escrever "buy" e "Sell". O texto e o campo de entrada terá cor vermelha na venda e azul na compra (Fig.12).

Fig.12. Compra através do campo de texto

Fig.12. Compra através do campo de texto

O código neste caso é 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;
        }

A versão atualizada do EA é chamado de EventProcessor9.mq5. Você pode encontrar o bloco de criação do campo de texto no arquivo de origem.


4.10. Evento de Modificação do Gráfico

O último evento que vamos considerar neste artigo está relacionado com a alteração das configurações do gráfico. Este é um evento peculiar porque neste momento lidamos com o próprio gráfico, e não objetos do gráfico. Os desenvolvedores dizem que este evento é gerado quando o tamanho de um gráfico é alterado ou um novo ajuste é introduzido.

Aqui está outro exemplo. Vamos supor que há uma proibição para alterar algumas das configurações de gráfico. Em seguida, todas as tentativas de alteração das configurações sob restrição serão ignorados. Na verdade, o EA vai simplesmente voltar aos valores anteriores. Vamos corrigir os seguintes parâmetros do gráfico:

  • grade de exibição;
  • tipo de display do gráfico;
  • cor de fundo.

O código para este caso é o seguinte:

//--- 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;
        }

A última versão será chamada de EventProcessor10.mq5.


Conclusão

Neste artigo eu tentei ilustrar a diversidade de eventos típicos do gráfico no MetaTrader 5. Eu espero que estes exemplos de manipulação de eventos seja útil para os programadores que começam a codificar em MQL5.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/689

Arquivos anexados |
code_en.zip (19.59 KB)
Guia Prático MQL5 - Expert Advisor Multi-Moeda e Trabalhando com ordens pendentes em MQL5 Guia Prático MQL5 - Expert Advisor Multi-Moeda e Trabalhando com ordens pendentes em MQL5
Desta vez, vamos criar um Expert Advisor multi-moeda com um algoritmo de negociação baseado no envio de ordens pendentes do tipo Buy Stop e Sell Stop. Neste artigo veremos os seguintes tópicos: a negociação em um intervalo de tempo especificado, colocar/modificar/remover as ordens pendentes, verificar se a última posição foi fechada no Take Profit ou no Stop Loss e controlar o histórico de transações para cada símbolo.
Guia Prático do MQL5: Processamento do Evento TradeTransaction Guia Prático do MQL5: Processamento do Evento TradeTransaction
Neste artigo estudaremos as capacidades da linguagem MQL5 do ponto de vista da programação orientada a eventos. A grande vantagem dessa abordagem está na possibilidade do programa receber informações por etapas sobre a implementação das operações de negociação. O artigo também contém um exemplo do recebimento e processamento de informações sobre as operações de negociação em curso usando o manipulador de eventos TradeTransaction. Em minha opinião, esta abordagem pode ser usada para copiar as ordens de um terminal para outro.
Como acessar o banco de dados MySQL a partir do MQL5 (MQL4) Como acessar o banco de dados MySQL a partir do MQL5 (MQL4)
Este artigo descreve o desenvolvimento de uma interface entre o banco de dados MySQL e a linguagem MQL. Ele discute soluções práticas existentes e oferece uma maneira mais conveniente de implementar uma biblioteca para trabalhar com o bancos de dados. O artigo contém uma descrição detalhada das funções, a estrutura da interface, exemplos e algumas características específicas de se trabalhar com o MySQL. Quanto às soluções de software, encontramos em anexo no artigo os arquivos de bibliotecas dinâmicas, documentação e exemplos de script para as linguagem MQL4 e MQL5.
Análise de Regressão da Influência dos Dados Macroeconômicos sobre a Flutuação nos Preços da Moeda Análise de Regressão da Influência dos Dados Macroeconômicos sobre a Flutuação nos Preços da Moeda
Este artigo considera a aplicação da análise de regressão múltipla com estatísticas macroeconômicas. Ele também nos dá uma visão sobre a avaliação dos impactos estatísticos sobre a flutuação da taxa de câmbio, utilizando como exemplo o par de moeda EURUSD. Essa avaliação permite automatizar a análise fundamental, tornando-se disponível até mesmo para os traders novatos.