Fibonacci ZigZag: Der Indikator für MetaTrader 5

Mike 2025.03.03 08:57 15 0 0
Anhang

Die Einrichtung

Um den Fibonacci ZigZag Indikator einzurichten, benötigen wir:

  • Ein ZigZag-Diagramm
  • Zwei Datenpuffer für die Hoch- und Tiefpunkte
  • Eingabeparameter
  • Ein laufendes Set von Systemvariablen, das zurückgesetzt wird, wann immer der Indikator neu berechnet wird

Der upWaves-Array speichert die Hochpunkte, während der dwWaves-Array die Tiefpunkte speichert.

Systemvariablen:

Wir müssen den Typ der letzten Welle, ihren Start- und Endpunkt sowie die Abstände in Bars vom Start- und Endpunkt kennen.

Zusätzlich benötigen wir lokale Hoch- und Tiefvariablen sowie Abstände in Bars von jedem Punkt.

//--- ZigZag-Tracking
  int wave_type=0;
  double wave_start_price=0.0;
  double wave_end_price=0.0;
  int wave_start_distance=0;
  int wave_end_distance=0;
  double high_mem=0.0;
  int distance_from_high=0;
  double low_mem=0.0;
  int distance_from_low=0;
  double rollingAtr=0.0;
  int rollingAtrs=0;

Wir erstellen anschließend eine Funktion zum Zurücksetzen des Systems:

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;
}

Das ist Standard: Fülle die Arrays mit Nullen und setze die Systemvariablen zurück.

In der Init-Funktion richten wir die Puffer, das Diagramm ein und rufen reset zum ersten Mal auf:

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

Lass uns direkt in die Berechnung eintauchen.

Der erste Schritt ist die Verwaltung des rollierenden ATR.

Solange wir nicht mehr Bars als die ATR-Periode gesammelt haben, machen wir nichts weiter.

Die Logik, die das rollierende ATR verwaltet, sieht so aus:

  • Wenn wir nicht mehr als die Periode gesammelt haben, fügen wir den Bereich der gefundenen Bars zu einer Summe hinzu
  • Sobald wir die Periode erreicht haben, führen wir die erste Division (Durchschnitt) durch
  • Danach entfernen wir einen Teil des rollierenden ATR, der atr/Periode ist, und fügen einen neuen Teil hinzu, der den Bereich der Bar / Periode ist
Wir setzen den letzten Teil zuerst, da er häufiger vorkommt und wir nicht auf zwei if-Anweisungen zugreifen müssen.
rollingAtrs++;
if(rollingAtrs>rollingAtrPeriod){
    double new_portion=((high[i]-low[i])/_Point)/((double)rollingAtrPeriod);
    rollingAtr=(rollingAtr)-(rollingAtr/((double)rollingAtrPeriod))+new_portion;
}
else if(rollingAtrs<=rollingAtrPeriod){
    rollingAtr+=(high[i]-low[i])/_Point;
    if(rollingAtrs==rollingAtrPeriod){
      rollingAtr/=((double)rollingAtrs);
      high_mem=high[i];
      low_mem=low[i];
      distance_from_high=0;
      distance_from_low=0;
    }
}

Super, jetzt steht ein weiteres Problem an.

Die Grundlage dieses ZigZags ist ein Retracement.

Doch um ein Retracement zu haben, muss es mindestens eine Welle geben.

Aber was wird die erste Welle retracen?

Deshalb machen wir Folgendes:

  • Sobald der ATR gefüllt ist (ATR gesammelt = Periode), erfassen wir das Hoch und das Tief in unseren Systemvariablen
  • Die Seite, die eine Welle mit einer gültigen Größe in ATR-Einheiten bildet und ein neues Hoch (Aufwärtswelle) oder ein neues Tief (Abwärtswelle) erreicht, gewinnt

So haben wir kein Retracement als Anfangswelle, aber wir müssen die Sequenz irgendwie starten.

Wir hätten auch einen klassischen Fraktalansatz für die erste Welle wählen können und dann mit Retracements fortfahren.

else{
    if(high[i]>high_mem&&low[i]>=low_mem){
      double new_wave_size_in_atr_units=((high[i]-low_mem)/_Point)/rollingAtr;
      if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
        wave_type=1;
        wave_start_price=low_mem;
        wave_start_distance=distance_from_low;
        wave_end_price=high[i];
        wave_end_distance=0;
        dwWaves[i-wave_start_distance]=low_mem;
        upWaves[i]=high[i];
        high_mem=high[i];
        distance_from_high=0;
        low_mem=low[i];
        distance_from_low=0;
    }
    }
else if(low[i]_Point)/rollingAtr;
      if(new_wave_size_in_atr_units>=minSizeInAtrUnits){
        wave_type=-1;
        wave_start_price=high_mem;
        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;
    }
    }
else if(low[i]high_mem){
    high_mem=high[i];
    low_mem=low[i];
    distance_from_high=0;
    distance_from_low=0;
    }
}

Jetzt der letzte Schritt.

Wenn wir eine Aufwärtswelle haben:

  1. Wenn ein neues Hoch erreicht wird, verschieben wir den ZigZag von der vorherigen Hochposition zur neuen Hochposition, da wir die Bar-Abstände beibehalten. Aktualisiere auch das Tief und den Abstand zum Tief.
  2. Wenn ein neues Tief erreicht wird, berechnen wir den Abstand vom Hoch zum Tief und dividieren ihn durch die Wellenhöhe. Wir multiplizieren mit 100, um den Eingabeparameter zu skalieren.
Hier ist der relevante Code für das oben Genannte:
if(wave_type==1){
    if(high[i]>wave_end_price){
      upWaves[i-wave_end_distance]=0.0;
      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;
    }
    if(low[i]0){
      low_mem=low[i];
      distance_from_low=0;
      double size_of_wave=(wave_end_price-wave_start_price)/_Point;
      double size_of_retracement=(wave_end_price-low_mem)/_Point;
      if(size_of_wave>0.0){
        double retraced=(size_of_retracement/size_of_wave)*100.0;
        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;
      }
    }
}

Das Gegenteil machen wir bei einer Abwärtswelle.

Und fertig, unser Retracement ZigZag ist bereit!

Hier ist der ZigZag mit 23,6% Retracement und 0,0 min Größe der Wellen in ATR-Einheiten


Und hier ist derselbe ZigZag mit 3 min Größe der Wellen in ATR-Einheiten


Liste
Kommentar 0