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:
- InpHmaPeriod = 20
- InpColorKind = single_color
- InpColorIndex = color_index_3
- 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:


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
- Boom Index Spike Pattern – Ein Leitfaden für MetaTrader 5 Trader
- Tägliche prozentuale Veränderung in MT4 – Indikator für MetaTrader 4
- Uniformitätsfaktor-Indikator für MetaTrader 5: Analysiere deine Preisbewegungen
- MA Cross Alert Once – Ein hilfreicher Indikator für MetaTrader 4
- Tägliche prozentuale Veränderung in MT5 – Indikator für MetaTrader 5