//--- descripción #property description "El script construye el objeto gráfico \"Línea de tendencia por ángulo\"." #property description "Las coordenadas de los puntos de anclaje se establecen en por cientos de las dimensiones" #property description "de la ventana del gráfico." //--- mostramos la ventana de los parámetros de entrada durante el arranque del script #property script_show_inputs //--- los parámetros de entrada del script input string InpName="Trend"; // Nombre de la línea input int InpDate1=50; // Fecha del 1-er punto en % input int InpPrice1=75; // Precio del 1-er punto en % input int InpAngle=0; // Ángulo de inclinación de la línea input color InpColor=clrRed; // Color de la línea input ENUM_LINE_STYLE InpStyle=STYLE_DASH; // Estilo de la línea input int InpWidth=2; // Grosor de la línea input bool InpBack=false; // Línea al fondo input bool InpSelection=true; // Seleccionar para mover input bool InpRayLeft=false; // Continuación de la línea a la izquierda input bool InpRayRight=true; // Continuación de la línea a la derecha input bool InpHidden=true; // Ocultar en la lista de objetos input long InpZOrder=0; // Prioridad para el clic del ratón //+------------------------------------------------------------------+ //| Crea la línea de tendencia por ángulo | //+------------------------------------------------------------------+ bool TrendByAngleCreate(const long chart_ID=0, // ID del gráfico const string name="TrendLine", // nombre de la línea const int sub_window=0, // número de subventana datetime time=0, // hora del punto double price=0, // precio del punto const double angle=45.0, // ángulo de inclinación const color clr=clrRed, // color de la línea const ENUM_LINE_STYLE style=STYLE_SOLID, // estilo de la línea const int width=1, // grosor de la línea const bool back=false, // al fondo const bool selection=true, // seleccionar para mover const bool ray_left=false, // continuación de la línea a la izquierda const bool ray_right=true, // continuación de la línea a la derecha const bool hidden=true, // ocultar en la lista de objetos const long z_order=0) // prioridad para el clic del ratón { //--- para que sea más cómodo mover la línea de tendencia con ratón, crearemos el segundo punto datetime time2=0; double price2=0; //--- establecemos las coordenadas de los puntos de anclaje si todavía no han sido establecidas ChangeTrendEmptyPoints(time,price,time2,price2); //--- anulamos el valor del error ResetLastError(); //--- creamos la línea de tendencia por 2 puntos if(!ObjectCreate(chart_ID,name,OBJ_TRENDBYANGLE,sub_window,time,price,time2,price2)) { Print(__FUNCTION__, ": ¡Fallo al crear la línea de tendencia! Código del error = ",GetLastError()); return(false); } //--- cambiamos el ángulo de inclinación de la línea; durante el cambio del ángulo la coordenada del segundo //--- punto de la línea se cambiará automáticamente de acuerdo con los nuevos valores del ángulo ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle); //--- establecemos el color de la línea 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 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); //--- activamos (true) o desactivamos (false) el modo de continuación de la línea a la izquierda ObjectSetInteger(chart_ID,name,OBJPROP_RAY_LEFT,ray_left); //--- activamos (true) o desactivamos (false) el modo de continuación de la línea a la derecha ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right); //--- 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); } //+------------------------------------------------------------------+ //| Cambia las coordenadas del punto de anclaje de la línea de tendencia | //+------------------------------------------------------------------+ bool TrendPointChange(const long chart_ID=0, // ID del gráfico const string name="TrendLine", // nombre de la línea datetime time=0, // coordenada del tiempo del punto de anclaje double price=0) // coordenada del precio del punto de anclaje { //--- si las coordenadas del punto de anclaje no han sido establecidas, lo movemos a la barra actual con el precio Bid if(!time) time=TimeCurrent(); if(!price) price=SymbolInfoDouble(Symbol(),SYMBOL_BID); //--- anulamos el valor del error ResetLastError(); //--- movemos el punto de anclaje de la línea de tendencia if(!ObjectMove(chart_ID,name,0,time,price)) { Print(__FUNCTION__, ": ¡Fallo al mover el punto de anclaje! Código del error = ",GetLastError()); return(false); } //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ //| Cambia el ángulo de inclinación de la línea de tendencia | //+------------------------------------------------------------------+ bool TrendAngleChange(const long chart_ID=0, // ID del gráfico const string name="TrendLine", // nombre de la línea de tendencia const double angle=45) // ángulo de inclinación de la línea de tendencia { //--- anulamos el valor del error ResetLastError(); //--- cambiamos el ángulo de inclinación de la línea de tendencia if(!ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle)) { Print(__FUNCTION__, ": ¡Fallo al cambiar el ángulo de inclinación de la línea de tendencia! Código del error = ",GetLastError()); return(false); } //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ //| Elimina la línea de tendencia | //+------------------------------------------------------------------+ bool TrendDelete(const long chart_ID=0, // ID del gráfico const string name="TrendLine") // nombre de la línea { //--- anulamos el valor del error ResetLastError(); //--- eliminamos la línea de tendencia if(!ObjectDelete(chart_ID,name)) { Print(__FUNCTION__, ": ¡Fallo al eliminar la línea de tendencia! Código del error = ",GetLastError()); return(false); } //--- ejecución con éxito return(true); } //+------------------------------------------------------------------+ //| Comprueba los valores de los puntos de anclaje de la línea y para | //| los valores vacíos establece los valores por defecto | //+------------------------------------------------------------------+ void ChangeTrendEmptyPoints(datetime &time1,double &price1, datetime &time2,double &price2) { //--- si la hora del primer punto no ha sido establecida, se colocará en la barra actual if(!time1) time1=TimeCurrent(); //--- si el precio del primer punto no ha sido establecido, tendrá el valor Bid if(!price1) price1=SymbolInfoDouble(Symbol(),SYMBOL_BID); //--- determinamos las coordenadas del segundo punto auxiliar //--- el segundo punto va a estar 9 barras a la izquierda y tener el mismo precio datetime second_point_time[10]; CopyTime(Symbol(),Period(),time1,10,second_point_time); time2=second_point_time[0]; price2=price1; } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- comprobamos si los parámetros de entrada son correctos if(InpDate1<0 || InpDate1>100 || InpPrice1<0 || InpPrice1>100) { Print("¡Error. Los parámetros de entrada no son correctos!"); return; } //--- número de barras visibles en la ventana del gráfico int bars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS); //--- tamaño del array price int accuracy=1000; //--- arrays para guardar los valores de las fechas y precios que van a utilizarse //--- para establecer y modificar las coordenadas de los puntos de anclaje de la línea datetime date[]; double price[]; //--- asignación de la memoria ArrayResize(date,bars); ArrayResize(price,accuracy); //--- llenamos el array de datos ResetLastError(); if(CopyTime(Symbol(),Period(),0,bars,date)==-1) { Print("¡Fallo al copiar el valor de la hora! Código del error = ",GetLastError()); return; } //--- llenamos el array de precios //--- encontramos el valor máximo y mínimo del gráfico double max_price=ChartGetDouble(0,CHART_PRICE_MAX); double min_price=ChartGetDouble(0,CHART_PRICE_MIN); //--- determinamos el paso del cambio del precio y llenamos el array double step=(max_price-min_price)/accuracy; for(int i=0;i<accuracy;i++) price[i]=min_price+i*step; //--- definimos puntos para trazar la línea int d1=InpDate1*(bars-1)/100; int p1=InpPrice1*(accuracy-1)/100; //--- creamos la línea de tendencia if(!TrendByAngleCreate(0,InpName,0,date[d1],price[p1],InpAngle,InpColor,InpStyle, InpWidth,InpBack,InpSelection,InpRayLeft,InpRayRight,InpHidden,InpZOrder)) { return; } //--- redibujamos el gráfico y esperamos 1 segundo ChartRedraw(); Sleep(1000); //--- ahora vamos a mover y girar la línea //--- contador del ciclo int v_steps=accuracy/2; //--- movemos el punto de anclaje y cambiamos el ángulo de inclinación de la línea for(int i=0;i<v_steps;i++) { //--- cogemos el siguiente valor if(p1>1) p1-=1; //--- movemos el punto if(!TrendPointChange(0,InpName,date[d1],price[p1])) return; if(!TrendAngleChange(0,InpName,18*(i+1))) return; //--- comprobamos si el trabajo del script ha sido finalizado forzosamente if(IsStopped()) return; //--- redibujamos el gráfico ChartRedraw(); } //--- retardo de 1 segundo Sleep(1000); //--- eliminamos del gráfico TrendDelete(0,InpName); ChartRedraw(); //--- retardo de 1 segundo Sleep(1000); //--- } |