Fibonacci ZigZag : Un Indicateur Pratique pour MetaTrader 5

Mike 2025.03.03 08:57 18 0 0
Pièce jointe

La mise en place

Pour commencer, voici ce dont nous aurons besoin :

  • 1 tracé ZigZag
  • 2 buffers de données pour les sommets et les creux
  • Des paramètres d'entrée
  • Un ensemble de variables système qui se réinitialisent chaque fois que l'indicateur se recalcul

Le tableau upWaves stockera les sommets et le tableau dwWaves stockera les creux.

Variables système :

Nous devons connaître le dernier type de vague, son point de départ, son point d'arrivée, ainsi que la distance en barres entre le début et la fin.

Ensuite, nous avons besoin d'une variable pour le sommet local et une pour le creux local, ainsi que des distances en barres de chaque point.

//--- suivi du zigzag
int wave_type=0;
//--- prix de départ de la vague
double wave_start_price=0.0;
//--- prix d'arrivée de la vague
double wave_end_price=0.0;
//--- distance en barres depuis le prix de départ
int wave_start_distance=0;
//--- distance en barres depuis le prix d'arrivée
int wave_end_distance=0;
//--- suivi des prix hauts
double high_mem=0.0;
int distance_from_high=0;
//--- suivi des prix bas
double low_mem=0.0;
int distance_from_low=0;
//--- ATR roulant
double rollingAtr=0.0;
int rollingAtrs=0;

Enfin, l'unité ATR roulante et combien ont été calculées.

Nous créons ensuite une fonction de réinitialisation :

void resetSystem(){
ArrayFill(upWaves,0,ArraySize(upWaves),0.0);
ArrayFill(dwWaves,0,ArraySize(dwWaves),0.0);
wake_type=0;
wake_start_price=0.0;
wake_end_price=0.0;
wake_start_distance=0;
wake_end_distance=0;
high_mem=0.0;
low_mem=0.0;
distance_from_high=0;
distance_from_low=0;
rollingAtr=0.0;
rollingAtrs=0;
}

Des choses standard, remplissons les tableaux avec des zéros et réinitialisons les variables système.

À l'initialisation, nous configurons les buffers, le tracé et appelons la réinitialisation pour la première fois :

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();

Passons maintenant au calcul.

La première chose à gérer est l'ATR roulant.

Jusqu'à ce que nous ayons collecté plus de barres que la période ATR, nous ne ferons rien d'autre.

La portion qui gère l'ATR roulant est la suivante :

  • Si nous n'avons pas encore atteint la période, continuez à ajouter la plage des barres trouvées à une somme.
  • Une fois la période atteinte, nous effectuons la première division (moyenne).
  • Après cela, nous coupons une portion de l'ATR roulant, soit ATR/période, puis ajoutons une nouvelle portion qui est la plage de la barre / période.
Nous plaçons la dernière partie en premier car elle se produira plus souvent et nous n'aurons pas besoin d'accéder à deux instructions conditionnelles.
//--- gérer l'ATR
rollingAtrs++;
if(rollingAtrs>rollingAtrPeriod){
    double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
    //--- nous retirons une ancienne portion et ajoutons une nouvelle portion
    rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
}
else if(rollingAtrs<=rollingAtrPeriod){
    rollingAtr+=(high[i]-low[i])/_Point;
    if(rollingAtrs==rollingAtrPeriod){
        rollingAtr/=((double)rollingAtrs);
        //--- démarrer la mémoire pour les hauts et les bas et le système
        high_mem=high[i];
        low_mem=low[i];
        distance_from_high=0;
        distance_from_low=0;
    }
}

Super, maintenant, il y a un autre problème.

La base de ce zigzag est un retracement.

Cependant, pour qu'un retracement se produise, il doit y avoir au moins une vague.

Mais quelle sera la première vague de retracement ? xD

Pour cela, nous allons faire ce qui suit :

  • Dès que l'ATR se remplit (ATR collecté = période), nous allons saisir le haut et le bas dans nos variables système.
  • Quel que soit le côté qui réussit à former une vague ayant une taille valide en unités ATR et formant un nouveau sommet (vague ascendante) ou un nouveau creux (vague descendante), remporte.

De cette façon, nous n'avons pas un retracement comme première vague, mais nous devons commencer la séquence d'une manière ou d'une autre.

Notez que nous aurions également pu opter pour une approche classique de fractales ici pour la première vague uniquement et ensuite continuer avec les retracements.

//--- si nous n'avons pas encore de type de vague
else{
    //--- si nous avons franchi le haut et non le bas
    if(high[i]>high_mem&&low[i]>=low_mem){
        double new_wave_size_in_atr_units=((high[i]-low_mem)/_Point)/rollingAtr;
        //--- si la nouvelle taille de vague est valide
        if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
            //--- démarrer une nouvelle vague ascendante
            wave_type=1;
            //--- prix de départ est le bas mémorisé
            wave_start_price=low_mem;
            wave_start_distance=distance_from_low;
            //--- prix d'arrivée est le nouveau sommet
            wave_end_price=high[i];
            wave_end_distance=0;
            //--- dessiner la vague
            dwWaves[i-wave_start_distance]=low_mem;
            upWaves[i]=high[i];
            //--- changer le sommet
            high_mem=high[i];
            distance_from_high=0;
            //--- changer le bas
            low_mem=low[i];
            distance_from_low=0;
        }
    }
    //--- si nous avons franchi le bas et non le haut
    else if(low[i]=minSizeInAtrUnits){
            //--- démarrer une nouvelle vague descendante
            wave_type=-1;
            //--- prix de départ est le haut mémorisé
            wave_start_price=high_mem;
            wave_start_distance=distance_from_high;
            //--- prix d'arrivée est le nouveau creux
            wave_end_price=low[i];
            wave_end_distance=0;
            //--- dessiner la vague
            upWaves[i-wave_start_distance]=high_mem;
            dwWaves[i]=low[i];
            //--- changer le sommet
            high_mem=high[i];
            distance_from_high=0;
            //--- changer le bas
            low_mem=low[i];
            distance_from_low=0;
        }
    }
    //--- si nous avons franchi les deux
    else if(low[i]high_mem){
        //--- les changer
        high_mem=high[i];
        low_mem=low[i];
        distance_from_high=0;
        distance_from_low=0;
    }
}

Super, maintenant la dernière pièce.

  • Si nous avons une vague ascendante :
  1. Si un nouveau sommet est créé, déplacez le zigzag de la position précédente vers la nouvelle position, ce que nous pouvons faire puisque nous conservons les distances en barres. Mettez également à jour le creux et la distance depuis le creux. Nous faisons cela pour pouvoir attraper le creux le plus bas depuis le sommet et vérifier s'il se retrace suffisamment pour commencer un nouveau creux.
  2. Si un nouveau creux est créé ou un nouveau creux est fixé, nous calculons la distance entre le sommet et le creux et la divisons par la taille de la vague. Et multiplions également par 100 pour correspondre à l'échelle des paramètres d'entrée. Ainsi, si la taille de la nouvelle "serait" vague qui retrace la précédente est également valide par rapport aux unités ATR, nous commençons une nouvelle vague descendante, définissons les nouveaux sommets et creux locaux, et établissons les distances en barres.

Voici le code pertinent pour ce qui précède :

//--- si nous avons une vague ascendante
if(wave_type==1){
    //--- si la vague s'étend vers le haut
    if(high[i]>wave_end_price){
        //--- retirer l'ancien prix final de sa position dans le tableau (0.0=vide)
        upWaves[i-wave_end_distance]=0.0;
        //--- le placer à la nouvelle position
        upWaves[i]=high[i];
        wave_end_price=high[i];
        wave_end_distance=0;
        //--- changer le sommet
        high_mem=high[i];
        distance_from_high=0;
        //--- changer le bas
        low_mem=low[i];
        distance_from_low=0;
    }
    //--- vérifier le retracement
    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 la nouvelle taille de vague est valide
            if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
                //--- si le retracement est significatif, démarrer une vague descendante
                if(retraced>=retracement){
                    //--- démarrer une nouvelle vague descendante
                    wave_type=-1;
                    //--- prix de départ est le haut mémorisé
                    wave_start_price=high[i-distance_from_high];
                    wave_start_distance=distance_from_high;
                    //--- prix d'arrivée est le nouveau creux
                    wave_end_price=low[i];
                    wave_end_distance=0;
                    //--- dessiner la vague
                    upWaves[i-wave_start_distance]=high_mem;
                    dwWaves[i]=low[i];
                    //--- changer le sommet
                    high_mem=high[i];
                    distance_from_high=0;
                    //--- changer le bas
                    low_mem=low[i];
                    distance_from_low=0;
                }
            }
        }
    }
}

Nous faisons l'inverse lorsque nous avons une vague descendante.

Et voilà, notre retracement ZigZag est prêt.

Voici le zigzag avec 23.6% de retracement et 0.0 taille minimale des vagues en unités ATR.


Et voici le même zigzag avec 3 min taille des vagues en unités ATR.






Liste
Commentaire 0