Testare i diversi tipi di media mobile per vedere quanto sono efficaci
Introduzione
Nel mio precedente articolo abbiamo preso in considerazione i tipi più diffusi di Medie Mobili (semplici, ponderate, esponenziali): Scopri come progettare diversi sistemi di Media Mobile. Continueremo questo argomento in questo articolo e utilizzeremo il tipo semplice per confrontare i suoi risultati con altri tipi di medie mobili. Molti trader utilizzano la media mobile in diverse tipologie a seconda delle loro preferenze. In questo articolo, quindi, ne considereremo in dettaglio diversi tipi, ne testeremo le prestazioni e confronteremo i risultati per definire quale di questi tipi si comporta meglio.
Ai fini di questo articolo, creeremo una semplice applicazione in modo da eseguire il backtesting delle medie nello Strategy Tester integrato di MetaTrader 5. Per capire su cosa dobbiamo concentrarci quando studiamo i risultati dei test, consultate il mio articolo precedente Comprendere e Utilizzare Efficacemente lo Strategy Tester MQL5; fornisce molte informazioni utili.
Per considerare i diversi tipi di medie mobili e vedere come si comportano, esamineremo i seguenti argomenti:
- Test del Sistema della Media Mobile Semplice (SMA)
- Media Mobile Adattiva (iAMA)
- Doppia Media Mobile Esponenziale (iDEMA)
- Tripla Media Mobile Esponenziale (iTEMA)
- Media Mobile Adattativa Frattale (iFrAMA)
- Confronto dei Risultati con i Risultati della Media Mobile Semplice (SMA)
- Conclusioni
Notare che, sebbene cercherò di ottimizzare le impostazioni di ogni media mobile per ottenere i migliori risultati, è necessario effettuare più controlli e test da soli, poiché l'obiettivo qui è solo educativo. Pertanto, è necessario testare, ottimizzare e trovare le migliori impostazioni che possano dare risultati superiori. Può accadere che una o tutte queste tipologie non siano adatte al vostro stile di trading. Ma spero che possiate trovare spunti utili per migliorare il vostro trading. In generale, qualunque sia l'ideale che si incontra, è importante misurare la performance di qualsiasi strategia di trading prima di utilizzarla su un conto reale.
Test del Sistema della Media Mobile Semplice (SMA)
In questa parte, condividerò i risultati del semplice sistema basato solo su una semplice strategia con una media mobile. Trova l'incrocio tra il prezzo e la linea della media mobile semplice che genererà segnali di acquisto e di vendita. Creeremo un sistema in grado di eseguire questi segnali automaticamente.
Utilizzeremo i seguenti segnali per eseguire operazioni di trading:
Segnale di acquisto:
Il prezzo di chiusura è superiore al valore della media mobile semplice
E il prezzo di chiusura precedente era inferiore al valore della media mobile semplice precedente.
Segnale di vendita:
Il prezzo di chiusura è al di sotto del valore della media mobile semplice
E il prezzo di chiusura precedente era superiore al valore della media mobile semplice precedente.
Se volete leggere altro sulla media mobile semplice e sugli altri tipi di media mobile più diffusi, vi consiglio di leggere il mio precedente articolo Impara a progettare diversi sistemi di Medie Mobili, vi aiuterà a comprenderle bene e a capire meglio questo articolo.
Di seguito sono illustrati i passaggi per creare questo tipo di sistema di trading in grado di eseguire automaticamente gli ordini di acquisto e di vendita sulla base dei segnali citati.
Nell'ambito globale, includeremo nel software il file include, Trade, che consente di eseguire gli ordini in base ai nostri segnali utilizzando il preprocessore #include. Se volete saperne di più sul preprocessore, potete leggere l'articolo Tutto quello che c'è da apprendere sulla struttura del programma MQL5 per maggiori dettagli.
#include <Trade\Trade.mqh> Creare tre input utente per la variabile double lotSize, la variabile ENUM_TIMEFRAMES timeFrame e la variabile integer MAPeriod da modificare secondo i desideri dell'utente con valori predefiniti:
input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50;
Creare le due variabili integer simpleMA e barsTotal senza assegnazione, poiché le definiremo in seguito nella parte OnInit()
int simpleMA; int barsTotal;
Creare trade come oggetto della classe CTrade per accedere facilmente alle funzioni di trade.
CTrade trade;
Nella parte OnInit(), definiremo la simpleMA utilizzando la funzione iMA che restituisce l'handle dell'indicatore di media mobile e i suoi parametri sono:
- symbol: per specificare il nome del simbolo, utilizzeremo _Symbol per il simbolo corrente
- period: per specificare il time frame utilizzeremo l'input dell'utente con un valore predefinito di 1 ora, ma l'utente può regolarlo
- ma_period: per specificare il periodo della media mobile semplice, utilizzeremo l'input dell'utente con un valore predefinito di 50, ma l'utente può regolare anche questo.
- ma_shift: per specificare lo spostamento orizzontale, useremo 0
- applied_price: per specificare il tipo di prezzo, utilizzeremo il prezzo di chiusura per il calcolo della media mobile semplice.
simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
E barsTotal utilizzando la funzione iBars che restituisce il numero di barre; i suoi parametri sono:
- symbol: per specificare il simbolo, useremo (_Symbol) da applicare al simbolo corrente
- timeframe: per specificare il time frame, utilizzeremo il time frame creato dall'utente con il valore predefinito di 1 ora, che l'utente potrà regolare
barsTotal=iBars(_Symbol,timeFrame);
Nella parte OnTick(), creeremo due array, uno per i prezzi utilizzando MqlRates per memorizzare le informazioni su prezzi, volumi e spread e l'altro per la media mobile semplice:
MqlRates priceArray[]; double mySMAArray[];
Per impostare il flag AS_SERIES su questi due array creati, si utilizza la funzione ArraySetAsSeries, i cui parametri sono:
- array[]: per specificare l'array per riferimento
- flag: per specificare la direzione di indicizzazione dell'array
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);
Definire i prezzi Ask e Bid dopo aver creato due variabili double
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
Ottenere i dati storici di MqlRates utilizzando la funzione CopyRates, i cui parametri sono:
- symbol_name: per determinare il nome del simbolo
- timeframe: per determinare il time frame
- start_pos: per specificare la posizione iniziale
- count: per specificare il numero di dati da copiare
- rates_array[]: per specificare l'array di destinazione i cui copiare
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
Ottenere i dati del buffer dell'indicatore utilizzando la funzione CopyBuffer, i cui parametri sono:
- indicator_handle: per specificare l'handle dell'indicatore che è simpleMA qui
- buffer_num: per specificare il numero di buffer dell'indicatore, che è 0
- start_pos: per determinare la posizione iniziale, che è 0, ovvero la candela attuale
- count: per specificare la quantità che abbiamo bisogno di copiare, che è 3
- buffer[]: per specificare l'array di destinazione in cui copiare, che è mySMAArray
CopyBuffer(simpleMA,0,0,3,mySMAArray);
Definizione dell'ultimo prezzo di chiusura e del valore della media mobile semplice della stessa candela dopo la creazione di due variabili double per questi due valori
double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
Definire il prezzo di chiusura precedente e il valore della media mobile semplice di questa stessa candela dopo aver creato altre due variabili double per questi due valori
double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
Creazione di una variabile integer bars da confrontare con la variabile barsTotal creata
int bars=iBars(_Symbol,timeFrame);
Verificare se è stata creata una nuova barra controllando barsTotal se non è uguale a bars
if(barsTotal != bars) Se barsTotal non è uguale a bars, occorre aggiornare barsTotal con il valore di bars.
barsTotal=bars;
Se barsTotal non è uguale a bars, dobbiamo anche verificare le condizioni della strategia se la precedente chiusura è inferiore al valore della media mobile semplice della stessa candela e allo stesso tempo l'ultimo prezzo di chiusura è superiore al valore della media mobile semplice della stessa candela. Il programma deve chiudere la posizione aperta corrente e aprire una posizione di acquisto.
if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); }
Se la precedente chiusura è superiore al valore della media mobile semplice della stessa candela e allo stesso tempo l'ultimo prezzo di chiusura è inferiore al valore della media mobile semplice della stessa candela. Il programma deve chiudere la posizione aperta e aprire una posizione di vendita.
if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); }
Compiliamo quindi il codice e lo troveremo compilato senza errori o avvertimenti.
Di seguito viene riportato il codice completo in un unico blocco:
//+------------------------------------------------------------------+ //| SMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int simpleMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { simpleMA = iMA(_Symbol, timeFrame, MAPeriod, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true); int Data=CopyRates(_Symbol,_Period,0,3,priceArray); CopyBuffer(simpleMA,0,0,3,mySMAArray); double lastClose=(priceArray[1].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Compiliamo l'EA e lo eseguiamo sui dati EURUSD per eseguire il backtest della strategia. Il periodo di test va dal 1° gennaio al 30 giugno 2022, come abbiamo fatto per tutti i tipi di media mobile menzionati. Le nostre impostazioni per la SMA saranno le seguenti:
- Dimensioni del lotto: 1
- Time frame: 1 ora
- Periodo MA: 50
I risultati del test:

Come possiamo vedere, le figure seguenti devono essere studiate dopo aver testato l'indicatore SMA:
- Utile Netto: 2700.30 (27%)
- Saldo DD relativo: 37.07%
- Equity DD relativo: 41.76%
- Fattore di profitto: 1.10
- Profitto atteso: 12.68
- Fattore di recupero: 0.45
- Indice di Sharpe 0.57
Media Mobile Adattiva (iAMA)
In questa parte, impareremo a conoscere un altro tipo di media mobile, la AMA (Adaptive Moving Average). È stata sviluppata da Perry J. Kaufman e si chiama (KAMA) e il concetto principale è quello di ridurre il rumore nel movimento dei prezzi. Segue il movimento dei prezzi, indipendentemente dalla volatilità di questo movimento, adattandosi ad esso. L'indicatore è un trend-follower, quindi può essere utilizzato per identificare la tendenza e i punti di svolta.
L'indicatore viene calcolato in pochi passaggi.
Primo passo: Calcolo di AMA o KAMA

Secondo passo: Calcolo della costante di attenuazione (SC)

Terzo passo: Calcolo del Rapporto di Efficienza (ER)

Ora, abbiamo imparato a calcolare manualmente l'indicatore AMA, ma non ne abbiamo bisogno perché possiamo inserirlo automaticamente in MetaTrader 5 scegliendolo tra gli indicatori già pronti. È il momento di creare un sistema di trading in grado di eseguire ordini di acquisto e di vendita in base all'incrocio tra il prezzo di chiusura e l'indicatore AMA. Pertanto, per la nostra strategia utilizzeremo i seguenti segnali.
Segnale d’acquisto:
Il prezzo di chiusura è superiore al valore della media mobile adattativa
E il prezzo di chiusura precedente era inferiore al valore della media mobile adattiva precedente.
Segnale di vendita:
Il prezzo di chiusura è inferiore al valore della media mobile adattiva
E il prezzo di chiusura precedente era superiore al valore della media mobile adattiva precedente.
Di seguito è riportato il codice completo per la creazione di questo tipo di sistema di trading:
//+------------------------------------------------------------------+ //| iAMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; input int fastMAPeriod= 5; input int slowMAPeriod= 100; int adaptiveMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { adaptiveMA = iAMA(_Symbol, timeFrame, MAPeriod,fastMAPeriod,slowMAPeriod, 0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myAMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myAMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(adaptiveMA,0,0,3,myAMAArray); double lastClose=(priceArray[1].close); double AMAVal = NormalizeDouble(myAMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevAMAVal = NormalizeDouble(myAMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>AMAVal && prevClose<prevAMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<AMAVal && prevClose>prevAMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
La differenza in questo codice è l'utilizzo della funzione iAMA che restituisce l'handle dell'indicatore della media mobile adattiva e i suoi parametri sono:
- symbol: per specificare il nome del simbolo, utilizzeremo _Symbol per il simbolo corrente
- period: per specificare il time frame, utilizzeremo l'input dell'utente con un valore predefinito di 1 ora
- ama_period: per specificare il periodo della media mobile adattiva
- fast_ma_period: per specificare il periodo di fast MA
- slow_ma_period: per specificare il periodo di slow MA
- ama_shift: per specificare lo spostamento orizzontale, useremo 0
- applied_price: per specificare il tipo di prezzo, utilizzeremo il prezzo di chiusura
Per vedere i risultati dell'indicatore AMA è necessario eseguire un backtest per lo stesso periodo:
- Dimensione del lotto =1
- Time frame = 1 ora
- MAperiod = 50
- MA veloce = 5
- MA lenta = 100
I risultati:

Come si può vedere, le figure seguenti devono essere studiate dopo aver testato l'indicatore AMA:
- Utile Netto: 3638.20 (36.39%)
- Saldo DD relativo: 22.48%
- Equity DD relativo: 35.53%
- Fattore di profitto: 1.31
- Profitto atteso: 35.67
- Fattore di recupero: 0.65
- Indice di Sharpe 0.86
Doppia Media Mobile Esponenziale (iDEMA)
In questa parte identificheremo un altro tipo di media mobile, l'indicatore tecnico Double Exponential Moving Average (DEMA). Si tratta di un indicatore trend-follower sviluppato da Patrick Mulloy. L'obiettivo principale di questo indicatore è quello di ridurre il ritardo delle EMA, e di renderlo più reattivo al movimento del mercato, come vedremo nel calcolo di questo indicatore.
Questo indicatore può essere utilizzato per identificare il trend o i punti di inversione nel trend rilevando la posizione dei prezzi rispetto a questa media mobile. Le fasi di calcolo dell'indicatore sono illustrate di seguito:
1. Calcolo della prima Media Mobile Esponenziale (EMA)
EMA uno = EMA di n periodi di prezzo
2. Calcolo dell'EMA di EMA uno
EMA due = EMA di EMA uno
3. Calcolo di DEMA
DEMA = (2 * EMA uno) - EMA due
Come sappiamo, non è necessario eseguire questo calcolo manuale, ma è per comprendere bene l'indicatore, abbiamo questo indicatore come molti altri indicatori tecnici nella MetaTrader 5. Ora dobbiamo creare lo stesso sistema di trading che abbiamo creato in precedenza, ma questa volta utilizzeremo DEMA per testare i suoi risultati rispetto ad altri tipi. Questo sistema di trading eseguirà gli stessi ordini menzionati, che acquistano e vendono in base al crossover, ma questa volta si tratterà del crossover tra il prezzo e l'indicatore DEMA. I segnali saranno:
Segnale d’acquisto:
Il prezzo di chiusura è al di sopra del valore della doppia media mobile esponenziale (DEMA).
E il prezzo di chiusura precedente era inferiore al valore DEMA precedente.
Segnale di vendita:
Il prezzo di chiusura è inferiore al valore DEMA
E il prezzo di chiusura precedente era superiore al valore DEMA precedente.
Di seguito è riportato il codice completo di questo sistema di trading con la piccola differenza di utilizzare la funzione iDEMA che restituisce l'handle dell'indicatore della doppia media mobile esponenziale e i suoi parametri sono:
- symbol: per specificare il nome del simbolo, utilizzeremo (_Symbol) per il simbolo corrente
- period: per specificare il time frame, utilizzeremo l'input dell'utente con un time frame predefinito di 1 ora
- ma_period: per specificare il periodo della media mobile, utilizzeremo l'input dell'utente con un valore predefinito di 50
- ma_shift: per specificare lo spostamento orizzontale, utilizzeremo 0 in quanto non abbiamo bisogno di uno spostamento sul grafico.
- applied_price: per specificare il tipo di prezzo, useremo il prezzo di chiusura per calcolare la media mobile
Sarà uguale al blocco di codice sottostante:
//+------------------------------------------------------------------+ //| iDEMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int DEMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { DEMA = iDEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myDEMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myDEMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(DEMA,0,0,3,myDEMAArray); double lastClose=(priceArray[1].close); double DEMAVal = NormalizeDouble(myDEMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevDEMAVal = NormalizeDouble(myDEMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>DEMAVal && prevClose<prevDEMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<DEMAVal && prevClose>prevDEMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Dopo aver compilato questo codice, possiamo effettuare il backtest sullo stesso periodo utilizzato per gli altri tipi precedenti e l'impostazione o gli input di questo indicatore saranno i seguenti:
- Dimensione del lotto = 1
- Time frame = 1 ora
- Periodo MA = 50
Dopo aver eseguito il test, si ottengono i seguenti risultati:

Come si può vedere, le figure seguenti devono essere studiate dopo aver testato iDEMA:
- Utile netto: - 961,60 (- 9,62%)
- Saldo DD relativo: 39.62%
- Equity DD relativo: 41.15%
- Fattore di profitto: 0.97
- Profitto atteso: -3.12
- Fattore di recupero: - 0.18
- Indice di Sharpe: - 0.21
Tripla Media Mobile Esponenziale (iTEMA)
Ora identificheremo un altro tipo di media mobile, la Tripla Media Mobile Esponenziale (TEMA), sviluppata da Patrick Mulloy per aggiungere maggiore reattività all'indicatore e renderlo adatto al trading a breve termine. In questo indicatore utilizziamo EMA a tripla attenuazione, EMA singole e EMA a doppia attenuazione. Quindi, questo indicatore sarà più vicino al prezzo per essere più reattivo, come abbiamo detto. Così come abbiamo utilizzato la doppia media mobile esponenziale, possiamo utilizzare la TEMA allo stesso modo, oltre alla sua risposta più rapida al prezzo, può essere utilizzata per identificare la tendenza e i punti di inversione o i cambiamenti nel trend.
Di seguito sono riportati i passaggi per il calcolo dell'indicatore TEMA:
1. Calcolo della prima Media Mobile Esponenziale (EMA)
EMA uno = EMA di n periodi di prezzo
2. Calcolo dell'EMA di EMA uno
EMA due = EMA di EMA uno
3. Calcolo dell'EMA di EMA due
EMA tre = EMA di EMA due
4. Calcolo di TEMA
DEMA = (3 * EMA uno) - (3 * EMA due) + (EMA3)
Possiamo inserire questo indicatore tra gli indicatori tecnici già pronti disponibili nella MetaTrader 5, senza doverlo calcolare manualmente, quindi dobbiamo creare il nostro sistema di trading utilizzando questo indicatore TEMA per testarlo e confrontare i suoi risultati con gli altri tipi. Di seguito è riportato il codice completo per creare questo sistema di trading come abbiamo fatto in precedenza, con la differenza di utilizzare la funzione iTEMA che restituisce l'handle dell'indicatore Triple Exponential Moving Average (Tripla Media Mobile Esponenziale) e i suoi parametri sono gli stessi di quelli menzionati per DEMA e SMA.
//+------------------------------------------------------------------+ //| iTEMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int TEMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { TEMA = iTEMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myTEMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myTEMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(TEMA,0,0,3,myTEMAArray); double lastClose=(priceArray[1].close); double TEMAVal = NormalizeDouble(myTEMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevTEMAVal = NormalizeDouble(myTEMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>TEMAVal && prevClose<prevTEMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<TEMAVal && prevClose>prevTEMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Dopo la compilazione e l'esecuzione di questo software, possiamo eseguire un backtest sullo stesso periodo per confrontare i suoi risultati con gli altri tipi di media mobile e di seguito sono riportate le impostazioni o gli input che verranno utilizzati per provare a consentire la correzione di tutti i parametri in questo processo di test:
- Dimensione del lotto = 1
- Time frame = 1 ora
- Periodo MA = 50
Dopo aver eseguito e completato questo test, si ottengono risultati simili ai seguenti:

Come si può vedere, le figure seguenti devono essere studiate:
- Utile Netto: - 3973,10 (- 39.74%)
- Saldo DD relativo: 63.98%
- Equity DD relativo: 66.06%
- Fattore di profitto: 0.90
- Profitto Atteso: - 10.59
- Fattore di recupero: - 0.52
- Indice di Sharpe: - 0.83
Media Mobile Adattativa Frattale (iFrAMA)
Abbiamo l'ultimo tipo di media mobile che dobbiamo identificare in questo articolo. Si tratta dell'indicatore Media Mobile Adattativa Frattale (FrAMA), sviluppato da John Ehlers. Si tratta di un indicatore trend-following e suppone che i prezzi di mercato siano frattali. Può essere utilizzato anche per individuare tendenze e punti di inversione. Di seguito sono riportati i passaggi per il calcolarla:

Possiamo inserire questo indicatore dagli indicatori tecnici già pronti disponibili nella MetaTrader 5. Ora dobbiamo creare lo stesso sistema di trading con la stessa strategia, ma utilizzeremo invece l'indicatore FrAMA per confrontare i suoi risultati dopo averli testati con gli altri tipi. La strategia si basa sull'incrocio tra il prezzo e l'indicatore FrAMA: quando il prezzo incrocia sopra FrAMA sarà un segnale di acquisto e quando incrocia sotto FrAMA è un segnale di vendita.
Segnale d’acquisto:
Il prezzo di chiusura è superiore al valore della media mobile adattiva frattale (FrAMA)
E il prezzo di chiusura precedente era inferiore al valore FrAMA precedente.
Segnale di vendita:
Il prezzo di chiusura è inferiore al valore FrAMA
E il prezzo di chiusura precedente era superiore al valore FrAMA precedente.
Di seguito è riportato il codice completo per creare questo sistema di trading, che sarà identico a quello citato in precedenza negli altri tipi, ma utilizzeremo la funzione (iFrAMA) che restituisce l'handle della media mobile adattativa frattale e i suoi parametri sono:
- symbol: per specificare il nome del simbolo, utilizzeremo _Symbol per il simbolo corrente
- period: per specificare il time frame, utilizzeremo l'input dell'utente con un valore predefinito di 1 ora
- ma_period: per specificare il periodo della media mobile, utilizzeremo l'input dell'utente con un valore predefinito di 50
- ma_shift: per specificare lo spostamento orizzontale, useremo 0
- applied_price: per specificare il tipo di prezzo, useremo il prezzo di chiusura
//+------------------------------------------------------------------+ //| iFrAMA_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> input double lotSize = 1; input ENUM_TIMEFRAMES timeFrame = PERIOD_H1; input int MAPeriod= 50; int FrAMA; int barsTotal; CTrade trade; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { FrAMA = iFrAMA(_Symbol, timeFrame, MAPeriod,0, PRICE_CLOSE); barsTotal=iBars(_Symbol,timeFrame); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { MqlRates priceArray[]; double myFrAMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); ArraySetAsSeries(priceArray,true); ArraySetAsSeries(myFrAMAArray,true); int Data=CopyRates(_Symbol,timeFrame,0,3,priceArray); CopyBuffer(FrAMA,0,0,3,myFrAMAArray); double lastClose=(priceArray[1].close); double FrAMAVal = NormalizeDouble(myFrAMAArray[1],_Digits); double prevClose=(priceArray[2].close); double prevFrAMAVal = NormalizeDouble(myFrAMAArray[2],_Digits); int bars=iBars(_Symbol,timeFrame); if(barsTotal != bars) { barsTotal=bars; if(lastClose>FrAMAVal && prevClose<prevFrAMAVal) { trade.PositionClose(_Symbol); trade.Buy(lotSize,_Symbol,Ask,0,0,NULL); } if(lastClose<FrAMAVal && prevClose>prevFrAMAVal) { trade.PositionClose(_Symbol); trade.Sell(lotSize,_Symbol,Bid,0,0,NULL); } } } //+------------------------------------------------------------------+
Dopo aver compilato ed eseguito questo EA, testeremo questa strategia utilizzando l'indicatore FrAMA con le seguenti impostazioni o input:
- Dimensioni del lotto: 1
- Time frame: 1 ora
- Periodo MA: 50
Proviamo questo EA nello stesso periodo di tutte le altre medie mobili menzionate e otteniamo i seguenti risultati:

Come si può notare, le cifre più importanti da studiare sono le seguenti:
- Utile netto: - 2993.70 (- 29.94%)
- Saldo DD relativo: 73.28%
- Equity DD relativo: 74.81%
- Fattore di profitto: 0.93
- Profitto atteso: -6.45
- Fattore di recupero: - 0.33
- Indice di Sharpe: - 0.46
Confronto dei Risultati con i Risultati della Media Mobile Semplice (SMA)
In questa parte, fornirò un confronto dei risultati per ogni tipo di media mobile menzionata e dovete sapere che cercherò di fornire i migliori risultati possibili, ma ogni media mobile può dare risultati diversi se la ottimizziamo e cambiamo i periodi o i periodi testati, poiché sappiamo che la media mobile può dare risultati differenti in base alle impostazioni dell'indicatore e alle condizioni del mercato.
L'obiettivo principale è fornire le stesse condizioni il più possibile per vedere se c'è un tipo migliore di altri con le migliori impostazioni che possiamo scegliere dal nostro punto di vista. Ma per capire cosa stiamo cercando dobbiamo vedere le misure più importanti nelle loro massime prestazioni:
- Utile Netto: Il valore più alto è il migliore
- Drawdown (DD): Il più basso è il migliore
- Fattore di Profitto: Il più alto è il migliore
- Profitto Atteso: Il valore più alto è il migliore
- Fattore di Recupero: Quello più alto è il migliore
- Indice di Sharpe: Lo Sharpe Ratio più elevato è il migliore
Ora confronteremo i risultati della precedente media mobile semplice con altri tipi di media mobile sulla base di questo contesto attraverso la seguente tabella:
| Misura | SMA | AMA | DEMA | TEMA | FrAMA |
|---|---|---|---|---|---|
| Utile Netto | 2700.30 (27%) | 3638.20 (36.39%) | - 961.60 (- 9.62%) | - 3973.10 (- 39.74%) | - 2993.70 (- 29.94%) |
| Saldo Drawdown Relativo: | 37.07% | 22.48% | 39.62% | 63.98% | 73.28% |
| Equity Drawdown Relativo: | 41.76% | 35.53% | 41.15% | 66.06% | 74.81% |
| Fattore di Profitto | 1.10 | 1.31 | 0.97 | 0.90 | 0.93 |
| Profitto Atteso | 12.68 | 35.67 | - 3.12 | - 10.59 | - 6.45 |
| Fattore di Recupero | 0.45 | 0.65 | - 0.18 | - 0.52 | - 0.33 |
| Indice di Sharpe | 0.57 | 0.86 | - 0.21 | - 0.83 | - 0.46 |
In base ai risultati di tutti i nostri test, abbiamo due tipi che hanno le migliori prestazioni in base alle impostazioni e al periodo di prova. Si tratta della media mobile semplice e della media mobile adattiva. La migliore è la media mobile adattiva. Possiede:
- L'utile netto più elevato
- Il DD Relativo al saldo più basso
- Il DD Relativo all’equity più basso
- Il miglior Fattore di Profitto
- Il più alto Profitto Atteso
- Il Fattore di Recupero più elevato
- Il più alto Sharpe Ratio
Come abbiamo detto in precedenza, potremmo ottenere risultati migliori con una maggiore ottimizzazione delle impostazioni e delle strategie, ma l'obiettivo è quello di comprendere e applicare il processo di test su un esempio reale, per poi poter utilizzare lo stesso processo per qualsiasi scopo di test.
Conclusioni
In questo articolo abbiamo considerato i risultati delle performance dei seguenti tipi di media mobile:
- La Media Mobile Adattiva (AMA)
- La Doppia Media Mobile Esponenziale (DEMA)
- La Tripla Media Mobile Esponenziale (TEMA)
- La Media Mobile Adattativa Frattale (FrAMA)
Abbiamo creato sistemi di trading per ogni tipo e confrontato i loro risultati con la media mobile semplice, che è il tipo di media mobile più popolare. In base ai risultati dei test, abbiamo scoperto che i risultati migliori sono stati generati dalla media mobile semplice e dalla media mobile adattiva, di cui la migliore è quella adattiva (AMA). Abbiamo analizzato e confrontato le seguenti metriche per identificare il vincitore:
- Utile Netto
- Drawdown (DD)
- Fattore di Profitto
- Profitto Atteso
- Fattore di Recupero
- Indice di Sharpe
I test sono un argomento molto importante nel trading. Pertanto, vi incoraggio a eseguire più test su più strategie. Oltre a valutare la strategia in sé, può farvi ottenere delle intuizioni inaspettate, poiché ogni test approfondisce la vostra comprensione.
Grazie per il tempo dedicato alla lettura di questo articolo. Spero che questo articolo vi sia stato utile e che abbia aggiunto valore alle vostre conoscenze. Se volete leggere altri articoli sulla creazione di sistemi di trading basati sugli indicatori tecnici popolari come RSI, MACD, Stocastico, Bande di Bollinger e altri argomenti, potete consultare i miei articoli attraverso le Pubblicazioni, spero che anche voi li troviate utili.
Tradotto dall’inglese da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/en/articles/13130
Avvertimento: Tutti i diritti su questi materiali sono riservati a MetaQuotes Ltd. La copia o la ristampa di questi materiali in tutto o in parte sono proibite.
Questo articolo è stato scritto da un utente del sito e riflette le sue opinioni personali. MetaQuotes Ltd non è responsabile dell'accuratezza delle informazioni presentate, né di eventuali conseguenze derivanti dall'utilizzo delle soluzioni, strategie o raccomandazioni descritte.
Introduzione a MQL5 Algo Forge
Passaggio a MQL5 Algo Forge (parte 1): Creazione del repository principale
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso