Guia Prático MQL5: Processamento de Eventos Típicos do Gráfico
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
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
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
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
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
Temos de remover apenas uma linha vertical que o restante o Expert irá remover (fig.6).
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"
Se agora clicarmos em cada seta "comprar", iremos receber a seguinte imagem (Fig.8).
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"
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"
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
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
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
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso