![Un Avvio Rapido o una Breve Guida per Principianti](https://c.mql5.com/i/articles/overlay.png)
Un Avvio Rapido o una Breve Guida per Principianti
Introduzione
Ciao caro lettore! In questo articolo, cercherò di spiegarti e mostrarti come puoi imparare facilmente e rapidamente i principi della creazione dell’Expert Advisor, lavorare con gli indicatori, ecc. È rivolto ai principianti e non presenterà alcun esempio difficile o astruso. Quindi l'articolo potrebbe non essere così stimolante e informativo per coloro che tra voi che sanno già come programmare gli Expert Advisor.
Expert Advisor e la Sua Struttura
L’Expert Advisor è un programma scritto nel linguaggio MQL che specifica le condizioni per fare trading o accantonare.
Fondamentalmente, la struttura di un EA può essere composta da un gran numero di blocchi ma per renderla più comprensibile, farò un esempio molto semplice generato di default in MetaEditor.
L'intero EA può essere diviso visivamente in 4 parti, ciascuna delle quali è responsabile di una certa parte del lavoro da eseguire.
Fig. 1. I principali blocchi EA
- Parameter Block contiene le informazioni per il terminale che gli consentono di gestire l'EA in modo corretto. I parametri più comuni sono la versione EA, il nome dell'azienda produttrice e una breve descrizione.
- OnInit() Block ottiene il controllo una volta che l'EA viene caricato nel terminale. Può contenere vari dati relativi all'inizializzazione dell'EA - dichiarare variabili e array, ottenere handle di indicatori, ecc. In altre parole, questo blocco non ha alcuna funzione che sarebbe direttamente associata al trading.
- Il Blocco OnDeinit() agisce come l'inverso del Blocco OnInit(). Viene chiamato quando l'EA completa la sua operazione (arresto EA/Terminale o inizializzazione non riuscita di un EA). Una delle funzioni principali di questo blocco è la deallocazione dello spazio di memoria occupato dall'EA quando non è più necessario. In altre parole, descrive i processi di eliminazione di variabili, array e handle di indicatori, ecc.
- Il Blocco OnTick() viene chiamato ogni volta che le nuove informazioni sul simbolo (coppia di valute) vengono ricevute dal server. Specifica le condizioni per svolgere il trading e le funzioni del trading stesso.
Fig. 2. Esempio di un nuovo documento generato di default in MetaEditor
Lascia che te lo spieghi usando l'esempio sopra. Abbiamo un codice dell'Expert Advisor "vuoto", una sorta di template dell'Expert Advisor che poi andrà riempito.
Quello che possiamo vedere qui è quanto segue:
- le prime cinque righe (da 1 a 5) rappresentano commenti contenenti il nome dell'EA (nome file), il nome dell'azienda produttrice e il suo sito web. Puoi scrivere qui quello che vuoi. Questo testo non verrà visualizzato da nessuna parte e può anche essere saltato. Le informazioni che contiene sono destinate esclusivamente allo sviluppatore;
- le successive 3 righe (dalla 6 alla 8) rappresentano il Blocco Parametro. Possiamo osservare queste informazioni quando si avvia l'EA nel terminale;
- è seguito dalla funzione OnInit() (righe da 12 a 19). Questo è il blocco OnInit(). Questa funzione non ottiene alcun parametro ma restituisce (anche se potrebbe tranquillamente non farlo) il codice di inizializzazione;
- la funzione OnDeinit(const int reason) va avanti(righe da 22 a 26). Questo è il blocco OnDeinit(). Ha un parametro che specifica il motivo dell'arresto dell’EA.
Se l'inizializzazione dell'EA fallisce, questa funzione riceve un relativo codice come parametro; - l'ultima funzione è OnTick() (righe da 30 a 34). Questo è il blocco OnTick() descritto in precedenza. Si può dire che questo blocco sia il "cervello" dell'EA in quanto comprende tutte le funzioni preposte alle operazioni.
Come ho detto prima, la struttura può essere molto più complessa ed essere composta da una buona quantità di blocchi a differenza di questo esempio di facile comprensione. Quando ritieni che questo non sia abbastanza, puoi aggiungere i tuoi blocchi.
Indicatori e Come Gestirli
Gli indicatori sono piccoli programmi scritti in MQL che vengono visualizzati nel grafico dei prezzi o in una finestra separata sotto il grafico dei prezzi e ci consentono di eseguire analisi tecniche del mercato.
Tutti gli indicatori possono essere classificati in due tipi: indicatori di tendenza e oscillatori.
Gli indicatori che seguono il trend sono, di norma, disegnati nel grafico dei prezzi e vengono utilizzati per identificare la direzione del trend, mentre gli oscillatori possono essere normalmente visti sotto il grafico dei prezzi e servono per identificare i punti di entrata.
La maggior parte degli indicatori ha almeno un buffer (indicatore buffer) che contiene i dati di lettura in un determinato momento. Come un EA, l'indicatore ha il suo simbolo e l'intervallo su cui viene calcolato.
Il buffer dell'indicatore può essere considerato come una coda il cui ultimo elemento è un valore in esecuzione.
Fig. 3. Esempio dell'Indicatore della Media Mobile
Il buffer dell'indicatore è un array in cui il primo elemento (con indice 0) trasporta i dati sul candlestick più a destra e l'elemento successivo (con indice 1) trasporta i dati sul secondo candlestick a destra, ecc. Tale disposizione degli elementi è detta time series.
Dai un'occhiata all'esempio che segue:
Supponiamo che la coppia di valute che abbiamo sia EUR/USD, l'intervallo è di 1 ora.
Prima di tutto, dobbiamo aggiungere l'indicatore all'EA e ottenere il suo handle.
L’handle è un puntatore univoco all'indicatore che ci consente di indirizzare quell'indicatore in qualsiasi punto del programma.
int iMA_handle; iMA_handle=iMA("EURUSD",PERIOD_H1,10,0,MODE_SMA,PRICE_CLOSE);Diamo un'occhiata più da vicino.
La prima riga definisce una variabile che memorizzerà l'handle dell'indicatore. La seconda riga chiama l'indicatore (qui, l'indicatore della Media Mobile), ne specifica i parametri e salva l'handle nella variabile per un uso futuro.
Fig. 4. Esempio di tooltip per i parametri dell'indicatore della Media Mobile
Possiamo vedere i seguenti parametri elencati da sinistra a destra:
- nome del simbolo (compare in grassetto nel tooltip) è un parametro di testo, coppia di valute (simbolo);
- intervallo;
- periodo dell’indicatore (qui, il periodo medio);
- spostamento del graficodi N barre avanti/indietro. Un numero positivo indica lo spostamento del grafico di N barre in avanti, mentre un numero negativo indica lo spostamento del grafico di N barre indietro;
- metodo di calcolo della media;
- prezzo applicato o un handle di un diverso indicatore.
C'è un insieme unico di variabili e dei loro tipi per ogni indicatore. Se ti imbatti in un indicatore sconosciuto, le informazioni su di esso possono sempre essere trovate nella sezione di Aiuto contestuale integrata. Ad esempio, dopo aver digitato iMA e premuto F1, si aprirà una finestra di Aiuto che fornisce informazioni su quell'indicatore specifico e una descrizione dettagliata di tutte le sue proprietà.
Fig. 5. Esempio di chiamata della finestra di Aiuto per la descrizione dell'indicatore premendo F1
Dopo aver scritto il codice e aver avviato l'EA nel terminale, vedremo (una volta che l'EA appare nell'angolo in alto a destra del grafico dei prezzi) che l'indicatore non è presente nel grafico. Questo non è un errore - era così voluto. Affinché appaia, dobbiamo aggiungere un'altra riga:
ChartIndicatorAdd(ChartID(),0,iMA_handle);
Vediamo ora cosa fa. Passare il cursore sul comando ChartIndicatorAdd e premere F1 per leggere le informazioni della Guida sullo scopo del comando. Dice che questo comando:
Aggiunge un indicatore con l'handle specificato in una finestra di grafico specificato.
Il secondo parametro che è uguale a zero è il numero della sottofinestra. Le finestre secondarie di solito contengono oscillatori sotto il grafico dei prezzi. Ti ricordi? Ce ne possono essere molti. Per visualizzare l'indicatore nella sottofinestra è sufficiente specificare il numero della sottofinestra in modo che sia maggiore del numero già esistente di 1, cioè il numero successivo all'ultimo esistente.
Avendo modificato la riga di codice come segue:
ChartIndicatorAdd(ChartID(),1,iMA_handle);
il nostro indicatore comparirà nella sottofinestra sotto il grafico dei prezzi.
Ora, è il momento di provare a ottenere alcuni dati dall'indicatore. A questo scopo, dichiariamo un array dinamico, organizziamo l'indicizzazione dell'array come time series per comodità e copiamo i valori dell'indicatore in questo array.
double iMA_buf[]; ArraySetAsSeries(iMA_buf,true); CopyBuffer(iMA_handle,0,0,3,iMA_buf);
L'esempio sopra mostra che abbiamo dichiarato l'array dinamico iMA_buf[] di tipo doppio poiché l'indicatore della Media Mobile si basa sui prezzi e i prezzi hanno frazioni.
La riga successiva imposta l'indicizzazione per l'array in modo che gli elementi con indici più piccoli memorizzino valori più vecchi, mentre gli elementi con indici più grandi memorizzino valori più recenti. Ciò viene usato per comodità e per evitare confusione poiché i buffer degli indicatori in tutti gli indicatori sono indicizzati come serie temporali.
L'ultima riga serve per copiare i valori dell'indicatore nell'array iMA_buf[]. Questi dati ora sono pronti per essere utilizzati.
Ordini, Trade e Posizioni
Cominciamo con gli ordini.
- Gli ordini sono richieste di trading accettate dal server di trading. Se la richiesta non è valida, verrà respinta.
Per evitare la difficoltà nel compilare la richiesta di trading, ti mostrerò in seguito come farlo utilizzando le librerie standard rendendo tutto molto più semplice.
Esistono 2 tipi di ordini: di mercato (per l'esecuzione immediata) e in sospeso.
Gli ordini di mercato rappresentano istruzioni per vendere o acquistare un determinato importo di uno specifico strumento finanziario al prezzo di mercato corrente.
Gli ordini in sospeso rappresentano le istruzioni per eseguire l'operazione soggetta a determinate condizioni. Gli ordini in sospeso hanno una data di scadenza in cui vengono eliminati.
- I trade rappresentano i risultati dell'esecuzione degli ordini (istruzioni per eseguire un'operazione). Ogni trade si basa su un determinato singolo ordine, mentre un singolo ordine può comportare più trade. Ad esempio, un ordine di acquisto di 10 lotti può essere eseguito mediante l'esecuzione parziale di un numero di trade consecutivi. I trade vengono sempre memorizzati nella cronologia di trading e non possono essere modificati. Il terminale mostra le negoziazioni nel tab "Cronologia".
- Le posizioni rappresentano l'esito degli ordini in atto. Per ogni singolo simbolo può essere aperta una sola posizione, Long o Short.
Per renderlo più chiaro, permettimi di spiegartelo con un esempio: apriamo una posizione lunga di 1 lotto, ovvero effettuiamo un ordine al prezzo di mercato corrente (ad esempio) e la dimensione di 1 lotto. Se la richiesta è valida, verrà inviata al server per l'elaborazione. Non appena l'elaborazione sarà completata, nel tab "Trade" del terminale comparirà una posizione con i parametri dell'ordine. Supponiamo di decidere, quindi, di aprire un'altra posizione lunga, anch'essa dimensionata a 1 lotto. Dopo l'elaborazione dell'ordine, non vedremo due ordini nel tab "Trade" bensì una posizione di 2 lotti. Vale a dire che la posizione è il risultato dell'esecuzione di più ordini.
Ora passiamo alla pratica. Per poter effettuare una richiesta è necessario compilare i seguenti campi della struttura:
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Type of action ulong magic; // Expert Advisor ID (magic number) ulong order; // Order ticket string symbol; // Trade instrument double volume; // Requested trade size in lots double price; // Price double stoplimit; // StopLimit level of the order double sl; // Stop Loss level of the order double tp; // Take Profit level of the order ulong deviation; // Maximum allowed deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order type by execution ENUM_ORDER_TYPE_TIME type_time; // Order type by duration datetime expiration; // Order expiration time (for orders of the ORDER_TIME_SPECIFIED type) string comment; // Comment to the order };
Poiché ci sono vari ordini, ogni tipo di ordine ha il proprio set di parametri obbligatori. Non tratterò a lungo questi campi. Il sito web offre molte informazioni su questo argomento. Se anche uno solo dei parametri obbligatori per un determinato tipo di ordine non viene specificato o specificato in modo errato, la richiesta avrà esito negativo.
La struttura di cui sopra viene qui presentata solo per dimostrare meglio la difficoltà che sorge durante la compilazione.
Stop Loss e Take Profit
Stop Loss e Take Profit sono ordini speciali piazzati come "misura di fallback". Ad esempio, in caso di errori o di una posizione aperta dall'Expert Advisor che mostra una perdita, un ordine Stop Loss può limitare le perdite ad un certo livello predefinito.
Take Profit agisce in modo simile, limitando solo il profitto in questo caso. Potrebbe essere necessario smettere di preoccuparsi di chiudere una posizione. Si chiuderà al raggiungimento di un certo livello di prezzo. In altre parole, questi ordini rappresentano il nostro "piano assicurativo", qualora il mercato si voltasse contro di noi o se volessimo trarne profitto.
Questo tipo di ordini non può essere piazzato separatamente da solo - può solo modificare posizioni già esistenti.
Utilizzo di Librerie Standard
Quindi siamo finalmente arrivati alla Libreria Standard. Questa libreria viene fornita insieme al terminale, da cui il nome - Libreria Standard. Comprende funzioni che facilitano la programmazione degli EA e intraprendono parzialmente processi complessi, ad esempio la generazione di richieste di trading.
Le librerie di trading (vedi anche trade classes) si trovano nel seguente percorso: Include\Trade\ e possono essere aggiunte utilizzando la direttiva #include.
Esempio:
#include <Trade\Trade.mqh> #include <Trade\PositionInfo.mqh>
Le classi di cui sopra possono essere considerate quelle di base in quanto la maggior parte degli Expert Advisor può essere programmata utilizzando solo queste due classi (librerie). Io le chiamo librerie:
- La prima è progettata per inserire e modificare gli ordini.
- La seconda serve per ottenere informazioni su posizioni già esistenti.
A volte, un'altra libreria può rivelarsi utile:
#include <Trade\OrderInfo.mqh>
Contiene funzioni per lavorare con gli ordini, se, ad esempio, la nostra strategia richiede l'uso di ordini in sospeso.Ricordi la struttura della richiesta di trading piena di vari parametri che richiedono conoscenze per essere utilizzati correttamente?
Ora, ti farò un esempio di una richiesta di trading effettuata utilizzando la libreria:
CTrade m_Trade; m_Trade.Sell(lot,symbol_name,price,sl,tp,comment);
Qui c’è un totale di 6 parametri, solo uno dei quali è obbligatorio (la dimensione dell'ordine - che è il primo parametro).
Ora specificherò ognuno di essi:
- il lotto è la dimensione dell'ordine da effettuare;
- symbol_name è il simbolo (coppia di valute) a cui si applica l'ordine (se non ne viene specificato nessuno, viene utilizzato il simbolo corrente dell'Expert Advisor);
- price è il prezzo di apertura (essendo questa la funzione per l'apertura di un ordine attivo, il suo prezzo potrebbe non essere specificato nel qual caso verrà automaticamente ottenuto direttamente dal grafico dei prezzi);
- sl è il prezzo a cui si chiuderà l'ordine, qualora il prezzo non fosse a nostro vantaggio (può essere tralasciato se la strategia non prevede l'utilizzo dello stop loss);
- tp è il prezzo a cui l'ordine si chiuderà, qualora il prezzo prendesse la direzione richiesta, cioè trae profitto (può essere omesso se la strategia non implica l'uso del take profit);
- comment è il commento all'ordine, ad esempio specificando il motivo dell'ordine.
Esistono diversi modi per chiudere una posizione:
- chiudere l'intera posizione
CPositionInfo m_Position; m_Position.Select(symbol_name); m_Trade.PositionClose(symbol_name);
- chiudere la posizione effettuando un ordine inverso della stessa dimensione
CTrade m_Trade; m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
- utilizzando un metodo più complicato in cui vengono prima cercate tutte le posizioni aperte per individuare quella che soddisfa i parametri richiesti (simbolo, tipo, numero magico, identificatore di posizione, ecc.) per essere chiusa ulteriormente.
Non farò alcun esempio di quanto detto sopra vista la sua difficoltà per i principianti.
Mettere Tutto Insieme
È giunto il momento di mettere le conoscenze appena acquisite in un unico Expert Advisor.
//+------------------------------------------------------------------+ //| fast-start-example.mq5 | //| Copyright 2012, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2012, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> //include the library for execution of trades #include <Trade\PositionInfo.mqh> //include the library for obtaining information on positions int iMA_handle; //variable for storing the indicator handle double iMA_buf[]; //dynamic array for storing indicator values double Close_buf[]; //dynamic array for storing the closing price of each bar string my_symbol; //variable for storing the symbol ENUM_TIMEFRAMES my_timeframe; //variable for storing the time frame CTrade m_Trade; //structure for execution of trades CPositionInfo m_Position; //structure for obtaining information of positions //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { my_symbol=Symbol(); //save the current chart symbol for further operation of the EA on this very symbol my_timeframe=PERIOD_CURRENT; //save the current time frame of the chart for further operation of the EA on this very time frame iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE); //apply the indicator and get its handle if(iMA_handle==INVALID_HANDLE) //check the availability of the indicator handle { Print("Failed to get the indicator handle"); //if the handle is not obtained, print the relevant error message into the log file return(-1); //complete handling the error } ChartIndicatorAdd(ChartID(),0,iMA_handle); //add the indicator to the price chart ArraySetAsSeries(iMA_buf,true); //set iMA_buf array indexing as time series ArraySetAsSeries(Close_buf,true); //set Close_buf array indexing as time series return(0); //return 0, initialization complete } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(iMA_handle); //deletes the indicator handle and deallocates the memory space it occupies ArrayFree(iMA_buf); //free the dynamic array iMA_buf of data ArrayFree(Close_buf); //free the dynamic array Close_buf of data } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { int err1=0; //variable for storing the results of working with the indicator buffer int err2=0; //variable for storing the results of working with the price chart err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf); //copy data from the indicator array into the dynamic array iMA_buf for further work with them err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf); //copy the price chart data into the dynamic array Close_buf for further work with them if(err1<0 || err2<0) //in case of errors { Print("Failed to copy data from the indicator buffer or price chart buffer"); //then print the relevant error message into the log file return; //and exit the function } if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0]) //if the indicator values were greater than the closing price and became smaller { if(m_Position.Select(my_symbol)) //if the position for this symbol already exists { if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol); //and this is a Sell position, then close it if(m_Position.PositionType()==POSITION_TYPE_BUY) return; //or else, if this is a Buy position, then exit } m_Trade.Buy(0.1,my_symbol); //if we got here, it means there is no position; then we open it } if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0]) //if the indicator values were less than the closing price and became greater { if(m_Position.Select(my_symbol)) //if the position for this symbol already exists { if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol); //and this is a Buy position, then close it if(m_Position.PositionType()==POSITION_TYPE_SELL) return; //or else, if this is a Sell position, then exit } m_Trade.Sell(0.1,my_symbol); //if we got here, it means there is no position; then we open it } } //+------------------------------------------------------------------+
Mettiamo alla prova il nostro Expert Advisor con i seguenti parametri:
- symbol - EURUSD;
- time frame - H1;
- trade mode "Opening prices only".
Poiché utilizziamo i valori dell'indicatore e i prezzi di chiusura a partire dalla prima barra (la barra zero è una barra corrente e attiva), il grafico non verrà ridisegnato. Significa che possiamo utilizzare la trade "Solo prezzi di apertura". Non influenzerà la qualità del test, ma lo renderà più veloce.
Ed ecco i risultati dei test rapidi utilizzando i dati storici.
Fig. 6. I risultati dei nostri test sull’Expert Advisor
I drawdown non possono certo passare inosservati. Tuttavia questo articolo non mirava a programmare un "super Expert Advisor" che avrebbe un grande potenziale di profitto con un drawdown minimo, ma piuttosto a dimostrare quanto facilmente si possa creare un EA quando si è armati di conoscenze di base.
Abbiamo l'Expert Advisor composto da meno di cento righe di codice.
Conclusione
Questo articolo ha trattato i principi fondamentali da considerare quando si programma un EA. Abbiamo imparato come usare l'Help contestuale integrato in MetaEditor 5 per ottenere informazioni su varie funzioni, abbiamo avuto un'idea generale di ordini e posizioni e ci siamo avvicinati all’uso delle librerie standard.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/496
![1003153 1003153](https://c.mql5.com/avatar/avatar_na2.png)
![Creare un Expert Advisor interattivo semiautomatico drag-and-drop basato su rischio predefinito e rapporto R/R](https://c.mql5.com/2/0/z5491084X.png)
![Visualizza una Strategia nel Tester MetaTrader 5](https://c.mql5.com/2/0/trade_robot_in_Backtester.png)
![Progettare e implementare nuovi widget GUI basati sulla classe CChartObject](https://c.mql5.com/2/0/Design_Widgets_MQL5.png)
![MetaTrader 5 - Più di Quanto Tu Possa Immaginare!](https://c.mql5.com/2/0/diamond_MetaTrader_5.png)
![MQL5 - Linguaggio delle strategie di trading integrato nel client terminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- 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