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:
- Periodo HMA (InpHmaPeriod) = 20
- Tipo di colore (InpColorKind) = colore singolo
- Indice del colore (InpColorIndex) = indice_colore_3
- 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:


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!
Commento 0