//+------------------------------------------------------------------+ //| DRAW_CANDLES.mq5 | //| Copyright 2000-2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property description "Indicador para demostrar DRAW_CANDLES." #property description "Dibuja en la ventana separada las velas para el símbolo seleccionado al azar desde MarketWatch." #property description " " #property description "El color y el grosor de las velas, igual que el estilo, se cambian" #property description "de forma aleatoria cada N tics." #property indicator_separate_window #property indicator_buffers 4 #property indicator_plots 1 //--- plot Bars #property indicator_label1 "DRAW_CANDLES1" #property indicator_type1 DRAW_CANDLES #property indicator_color1 clrGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- parámetros input input int N=5; // número de tics para el cambio de apariencia input int bars=500; // número de barras a mostrar input bool messages=false; // mostrar mensajes en el log "Asesores Expertos" //--- búfers indicadores double Candle1Buffer1[]; double Candle1Buffer2[]; double Candle1Buffer3[]; double Candle1Buffer4[]; //--- nombre del símbolo string symbol; //--- array para almacenar colores color colors[]={clrRed,clrBlue,clrGreen,clrPurple,clrBrown,clrIndianRed}; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- si bars es muy pequeño - finalizamos el trabajo antes de tiempo if(bars<50) { Comment("¡Por favor, indique el número más grande de barras! El trabajo del indicador ha sido finalizado"); return(INIT_PARAMETERS_INCORRECT); } //--- indicator buffers mapping SetIndexBuffer(0,Candle1Buffer1,INDICATOR_DATA); SetIndexBuffer(1,Candle1Buffer2,INDICATOR_DATA); SetIndexBuffer(2,Candle1Buffer3,INDICATOR_DATA); SetIndexBuffer(3,Candle1Buffer4,INDICATOR_DATA); //--- valor vacío PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); //--- nombre del símbolo para el que se dibujan las barras symbol=_Symbol; //--- estableceremos la visualización del símbolo PlotIndexSetString(0,PLOT_LABEL,symbol+" Open;"+symbol+" High;"+symbol+" Low;"+symbol+" Close"); IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_CANDLES("+symbol+")"); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { static int ticks=INT_MAX-100; //--- contamos los tics para el cambio del estilo, color y grosor de la línea ticks++; //--- si tenemos acumulado un número suficiente de tics if(ticks>=N) { //--- escogeremos nuevo símbolo en la ventana "Observación del mercado" symbol=GetRandomSymbolName(); //--- cambiamos la apariencia ChangeLineAppearance(); //--- escogeremos nuevo símbolo en la ventana "Observación del mercado" int tries=0; //--- haremos 5 intentos de llenar el búfer plot1 con los precios desde symbol while(!CopyFromSymbolToBuffers(symbol,rates_total,0, Candle1Buffer1,Candle1Buffer2,Candle1Buffer3,Candle1Buffer4) && tries<5) { //--- contador de llamadas a la función CopyFromSymbolToBuffers() tries++; } //--- actualizamos el contador de tics pasándolo a cero ticks=0; } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Llena la vela indicada | //+------------------------------------------------------------------+ bool CopyFromSymbolToBuffers(string name, int total, int plot_index, double &buff1[], double &buff2[], double &buff3[], double &buff4[] ) { //--- vamos a copiar los precios Open, High, Low y Close al array rates[] MqlRates rates[]; //--- contador de intentos int attempts=0; //--- cantidad que se ha copiado ya int copied=0; //--- hacemos 25 intentos de obtener la serie temporal para el símbolo necesario while(attempts<25 && (copied=CopyRates(name,_Period,0,bars,rates))<0) { Sleep(100); attempts++; if(messages) PrintFormat("%s CopyRates(%s) attempts=%d",__FUNCTION__,name,attempts); } //--- si no se ha podido copiar la cantidad suficiente de barras if(copied!=bars) { //--- formaremos la cadena del mensaje string comm=StringFormat("Para el símbolo %s se ha logrado obtener sólo %d barras de %d solicitadas", name, copied, bars ); //--- mostraremos el mensaje en un comentario en la ventana principal del gráfico Comment(comm); //--- mostramos el mensaje if(messages) Print(comm); return(false); } else { //--- estableceremos la visualización del símbolo PlotIndexSetString(plot_index,PLOT_LABEL,name+" Open;"+name+" High;"+name+" Low;"+name+" Close"); } //--- inicializaremos los búfers con valores vacíos ArrayInitialize(buff1,0.0); ArrayInitialize(buff2,0.0); ArrayInitialize(buff3,0.0); ArrayInitialize(buff4,0.0); //--- en cada tic copiamos los precios a los búfers for(int i=0;i<copied;i++) { //--- calcularemos el índice correspondiente para los búfers int buffer_index=total-copied+i; //--- escribimos los precios en los búfers buff1[buffer_index]=rates[i].open; buff2[buffer_index]=rates[i].high; buff3[buffer_index]=rates[i].low; buff4[buffer_index]=rates[i].close; } return(true); } //+------------------------------------------------------------------+ //| devuelve aleatoriamente el símbolo desde Market Watch | //+------------------------------------------------------------------+ string GetRandomSymbolName() { //--- número de símbolos mostrados en la ventana "Observación del mercado" int symbols=SymbolsTotal(true); //--- posición del símbolo en la lista - un número aleatorio de 0 a symbols int number=MathRand()%symbols; //--- devolvemos el nombre del símbolo sobre la posición indicada return SymbolName(number,true); } //+------------------------------------------------------------------+ //| cambia la apariencia de las barras | //+------------------------------------------------------------------+ void ChangeLineAppearance() { //--- cadena para formar la información sobre las propiedades de las barras string comm=""; //--- bloque del cambio del color de las barras int number=MathRand(); // obtenemos un número aleatorio //--- el divisor del número es igual al tamaño del array colors[] int size=ArraySize(colors); //--- obtenemos el índice para seleccionar nuevo color como el remanente de la división de números enteros int color_index=number%size; //--- estableceremos el color como la propiedad PLOT_LINE_COLOR PlotIndexSetInteger(0,PLOT_LINE_COLOR,colors[color_index]); //--- apuntamos el color comm=comm+"\r\n"+(string)colors[color_index]; //--- apuntamos el nombre del símbolo comm="\r\n"+symbol+comm; //--- mostraremos la información en el gráfico a través del comentario Comment(comm); } |