//+------------------------------------------------------------------+
//| Test_ChartSaveTemplate.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 script_show_inputs
//--- input parameters
input string symbol="GBPUSD"; // símbolo del gráfico nuevo
input ENUM_TIMEFRAMES period=PERIOD_H3; // período de tiempo del gráfico nuevo
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- primero adjuntamos al gráfico los indicadores
int handle;
//--- preparamos los indicadores para el uso
if(!PrepareZigzag(NULL,0,handle)) return; // fallo, entonces salimos
//--- colocamos el indicador en el gráfico actual, pero... en otra ventana :)
if(!ChartIndicatorAdd(0,1,handle))
{
PrintFormat("Fallo al adjuntar al gráfico %s/%s el indicador con el manejador=%d. Código del error %d",
_Symbol,
EnumToString(_Period),
handle,
GetLastError());
//--- finalizamos anticipadamente el trabajo del programa
return;
}
//--- actualizamos el gráfico para ver el indicador colocado
ChartRedraw();
//--- encontraremos los dos últimos virajes del zigzag
double two_values[];
datetime two_times[];
if(!GetLastTwoFractures(two_values,two_times,handle))
{
PrintFormat("No se ha podido encontrar los dos últimos virajes en el indicador Zigzag!");
//--- finalizamos anticipadamente el trabajo del programa
return;
}
//--- ahora adjuntamos el canal de desviación estándar
string channel="StdDeviation Channel";
if(!ObjectCreate(0,channel,OBJ_STDDEVCHANNEL,0,two_times[1],0))
{
PrintFormat("Fallo al crear el objeto %s. Código del error %d",
EnumToString(OBJ_STDDEVCHANNEL),GetLastError());
return;
}
else
{
//--- el canal está creado, definimos el segundo punto de apoyo
ObjectSetInteger(0,channel,OBJPROP_TIME,1,two_times[0]);
//--- asignaremos al canal el texto de ayuda emergente
ObjectSetString(0,channel,OBJPROP_TOOLTIP,"Demo from MQL5 Help");
//--- actualizaremos el gráfico
ChartRedraw();
}
//--- guardaremos toda esta maravilla en la plantilla
ChartSaveTemplate(0,"StdDevChannelOnZigzag");
//--- abriremos nuevo gráfico y aplicaremos la plantilla guardada
long new_chart=ChartOpen(symbol,period);
//--- activaremos la opción de descripción emergente para los objetos gráficos
ChartSetInteger(new_chart,CHART_SHOW_OBJECT_DESCR,true);
if(new_chart!=0)
{
//--- aplicaremos al gráfico nuevo la plantilla guardada
ChartApplyTemplate(new_chart,"StdDevChannelOnZigzag");
}
Sleep(10000);
}
//+------------------------------------------------------------------+
//| crea el manejador del zigzag y asegura la disponibilidad de sus datos |
//+------------------------------------------------------------------+
bool PrepareZigzag(string sym,ENUM_TIMEFRAMES tf,int &h)
{
ResetLastError();
//--- el indicador Zigzag debe ubicarse en la carpeta catálogo_de_datos_del_terminal\MQL5\Examples
h=iCustom(sym,tf,"Examples\\Zigzag");
if(h==INVALID_HANDLE)
{
PrintFormat("%s: Fallo al crear el manejador del indicador Zigzag. Código del error %d",
__FUNCTION__,GetLastError());
return false;
}
//--- cuando se crea el manejador del indicador, él necesita tiempo para calcular los valores
int k=0; // número de intentos para conseguir la calculación del indicador
//--- esperamos el cálculo en el ciclo, hacemos una pausa de 50 millisegundos si el cálculo aún no está listo
while(BarsCalculated(h)<=0)
{
k++;
//--- mostramos el número de intentos
PrintFormat("%s: k=%d",__FUNCTION__,k);
//--- esperamos 50 millisegundos hasta que el indicador se calcule
Sleep(50);
//--- si han sido más de 100 intentos, algo va mal
if(k>100)
{
//--- avisamos sobre el problema
PrintFormat("No se ha podido calcular el indicador con %d intentos!");
//--- finalizamos anticipadamente el trabajo del programa
return false;
}
}
//--- todo está listo, el indicador está creado y los valores están calculados
return true;
}
//+------------------------------------------------------------------+
//| busca los dos últimos virajes del zigzag y coloca en los arrays |
//+------------------------------------------------------------------+
bool GetLastTwoFractures(double &get_values[],datetime &get_times[],int handle)
{
double values[]; // array para obtener los valores del zigzag
datetime times[]; // array para obtener el tiempo
int size=100; // tamaño de arrays
ResetLastError();
//--- copiamos los 100 últimos valores del indicador
int copied=CopyBuffer(handle,0,0,size,values);
//--- comprobamos cuántos se han copiado
if(copied<100)
{
PrintFormat("%s: No se han copiado %d valores del indicador con el manejador=%d. Código del error %d",
__FUNCTION__,size,handle,GetLastError());
return false;
}
//--- definimos el orden de acceso al array como en una serie temporal
ArraySetAsSeries(values,true);
//--- escribiremos aquí los números de las barras en las que se han encontrado los virajes
int positions[];
//--- fijaremos los tamaños de arrays
ArrayResize(get_values,3); ArrayResize(get_times,3); ArrayResize(positions,3);
//--- contadores
int i=0,k=0;
//--- empezamos a buscar los virajes
while(i<100)
{
double v=values[i];
//--- los valores vacíos no nos interesan
if(v!=0.0)
{
//--- recordamos el número de la barra
positions[k]=i;
//--- recordamos el valor del zigzag en el viraje
get_values[k]=values[i];
PrintFormat("%s: Zigzag[%d]=%G",__FUNCTION__,i,values[i]);
//--- aumentamos contadores
k++;
//--- si hemos encontrado dos virajes, rompemos el ciclo
if(k>2) break;
}
i++;
}
//--- definimos el orden de acceso a los arrays como en una serie temporal
ArraySetAsSeries(times,true); ArraySetAsSeries(get_times,true);
if(CopyTime(_Symbol,_Period,0,size,times)<=0)
{
PrintFormat("%s: Fallo al copiar %d valores desde CopyTime(). Código del error %d",
__FUNCTION__,size,GetLastError());
return false;
}
//--- encontraremos el tiempo de apertura de las barras en las que han sido encontrados los 2 últimos virajes
get_times[0]=times[positions[1]];// el penúltimo valor se escribirá como el primer viraje
get_times[1]=times[positions[2]];// el tercer valor desde el final será el segundo viraje
PrintFormat("%s: el primero=%s, el segundo=%s",__FUNCTION__,TimeToString(get_times[1]),TimeToString(get_times[0]));
//--- todo ha salido bien
return true;
}
|