MetaTrader5
Fibonacci ZigZag: Configuración y Uso en MetaTrader 5
La Configuración
Para utilizar el indicador ZigZag basado en Fibonacci, necesitaremos lo siguiente:
1 gráfico de zigzag
2 buffers de datos para los máximos y mínimos
parámetros de entrada
un conjunto de variables del sistema que se reinician cada vez que el indicador recalcula
El array upWaves almacenará los máximos y el array dwWaves almacenará los mínimos.
Variables del sistema:
Debemos conocer el último tipo de ola, dónde comenzó, dónde terminó, la distancia en barras desde el inicio hasta el final.
También necesitaremos una variable de máximo local, una de mínimo local, así como distancias en barras desde cada punto.
//--- llevamos un registro del zigzag
int wave_type=0; // tipo de ola [0] ninguna [1] arriba [2] abajo
double wave_start_price=0.0; // precio de inicio de la ola
double wave_end_price=0.0; // precio final de la ola
int wave_start_distance=0; // distancia en barras desde el precio de inicio
int wave_end_distance=0; // distancia en barras desde el precio final
//--- seguimiento de precios máximos
double high_mem=0.0;
int distance_from_high=0;
//--- seguimiento de precios mínimos
double low_mem=0.0;
int distance_from_low=0;
//--- cálculo del ATR móvil
double rollingAtr=0.0;
int rollingAtrs=0;
Finalmente, el ATR móvil y cuántos se han calculado.
Luego creamos una función para reiniciar el sistema:
void resetSystem(){
ArrayFill(upWaves,0,ArraySize(upWaves),0.0);
ArrayFill(dwWaves,0,ArraySize(dwWaves),0.0);
wave_type=0;
wave_start_price=0.0;
wave_end_price=0.0;
wave_start_distance=0;
wave_end_distance=0;
high_mem=0.0;
low_mem=0.0;
distance_from_high=0;
distance_from_low=0;
rollingAtr=0.0;
rollingAtrs=0;
}
Esto es lo estándar: llenar los arrays con ceros y reiniciar las variables del sistema.
En OnInit configuramos los buffers, el gráfico y llamamos a reset por primera vez:
SetIndexBuffer(0,upWaves,INDICATOR_DATA);
SetIndexBuffer(1,dwWaves,INDICATOR_DATA);
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Color);
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,Width);
PlotIndexSetInteger(0,PLOT_LINE_STYLE,Style);
resetSystem();
Ahora, ¡vamos al cálculo!
Lo primero que debemos cuidar es el ATR móvil.
Hasta que hayamos recolectado más barras que el período del ATR, no haremos nada más.
La parte que maneja el ATR móvil es la siguiente:
si no hemos recolectado más que el período, seguimos sumando el rango de las barras encontradas
una vez que alcanzamos el período, realizamos la primera división (promedio)
después, recortamos una porción del ATR móvil, que es ATR/período, y luego añadimos una nueva porción que es rango de la barra/período
Colocamos la última parte primero porque sucederá con más frecuencia y no necesitaremos acceder a 2 declaraciones if.
//--- gestionar el ATR
rollingAtrs++;
if(rollingAtrs>rollingAtrPeriod){
double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
//--- eliminamos una porción antigua y añadimos una nueva
rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
}
else if(rollingAtrshigh_mem&&low[i]>=low_mem){
double new_wave_size_in_atr_units=((high[i]-low_mem)/_Point)/rollingAtr;
//--- si el nuevo tamaño de ola es válido
if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
//--- iniciamos una nueva ola ascendente
wave_type=1;
wave_start_price=low_mem;
wave_start_distance=distance_from_low;
wave_end_price=high[i];
wave_end_distance=0;
upWaves[i]=high[i];
high_mem=high[i];
distance_from_high=0;
low_mem=low[i];
distance_from_low=0;
}
}
//--- si rompimos el mínimo y no el máximo
else if(low[i]wave_end_price){
upWaves[i-wave_end_distance]=0.0; // eliminamos el precio final anterior de su posición en el array
upWaves[i]=high[i];
wave_end_price=high[i];
wave_end_distance=0;
high_mem=high[i];
distance_from_high=0;
low_mem=low[i];
distance_from_low=0;
}
//--- verificamos el retroceso
if(low[i]0.0){
double retraced=(size_of_retracement/size_of_wave)*100.0;
double new_wave_size_in_atr_units=((wave_end_price-low_mem)/_Point)/rollingAtr;
//--- si el nuevo tamaño de ola es válido
if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
//--- si el retroceso es significativo, iniciamos una ola descendente
if(retraced>=retracement){
wave_type=-1;
wave_start_price=high[i-distance_from_high];
wave_start_distance=distance_from_high;
wave_end_price=low[i];
wave_end_distance=0;
upWaves[i-wave_start_distance]=high_mem;
dwWaves[i]=low[i];
high_mem=high[i];
distance_from_high=0;
low_mem=low[i];
distance_from_low=0;
}
}
}
}
}
Hacemos lo opuesto cuando tenemos una ola descendente.
Y hemos terminado, nuestro zigzag de retroceso está listo.
Aquí está el zigzag con 23.6% de retroceso y 0.0 de tamaño mínimo de olas en unidades de ATR.
Y aquí está el mismo zigzag con 3 de tamaño mínimo de olas en unidades de ATR.
2025.03.03