Unisciti alla nostra fan page
- Visualizzazioni:
- 772
- Valutazioni:
- Pubblicato:
- 2021.11.01 12:40
-
Hai bisogno di un robot o indicatore basato su questo codice? Ordinalo su Freelance Vai a Freelance
L'EA Moving Average è incluso nel pacchetto standard del terminale della MetaTrader 5 ed è un esempio di un EA che trada utilizzando l'indicatore Media Mobile.
Il file dell'EA Moving Average.mq5 è posizionato nella cartella "terminal_data_folder\MQL5\Experts\Examples\Moving Average\". Questo EA è un esempio dell'uso delle funzioni degli indicatori tecnici, storico dei trade e delle classi di trading della Libreria Standard. In più, l'EA include un sistema di money management che si basa sui risultati dei trade.
Andiamo a considerare la struttura dell'Expert Advisor e come lavora.
1. Proprietà dell'EA
//+------------------------------------------------------------------+ //| Moving Averages.mq5 | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2009-2013, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00
Le prime 5 righe contengono un commento, le tre linee succesive impostano le proprietà del programma MQL5 (copyright, link, version), utilizzando le direttive del preprocessore #property.
Quando esegui gli Expert Advisor sono mostrati nella scheda "Comune":
Figure 1. Parametri Comuni dell'EA Moving Average
1.2. File dell' Include
Dopo, la direttiva dell' #include dice al compilatore di includere il file "Trade.mqh" .
Questo file è parte della Libreria Standard, contiene la classe CTrade per un facile accesso alle funzioni di trading.
#include <Trade\Trade.mqh>
Il nome del file dell'include è visualizzato tra parentesi "<>", così il suo percorso relativo alla directory: "terminal_data_folder\Include\".
1.3 Inputs
Poi troviamo il tipo,nome,valori predefiniti e un commento. Il loro ruolo è mostrato in fig. 2.
input double MaximumRisk = 0.02; // Maximum Risk in percentage input double DecreaseFactor = 3; // Descrease factor input int MovingPeriod = 12; // Moving Average period input int MovingShift = 6; // Moving Average shift
I Parametri MaximumRisk e DecreaseFactor saranno utilizzati per il money management, MovingPeriod e MovingShift impostano il periodo e lo slittamento dell'indicatore tecnico Moving Average che sarà utilizzato per verificare le condizioni di trade.
Il testo nel commento nella linea dei parametri di input, affianco ai valori predefiniti, sono visualizzati nella scheda "Opzioni" anzichè il nome del parametro di input.
Fig. 2. Parametri di Input dell'EA Moving Average
1.4. Variabili Globali
Poi è dichiarata la variabile globale ExtHandle. Verrà utilizzata per memorizzare l'handle dell'indicatore Moving Average.
//--- int ExtHandle=0;
E' seguito da 6 funzioni. Lo scopo di ciascuna di esse è descritto nel commento prima del corpo della funzione:
- TradeSizeOptimized() - Calcola la dimensione del lotto ottimale;
- CheckForOpen() - Verifica le condizioni per l'apertura di una posizione;
- CheckForClose() - Verifica le condizioni per la chiusura di una posizione;
- OnInit() - Funzione di inizializzazione dell'Expert;
- OnTick() - funzione tick dell'Expert;
- OnDeinit() - Funzione di deinizializzazione dell'Expert;
Le ultime tre funzioni sono funzioni di gestione degli eventi; le prime tre funzioni di servizio sono chiamate nel loro codice.
2. Funzioni di Gestione degli Eventi
2.1. La funzione di inizializzazione OnInit()
La funzione OnInit() è chiamata una sola volta durante il primo avvio dell'Expert Advisor. Normalmente nelle gestione dll'evento OnInit() l'EA è pronto ad operare: vengono verificati i parametri di input, indicatori e i parametri sono inizializzati, etc. In caso di errori critici, quando ulteriore lavoro non ha senso, la funzione viene chiusa con il codice di ritorno INIT_FAILED.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(void) { //--- ExtHandle=iMA(_Symbol,_Period,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE); if(ExtHandle==INVALID_HANDLE) { printf("Error creating MA indicator"); return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); }
Poiché il trading dell'EA si basa sull'indicatore Moving Average, chiamando iMA() l'indicatore Moving Average viene creato e il suo handle è salvato nella variabile globale ExtHandle.
In caso di errore, si esce da OnInit() con il codice di ritorno INIT_FAILED - è il modo corretto per completare l'operazione EA/indicatore in caso di inizializzazione non riuscita.
2.2. Funzione OnTick()
La funzione OnTick() è chiamata ogni volta che si riceve una nuova quotazione per il simbolo sul grafico, o sulla quale l'EA è eseguito.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(void) { //--- if(PositionSelect(_Symbol)) CheckForClose(); else CheckForOpen(); //--- }
La funzione PositionSelect() è utilizzata per definire se c'è una posizione aperta per il simbolo corrente.
Se ci sono posizioni aperte, è chiamata la funzione CheckForClose(), la quale analizza lo stato corrente del mercato e chiude le posizioni aperte,altrimenti è chiamata la CheckForOpen(), la quale verifica le condizioni di entrata a mercato e apre una nuova posizione se tali condizioni si verificano.
2.3. La funzione di deinizializzazione OnDeint()
OnDeInit() è chiamata quando un EA è rimosso dal garfico. Se un programma piazza oggetti grafici durante la sua operatività, possono essere rimossi dal grafico.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+
In questo caso nessuna operazione viene eseguita durante la deinizializzazione dell'Expert Advisor.
3. Funzioni di Servizio
3.1. Funzione TradeSizeOptimized()
Questa funzione calcola e ritorna il valore della dimensione ottimale del lotto per la posizione da aprire con il livello di rischio specificato e i risultati di trading.
//+------------------------------------------------------------------+ //| Calculate optimal lot size | //+------------------------------------------------------------------+ double TradeSizeOptimized(void) { double price=0.0; double margin=0.0; //--- Calculate the lot size if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price)) return(0.0); if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin)) return(0.0); if(margin<=0.0) return(0.0); double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_FREEMARGIN)*MaximumRisk/margin,2); //--- calculate the length of the series of consecutive losing trades if(DecreaseFactor>0) { //--- request the entire trading history HistorySelect(0,TimeCurrent()); //-- int orders=HistoryDealsTotal(); // the total number of deals int losses=0; // the number of loss deals in the series for(int i=orders-1;i>=0;i--) { ulong ticket=HistoryDealGetTicket(i); if(ticket==0) { Print("HistoryDealGetTicket failed, no trade history"); break; } //--- checking the deal symbol if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol) continue; //--- checking the profit double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT); if(profit>0.0) break; if(profit<0.0) losses++; } //--- if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1); } //--- normalizing and checking the allowed values of the trade volume double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); lot=stepvol*NormalizeDouble(lot/stepvol,0); double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); if(lot<minvol) lot=minvol; double maxvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(lot>maxvol) lot=maxvol; //--- return the value of the trade volume return(lot); }
La funzione SymbolInfoDouble() è utilizzata per verificare la disponibilità dei prezzi per il simbolo corrente, in seguito la funzione OrderCalcMargin()è utilizzata per richiedere il margine necessario a piazzare un ordine (in questo caso un ordine buy). La dimensione del lotto iniziale è determinata dal valore del margine richiesto per piazzare un ordine, il margine libero dell'account (AccountInfoDouble(ACCOUNT_FREEMARGIN)) e il massimo valore consentito di rischio specificato nei parametri di input MaximumRisk.
Se il valore del parametro di input DecreaseFactor è positivo,vengono analizzati gli affari nello storico e la dimensione del lotto è adeguato prendendo dalle informazioni dell'account la massima serie di trade perdenti: la dimensione del lotto iniziale è moltiplicata per la dimensione (1-Perdite/DecreaseFactor).
Dopo il volume è "arrotondato" al valore che è multiplo del passo minimo consentito (stepvol) per il corrente simbolo. Vengono richiesti anche i valori minimo (minvol) e massimo possibile (maxvol) del volume di trade, e se il valore del lotto esce dai limiti consentiti, viene rettificato. Come risultato, la funzione ritorna il valore calcolato del volume di trading.
3.2. Funzione CheckForOpen()
CheckForOpen() è utilizzat per verificare le condizioni di apertura di una posizione e la apre quando le condizione sono verificate.
//+------------------------------------------------------------------+ //| Check for open position conditions | //+------------------------------------------------------------------+ void CheckForOpen(void) { MqlRates rt[2]; //--- copy the price values if(CopyRates(_Symbol,_Period,0,2,rt)!=2) { Print("CopyRates of ",_Symbol," failed, no history"); return; } //--- Trade only on the first tick of the new bar if(rt[1].tick_volume>1) return; //--- Get the current value of the Moving Average indicator double ma[1]; if(CopyBuffer(ExtHandle,0,0,1,ma)!=1) { Print("CopyBuffer from iMA failed, no data"); return; } //--- check the signals ENUM_ORDER_TYPE signal=WRONG_VALUE; if(rt[0].open>ma[0] && rt[0].close<ma[0]) signal=ORDER_TYPE_SELL; // sell condition else { if(rt[0].open<ma[0] && rt[0].close>ma[0]) signal=ORDER_TYPE_BUY; // buy condition } //--- additional checks if(signal!=WRONG_VALUE) if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) if(Bars(_Symbol,_Period)>100) { CTrade trade; trade.PositionOpen(_Symbol,signal,TradeSizeOptimized(), SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK), 0,0); } //--- }
Quando si trada utilizzando la moving, è necessario verificare se il prezzo attraversa la moving average Utilizzando la funzione CopyRates(), due valori dei prezzi correnti vengono copiati nell'array di strutture rt[], rt[1] corrisponde alla barra corrente, rt[0] - barra completata.
Una nuova barra è iniziata controllando il volume dei tick della barra corrente se è uguale a 1, è iniziata una nuova barra. Va notato che questo metodo di rilevamento di una nuova barra può fallire in alcuni casi (quando le quotazioni arrivano in pacchetti), quindi il fatto di iniziare una nuova formazione della barra dovrebbe essere fatto salvando e confrontando il tempo della quotazione corrente (vedi IsNewBar).
Il valore corrente dell'indicatore della Moving Average viene richiesto utilizzando la funzione CopyBuffer() e viene salvato nell'array ma[] che contiene un solo valore. Il programma quindi verifica se il prezzo ha superato la media mobile ed effettua ulteriori controlli (se è possibile fare trading utilizzando l'EA e la presenza di barre nella cronologia). In caso di successo, viene aperta una posizione appropriata per il simbolo chiamando la PositionOpen() metodo dell'oggetto del trade (un'istanza di CTrade).
Il prezzo di apertura della posizione viene impostato utilizzando la funzione SymbolInfoDouble() che restituisce il prezzo Bid o Ask a seconda del valore della variabile segnale. Il volume della posizione è determinato chiamando TradeSizeOptimized() descritto sopra.
3.3. Funzione CheckForClose()
CheckForClose() verifica le condizioni per chiudere la posizione e la chiude se queste sono verificate.
//+------------------------------------------------------------------+ //| Check for close position conditions | //+------------------------------------------------------------------+ void CheckForClose(void) { MqlRates rt[2]; //--- Copy price values if(CopyRates(_Symbol,_Period,0,2,rt)!=2) { Print("CopyRates of ",_Symbol," failed, no history"); return; } //--- Trade only on the first tick o the new bar if(rt[1].tick_volume>1) return; //--- get the current value of the Moving Average indicator double ma[1]; if(CopyBuffer(ExtHandle,0,0,1,ma)!=1) { Print("CopyBuffer from iMA failed, no data"); return; } //--- get the type of the position selected earlier using PositionSelect() bool signal=false; long type=PositionGetInteger(POSITION_TYPE); if(type==(long)POSITION_TYPE_BUY && rt[0].open>ma[0] && rt[0].close<ma[0]) signal=true; if(type==(long)POSITION_TYPE_SELL && rt[0].open<ma[0] && rt[0].close>ma[0]) signal=true; //--- additional checks if(signal) if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) if(Bars(_Symbol,_Period)>100) { CTrade trade; trade.PositionClose(_Symbol,3); } //--- }
L'algoritmo della funzione CheckForClose() è simile all'algoritmo di CheckForOpen(). A seconda della direzione delle posizioni aperte, vengono ricontrollate le condizioni della sua chiusura (prezzo che attraversa la MA al ribasso per comprare o al rialzo per vendere). Una posizione aperta viene chiusa chiamando la PositionClose() metodo degli oggetti di trade (istanza di CTrade).
4. Backtest
I valori migliori dei parametri possono essere trovati utilizzando lo Strategy Tester del terminale MetaTrader 5.
Per esempio, quando ottimizziamo il parametro MovingPeriod nell'intervallo 2012.01.01-2013.08.01, il miglior risultato è stato ottenuto con MovingPeriod=45:
Risultato del Backtest dell'Expert Advisor Moving Average
Conclusioni:
L'Expert Advisor Moving Average incluso nel pacchetto standard del terminale MetaTrader 5 è un esempio dell'uso di indicatori tecnici, funzioni sullo storico dei trade e delle classi di trade della Libreria Standard. In più, l'EA include un sistema di money management che si basa sui risultati dei trade.
Tradotto dal russo da MetaQuotes Ltd.
Codice originale https://www.mql5.com/ru/code/1921
![ALGLIB - Libreria di Analisi Numerica](https://c.mql5.com/i/code/library.png)
ALGLIB libreria di funzioni matematiche (v. 3.19) portata a MQL5.
![Esempio dell'uso di IndicatorParameters()](https://c.mql5.com/i/code/expert.png)
Questo Expert Advisor illustra l'uso della funzione IndicatorParameters() per ricavare le informazioni sul numero dei parametri d'entrata, il loro tipo e valori.
![Esempio di MACD](https://c.mql5.com/i/code/expert.png)
L'esempio di Expert Advisor MACD trada all'incrocio delle linee main e signal dell'MACD. Questo Expert Advisor è un esempio di approccio orietato agli oggetti nello sviluppo di un EA.
![Bollinger Bands ®](https://c.mql5.com/i/code/indicator.png)
L'indicatore Bollinger Bands ® (BB) è simile a Envelopes. L'unica differenza è che le bande Envelopes sono tracciate ad una distanza fissa (%) dalla media mobile, mentre le Bande di Bollinger sono tracciate ad un certo numero di deviazioni standard da essa.