Hull Moving Average: L'indicatore per MetaTrader 5

Mike 2023.09.21 03:55 23 0 0
Allegato

Ciao a tutti! Oggi parliamo di un indicatore molto utile per i trader: la Hull Moving Average (HMA). Ho deciso di implementare personalmente questo indicatore, poiché non ero soddisfatto delle versioni già disponibili. La mia versione ha quattro parametri che puoi personalizzare:

  1. Periodo HMA (InpHmaPeriod) = 20
  2. Tipo di colore (InpColorKind) = colore singolo
  3. Indice del colore (InpColorIndex) = indice_colore_3
  4. Massimo numero di barre storiche (InpMaxHistoryBars) = 240

Questi parametri sono abbastanza intuitivi. L'enumerazione ENUM_COLOR_KIND permette di scegliere tra un colore singolo e uno multicolore; il valore di default è il colore singolo. Se scegli l'opzione multicolore, la HMA cambierà colore in base al trend: verde per i valori in crescita e rosso per quelli in calo. Nella modalità a colore singolo, l'indice del colore (ENUM_COLOR_INDEX) imposta il colore della HMA. Il colore di default nella modalità multicolore è il grigio. Ecco due immagini che mostrano i parametri e le opzioni di colore:

Inputs

Available colors

Ora vediamo il codice dell'indicatore:

//+------------------------------------------------------------------+
//| MelzHull.mq5 | 
//| Copyright 2022, wm1@gmx.de | 
//| https://melz.one |
//+------------------------------------------------------------------+

// Implementazione della Hull Moving Average

enum ENUM_COLOR_KIND { // singolo o multicolore
    single_color,
    multi_color
};

enum ENUM_COLOR_INDEX { // indice dei colori dell'indicatore
    color_index_0,
    color_index_1,
    color_index_2,
    color_index_3,
    color_index_4,
    color_index_5,
    color_index_6
};

// Proprietà dell'indicatore
#property copyright "Copyright 2022 by W. Melz, wm1@gmx.de"
#property link "https://melz.one"
#property version "1.00"
#property indicator_chart_window // disegna nella finestra del grafico
#property indicator_buffers 4 // buffer per: fullWMA, halfWMA, vHull, cHull
#property indicator_plots 1 // traccia solo una linea
#property indicator_type1 DRAW_COLOR_LINE // disegna come linea colorata
#property indicator_color1 clrGray, clrGreen, clrRed, clrBlue, clrGreenYellow, clrDodgerBlue, clrFireBrick
#property indicator_width1 1 // larghezza della linea
#property indicator_label1 "HMA" // nome dell'indicatore

// Parametri di input
input int InpHmaPeriod = 20; // periodo dell'indicatore, di default 20
input ENUM_COLOR_KIND InpColorKind = single_color; // tipo di colore dell'indicatore
input ENUM_COLOR_INDEX InpColorIndex = color_index_3; // setta il colore dell'indicatore a colore singolo
input int InpMaxHistoryBars = 240; // calcola barre storiche, di default 240, non di più

// Buffers dell'indicatore
double valueBuffer[]; // valori dell'indicatore HMA
double colorBuffer[]; // colore dell'indicatore sulle barre
double fullWMABuffer[]; // calcolo del WMA periodo completo
double halfWMABuffer[]; // calcolo del WMA metà periodo

// Variabili globali dell'indicatore
int hmaPeriod, fullPeriod, halfPeriod, sqrtPeriod, maxHistoryBars; // memorizza valore di input o valore di default

// Funzione di inizializzazione dell'indicatore
int OnInit() {
    ENUM_INIT_RETCODE result = checkInput(); // controlla i parametri di input
    SetIndexBuffer(0,valueBuffer,INDICATOR_DATA); // mappatura del buffer dell'indicatore
    SetIndexBuffer(1,colorBuffer,INDICATOR_COLOR_INDEX); // colore della candela dell'indicatore
    SetIndexBuffer(2,fullWMABuffer,INDICATOR_CALCULATIONS); // risultato del calcolo fullWMA
    SetIndexBuffer(3,halfWMABuffer,INDICATOR_CALCULATIONS); // risultato del calcolo halfWMA
    IndicatorSetInteger(INDICATOR_DIGITS,_Digits); // setta i decimali dell'indicatore
    string shortName = StringFormat("HMA(%d)",hmaPeriod); // nome del DataWindow e dell'etichetta della sottofinestra dell'indicatore
    IndicatorSetString(INDICATOR_SHORTNAME,shortName);
    PlotIndexSetString(0,PLOT_LABEL,shortName);

    // calcola valori globali per l'indicatore
    fullPeriod = hmaPeriod; // periodo dall'input
    halfPeriod = fullPeriod / 2; // calcola metà periodo
    sqrtPeriod = (int)round(sqrt((double)fullPeriod)); // calcola la radice quadrata del periodo

    return(result); // successo o fallimento, inizializzazione completata
}

// Funzione di controllo degli input
ENUM_INIT_RETCODE checkInput(void) {
    if(InpHmaPeriod <= 0) { // controlla il range dei valori di input
        hmaPeriod = 14; // se input non valido setta il periodo a 14
        PrintFormat("Parametri di input errati InpTestPeriod = %d. L'indicatore utilizzerà il valore %d per i calcoli.",InpHmaPeriod,hmaPeriod);
    } else
        hmaPeriod = InpHmaPeriod; // setta il periodo dall'input

    maxHistoryBars = InpMaxHistoryBars; // altrimenti utilizza il valore di input
    return(INIT_SUCCEEDED); // o INIT_FAILED
}

// Funzione di de-inizializzazione dell'indicatore
void OnDeinit(const int reason) {
    ArrayFree(valueBuffer);
    ArrayFree(colorBuffer);
    ArrayFree(fullWMABuffer);
    ArrayFree(halfWMABuffer);
}

// Funzione di calcolo dell'indicatore
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)
        return(0); // quando non ci sono barre disponibili, non fare nulla su questo tick.

    int startBar; // memorizza gli indici
    if(prev_calculated == 0) { // se non ci sono barre storiche calcolate prima
        startBar = rates_total - maxHistoryBars - hmaPeriod - 1; // calcola tutte le barre storiche
        PlotIndexSetInteger(0,PLOT_DRAW_BEGIN, startBar + hmaPeriod); // setta l'inizio del plot
        CalcHma(startBar,rates_total,close); // calcola le MA sul volume e confronta con la dimensione della barra
    }
    
    if(rates_total - prev_calculated == 1) {
        startBar = rates_total - 1; // calcola la barra aperta attuale
        CalcHma(startBar,rates_total,close); // calcola le MA sul volume e confronta con la dimensione della barra
    }

    return(rates_total); // restituisce il valore di prev_calculated per la prossima chiamata
}

// calcola la MA da startBar a rates_total sull'array buf
void CalcHma(int startBar, const int rates_total, const double &buf[]) {
    for(int bar = startBar; bar < rates_total && !IsStopped(); bar++) { // Loop over bars
        // Calcoli dell'indicatore, WMA periodo completo
        double sum = 0.0; // memorizza il valore totale per la divisione successiva
        double wMA = 0.0; // memorizza il valore calcolato per quella barra
        int wf = 1; // setta il fattore di ponderazione iniziale a 1
        int sumWf = 0; // setta la somma dei fattori di ponderazione a 0
        for(int i = fullPeriod - 1; i >= 0; i--) { // loop sul periodo completo per la barra attuale
            sum += buf[(bar - i)] * wf; // somma dei valori applicati e aggiungi i prezzi sulle n barre
            sumWf += wf; // aggiungi tutti i fattori di ponderazione per la divisione
            wf += 1; // aumenta i fattori di ponderazione per la ponderazione lineare della barra successiva
        }
        wMA = sum / sumWf; // calcola il valore medio ponderato lineare per il periodo completo
        fullWMABuffer[bar] = wMA; // salva il valore nel buffer per usi successivi

        // Calcoli dell'indicatore, WMA periodo metà
        sum = 0.0; // memorizza il valore totale per la divisione successiva
        wMA = 0.0; // memorizza il valore calcolato per quella barra
        wf = 1; // setta il fattore di ponderazione iniziale a 1
        sumWf = 0; // setta la somma dei fattori di ponderazione a 0
        for(int i = halfPeriod - 1; i >= 0; i--) { // loop sul periodo metà per la barra attuale
            sum += buf[(bar - i)] * wf; // somma dei valori applicati e aggiungi i prezzi sulle n barre
            sumWf += wf; // aggiungi tutti i fattori di ponderazione per la divisione
            wf += 1; // aumenta i fattori di ponderazione per la ponderazione lineare della barra successiva
        }
        wMA = sum / sumWf; // calcola il valore medio ponderato lineare per il periodo metà
        halfWMABuffer[bar] = wMA; // salva il valore nel buffer per usi successivi

        // Calcoli dell'indicatore, calcola Hull
        sum = 0.0; // memorizza il valore totale per la divisione successiva
        wf = 1; // setta il fattore di ponderazione iniziale a 1
        sumWf = 0; // setta la somma dei fattori di ponderazione a 0
        for(int i = sqrtPeriod - 1; i >= 0; i--) { // loop sul periodo per la barra attuale
            sum += (2 * halfWMABuffer[bar - i] - fullWMABuffer[bar - i]) * wf; // calcola la somma e moltiplica per il fattore di ponderazione
            sumWf += wf; // aggiungi tutti i fattori di ponderazione per la divisione
            wf += 1; // aumenta i fattori di ponderazione per la ponderazione lineare della barra successiva
        }
        wMA = sum / sumWf; // calcola il valore medio ponderato lineare per il periodo metà
        valueBuffer[bar] = wMA; // memorizza la HMA per la visualizzazione

        // Calcoli del colore dell'indicatore
        colorBuffer[bar] = getColor(bar);
    }
}

// calcola il colore per ogni barra
double getColor(int bar) {
    double retval; // memorizza il valore di ritorno
    if(InpColorKind == single_color) // imposta colore singolo
        retval = InpColorIndex; // blu
    else { // imposta colore multicolore
        retval = 0; // grigio
        if(valueBuffer[bar - 1] < valueBuffer[bar]) // se l'indicatore è in salita, allora verde
            retval = 1; // verde
        if(valueBuffer[bar - 1] > valueBuffer[bar]) // se l'indicatore è in discesa, allora rosso
            retval = 2; // rosso
    }
    return(retval); // restituisce il colore calcolato
}
//+------------------------------------------------------------------+

Buon utilizzo!

Elenco
Commento 0