MetaTrader5
Ideal ZigZag: Un Indicador Rápido para MetaTrader 5
¡Hola, traders! Hoy quiero hablarles sobre un indicador que puede revolucionar su forma de operar: el Ideal ZigZag. Este indicador es sencillo, pero su rapidez es impresionante.
No más picos suspendidos o valores erróneos. La recuperación de picos ha sido optimizada en tiempo, lo que lo convierte en una herramienta muy eficiente.
Ventajas:
La función más costosa en cálculos es iBarShift, pero aquí se reemplaza por ArrayBSearch, haciendo que el indicador sea más eficiente que su equivalente en MQL4.
Todos los datos necesarios para cada barra están disponibles en cualquier momento y accesibles para un Asesor Experto (EA) en cualquier momento de la historia.
No hay picos suspendidos.
Método eficiente para encontrar picos sin necesidad de buscar los valores del indicador.
¡Es muy rápido!
Funciona correctamente con inserciones históricas y al cambiar de marcos de tiempo.
Perfecto para su uso en EAs.
Desventajas:
Requisitos de memoria. El ZigZag necesita 2 buffers (uno no es suficiente por los retrasos) para un dibujo correcto; aquí se utilizan 5 buffers. Sin embargo, esta desventaja queda eclipsada por la ventaja #6. Ningún ZigZag rápido puede procesar correctamente las inserciones históricas con dos buffers.
Se requieren líneas adicionales para hacer visibles los datos a un Asesor Experto. Estas líneas nunca deben ser visibles.
Principio:
El ZigZag se dibuja bajo el principio de canalización. El ancho del canal se puede definir en puntos (IdealZZ) o en términos porcentuales (IdealZZP).
Recuperación de picos:
input int ChannelWidth=100;
#property indicator_chart_window
datetime LastTime;
int ZZHandle;
//+------------------------------------------------------------------+
//| Función de inicialización del indicador personalizado |
//+------------------------------------------------------------------+
void OnInit()
{
LastTime = 0;
ZZHandle = iCustom(_Symbol, Period(), "IdealZZ", ChannelWidth);
}
//+------------------------------------------------------------------+
//| GetValue |
//+------------------------------------------------------------------+
bool GetValue(double dir,int bar,int prevBar,double &peak,
int &peakBar,datetime &peakTime,const datetime &T[])
{
if(dir<0)
{
double t[1];
if(0>=CopyBuffer(ZZHandle,2,bar,1,t)) return false;
int i= ArrayBsearch(T, (datetime)t[0]);
if(i==prevBar)
{
if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false;
i=ArrayBsearch(T,(datetime)t[0]);
}
double v[1];
if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false;
if(v[0]==EMPTY_VALUE)
{
if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false;
i=ArrayBsearch(T,(datetime)t[0]);
if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false;
}
peak=v[0];
peakBar=i;
peakTime=(datetime)t[0];
}
else if(dir>0)
{
double t[1];
if(0>=CopyBuffer(ZZHandle,3,bar,1,t)) return false;
int i= ArrayBsearch(T, (datetime)t[0]);
if(i==prevBar)
{
if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false;
i=ArrayBsearch(T,(datetime)t[0]);
}
double v[1];
if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false;
if(v[0]==EMPTY_VALUE)
{
if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false;
i=ArrayBsearch(T,(datetime)t[0]);
if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false;
}
peak=v[0];
peakBar=i;
peakTime=(datetime)t[0];
}
else
{
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| GetValue |
//+------------------------------------------------------------------+
void SetPt(string name,double price,datetime time)
{
ObjectCreate(0,name,OBJ_ARROW,0,time,price);
ObjectSetInteger(0,name,OBJPROP_ARROWCODE,108);
ObjectSetDouble(0,name,OBJPROP_PRICE,price);
ObjectSetInteger(0,name,OBJPROP_TIME,time);
}
//+------------------------------------------------------------------+
//| Iteración del indicador personalizado |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &T[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(LastTime==T[0]) return(rates_total);
LastTime=T[0];
ArraySetAsSeries(T,true);
double dir_[1];
if(0>=CopyBuffer(ZZHandle,4,1,1,dir_)) return rates_total;
double dir=dir_[0];
double rdir=-dir;
if(dir==EMPTY_VALUE) return(rates_total);
double v1,v2,v3,v4,v5;
int i1,i2,i3,i4,i5;
datetime t1,t2,t3,t4,t5;
if(
GetValue(dir,1,0,v1,i1,t1,T) &&
GetValue(rdir,i1,0,v2,i2,t2,T) &&
GetValue(dir,i2,i1,v3,i3,t3,T) &&
GetValue(rdir,i3,i2,v4,i4,t4,T) &&
GetValue(dir,i4,i3,v5,i5,t5,T)
)
{
SetPt("1",v1,t1);
SetPt("2",v2,t2);
SetPt("3",v3,t3);
SetPt("4",v4,t4);
SetPt("5",v5,t5);
Print(v1," ",v2," ",v3," ",v4," ",v5," ",i1," ",i2," ",i3," ",i4," ",i5);
}
else
{
Print("Parece que hubo un error...");
}
return(rates_total);
}
//+------------------------------------------------------------------+
Este es un ejemplo de un indicador que marca (una vez por barra) los primeros cinco picos (incluyendo el que se está formando actualmente).
¡Atención! El código puede funcionar incorrectamente si se activa el modo de barra cero.
Modo de Barra Cero:
Este modo puede ser habilitado en la variable DrawZeroBar. Por defecto está desactivado y no se recomienda activarlo, especialmente si el indicador se utiliza en un Asesor Experto.
Disfruten usándolo y no duden en informarme sobre cualquier inconveniente que encuentren.
2012.07.20