Startseite Technischer Indikator Beitrag

Hull Moving Average: Ein unverzichtbarer Indikator für MetaTrader 5

Anhang
39735.zip (3 KB, Herunterladen 0 mal)

Willkommen zurück, Trader-Freunde! Heute möchte ich euch einen spannenden Indikator vorstellen: den Hull Moving Average (HMA). Ich war selbst neugierig und habe ihn implementiert, da ich die Quellen anderer HMA-Implementierungen nicht ganz nachvollziehen konnte. Der HMA hat vier Eingabeparameter, die ich euch hier näherbringen möchte:

  1. InpHmaPeriod = 20
  2. InpColorKind = single_color
  3. InpColorIndex = color_index_3
  4. InpMaxHistoryBars = 240

Diese Parameter sind selbsterklärend. Die Enumeration ENUM_COLOR_KIND erlaubt es uns, zwischen einfarbiger und mehrfarbiger Darstellung zu wählen, wobei standardmäßig die einfarbige Variante gewählt wird. Im mehrfarbigen Modus zeigt der Hull MA eine andere Farbe für steigende und fallende Werte. Im einfarbigen Modus legt ENUM_COLOR_INDEX die Farbe des Hull MA fest. Standardmäßig ist die Farbe grau; bei Aufwärtstrends wird sie grün und bei Abwärtstrends rot. Ihr könnt das in den folgenden Bildern sehen:

Inputs

Available colors

Hier ist der Code für den HMA:

//+------------------------------------------------------------------+
//|                                                     MelzHull.mq5 |
//|                                                 Copyright 2022, wm1@gmx.de |
//|                                                       https://melz.one |
//+------------------------------------------------------------------+
/*
  === Meine Hull Moving Average Implementierung
  In meinem Indikator könnt ihr zwischen einfarbiger und mehrfarbiger Darstellung für die Indikatorlinie wählen.
*/

enum ENUM_COLOR_KIND {  // einfarbige oder wechselnde Farben
  single_color,
  multi_color
};

enum ENUM_COLOR_INDEX { // Index der Indikatorfarben
  color_index_0,
  color_index_1,
  color_index_2,
  color_index_3,
  color_index_4,
  color_index_5,
  color_index_6
};

#property copyright   "Copyright 2022 by W. Melz, wm1@gmx.de"
#property link        "https://melz.one"
#property version     "1.00"
#property description "Implementierung meines Hull Moving Average"
//--- Indikatoreinstellungen
#property indicator_chart_window              // im Chartfenster zeichnen
#property indicator_buffers 4                 // Buffer für: fullWMA, halfWMA, vHull, cHull
#property indicator_plots   1                 // nur eine Linie darstellen
#property indicator_type1   DRAW_COLOR_LINE   // als farbige Linie darstellen
// Farbindex zur Auswahl: 0        1      2       3              4             5            6, erweiterbar bis zu 64 Farben
#property indicator_color1  clrGray,clrGreen,clrRed,clrBlue,clrGreenYellow,clrDodgerBlue,clrFireBrick
#property indicator_width1  1                 // Linienstärke
#property indicator_label1  "HMA"             // Name des Indikators

//--- Eingabeparameter
input int                 InpHmaPeriod        = 20;             // Indikatorperiode, standard 20
input ENUM_COLOR_KIND     InpColorKind        = single_color;   // Art der Indikatorfarbe, einfarbig oder mehrfarbig
input ENUM_COLOR_INDEX    InpColorIndex       = color_index_3;  // Farbe der einfarbigen Anzeige
input int                 InpMaxHistoryBars   = 240;            // maximale historische Balken, standard 240

//--- Indikatorpuffer
double valueBuffer[];           // speichert Hull-Indikatorwerte
double colorBuffer[];           // speichert die Farbe des Hull-Indikators
double fullWMABuffer[];         // speichert das Ergebnis der WMA-Berechnung für die volle Periode
double halfWMABuffer[];         // speichert das Ergebnis der WMA-Berechnung für die halbe Periode

//--- Globale Variablen des Indikators
int hmaPeriod, fullPeriod, halfPeriod, sqrtPeriod, maxHistoryBars;  // speichert Eingabewerte oder Standardwerte

//+------------------------------------------------------------------+
//| Funktion zur Initialisierung des benutzerdefinierten Indikators                        |
//+------------------------------------------------------------------+
int OnInit() {
  ENUM_INIT_RETCODE result = checkInput();                // Überprüfen der Eingabeparameter

  SetIndexBuffer(0,valueBuffer,INDICATOR_DATA);           // Zuordnung des Indikatorpuffers
  SetIndexBuffer(1,colorBuffer,INDICATOR_COLOR_INDEX);    // Zuordnung der Kerzenfarbe des Indikators
  SetIndexBuffer(2,fullWMABuffer,INDICATOR_CALCULATIONS); // Zuordnung des Ergebnisses der vollen WMA-Berechnung
  SetIndexBuffer(3,halfWMABuffer,INDICATOR_CALCULATIONS); // Zuordnung des Ergebnisses der halben WMA-Berechnung
  IndicatorSetInteger(INDICATOR_DIGITS,_Digits);          // Setzen der Indikatorstellen
  string shortName = StringFormat("HMA(%d)",hmaPeriod);   // Name für DataWindow und Indikatorunterfenster
  IndicatorSetString(INDICATOR_SHORTNAME,shortName);
  PlotIndexSetString(0,PLOT_LABEL,shortName);

// Berechnung der globalen Werte für den Indikator
  fullPeriod = hmaPeriod;                             // Periode aus der Eingabe
  halfPeriod = fullPeriod / 2;                        // Berechnung der halben Periode
  sqrtPeriod = (int)round(sqrt((double)fullPeriod));  // Berechnung der Quadratwurzel der Periode

  return(result);                                     // Erfolg oder Misserfolg, Init abgeschlossen
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_INIT_RETCODE checkInput(void) {      // Diese Funktion für eigene Indikatorparameter anpassen
  if(InpHmaPeriod <= 0) {                 // Überprüfung der Eingabewerte
    hmaPeriod = 14;                       // Bei ungültigem Input auf 14 setzen
    PrintFormat("Ungültiger Eingabeparameter InpTestPeriod = %d. Indikator verwendet Wert %d für Berechnungen.",InpHmaPeriod,hmaPeriod);
  } else
    hmaPeriod = InpHmaPeriod;             // Periode aus der Eingabe setzen

  maxHistoryBars = InpMaxHistoryBars;   // andernfalls Eingabewert verwenden

  return(INIT_SUCCEEDED);                 // oder INIT_FAILED
}

//------------------------------------------------------------------
// Funktion zur Deinitialisierung des benutzerdefinierten Indikators
//------------------------------------------------------------------
void OnDeinit(const int reason) {
  ArrayFree(valueBuffer);
  ArrayFree(colorBuffer);
  ArrayFree(fullWMABuffer);
  ArrayFree(halfWMABuffer);
}

//+------------------------------------------------------------------+
//| Funktion zur Berechnung des benutzerdefinierten Indikators                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) {
  if(rates_total < maxHistoryBars + hmaPeriod)  // Überprüfung der verfügbaren Balken, Anpassung für die Periode bei der Berechnung anderer Indikatoren
    return(0);                                  // Wenn keine Balken verfügbar sind, nichts tun bei diesem Tick.

  int startBar;                 // speichert Indexwerte
  if(prev_calculated == 0) {    // Wenn keine historischen Balken zuvor berechnet wurden
    //Print("--- Berechnung historischer Balken");
    // Erster Tick, berechnet alle historischen Balken, ältester Index 0, plus rates_total - InpMaxHistoryBars -1 für Startindex
    startBar = rates_total - maxHistoryBars - hmaPeriod - 1;
    PlotIndexSetInteger(0,PLOT_DRAW_BEGIN, startBar + hmaPeriod);  // Setzt den Plotstart von dem Balken mit Index startBar + hmaPeriod
    // Berechnung
    CalcHma(startBar,rates_total,close);   // Berechnet die MA über das Volumen und vergleicht es mit der Balkengröße
  }
  
  if(rates_total - prev_calculated == 1) {
    //Print("-- Berechnung neuer Balken");
    startBar = rates_total - 1; // Berechnet den aktuellen neuen offenen Balken
    // Berechnung
    CalcHma(startBar,rates_total,close);   // Berechnet die MA über das Volumen und vergleicht es mit der Balkengröße
  }

  // Berechnung
  //Print("- Berechnung bei jedem Tick");
  return(rates_total);  // Gibt den Wert von prev_calculated für den nächsten Aufruf zurück
}

// Berechnung der MA von startBar bis rates_total im Array buf
void CalcHma(int startBar, const int rates_total, const double &buf[]) {
  for(int bar = startBar; bar < rates_total && !IsStopped(); bar++) { // Schleife über die Balken
  
    // (1) Indikatorberechnungen, WMA volle Periode
    double sum = 0.0;                                       // speichert den Periodensummenwert für die spätere Division
    double wMA = 0.0;                                      // speichert den berechneten Wert für diesen Balken
    int wf = 1;                                             // Startgewichtungsfaktor auf 1 setzen
    int sumWf = 0;                                          // Summe der Gewichtungsfaktoren auf 0 setzen
    for(int i = fullPeriod - 1; i >= 0 ; i--) {             // Schleife über die volle Periode für den aktuellen Balken
//      sum += getPrice(open,high,low,close,(bar - i)) * wf;  // Preis abrufen und Preise über n Balken addieren, ab ältestem Balken, niedrigster Index
      sum += buf[(bar - i)] * wf;                           // Preis abrufen und Preise über n Balken addieren, ab ältestem Balken, niedrigster Index
      sumWf += wf;                                          // Alle Gewichtungsfaktoren zur Division addieren
      wf += 1;                                              // Gewichtungsfaktoren für die lineare Gewichtung des nächsten neueren Balkens erhöhen
    }
    wMA = sum / sumWf;                                     // Berechnung des linear gewichteten Durchschnittswertes für die volle MA-Periode
    fullWMABuffer[bar] = wMA;                               // Wert im Puffer für die spätere Verwendung speichern

    // (2) Indikatorberechnungen, WMA halbe Periode
    sum = 0.0                                              // speichert den Periodensummenwert für die spätere Division
    wMA = 0.0                                              // speichert den berechneten Wert für diesen Balken
    wf = 1                                                 // Startgewichtungsfaktor auf 1 setzen
    sumWf = 0                                              // Summe der Gewichtungsfaktoren auf 0 setzen
    for(int i = halfPeriod - 1; i >= 0 ; i--) {             // Schleife über die halbe Periode für den aktuellen Balken
//      sum += getPrice(open,high,low,close,(bar - i)) * wf;  // Preis abrufen und Preise über n Balken addieren, ab ältestem Balken, niedrigster Index
      sum += buf[(bar - i)] * wf;                           // Preis abrufen und Preise über n Balken addieren, ab ältestem Balken, niedrigster Index
      sumWf += wf;                                          // Alle Gewichtungsfaktoren zur Division addieren
      wf += 1                                              // Gewichtungsfaktoren für die lineare Gewichtung des nächsten neueren Balkens erhöhen
    }
    wMA = sum / sumWf;                                     // Berechnung des linear gewichteten Durchschnittswertes für die halbe MA-Periode
    halfWMABuffer[bar] = wMA;                               // Wert im Puffer für die spätere Verwendung speichern

    // (3) Indikatorberechnungen, Hull berechnen
    sum = 0.0                                              // speichert den Periodensummenwert für die spätere Division
    wf = 1                                                 // Startgewichtungsfaktor auf 1 setzen
    sumWf = 0                                              // Summe der Gewichtungsfaktoren auf 0 setzen
    for(int i = sqrtPeriod - 1; i >= 0 ; i--) {             // Schleife über die halbe Periode für den aktuellen Balken
      sum += (2 * halfWMABuffer[bar - i] - fullWMABuffer[bar - i]) * wf;// Berechnung der Summe der Quadratwurzel(Periode) und Multiplikation mit dem Gewichtungsfaktor
      sumWf += wf;                                          // Alle Gewichtungsfaktoren zur Division addieren
      wf += 1                                              // Gewichtungsfaktoren für die lineare Gewichtung des nächsten neueren Balkens erhöhen
    }
    wMA = sum / sumWf;                                     // Berechnung des linear gewichteten Durchschnittswertes für die halbe MA-Periode
    valueBuffer[bar] = wMA;                                 // Speichert den HMA zur Anzeige

    // (4) Indikatorfarbberechnungen, anpassen nach Bedarf
    colorBuffer[bar] = getColor(bar);
  }
}

// Berechnung der Farbe für jeden Balken, nach Bedarf anpassen
double getColor(int bar) {
  double retval;                                  // Speichert den Rückgabewert
  if(InpColorKind == single_color)                // Einfarbige Darstellung
    retval = InpColorIndex;                       // blau
//    retval = InpHullColor;
    else {                                                  // Mehrfarbige Darstellung, standard ist grau
    retval = 0                                              // grau
    if(valueBuffer[bar - 1] < valueBuffer[bar])   // Bei Aufwärtstrend, grün
      retval = 1                                              // grün
    if(valueBuffer[bar - 1] > valueBuffer[bar])   // Bei Abwärtstrend, rot
      retval = 2                                              // rot
  }
  return(retval);                                   // Rückgabewert der berechneten Farbe
}

//+------------------------------------------------------------------+

Ich hoffe, ihr findet diesen Indikator genauso nützlich wie ich. Viel Spaß beim Trading!

Verwandte Beiträge

Kommentar (0)