
Recetas de MQL5 - procesamiento de eventos típicos del gráfico
Introducción
En este artículo me gustaría describir las posibilidades y el aspecto práctico del manejador OnChartEvent() respecto a los eventos típicos (estándar), ya definidos por el programador del MQL5. Los artículos del foro MQL5 y Code Base ya contienen los ejemplos del uso de este manejador.
Sin embargo, mi objetivo consiste en analizar las posibilidades de esta herramienta de la programación dirigida por eventos (PDE). Supongo que el manejador en cuestión puede ser utilizado tanto para los sistemas de trading totalmente automáticos, como para los semiautomáticos.
1. Evento ChartEvent
Pues bien, para empezar vamos a aclarar qué es lo que representa este tipo de evento.
Según la documentación, el evento ChartEvent puede aparecer durante el trabajo con el gráfico, a saber:
- teclazo cuando la ventana del gráfico se encuentra enfocada;
- creación del objeto gráfico;
- eliminación del objeto gráfico;
- clic con ratón en un objeto gráfico que pertenece al gráfico;
- arrastre de un objeto gráfico con ratón;
- fin de edición del texto en el campo de introducción del objeto gráfico LabelEdit.
De esta manera, este evento introduce la interactividad y permite interactuar con el gráfico. Es más, dicha interacción puede ser resultado tanto del trabajo "con las manos" (trading manual), como de unas acciones algorítmicas (trading automático).
El programador clasifica el evento ChartEvent según los tipos que se establecen por la enumeración ENUM_CHART_EVENT.
Es importante mencionar que en la lista de los tipos existen los que establecen el rango de los eventos personalizados. Dichos eventos representan aquella oculta reserva que el programador puede utilizar a su gusto. Los desarrolladores del MQL5 han previstos 65535 identificadores de eventos personalizados.
En cuanto a los eventos personalizados, el programador cuenta con una función-generador especializada EventChartCustom(). Pero en el presente artículo no vamos a tratar el tema de los eventos personalizados.
2. Manejador y generador del ChartEvent
La función/manejador especial OnChartEvent() se encarga de todo el trabajo de procesamiento del ChartEvent. Y eso cuadra completamente con la concepción del lenguaje MQL5 según la cual, por ejemplo, el evento Trade se procesa por la función OnTrade(), el evento Init se procesa por la función OnInit(), etc.
La función OnChartEvent() tiene el siguiente encabezamiento:
void OnChartEvent(const int id, // identificador del evento const long& lparam, // parámetro del evento del tipo long const double& dparam, // parámetro del evento del tipo double const string& sparam // parámetro del evento del tipo string )
Todos los parámetros de entrada son constantes y llevan una determinada carga informativa cuando se invoca el manejador.
Así, según el valor del parámetro id se puede identificar el evento que ha llamado al manejador. Los demás pueden poseer los valores de «sus» tipos: long, double y string. Se supone que de esta manera se puede captar algunos datos más sobre el evento.
Más tarde intentaremos crear un ejemplo en el que van a utilizarse los valores de los parámetros mencionados para análizar lo que está pasando.
La parte personalizada del evento ChartEvent de la que se encarga el programador está vinculada con la función EventChartCustom(). Precisamente ella es la que puede generar este evento. El encabezado de la función es el siguiente:
bool EventChartCustom(long chart_id, // identificador del gráfico receptor del evento ushort custom_event_id, // identificador del evento long lparam, // parámetro del tipo long double dparam, // parámetro del tipo double string sparam // parámetro string del evento )
En realidad, la función-generador es capaz de crear un evento y enviarlo a cualquier gráfico inclusive el actual con cualquier valor de parámetros de entrada. Los últimos pertenecen a los tipos: ushort, long, double, string.
Las funciones OnChartEvent() y EventChartCustom() son una herramienta muy potente que sirve de un brillante ejemplar de ventajas de la programación dirigida por eventos.
3. Plantilla de procesamiento de eventos estándar
Propongo trabajar del siguiente modo. Vamos a analizar los tipos de eventos del gráfico y para cada uno le pondré su ejemplo. Escribiremos para cada evento su versión del Asesor EXperto (EA) EventProcessor.mq5 en cuyo código estará presente el procesamiento del evento del gráfico. En MQL5 hay 10 eventos típicos.
Para tres eventos (evento del ratón, evento de creación del objeto gráfico, evento de eliminación del objeto gráfico) hay que preparar su propio gráfico. Esto se hace mediante la función ChartSetInteger(). Ella permite al gráfico reaccionar a los eventos indicados.
Entonces, el bloque de eventos procesados tendrá el siguiente aspecto:
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { string comment="Último evento: "; //--- selección del evento del gráfico switch(id) { //--- 1 case CHARTEVENT_KEYDOWN: { comment+="1) un teclazo"; break; } //--- 2 case CHARTEVENT_MOUSE_MOVE: { comment+="2) del ratón"; break; } //--- 3 case CHARTEVENT_OBJECT_CREATE: { comment+="3) creación del objeto gráfico"; break; } //--- 4 case CHARTEVENT_OBJECT_CHANGE: { comment+="4) cambio de propiedades del objeto mediante el diálogo de propiedades"; break; } //--- 5 case CHARTEVENT_OBJECT_DELETE: { comment+="5) eliminación del objeto gráfico"; break; } //--- 6 case CHARTEVENT_CLICK: { comment+="6) clic del ratón en el gráfico"; break; } //--- 7 case CHARTEVENT_OBJECT_CLICK: { comment+="7) clic del ratón en el objeto gráfico"; break; } //--- 8 case CHARTEVENT_OBJECT_DRAG: { comment+="8) arrastre del objeto gráfico con el ratón"; break; } //--- 9 case CHARTEVENT_OBJECT_ENDEDIT: { comment+="9) fin de edición del texto"; break; } //--- 10 case CHARTEVENT_CHART_CHANGE: { comment+="10) modificación del gráfico"; break; } } //--- Comment(comment); }
He insertado en cada case una línea que describe el evento seleccionado. Finalmente, en la línea del comentario veremos qué tipo de evento ha tenido lugar en el gráfico.
Cuando inicie la ejecución de la plantilla y vaya a realizar diferentes manipulaciones con el gráfico, verá que en la línea del comentario pueden aparecer diferentes textos.
A que la utilidad de este EA que determina el tipo del evento del gráfico no será muy grande, ¿verdad? Vamos a ampliar sus posibilidades y añadiremos en el código nuevos recursos.
4. Ejemplos de procesamiento de eventos estándar
4.1. Evento de un teclazo
Vamos a coger el primer módulo case y trabajaremos con las teclas del teclado, es decir, enseñaremos al EA reaccionar a las señales del teclado.
Que el EA abra la posición de compra cuando se pulse la tecla «flecha arriba» y la posición de venta cuando se pulse «flecha abajo».
Entonces, el código del módulo case puede tener el siguiente aspecto:
//--- 1 case CHARTEVENT_KEYDOWN: { //--- flecha arriba if(lparam==38) TryToBuy(); //--- flecha abajo else if(lparam==40) TryToSell(); comment+="1) un teclazo"; //--- break; }
Puede encontrar el código de las funciones TryToBuy() y TryToSell() en el archivo del EA.
Los parámetros del trading (lote, Stop Loss, Take Profit, etc.) se establecen como variables input (InpLot, InpStopLoss, InpTakeProfit, etc).
Señalaría también que el parámetro lparam recibe el código de la tecla pulsada.
Llamaremos la versión renovada del EA EventProcessor1.mq5.
4.2. Evento del ratón
Este tipo del evento será procesado sólo si para el gráfico ha sido establecida la propiedad CHART_EVENT_MOUSE_MOVE.
Para eso en el bloque de inicialización del EA he escrito las siguientes líneas:
//--- mouse move bool is_mouse=false; if(InpIsEventMouseMove) is_mouse=true; ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,is_mouse);
Hay que decir que si Usted trabaja con el ratón, entonces el evento del ratón naturalmente tendrá lugar con muchísima frecuencia. Por eso merece la pena realizar la posibilidad de desactivar el procesamiento de este evento.
Los parámetros del manejador lparam y dparam comunican las coordenadas X y Y, respectivamente.
Vamos a inventar un ejemplo. Que en el gráfico haya sangría de la barra cero desde el borde derecho. Al situar el cursor del ratón sobre el área a la derecha del límite de la sangría, aparecerá la ventana con la propuesta de comprar o vender.
Para empezar, hay que determinarse con la sangría. Crearemos la variable input para determinar el tamaño de la sangría de la barra cero desde el borde derecho en por cientos (InpChartShiftSize).
Fig. 1 Ventana de la operación comercial
Luego usaremos las funciones que activan y fijan el tamaño de la sangría ChartShiftSet() y ChartShiftSizeSet(). A continuación, averiguaremos si la coordenada X del ratón se encontraba antes a la izquierda del límite, y ahora se encuentra a la derecha. Si es así, aparece la ventana con la propuesta de comprar/vender (Fig. 1).
El código que implementa esta tarea es el siguiente:
//--- 2 case CHARTEVENT_MOUSE_MOVE: { comment+="2) del ratón"; //--- si procesar el evento del ratón if(InpIsEventMouseMove) { long static last_mouse_x; //--- activar la sangría if(ChartShiftSet(true)) //--- fijar el tamaño de la sangría if(ChartShiftSizeSet(InpChartShiftSize)) { //--- ancho del gráfico int chart_width=ChartWidthInPixels(); //--- determinar la coordenada X del límite de la sangría int chart_shift_x=(int)(chart_width-chart_width*InpChartShiftSize/100.); //--- condición del cruce del límite if(lparam>chart_shift_x && last_mouse_x<chart_shift_x) { int res=MessageBox("Sí: comprar / No: vender","Operación de trading",MB_YESNO); //--- si comprar if(res==IDYES) TryToBuy(); //--- si vender else if(res==IDNO) TryToSell(); } //--- recordar la coordenada X del ratón last_mouse_x=lparam; } } //--- break; }
Las funciones creadas anteriormente se encargan de las compras y las ventas. Llamaremos la versión renovada del EA EventProcessor2.mq5.
4.3. Evento de creación del objeto gráfico
Este tipo del evento surge cuando en el gráfico se crea algún objeto. Igual que el evento del ratón, este tipo debe obtener permiso para el procesamiento mediante la función de la propiedad CHART_EVENT_OBJECT_CREATE.
En el bloque de inicialización se puede indicar una vez si vamos a reaccionar a la aparición de un nuevo objeto gráfico, o no.
//--- object create bool is_obj_create=false; if(InpIsEventObjectCreate) is_obj_create=true; ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,is_obj_create);
Sólo un parámetro del manejador va a contener aquí la información. Es sparam de cadena con el nombre del objeto gráfico creado.
Podremos encontrar este objeto por su nombre y decidir qué es lo que vamos a hacer con él en adelante.
Aquí propongo un simple ejemplo. Colocamos una línea horizontal en el gráfico. Y que nuestro robot la coloque sobre el precio máximo de todas las barras visibles del gráfico y trace otras dos líneas más. La línea inferior estará situada sobre el precio mínimo, y la última será equidistante entre otras dos.
Aquí tiene el código para la solución de la tarea propuesta:
//--- 3 case CHARTEVENT_OBJECT_CREATE: { comment+="3) creación del objeto gráfico"; //--- si procesar el evento de creación del objeto gráfico if(InpIsEventObjectCreate) { //--- "captar" la creación de la horizontal int all_hor_lines=ObjectsTotal(0,0,OBJ_HLINE); //--- si es la única línea if(all_hor_lines==1) { string hor_line_name1=sparam; //--- calcular los niveles int visible_bars_num=ChartVisibleBars(); //--- los arrays high y low 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; } //--- precios high y low 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); //--- colocar la línea creada en el máximo if(ObjectFind(0,hor_line_name1)>-1) if(!ObjectMove(0,hor_line_name1,0,0,ch_high_pr)) { Print("Failed to move!"); return; } //--- crear la línea en el mínimo 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; } //--- crear la línea entre high y 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; }
Llamaremos la versión renovada del EA EventProcessor3.mq5.
Fig. 2. Resultado de procesamiento del evento de creación del objeto gráfico
Después de realizar esta operación, me ha salido la siguiente imagen (Fig. 2). De esta manera, cuando creamos un objeto gráfico, podemos enseñar reaccionar a nuestro EA y luego ejecutar alguna acción.
4.4. Evento del cambio de propiedades de un objeto mediante el diálogo de propiedades
Este tipo del evento parece parcialmente al tipo anterior. Se activa cuando alguna propiedad del objeto gráfico se cambia mediante el diálogo de propiedades. Es una herramienta bastante cómoda, por ejemplo, para la sincronización de las propiedades gráficas de los objetos del mismo tipo.
Imagínese que tiene en su gráfico varios objetos. Habitualmente el trader siempre tiene en su gráfico muchas lineas de diferentes tipos. Y necesitamos hacer que estas líneas sean invisibles por algún tiempo sin eliminarlas del gráfico. Intentaremos resolver este problema.
Se puede descolorar la línea modificada y, por lo tanto, hacer lo mismo con otros objetos gráficos.
Entonces, el código puede ser el siguiente:
//--- 4 case CHARTEVENT_OBJECT_CHANGE: { comment+="4) cambio de propiedades del objeto mediante el diálogo de propiedades"; //--- string curr_obj_name=sparam; //--- buscar objeto modificado if(ObjectFind(0,curr_obj_name)>-1) { //--- obtener el color del objeto color curr_obj_color=(color)ObjectGetInteger(0,curr_obj_name,OBJPROP_COLOR); //--- total de objetos en el gráfico int all_other_objects=ObjectsTotal(0); //--- buscar otros objetos 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; } } //--- redibujar el gráfico ChartRedraw(); } //--- break;
Que haya una serie de líneas en el gráfico (Fig. 3).
Fig. 3. Líneas dinámicas de varios colores
Si intentamos entrar en el diálogo de propiedades y cambiar el color de cualquier línea, es decir, descolorarla (Fig. 4), en el gráfico no se verá ninguna línea. Los objetos gráficos no se eliminan físicamente.
Fig. 4. Cambio del color de la línea
La nueva versión del EA obtiene el nombre EventProcessor4.mq5.
4.5. Evento de eliminación del objeto gráfico
Como se desprende del nombre del tipo del evento del gráfico, este evento aparece cuando un objeto se quita del gráfico.
Se trata del último evento entre los demás que requiere directamente el permiso previo para su procesamiento. Se puede hacerlo a través de la propiedad 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);
Vamos a mostrar el siguiente ejemplo. En el gráfico donde se encuentra nuestro EA hay una serie de objetos gráficos de diferentes tipos. Supongamos que hay que eliminar los objetos de un solo tipo. Que sean las líneas verticales (Fig. 5).
Fig. 5. Cinco verticales y otras líneas
Eliminaremos manualmente una de las líneas verticales, el EA eliminará las cuatro restantes (Fig. 6).
Fig. 6. Líneas restantes
En el diario «Asesores Expertos» aparecerán las siguientes entradas:NS 0 10:31:17.937 EventProcessor5 (EURUSD.e,W1) Líneas verticales antes de eliminación: 4 MD 0 10:31:17.937 EventProcessor5 (EURUSD.e,W1) Número de líneas verticales eliminadas: 4 QJ 0 10:31:18.078 EventProcessor5 (EURUSD.e,W1) Líneas verticales después de eliminación: 0
Habría que matizar una cosa. Si un objeto ha sido eliminado, ya no se puede acceder a sus propiedades. Eso significa que si no nos hemos preocupado de antemano de obtener los datos necesarios sobre el objeto, tras su eliminación ya no estarán disponibles. Por eso, por ejemplo, para averiguar el tipo del objeto eliminado, hace falta memorizarlo antes de eliminar el objeto. Y se me ha ocurrido una propuesta para el desarrollador de MQL5 que consiste en crear el historial del gráfico abierto en el terminal. Entonces tendremos la posibilidad de dirigirse, por ejemplo, a las propiedades de objetos eliminados.
Nombraremos la última versión del EA EventProcessor5.mq5.
4.6. Evento de un clic del ratón sobre un gráfico
Este evento surge si hacemos un clic del ratón sobre el gráfico. El manejador reaccionará sólo al clic izquierdo. Si hacemos clic con el botón derecho, se abre el menú contextual, si usamos el botón intermedio, aparece el cursor en cruz.
Los parámetros del manejador lparam y dparam comunican las coordenadas X y Y, respectivamente.
Cogemos como ejemplo una tarea no tan complicada. Necesitamos que en el punto del gráfico donde ha sido hecho el clic del ratón se dibuje la flecha buy. El objeto de la flecha tiene sólo un punto de anclaje. Por eso vamos a necesitar una conversión de coordenadas X y Y en el valor del tiempo del punto de anclaje y del precio del punto de anclaje.
Aquí tiene el código para este ejemplo:
//--- 6 case CHARTEVENT_CLICK: { comment+="6) clic del ratón en el gráfico"; //--- contador de objetos static uint sign_obj_cnt; string buy_sign_name="buy_sign_"+IntegerToString(sign_obj_cnt+1); //--- coordenadas int mouse_x=(int)lparam; int mouse_y=(int)dparam; //--- tiempo y precio datetime obj_time; double obj_price; int sub_window; //--- convertir las coordenadas X y Y en los valores de tiempo y precio if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price)) { //--- creación del objeto if(!ObjectCreate(0,buy_sign_name,OBJ_ARROW_BUY,0,obj_time,obj_price)) { Print("Failed to create buy sign!"); return(false); } //--- redibujar el gráfico ChartRedraw(); //--- aumentar el contador de objetos sign_obj_cnt++; } //--- break; }
La versión actual del EA recibe el nombre EventProcessor6.mq5.
4.7. Evento de un clic del ratón sobre un objeto gráfico
Este tipo del evento se diferencia del anterior sólo en que el clic del ratón se hace en un objeto gráfico. El parámetro de cadena sparam indicará el nombre del objeto pulsado.
En el último ejemplo hemos creado las flechas buy. Ahora vamos a hacer que el clic en el objeto de este tipo lo cambie por la flecha sell.
El código del bloque del manejador puede tener aproximadamente el siguiente aspecto:
//--- 7 case CHARTEVENT_OBJECT_CLICK: { comment+="7) clic del ratón en el objeto gráfico"; //--- string sign_name=sparam; //--- eliminar la flecha buy if(ObjectDelete(0,sign_name)) { //--- redibujar el gráfico ChartRedraw(); //--- static uint sign_obj_cnt; string sell_sign_name="sell_sign_"+IntegerToString(sign_obj_cnt+1); //--- coordenadas int mouse_x=(int)lparam; int mouse_y=(int)dparam; //--- tiempo y precio datetime obj_time; double obj_price; int sub_window; //--- convertir las coordenadas X y Y en los valores de tiempo y precio if(ChartXYToTimePrice(0,mouse_x,mouse_y,sub_window,obj_time,obj_price)) { //--- creación del objeto if(!ObjectCreate(0,sell_sign_name,OBJ_ARROW_SELL,0,obj_time,obj_price)) { Print("Failed to create sell sign!"); return; } //--- redibujar el gráfico ChartRedraw(); //--- aumentar el contador de objetos sign_obj_cnt++; } } //--- break; }
Para los fines del ejemplo he dejado intacto el módulo case del procesamiento del clic del ratón.
Al iniciar el EA, he hecho tres clics izquierdos y he obtenido 3 flechas de compra (Fig. 7). Su ubicación he resaltado con el color amarillo.
Fig. 7. Flechas buy
Y si ahora hacemos clic en cada flecha buy, obtendremos la siguiente imagen (Fig. 8).
Fig. 8. Flechas buy y sell
Aparecieron las flechas sell tal como habíamos pensado, pero también aparecieron las flechas buy como no habíamos pensado. Muestro intencionadamente la lista de objetos en el gráfico donde he resaltado con amarillo los nombres de las flechas buy.
Es fácil de notar que el EA ha creado la cuarta, la quinta, y la sexta flecha buy. ¿Por qué ha pasado eso? Quizás porque el primer clic en el objeto ha provocado dos eventos: el primero ha sido el clic en el objeto, y el segundo, el clic en el gráfico. Precisamente el último evento genera la creación de la flecha buy. Entonces, surge la necesidad de añadir algún mecanismo que corte el procesamiento del segundo evento- clic en el gráfico. Creo que este mecanismo puede ser el control del tiempo.
Añadiremos la variable global gLastTime. Vamos a usarla para controlar el tiempo de creación de la flecha buy. Si el manejador de un clic habitual se invoca dentro de un período inferior a 250 milisegundos tras la creación de la flecha sell, vamos a considerar que hay que omitir su llamada.
Antes de redibujar el gráfico, hay que insertar la línea en el bloque de procesamiento del clic en el objeto:
//--- recordar el momento de creación gLastTime=GetTickCount();
Y en el bloque de procesamiento del clic en el gráfico hay que insertar la comprobación por el tiempo:
uint lastTime=GetTickCount(); if((lastTime-gLastTime)>250) { //--- aquí procesamiento del clic }
Volveremos a crear tres flechas del tipo buy (Fig. 9).
Fig. 9. Flechas buy
A pesar de su reducido tamaño intentaremos hacer clic sobre ellas. Las flechas han sido cambiadas por las del tipo sell (Fig. 10).
Fig. 10 Flechas sell
Siguiendo el costumbre, llamaremos la nueva versión del EA EventProcessor7.mq5.
4.8. Evento de desplazamiento de un objeto gráfico con el ratón
Este evento tiene lugar cuando el objeto se desplaza dentro de los límites del gráfico. El manejador recibe el nombre del objeto en forma del parámetro de cadena sparam.
Vamos a verlo en un ejemplo. El trader intradía opera muy a menudo dentro de un intervalo temporal. Marcaremos sus límites con dos líneas verticales. La imagen será aproximadamente la siguiente (Fig. 11). El período que nos interesa está resaltado con color más claro.
Fig. 11 Límites del intervalo temporal
Usted puede cambiar el intervalo manualmente. Entonces, nuestro semiautomático debe reaccionar a este cambio.
Crearemos a nivel global dos variables que describen los nombres de dos verticales: gTimeLimit1_name y gTimeLimit2_name. Además, hay que crear dos variables para los nombres de los rectángulos que oscurecen el tiempo fuera del trading en el gráfico. También hay que crear las variables globales para los puntos de anclaje. Como tenemos dos rectángulos, serán cuatro puntos.
Aquí mostraré el código del módulo case del manejador del evento CHARTEVENT_OBJECT_DRAG:
//--- 8 case CHARTEVENT_OBJECT_DRAG: { comment+="8) arrastre del objeto gráfico con el ratón"; string curr_obj_name=sparam; //--- si se mueve una de las verticales if(!StringCompare(curr_obj_name,gTimeLimit1_name) || !StringCompare(curr_obj_name,gTimeLimit2_name)) { //--- coordenada del tiempo de las verticales datetime time_limit1=0; datetime time_limit2=0; //--- encontrar la primera vertical if(ObjectFind(0,gTimeLimit1_name)>-1) time_limit1=(datetime)ObjectGetInteger(0,gTimeLimit1_name,OBJPROP_TIME); //--- encontrar la segunda vertical if(ObjectFind(0,gTimeLimit2_name)>-1) time_limit2=(datetime)ObjectGetInteger(0,gTimeLimit2_name,OBJPROP_TIME); //--- si las verticales han sido encontradas if(time_limit1>0 && time_limit2>0) if(time_limit1<time_limit2) { //--- actualizar los parámetros de los rectángulos 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; }
Aquí hay una función personalizada RefreshRecPoints(). Ella se encarga de actualizar los valores de los puntos de anclaje para dos rectángulos. En el bloque de inicialización del EA puede informarse sobre cómo se crean los objetos gráficos. Llamaré la nueva versión EventProcessor8.mq5.
4.9. Evento del fin de edición del texto en el campo de introducción
Este tipo de evento es de carácter estrechamente especializado y aparece cuando en el campo de introducción se edita el texto. El parámetro sparam comunicará el nombre del objeto con el que se trabaja.
Vamos a crear un ejemplo. En el campo de introducción vamos a escribir la operación que queremos ejecutar. Que sean 2 operaciones: compra y venta en el mercado. Si introducimos en el campo la palabra «Buy», el EA comprará el activo, si escribimos «Sell», lo venderá. Vamos a arreglar que no dependamos del cambio de minúsculas y mayúsculas. Por eso se puede escribir «buy» y «sell». Además, en caso de la venta el texto y el borde del campo estarán en rojo, y en caso de la compra, en azul (Fig. 12).
Fig. 12 Compra a través del campo de introducción
Este es el código en el módulo case CHARTEVENT_OBJECT_ENDEDIT:
//--- 9 case CHARTEVENT_OBJECT_ENDEDIT: { comment+="9) fin de edición del texto en el campo de introducción"; //--- string curr_obj_name=sparam; //--- si se edita el campo establecido if(!StringCompare(curr_obj_name,gEdit_name)) { //--- obtener la descripción del objeto string obj_text=NULL; if(ObjectGetString(0,curr_obj_name,OBJPROP_TEXT,0,obj_text)) { //--- comprobar el valor if(!StringCompare(obj_text,"Buy",false)) { if(TryToBuy()) //--- establecer el color del texto ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrBlue); } else if(!StringCompare(obj_text,"Sell",false)) { if(TryToSell()) //--- establecer el color del texto ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrRed); } else { //--- establecer el color del texto ObjectSetInteger(0,gEdit_name,OBJPROP_COLOR,clrGray); } //--- redibujar el gráfico ChartRedraw(); } } //--- break; }
La versión del EA se llama EventProcessor9.mq5. En el archivo fuente se puede ver también el bloque de creación del campo de introducción.
4.10. Evento de modificación del gráfico
Y el último evento del que vamos a tratar en este artículo está relacionado con el cambio de configuraciones del propio gráfico. Este tipo del evento se destaca de los demás ya que no se trata de algún objeto en el gráfico sino del propio gráfico. El programador afirma que el evento se genera cuando se cambia el tamaño del gráfico o algo nuevo aparece en sus ajustes. Vamos a ver el siguiente ejemplo.
Que haya prohibición para cambiar algunos ajustes del gráfico. Entonces todos los intentos de cambiarlos serán ignorados. En realidad, el EA simplemente va a devolver los ajustes anteriores. Vamos a fijar los siguientes parámetros del gráfico:
- visualización de cuadrícula;
- tipo de visualización del gráfico;
- color del fondo.
Aquí tenemos el código para este módulo case:
//--- 10 case CHARTEVENT_CHART_CHANGE: { //--- alto y ancho actuales del gráfico int curr_ch_height=ChartHeightInPixelsGet(); int curr_ch_width=ChartWidthInPixels(); //--- si el alto y el ancho no se han cambiado if(gChartHeight==curr_ch_height && gChartWidth==curr_ch_width) { //--- fijar la propiedad: //--- visualización de cuadrícula if(!ChartShowGridSet(InpToShowGrid)) { Print("Failed to show grid!"); return(false); } //--- tipo de visualización del gráfico if(!ChartModeSet(InpMode)) { Print("Failed to set mode!"); return(false); } //--- color del fondo if(!ChartBackColorSet(InpBackColor)) { Print("Failed to set background сolor!"); return(false); } } //--- recordar las dimensiones de la ventana else { gChartHeight=curr_ch_height; gChartWidth=curr_ch_width; } //--- comment+="10) modificación del gráfico"; //--- break; }
El nombre de la última versión será EventProcessor10.mq5.
Conclusión
En este artículo he intentado demostrar la variedad de los eventos típicos del gráfico en MetaTrader 5. Espero que el material con los ejemplos de procesamiento de eventos sea útil para los que se inician en el lenguaje MQL5.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/689





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso