//+------------------------------------------------------------------+ //| GraphicObjects.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372/news | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372/news" #property strict #ifndef MQL_ARTICLES_UTILS_GRAPHIC_OBJECTS #define MQL_ARTICLES_UTILS_GRAPHIC_OBJECTS //+------------------------------------------------------------------+ //| Includes | //+------------------------------------------------------------------+ #include "..\\Utils\\Funciones Array.mqh" //+------------------------------------------------------------------+ //| Functions for creating native MT5 graphical objects | //+------------------------------------------------------------------+ bool VLineCreate(const long chart_ID, // ID del gráfico const string name, // nombre de la línea const int sub_window, // índice de subventana datetime time, // hora de la línea const color clr, // color de la línea const ENUM_LINE_STYLE style, // estilo de la línea const int width, // grosor de la línea const bool back, // al fondo const bool selection, // seleccionar para mover const bool ray, const string tooltip, // continuación de la línea abajo const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos la línea vertical if(!ObjectCreate(chart_ID, name, OBJ_VLINE, sub_window, time, 0)) { Print(__FUNCTION__, ": ¡Fallo al crear la línea vertical! Código del error = ", GetLastError()); return(false); } //--- establecemos el color de la línea ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de visualización de la línea ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el grosor de la línea ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento de la línea con ratón //--- cuando el objeto gráfico se crea usando la función ObjectCreate, por defecto el objeto //--- no se puede seleccionar y mover. Mientras que dentro de este método el parámetro selection //--- por defecto es igual a true, lo que permite seleccionar y mover este objeto ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- activar (true) o desactivar (false) el modo de visualización de la línea en las subventanas del gráfico ObjectSetInteger(chart_ID, name, OBJPROP_RAY, ray); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, tooltip); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool TrendCreate(long chart_ID, // ID del gráfico string name, // Nombre de la línea int sub_window, // índice de subventana datetime time1, // hora del primer punto double price1, // precio del primer punto datetime time2, // hora del segundo punto double price2, // precio del segundo punto color clr, // color de la línea ENUM_LINE_STYLE style, // estilo de la línea int width, // grosor de la línea bool back, // al fondo bool selection, // seleccionar para mover string toltip ) { //--- establecemos las coordenadas de los puntos de anclaje si todavía no han sido establecidas //--- anulamos el valor del error ResetLastError(); //--- creamos la línea de tendencia según las coordenadas establecidas if(!ObjectCreate(chart_ID, name, OBJ_TREND, sub_window, time1, price1, time2, price2)) { Print(__FUNCTION__, ": ¡Fallo al crear la línea de tendencia! Código del error = ", GetLastError()); return(false); } //--- establecemos el color de la línea ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, toltip); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); return(true); } //+------------------------------------------------------------------+ bool TrendaAngleCreate(long chart_ID, // ID del gráfico string name, // Nombre de la línea int sub_window, // índice de subventana datetime time1, // hora del primer punto double price1, // precio del primer punto datetime time2, // hora del segundo punto double price2, // precio del segundo punto color clr, // color de la línea ENUM_LINE_STYLE style, // estilo de la línea int width, // grosor de la línea bool back, // al fondo bool selection, // seleccionar para mover string toltip ) { //--- establecemos las coordenadas de los puntos de anclaje si todavía no han sido establecidas //--- anulamos el valor del error ResetLastError(); //--- creamos la línea de tendencia según las coordenadas establecidas if(!ObjectCreate(chart_ID, name, OBJ_TRENDBYANGLE, sub_window, time1, price1, time2, price2)) { Print(__FUNCTION__, ": ¡Fallo al crear la línea de tendencia! Código del error = ", GetLastError()); return(false); } //--- establecemos el color de la línea ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, toltip); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); return(true); } //+------------------------------------------------------------------+ bool TextCreate(long chart_ID, // ID del gráfico string name, // nombre del objeto int sub_window, // número de subventana datetime time, // hora del punto de anclaje double price, // precio del punto de anclaje string text, // el texto string font, // fuente int font_size, // tamaño de la fuente color clr, // color double angle, // inclinación del texto ENUM_ANCHOR_POINT anchor, // modo de anclaje bool back = false, // al fondo bool selection = false) // seleccionar para mover { //--- anulamos el valor del error ResetLastError(); //--- creamos el objeto "Texto" if(!ObjectCreate(chart_ID, name, OBJ_TEXT, sub_window, time, price)) { PrintFormat("Fallo al crear el texto %s, ultimo error %i", name, GetLastError()); return(false); } //--- ponemos el texto ObjectSetString(chart_ID, name, OBJPROP_TEXT, text); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, text); //--- establecemos la fuente del texto ObjectSetString(chart_ID, name, OBJPROP_FONT, font); //--- establecemos el tamaño del texto ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size); //--- establecemos el ángulo de inclinación del texto ObjectSetDouble(chart_ID, name, OBJPROP_ANGLE, angle); //--- establecemos el modo de anclaje ObjectSetInteger(chart_ID, name, OBJPROP_ANCHOR, anchor); //--- establecemos el color ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento del texto con ratón ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //ChartRedraw(chart_ID); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool ArrowCreate(const long chart_ID, // ID del gráfico const string name, // nombre de la flecha const int sub_window, // número de subventana datetime time, // hora del punto de anclaje double price, // precio del punto de anclaje const uchar arrow_code, // código de la flecha const ENUM_ARROW_ANCHOR anchor, // posición del punto de anclaje const color clr, // color de la flecha const ENUM_LINE_STYLE style, // estilo de la línea del contorno const int width, // tamaño de la flecha const bool back = true, // al fondo const bool selection = false, // seleccionar para mover const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos la flecha if(!ObjectCreate(chart_ID, name, OBJ_ARROW, sub_window, time, price)) { Print(__FUNCTION__, ": ¡Fallo al crear la flecha! Código del error = ", GetLastError(), " el nombre: ", name); return(false); } //--- establecemos el código de la flecha ObjectSetInteger(chart_ID, name, OBJPROP_ARROWCODE, arrow_code); //--- establecemos el modo de anclaje ObjectSetInteger(chart_ID, name, OBJPROP_ANCHOR, anchor); //--- establecemos el color de la flecha ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de la línea del contorno ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el tamaño de la flecha ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento de la flecha con ratón //--- cuando el objeto gráfico se crea usando la función ObjectCreate, por defecto el objeto //--- no se puede seleccionar y mover. Mientras que dentro de este método el parámetro selection //--- por defecto es igual a true, lo que permite seleccionar y mover este objeto ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool EditCreate(const long chart_ID, // ID del gráfico const string name, // nombre del objeto const int sub_window, // número de subventana const int x, // coordenada por el eje X const int y, // coordenada por el eje Y const int width, // ancho const int height, // alto const string text, // texto const string font, // fuente const int font_size, // tamaño de la fuente const ENUM_ALIGN_MODE align, // modo de alineación const bool read_only, // posibilidad de edición const ENUM_BASE_CORNER corner, // esquina del gráfico para el enlace const color clr, // color del texto const color back_clr, // color del fondo const color border_clr, // color del borde const bool back = false, // al fondo const bool selection = false, // seleccionar para mover const bool hidden = true, // ocultar en la lista de objetos const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos el campo de edición if(!ObjectCreate(chart_ID, name, OBJ_EDIT, sub_window, 0, 0)) { Print(__FUNCTION__, ": ¡Fallo al crear el objeto \"Campo de edición\"! Código del error = ", GetLastError()); return(false); } //--- establecemos las coordenadas del objeto ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y); //--- establecemos el tamaño del objeto ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width); ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height); //--- ponemos el texto ObjectSetString(chart_ID, name, OBJPROP_TEXT, text); //--- establecemos la fuente del texto ObjectSetString(chart_ID, name, OBJPROP_FONT, font); //--- establecemos el tamaño del texto ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size); //--- establecemos el modo de alineación del texto dentro del objeto ObjectSetInteger(chart_ID, name, OBJPROP_ALIGN, align); //--- ponemos (true) o cancelamos (false) el modo sólo para lectura ObjectSetInteger(chart_ID, name, OBJPROP_READONLY, read_only); //--- establecemos la esquina del gráfico respecto a la cual van a determinarse las coordenadas del objeto ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner); //--- establecemos el color del texto ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el color del fondo ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr); //--- establecemos el color del borde ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_COLOR, border_clr); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento de la etiqueta con ratón ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- ocultamos (true) o mostramos (false) el nombre del objeto gráfico en la lista de objetos ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool ButtonCreate(const long chart_ID, // ID del gráfico const string name, // nombre del botón const int sub_window, // número de subventana const int x, // coordenada por el eje X const int y, // coordenada por el eje Y const int width, // ancho del botón const int height, // alto del botón const ENUM_BASE_CORNER corner, // esquina del gráfico para el enlace const string text, // texto const string font, // fuente const int font_size, // tamaño de la fuente const color clr, // color del texto const color back_clr, // color del fondo const color border_clr, // color del borde const bool state = false, // pulsado/no pulsado const bool back = false, // al fondo const bool selection = false, // seleccionar para mover const bool hidden = false, // ocultar en la lista de objetos const long z_order = 0) //prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos el botón if(!ObjectCreate(chart_ID, name, OBJ_BUTTON, sub_window, 0, 0)) { Print(__FUNCTION__, ": ¡Fallo al crear el botón! Código del error = ", GetLastError()); return(false); } //--- establecemos las coordenadas del botón ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y); //--- establecemos el tamaño del botón ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width); ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height); //--- establecemos la esquina del gráfico respecto a la cual van a determinarse las coordenadas del punto ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner); //--- ponemos el texto ObjectSetString(chart_ID, name, OBJPROP_TEXT, text); //--- establecemos la fuente del texto ObjectSetString(chart_ID, name, OBJPROP_FONT, font); //--- establecemos el tamaño del texto ObjectSetInteger(chart_ID, name, OBJPROP_FONTSIZE, font_size); //--- establecemos el color del texto ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el color del fondo ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr); //--- establecemos el color del borde ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_COLOR, border_clr); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- set button state ObjectSetInteger(chart_ID, name, OBJPROP_STATE, state); //--- activar (true) o desactivar (false) el modo de desplazamiento del botón con ratón ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- ocultamos (true) o mostramos (false) el nombre del objeto gráfico en la lista de objetos ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool RectLabelCreate(const long chart_ID, // ID del gráfico const string name, // nombre de la etiqueta const int sub_window, // número de subventana const int x, // coordenada por el eje X const int y, // coordenada por el eje Y const int width, // ancho const int height, // alto const color back_clr, // color del fondo const ENUM_BORDER_TYPE border, // tipo del borde const ENUM_BASE_CORNER corner, // esquina del gráfico para el enlace const color clr, // color del contorno plano (Flat) const ENUM_LINE_STYLE style, // estilo del contorno plano const int line_width, // grosor del contorno plano const bool back = false, // al fondo const bool selection = false, // seleccionar para mover const bool hidden = true, // ocultar en la lista de objetos const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos la etiqueta rectangular if(!ObjectCreate(chart_ID, name, OBJ_RECTANGLE_LABEL, sub_window, 0, 0)) { Print(__FUNCTION__, ": ¡Fallo al crear la etiqueta rectangular! Código del error = ", GetLastError()); return(false); } //--- establecemos las coordenadas de la etiqueta ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y); //--- establecemos las dimensiones de la etiqueta ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width); ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height); //--- establecemos el color del fondo ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr); //--- establecemos el tipo del borde ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_TYPE, border); //--- establecemos la esquina del gráfico respecto a la cual van a determinarse las coordenadas del punto ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner); //--- establecemos el color del contorno plano (en modo Flat) ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de las líneas del contorno plano ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el grosor del contorno plano ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, line_width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento de la etiqueta con ratón ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- ocultamos (true) o mostramos (false) el nombre del objeto gráfico en la lista de objetos ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool ArrowRightPriceCreate(const long chart_ID, // ID del gráfico const string name, // nombre de la etiqueta de precio const int sub_window, // número de subventana datetime time, // hora del punto de anclaje double price, // precio del punto de anclaje const color clr, // color de la etiqueta de precio const ENUM_LINE_STYLE style, // estilo de la línea del contorno const int width, // tamaño de la etiqueta de precio const bool back, // al fondo const bool selection, // seleccionar para mover const bool hidden, // ocultar en la lista de objetos const long z_order) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos la etiqueta de precio if(!ObjectCreate(chart_ID, name, OBJ_ARROW_RIGHT_PRICE, sub_window, time, price)) { Print(__FUNCTION__, ": ¡Fallo al crear la etiqueta derecha de precio! Código del error = ", GetLastError()); return(false); } //--- establecemos el color de la etiqueta ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de la línea del contorno ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el tamaño de la etiqueta ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento de la etiqueta con ratón //--- cuando el objeto gráfico se crea usando la función ObjectCreate, por defecto el objeto //--- no se puede seleccionar y mover. Mientras que dentro de este método el parámetro selection //--- por defecto es igual a true, lo que permite seleccionar y mover este objeto ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- ocultamos (true) o mostramos (false) el nombre del objeto gráfico en la lista de objetos ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool EventCreate(const long chart_ID, // ID del gráfico const string name, // nombre del evento const int sub_window, // número de subventana const string text, // texto del evento datetime time, // hora const color clr, // color const int width, // grosor del punto durante la selección const bool back, // al fondo const string tooltip, const bool selection = false, // seleccionar para mover const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos el objeto "Evento" if(!ObjectCreate(chart_ID, name, OBJ_EVENT, sub_window, time, 0)) { Print(__FUNCTION__, ": ¡Fallo al crear el objeto \"Evento\"! Código del error = ", GetLastError()); return(false); } //--- ponemos el texto del evento ObjectSetString(chart_ID, name, OBJPROP_TEXT, text); //--- establecemos el color ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el grosor del punto de anclaje si el objeto está seleccionado ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de desplazamiento del evento con ratón ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- ocultamos (true) o mostramos (false) el nombre del objeto gráfico en la lista de objetos ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, tooltip); //--- establecemos la prioridad para obtener el evento de cliquear sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool RectangleCreate(long chart_ID, string name, const int sub_window, datetime time1, double price1, datetime time2, double price2, color clr, int width, bool fill, bool back, bool select, ENUM_LINE_STYLE style, string tooltip ) // ← 0% (totalmente opaco) a 100% (totalmente transparente) { ResetLastError(); // Crear objeto if(!ObjectCreate(chart_ID, name, OBJ_RECTANGLE, sub_window, time1, price1, time2, price2)) { Print(__FUNCTION__, ": Failed to create rectangle! Error code = ", GetLastError(), " name: ", name); return false; } // Seteo de propiedades ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); ObjectSetInteger(chart_ID, name, OBJPROP_FILL, fill); ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, select); ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, tooltip); return true; } //+------------------------------------------------------------------+ bool FiboLevelsCreate(const long chart_ID = 0, // ID del gráfico const string name = "FiboLevels", // nombre del objeto const int sub_window = 0, // número de subventana datetime time1 = 0, // hora del primer punto double price1 = 0, // precio del primer punto datetime time2 = 0, // hora del segundo punto double price2 = 0, // precio del segundo punto const color clr = clrRed, // color del objeto const ENUM_LINE_STYLE style = STYLE_SOLID, // estilo de las líneas del objeto const int width = 1, // grosor de las líneas del objeto const bool back = false, // al fondo const bool selection = true, // seleccionar para mover const bool ray_left = false, // continuación del objeto a la izquierda const bool ray_right = false, // continuación del objeto a la derecha const long z_order = 0) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos los "Retrocesos de Fibonacci" según las coordenadas establecidas if(!ObjectCreate(chart_ID, name, OBJ_FIBO, sub_window, time1, price1, time2, price2)) { Print(__FUNCTION__, ": ¡Falo al crear los \"Retrocesos de Fibonacci\"! Código del error = ", GetLastError()); return(false); } //--- establecemos el color ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de la línea ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el grosor de la línea ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de selección del objeto para mover //--- cuando el objeto gráfico se crea usando la función ObjectCreate, por defecto el objeto //--- no se puede seleccionar y mover. Mientras que dentro de este método el parámetro selection //--- por defecto es igual a true, lo que permite seleccionar y mover este objeto ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); //--- activamos (true) o desactivamos (false) el modo de continuación del objeto a la izquierda ObjectSetInteger(chart_ID, name, OBJPROP_RAY_LEFT, ray_left); //--- activamos (true) o desactivamos (false) el modo de continuación del objeto a la derecha ObjectSetInteger(chart_ID, name, OBJPROP_RAY_RIGHT, ray_right); //--- establecemos la prioridad para obtener el evento de cliquear con el ratón sobre el gráfico ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool FiboLevelsSet(int levels, // número de las líneas del nivel double &values[], // valores de las líneas del nivel color &colors[], // color de las líneas del nivel ENUM_LINE_STYLE &styles[], // estilo de las líneas del nivel int &widths[], // grosor de las líneas del nivel const long chart_ID = 0, // ID del gráfico const string name = "FiboLevels") // nombre del objeto { //--- comprobamos los tamaños de los arrays if(levels != ArraySize(colors) || levels != ArraySize(styles) || levels != ArraySize(widths)) { Print(__FUNCTION__, ": ¡Error. La longitud del array no corresponde al número de los niveles!"); return(false); } //--- establecemos el número de los niveles ObjectSetInteger(chart_ID, name, OBJPROP_LEVELS, levels); //--- establecemos las propiedades de los niveles en el ciclo for(int i = 0; i < levels; i++) { //--- valor del nivel ObjectSetDouble(chart_ID, name, OBJPROP_LEVELVALUE, i, values[i]); //--- color del nivel ObjectSetInteger(chart_ID, name, OBJPROP_LEVELCOLOR, i, colors[i]); //--- estilo del nivel ObjectSetInteger(chart_ID, name, OBJPROP_LEVELSTYLE, i, styles[i]); //--- grosor del nivel ObjectSetInteger(chart_ID, name, OBJPROP_LEVELWIDTH, i, widths[i]); //--- descripción del nivel ObjectSetString(chart_ID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); } //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ bool ChannelCreate(const long chart_ID, // ID del gráfico const string name, // nombre del canal const int sub_window, // número de subventana datetime time1, // hora del primer punto double price1, // precio del primer punto datetime time2, // hora del segundo punto double price2, // precio del segundo punto datetime time3, // hora del tercer punto double price3, // precio del tercer punto const color clr, // color del canal const ENUM_LINE_STYLE style, // estilo de las líneas del canal const int width, // grosor de las líneas del canal const bool fill, // relleno del canal con el color const bool back, // al fondo const bool selection, // seleccionar para mover string tooltip ) // prioridad para el clic del ratón { //--- anulamos el valor del error ResetLastError(); //--- creamos el canal según las coordenadas establecidas if(!ObjectCreate(chart_ID, name, OBJ_CHANNEL, sub_window, time1, price1, time2, price2, time3, price3)) { Print(__FUNCTION__, ": ¡Fallo al crear el canal equidistante! Código del error = ", GetLastError()); return(false); } //--- fijamos el color del canal ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr); //--- establecemos el estilo de las líneas del canal ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style); //--- establecemos el grosor de las líneas del canal ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, width); //--- activar (true) o desactivar (false) el modo de relleno del canal ObjectSetInteger(chart_ID, name, OBJPROP_FILL, fill); //--- mostramos en el primer plano (false) o al fondo (true) ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back); //--- activar (true) o desactivar (false) el modo de selección del canal para mover //--- cuando el objeto gráfico se crea usando la función ObjectCreate, por defecto el objeto //--- no se puede seleccionar y mover. Mientras que dentro de este método el parámetro selection //--- por defecto es igual a true, lo que permite seleccionar y mover este objeto ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection); ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection); ObjectSetString(chart_ID, name, OBJPROP_TOOLTIP, tooltip); //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ //| Extra functions | //+------------------------------------------------------------------+ void ModifiedIntegerPropertyByPrefix(long chart_id, int subwin, string prefix, ENUM_OBJECT obj_type, ENUM_OBJECT_PROPERTY_INTEGER property, long value) { int objtotal = ObjectsTotal(chart_id, subwin, obj_type); for(int i = 0; i < objtotal ; i++) { const string obj_name = ObjectName(chart_id, i, subwin, obj_type); if(StringFind(obj_name, prefix, 0) >= 0) { ObjectSetInteger(chart_id, obj_name, property, value); } } } //+------------------------------------------------------------------+ void DrawTPSL(long chart_id, int subwin, string prefix_, double tp, double sl, double entry, datetime time_entry, datetime end_time , color clr_tp_, color clr_sl_, bool fill_rect, int width_rect_, ENUM_LINE_STYLE style_rect) { string name_rect_tp = prefix_ + "tp_" + TimeToString(end_time); string name_rect_sl = prefix_ + "sl_" + TimeToString(end_time); RectangleCreate(chart_id, name_rect_tp, subwin, time_entry, entry, end_time, tp, clr_tp_, width_rect_, fill_rect, true, false, style_rect, "Take profit"); RectangleCreate(chart_id, name_rect_sl, subwin, time_entry, entry, end_time, sl, clr_sl_, width_rect_, fill_rect, true, false, style_rect, "Stop Loss"); } //+------------------------------------------------------------------+ #define HIDE_OBJECT(obj_name, chart_id) ObjectSetInteger(chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS) //+------------------------------------------------------------------+ #define SHOW_OBJECT(obj_name, chart_id) ObjectSetInteger(chart_id, obj_name, OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS) //+------------------------------------------------------------------+ inline long BarrasInRange(datetime init_time, datetime end_time, ENUM_TIMEFRAMES timeframe) { return (init_time > end_time) ? 0 : iBarShift(_Symbol, timeframe, init_time) - iBarShift(_Symbol, timeframe, end_time); } //+------------------------------------------------------------------+ //| Structure that stores a group of graphic objects to be deleted | //| at a specific time | //+------------------------------------------------------------------+ struct GraphicObjEliminations { // Array with the names of the objects that will be deleted when the current time is greater than "time_to_delete" string m_object_names[]; // Time at which the objects will be deleted datetime time_to_delete; }; //+------------------------------------------------------------------+ //| Class to manage the scheduled deletion of graphic objects | //| from a specified chart | //+------------------------------------------------------------------+ class CGraphicObjEliminations { private: //--- Internal variables GraphicObjEliminations m_eliminations[]; // Array of deletions int m_indexes_to_remove[]; // Indexes to remove from the deletions array int m_last_element_index; // Variable that stores the "position" of the last added element int m_current_object_index; // Variable that stores the "position" of the last string added to the last added element //--- Parameters long m_chart_id; // ID of the chart where the objects to be deleted should be found int m_reserve_delete_array; // Reserve for the deletions array 'm_indexes_to_remove' int m_reserve_main_array; // Reserve for the main array 'm_eliminations' int m_reserve_string_array; // Reserve for the string array of the last element added to the m_eliminations array public: CGraphicObjEliminations(void); //--- Initialization void Initilialize(long chart_id, int reserve_arr_delete, int reserve_main_arr, int reserve_str_arr); //--- Add a new set of names to delete void InitAddElement(datetime time_to_delete); inline void AddElement(const string& object_name); //--- General functions inline void DeleteAll(); inline void HideAll(); inline void ShowAll(); //--- General setters and getters // Chart id long ChartId() const { return m_chart_id; } void ChartId(long new_value) { m_chart_id = new_value; } // Reserve for the string "array" of the last element added to the deletions array int ElementStrArrayReserve() const { return m_reserve_string_array; } void ElementStrArrayReserve(int new_value) { m_reserve_string_array = new_value; } //--- Main function to check if graphic objects should be deleted void OnNewBar(datetime curr_time); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CGraphicObjEliminations::CGraphicObjEliminations(void) : m_reserve_delete_array(0), m_reserve_main_array(0), m_reserve_string_array(0), m_chart_id(0), m_last_element_index(0), m_current_object_index(0) { } //+------------------------------------------------------------------+ //| Initialization function | //+------------------------------------------------------------------+ void CGraphicObjEliminations::Initilialize(long chart_id, int reserve_arr_delete, int reserve_main_arr, int reserve_str_arr) { m_chart_id = chart_id; m_reserve_delete_array = reserve_arr_delete; m_reserve_main_array = reserve_main_arr; m_reserve_string_array = reserve_str_arr; } //+------------------------------------------------------------------+ //| Function to add a new group of graphic objects | //| that will be deleted at a specified time. | //+------------------------------------------------------------------+ void CGraphicObjEliminations::InitAddElement(datetime time_to_delete) { m_last_element_index = ArraySize(m_eliminations); m_current_object_index = 0; ArrayResize(m_eliminations, m_last_element_index + 1, m_reserve_main_array); m_eliminations[m_last_element_index].m_object_names.Reserve(m_reserve_string_array); m_eliminations[m_last_element_index].time_to_delete = time_to_delete; } //+----------------------------------------------------------------------+ //| Function to add a new object name to the last added set-element. | //+----------------------------------------------------------------------+ void CGraphicObjEliminations::AddElement(const string& object_name) { ArrayResize(m_eliminations[m_last_element_index].m_object_names, m_current_object_index + 1, m_reserve_string_array); m_eliminations[m_last_element_index].m_object_names[m_current_object_index] = object_name; m_current_object_index++; } //+------------------------------------------------------------------+ //| Deletes all stored graphic objects, and also | //| resizes the main array to 0 | //+------------------------------------------------------------------+ inline void CGraphicObjEliminations::DeleteAll(void) { for(int i = 0; i < ArraySize(m_eliminations); i++) for(int j = 0; j < ArraySize(m_eliminations[i].m_object_names); j++) ObjectDelete(m_chart_id, m_eliminations[i].m_object_names[j]); ArrayResize(m_eliminations, 0, m_reserve_main_array); } //+------------------------------------------------------------------+ //| Hides all stored graphic objects | //+------------------------------------------------------------------+ inline void CGraphicObjEliminations::HideAll(void) { for(int i = 0; i < ArraySize(m_eliminations); i++) for(int j = 0; j < ArraySize(m_eliminations[i].m_object_names); j++) HIDE_OBJECT(m_eliminations[i].m_object_names[j], m_chart_id); } //+------------------------------------------------------------------+ //| Shows all stored graphic objects | //+------------------------------------------------------------------+ inline void CGraphicObjEliminations::ShowAll(void) { for(int i = 0; i < ArraySize(m_eliminations); i++) for(int j = 0; j < ArraySize(m_eliminations[i].m_object_names); j++) SHOW_OBJECT(m_eliminations[i].m_object_names[j], m_chart_id); } //+----------------------------------------------------------------------+ //| Main function in which we check which elements of the deletions | //| array are ready to be deleted both from the array and graphically | //| from the chart with ObjectDelete | //+----------------------------------------------------------------------+ void CGraphicObjEliminations::OnNewBar(datetime curr_time) { //--- Initial const int total_eliminations = ArraySize(m_eliminations); ArrayResize(m_indexes_to_remove, 0, m_reserve_delete_array); int remove_index_count = 0; //--- Review for(int i = 0; i < total_eliminations; i++) // From oldest to newest { if(m_eliminations[i].time_to_delete < curr_time) { //--- Delete for(int j = 0; j < ArraySize(m_eliminations[i].m_object_names); j++) ObjectDelete(m_chart_id, m_eliminations[i].m_object_names[j]); //--- Mark ArrayResize(m_indexes_to_remove, remove_index_count + 1, m_reserve_delete_array); m_indexes_to_remove[remove_index_count] = i; remove_index_count++; } } //--- Delete RemoveMultipleIndexes(m_eliminations, m_indexes_to_remove, m_reserve_main_array); } //+------------------------------------------------------------------+ #endif