//+------------------------------------------------------------------+
//| DRAW_BARS.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_BARS"
#property description "Dibuja en la ventana separada las barras para el símbolo seleccionado"
#property description "El color y el grosor de las barras, igual que el estilo, se cambian de forma aleatoria "
#property description "cada N tics"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots 1
//--- plot Bars
#property indicator_label1 "Bars"
#property indicator_type1 DRAW_BARS
#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 BarsBuffer1[];
double BarsBuffer2[];
double BarsBuffer3[];
double BarsBuffer4[];
//--- 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,BarsBuffer1,INDICATOR_DATA);
SetIndexBuffer(1,BarsBuffer2,INDICATOR_DATA);
SetIndexBuffer(2,BarsBuffer3,INDICATOR_DATA);
SetIndexBuffer(3,BarsBuffer4,INDICATOR_DATA);
//--- 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_BARS("+symbol+")");
//--- valor vacío
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//---
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=0;
//--- 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 las propiedades de la línea
ChangeLineAppearance();
int tries=0;
//--- haremos 5 intentos de llenar el búfer con los precios desde symbol
while(!CopyFromSymbolToBuffers(symbol,rates_total) && 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);
}
//+------------------------------------------------------------------+
//| Llenamos los búfers indicadores con los precios |
//+------------------------------------------------------------------+
bool CopyFromSymbolToBuffers(string name,int total)
{
//--- 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(0,PLOT_LABEL,name+" Open;"+name+" High;"+name+" Low;"+name+" Close");
IndicatorSetString(INDICATOR_SHORTNAME,"DRAW_BARS("+name+")");
}
//--- inicializaremos los búfers con valores vacíos
ArrayInitialize(BarsBuffer1,0.0);
ArrayInitialize(BarsBuffer2,0.0);
ArrayInitialize(BarsBuffer3,0.0);
ArrayInitialize(BarsBuffer4,0.0);
//--- 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
BarsBuffer1[buffer_index]=rates[i].open;
BarsBuffer2[buffer_index]=rates[i].high;
BarsBuffer3[buffer_index]=rates[i].low;
BarsBuffer4[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]);
//--- apuntaremos el color de la línea
comm=comm+"\r\n"+(string)colors[color_index];
//--- bloque del cambio del grosor de las barras
number=MathRand();
//--- obtenemos el grosor como el remanente de la división de números enteros
int width=number%5; // el grosor puede ser de 0 a 4
//--- estableceremos el color como la propiedad PLOT_LINE_WIDTH
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,width);
//--- apuntaremos el grosor de la línea
comm=comm+"\r\nWidth="+IntegerToString(width);
//--- 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);
}
|