
Comprendere il piazzamento degli ordini in MQL5
Introduzione
In qualsiasi sistema di trading, dobbiamo occuparci degli ordini e delle loro operazioni, come l'apertura di posizioni, il posizionamento di stop-loss e take-profit e la modifica degli ordini. Pertanto, è molto importante capire come gestire gli ordini in mql5 quando si crea un sistema di trading per MetaTrader5. L'obiettivo di questo articolo è quello di fornire una guida semplice per la maggior parte delle operazioni di ordini e posizioni, in modo da poter affrontare efficacemente tutto ciò che riguarda questo argomento. In questo articolo tratteremo i seguenti argomenti:
- Ordini, posizioni e termini delle transazioni
- OrderSend()
- Applicazione OrderSend()
- Classe CTrade
- Applicazione della classe CTrade
- Conclusioni
Spero che troviate questo articolo utile e prezioso per sviluppare il vostro sistema di trading MetaTrader5 senza problemi per quanto riguarda l'inserimento degli ordini. Tutte le applicazioni presentate in questo articolo devono essere testate prima di essere utilizzate per assicurarsi che siano profittevoli o adatte al proprio trading, perché lo scopo principale della loro menzione è solo quello di fornire un esempio di creazione di un sistema di trading utilizzando due metodi differenti per quanto riguarda l’operatività con gli ordini, le transazioni e le posizioni.
Termini : Ordini, Posizioni e Transazioni
In questa parte parleremo di termini importanti per capire come gestire gli ordini in modo efficace. Capiremo le differenze tra tre termini correlati agli ordini nella MetaTrader 5. Questi termini sono ordine, transazione e posizione, che possiamo considerare come passi per l'esecuzione del trade.
Ordine: è una richiesta ricevuta dal server di trading per aprire un'operazione di acquisto o vendita con un lotto o un volume specifico a un prezzo specifico. Esistono due tipi di ordini: l'ordine a mercato e l'ordine pendente.
- Ordine a mercato: è un ordine che può essere eseguito immediatamente al prezzo di mercato corrente.
- Ordine pendente: è un ordine che esegue l'operazione a condizioni predeterminate riguardanti il prezzo di esecuzione dell'operazione al suo livello e il tempo di esecuzione dell'operazione.
Questi ordini pendenti possono essere uno dei seguenti:
- Buy stop: Piazza un ordine pendente di acquisto ad un prezzo specifico che è superiore al prezzo attuale di mercato.
- Buy limit: Piazza un ordine pendente di acquisto ad un prezzo specifico che è inferiore al prezzo attuale di mercato.
- Sell stop: Piazza un ordine pendente di vendita ad un prezzo specifico che è inferiore al prezzo attuale di mercato.
- Sell limit: Piazza un ordine pendente di vendita ad un prezzo specifico che è superiore al prezzo attuale di mercato.
Una volta piazzato l'ordine, indipendentemente dal fatto che si tratti di un ordine a mercato o di un ordine pendente, è possibile trovarlo nella scheda Operazioni di Trading del BoxAttrezzi di MetaTrader 5. Di seguito è riportato un esempio:
Quando l'ordine viene chiuso o cancellato senza essere eseguito, è possibile trovarlo nella scheda CroniStoria del BoxAttrezzi.
Quando vogliamo modificare una posizione corrente con MQL5, dobbiamo trattare questi ordini come vedremo in seguito quando gestiremo la modifica degli ordini.
Transazione: È il risultato quando l'ordine di compravendita viene eseguito o riempito. Possiamo trovarli come azioni di entrata e uscita basate sull'esecuzione del trade. Supponiamo che sia stato eseguito un ordine di acquisto di un lotto. Successivamente, abbiamo chiuso parzialmente la posizione di 0,5 lotti, poi abbiamo chiuso i restanti 0,5 lotti. Quindi, le transazioni saranno uguali alle seguenti:
- 1 buy in
- 0,5 sell out
- 0,5 sell out
Possiamo trovare queste transazioni nella scheda CroniStoria del BoxAttrezzi di MetaTrader 5, visualizzando i dati delle operazioni con un clic destro e scegliendoli.
Posizione: Si tratta del netto delle operazioni long o short basate sull'acquisto o sulla vendita dell'attività finanziaria. La possiamo trovare nella scheda Operazioni di Trading come trade attivo o nella scheda CroniStoria se scegliamo di far apparire le posizioni.
È bene ricordare che il prezzo eseguibile dell'ordine di acquisto è il prezzo Ask, mentre il prezzo eseguibile alla sua chiusura è il prezzo Bid. D'altra parte, il prezzo eseguibile dell'ordine di vendita è il prezzo Bid e il prezzo eseguibile alla sua chiusura è il prezzo Ask.
OrderSend()
Dopo aver compreso i termini importanti sull'esecuzione delle operazioni in MetaTrader 5, dobbiamo imparare come eseguire gli ordini automaticamente in MQL5. In primo luogo, per maggiori informazioni sulle funzioni destinate alla gestione delle attività, è possibile consultare il riferimento MQL5 Funzioni di Trade.
Discuteremo la funzione OrderSend(), che può essere utilizzata per eseguire operazioni di trade inviando richieste a un server di trade. In altre parole, può essere utilizzata per piazzare, modificare e chiudere ordini.
Il formato di questa funzione è il seguente:
bool OrderSend( MqlTradeRequest& request, MqlTradeResult& result );
Come si può notare, la funzione ha due parametri:
- Struttura MqlTradeRequest: Contiene i parametri dell'ordine e tutti i campi o le variabili necessarie per eseguire le transazioni del trade. Oggetti passati per riferimento come da &. TradeRequest è il metodo di interazione tra il terminale client e il server di trade per l'esecuzione degli ordini.
- Struttura MqlTradeResult: TradeResult restituisce i risultati della richiesta dell’ordine. Anche qui gli oggetti sono passati per riferimento.
La struttura MqlTradeRequest:
La struttura è un insieme di dati correlati di diverso tipo. La definizione della struttura MqlTradeRequest è la seguente:
struct MqlTradeRequest { ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type ulong magic; // Expert Advisor ID (magic number) ulong order; // Order ticket string symbol; // Trade symbol double volume; // Requested volume for a deal 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; // Maximal possible deviation from the requested price ENUM_ORDER_TYPE type; // Order type ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type ENUM_ORDER_TYPE_TIME type_time; // Order expiration type datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type) string comment; // Order comment ulong position; // Position ticket ulong position_by; // The ticket of an opposite position };
Se vogliamo dichiarare un oggetto MqlTradeRequest, possiamo farlo con la seguente riga di codice:
MqlTradeRequest request;
Quindi, si possono assegnare i parametri del trade alle variabili dell'oggetto request creato, aggiungendo un punto (.) dopo l'oggetto, come mostrato nell'esempio seguente:
request.symbol = _Symbol; request.volume = 0.01; request.type = ORDER_TYPE_BUY;
Di seguito sono elencati tutti i membri o le variabili della struttura MqlTradeRequest, insieme ai valori accettati per l'assegnazione.
Variabile | Descrizione | Valore accettato per l'assegnazione |
---|---|---|
action | Rappresenta il tipo di operazione di trade | Uno degli ENUM_TRADE_REQUEST_ACTIONS (TRADE_ACTION_DEAL, TRADE_ACTION_PENDING, TRADE_ACTION_SLTP, TRADE_ACTION_MODIFY, TRADE_ACTION_REMOVE, TRADE_ACTION_CLOSE_BY). |
magic | Rappresenta l'ID dell’expert advisor per identificare gli ordini effettuati da un determinato expert advisor | Qualsiasi valore ulong |
order | Rappresenta il ticket dell'ordine. È necessario quando si utilizza TRADE_ACTION_MODIFY o TRADE_ACTION_REMOVE nella variabile action. | Qualsiasi valore ulong |
symbol | Il simbolo specificato o lo strumento da negoziare. (_SYMBOL) si riferisce a quello corrente. | Qualsiasi simbolo di tipo string |
volume | Specifica il volume di trade o i lotti | Qualsiasi valore double consentito |
price | Il prezzo di apertura | Valore double |
stoplimit | Il prezzo di apertura dell'ordine pendente limite. Action deve essere TRADE_ACTION_PENDING e la variabile type deve essere ORDER_TYPE_BUY_STOP_LIMIT o ORDER_TYPE_SELL_STOP_LIMIT ed è necessaria per gli ordini stop limit. | Valore double |
sl | Il prezzo di stop loss dell'operazione | Valore double |
tp | Il prezzo di take profit dell'operazione | Valore double |
deviation | La deviazione massima del prezzo in punti | valore ulong |
type | Il tipo di ordine | Uno degli ENUM_ORDER_TYPE (ORDER_TYPE_BUY, ORDER_TYPE_SELL, ORDER_TYPE_BUY_STOP, ORDER_TYPE_SELL_STOP), ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT) |
type_filling | Tipo di esecuzione dell'ordine o politica di riempimento dell'ordine | Uno degli ENUM_ORDER_TYPE_FILLING (ORDER_FILLING_FOK, ORDER_FILLING_IOC, ORDER_FILLING_BOC, ORDER_FILLING_RETURN) |
type_time | Il tipo di scadenza dell'ordine pendente | Uno degli ENUM_ORDER_TYPE_TIME (ORDER_TIME_GTC, ORDER_TIME_DAY, ORDER_TIME_SPECIFIED, ORDER_TIME_SPECIFIED_DAY). |
expiration | L’ora di scadenza dell'ordine pendente. È necessario quando type_time è ORDER_TIME_SPECIFIED | valore datetime |
comment | Il commento all'ordine | valore string |
position | Il ticket di una posizione. È necessario quando una posizione viene modificata o chiusa per identificarla. | valore ulong |
position_by | Il ticket di una posizione opposta. Si utilizza quando la posizione è chiusa da una posizione aperta in direzione opposta per lo stesso simbolo. | valore ulong |
Ora citeremo alcune azioni importanti da utilizzare quando si piazzano ordini in MQL5.
- Ordine a mercato
- Aggiunta di stop-loss e take-profit
- Ordine pendente
- Modifica di ordine pendente
- Rimuovere l'ordine pendente
Ordine a mercato:
In questo tipo di azione, dobbiamo piazzare un ordine a mercato, il che significa che l'ordine sarà piazzato al prezzo di mercato corrente; useremo l’azione (TRADE_ACTION_DEAL). Se si tratta di un ordine di acquisto, l'ordine verrà piazzato al prezzo ask corrente o se si tratta di un ordine di vendita, l'ordine verrà piazzato al prezzo sell corrente. Ecco come fare:
Dopo aver dichiarato gli oggetti MqlTradeRequest e MqlTradeResult, possiamo assegnare i seguenti valori alle seguenti variabili:
request.action = TRADE_ACTION_DEAL; &nbsthe p; //market order palcement request.type = ORDER_TYPE_BUY; //type of order is buy request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); //the price is the current ask for buy request.sl = 0; //stop loss is 0 request.tp = 0; //take profit is 0 request.deviation = 50; //slippage is 50 OrderSend(request, result); //calling the OrderSend function
Come possiamo vedere nel codice precedente, non abbiamo aggiunto i valori di stop loss e take profit. Possiamo aggiungere i loro valori al codice insieme alle altre variabili, oppure possiamo aggiungerli attraverso un'altra azione, come vedremo nel prossimo punto.
Aggiunta di stop-loss e take-profit:
Quando dobbiamo aggiungere stop-loss e take-profit, assegniamo la TRADE_ACTION_SLTP alla variabile action, come mostrato nell'esempio seguente.
request.action = TRADE_ACTION_SLTP; //adding sl and tp request.symbol = _Symbol; //applied for the cuurrent symbol request.sl = 1.07000; //sl price request.sl = 1.09000; //tp price OrderSend(request, result); //calling the OrderSend function
Ordine pendente:
Se vogliamo piazzare un ordine pendente, possiamo utilizzare un'altra azione (TRADE_ACTION_PENDING). Quindi, si determina il tipo di ordine. Possiamo impostare l'ora se abbiamo bisogno di un’ora di scadenza per l'ordine pendente.
request.action = TRADE_ACTION_PENDING; //pending order placement request.type = ORDER_TYPE_BUY_STOP; //type of order is buy stop request.symbol = _Symbol; //applied for the cuurrent symbol request.volume = 0.1; //the lot size request.price = 1.07000; //opening price request.sl = 1.06950; //stop loss request.tp = 1.07100; //take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.08.31 00.00'; //expiration time - datetime constant request.type_filling = ORDER_FILLING_FOK; //the filling policy fill or kill request.stoplimit = 0; //for stoplimit order only OrderSend(request, result); //calling the OrderSend function
Modifica dell’ordine pendente:
Se dobbiamo modificare un ordine pendente, dobbiamo ottenere il numero di ticket dell'ordine pendente che dobbiamo modificare. Possiamo utilizzare la funzione OrderGetTicket per ottenere il ticket dell'ordine. Questa funzione restituisce il ticket dell'ordine corrispondente, che può essere utilizzato per selezionare l'ordine e lavorarci.
ulong OrderGetTicket( int index // Number in the list of orders );
Consideriamo di avere una variabile denominata (ticket) che contiene il numero del ticket dell'ordine. Possiamo usare questa variabile per assegnare il numero del ticket dell'ordine alla variabile order dell'oggetto request. Possiamo quindi modificare l'ordine utilizzando l'azione (TRADE_ACTION_MODIFY), come nell'esempio seguente.
request.action = TRADE_ACTION_MODIFY; //pending order modyfying request.order = ticket; //ticket variable that holds the pending order ticket to modify request.price = 1.07050; //new opening price request.sl = 1.07000; //new stop loss request.tp = 1.07150; //new take profit request.type_time = ORDER_TIME_SPECIFIED; //to set an expiration time request.expiration = D'2023.09.01 00.00'; //new expiration time - datetime constant OrderSend(request, result); //calling the OrderSend function
Rimuovere l’Ordine Pendente:
Se dobbiamo rimuovere l'ordine pendente, possiamo farlo utilizzando l'azione (TRADE_ACTION_REMOVE). Abbiamo bisogno anche del numero di ticket dell'ordine pendente che dobbiamo rimuovere. Possiamo usare la variabile ticket, supponendo che contenga il numero di ticket necessario.
request.action = TRADE_ACTION_REMOVE; //pending order remove request.order = ticket; //ticket variable that holds the pending order ticket to remove OrderSend(request, result); //calling the OrderSend function
La struttura MqlTradeResult:
La struttura MqlTradeResult restituisce il risultato che indica se l'ordine è andato o meno a buon fine dopo aver piazzato un ordine tramite la funzione OrderSend(). Contiene le informazioni sull'operazione provenienti dal server di trade, come il numero del ticket, il volume e il prezzo.
Di seguito è riportata la definizione della struttura MqlTradeResult:
struct MqlTradeResult { uint retcode; // Operation return code ulong deal; // Deal ticket, if it is performed ulong order; // Order ticket, if it is placed double volume; // Deal volume, confirmed by broker double price; // Deal price, confirmed by broker double bid; // Current Bid price double ask; // Current Ask price string comment; // Broker comment to operation (by default it is filled by description of trade server return code) uint request_id; // Request ID set by the terminal during the dispatch int retcode_external; // Return code of an external trading system };
Possiamo dichiarare un oggetto chiamato result per passarlo come secondo parametro dopo il primo (request) alla chiamata della funzione OrderSend().
MqlTradeResult result;
Come si può vedere nelle variabili della struttura MqlTradeResult, la variabile retcode è molto importante perché restituisce il codice del server di trade per indicare se la richiesta ha avuto successo o meno.
Se l'operazione non viene piazzata, il codice di ritorno indica uno stato di errore. Puoi consultare l'elenco dei codici di ritorno nel riferimento MQL5 per maggiori informazioni. È fondamentale includere un codice nel nostro sistema di trading per segnalare se viene restituito un errore o meno, come nell'esempio seguente:
if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) { Print("Trade Placed Successfully"); } else { Print("Trade Not Placed, Error ", result.retcode); }
Come si può vedere nel codice precedente, dopo la request viene stampato un messaggio con il risultato e vengono compilate le variabili result. Se l'operazione è stata effettuata, ci invierà un messaggio di conferma; se invece c'è un problema, stamperà un messaggio di errore e restituirà il codice di errore per aiutarci a risolvere il problema.
Applicazione OrderSend()
Dobbiamo creare un semplice sistema di trading che possa eseguire operazioni utilizzando la funzione OrderSend(). Il sistema di trading che dobbiamo creare è un semplice crossover di medie mobili e l'azione consiste nel piazzare un ordine a mercato.
L'obiettivo è quello di comprendere le differenze nella creazione dello stesso sistema di trading utilizzando OrderSend() e la classe CTrade. Di seguito sono illustrati i passaggi per creare questo crossover MA utilizzando la funzione OrderSend().
Nell’ambito globale creare due variabili integer (simpleMA, barsTotal) senza assegnazione, verranno assegnate successivamente nella parte OnInit.
int simpleMA; int barsTotal;
La simpleMA sarà assegnata alla funzione iMA che restituisce l'handle dell'indicatore tecnico della media mobile. I suoi parametri sono:
- symbol: Per specificare il nome del simbolo, _Symbol si riferisce allo strumento corrente.
- period: Per specificare il time frame, utilizzeremo PERIOD_H1, che si riferisce al time frame di un'ora.
- ma_period: il periodo della media mobile, che sarà di 50.
- ma_shift: per specificare lo spostamento orizzontale necessario.
- ma_method: Per specificare il tipo di media mobile, specificheremo quella semplice.
- applied_price: Per specificare il tipo di prezzo che verrà utilizzato nel calcolo della MA, imposteremo il prezzo di chiusura.
barsTotal verrà assegnato alla funzione iBars che restituisce il numero di barre. I suoi parametri sono:
- symbol: Il nome del simbolo
- timeframe: il periodo del time frame
simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1);
Nella parte OnTick, creeremo due array, uno per il prezzo, utilizzando il tipo MqlRates, che memorizza le informazioni su prezzo, volume e spread, e l'altro per la media mobile, utilizzando il tipo di variabile double.
MqlRates priceArray[]; double mySMAArray[];
Definizione dei prezzi ask e bid
double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
Creare due oggetti per la funzione OrderSend(), uno per la richiesta utilizzando MqlTradeRequest e l'altro per il risultato utilizzando MqlTradeResult, quindi resettare la variabile request per riferimento
ZeroMemory(request);
Impostare il flag AS_SERIES su questi due array creati, priceArray e mySMAArray utilizzando la funzione ArraySetAsSeries. I suoi parametri sono:
- array[]: Per specificare l'array necessario
- flag: Direzione di indicizzazione dell’array.
ArraySetAsSeries(priceArray,true); ArraySetAsSeries(mySMAArray,true);
Ottenere i dati storici MqlRates utilizzando la funzione CopyRates. I suoi parametri sono:
- symbol: il nome del simbolo o _Symbol per il simbolo o lo strumento corrente.
- time frame: periodo del time frame o _period per il time frame corrente.
- start position: la posizione da cui partire.
- count: numero dei dati da copiare.
- rates_array: l'array di destinazione in cui copiare.
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
Ottenere il buffer dei dati dell'indicatore utilizzando la funzione CopyBuffer. I suoi parametri sono:
- indicator_handle: Per specificare l’handle dell'indicatore MA.
- buffer_num: Per specificare il numero di buffer dell'indicatore.
- start_pos: la posizione iniziale da cui contare.
- count: quantità da copiare.
- buffer[]: l'array di destinazione.
CopyBuffer(simpleMA,0,0,3,mySMAArray);
Definizione dell'ultimo prezzo di chiusura, del prezzo di chiusura precedente, dell'ultimo valore SMA e del valore SMA precedente
double lastClose=(priceArray[1].close); double prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
Creare una variabile intera bars e assegnarle iBars.
int bars=iBars(_Symbol,PERIOD_H1);
Controllo delle barre, se barsTotal non è uguale alla variabile bars
if(barsTotal != bars)
Aggiornare il valore di barsTotal in modo che sia uguale a bars se non sono uguali tra loro
barsTotal=bars;
Verifica della condizione della strategia per aprire un'operazione, se l'ultima chiusura è superiore all'ultimo valore SMA dopo che la chiusura precedente era inferiore al valore SMA precedente
if(prevClose<prevSMAVal && lastClose>SMAVal)
Apertura di un ordine di acquisto a mercato utilizzando le variabili appropriate relative alla funzione MqlTradeRequest.
request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result);
Verifica della condizione della strategia per aprire un'operazione di vendita, se l'ultima chiusura è inferiore all'ultimo valore SMA dopo che la chiusura precedente era maggiore del valore SMA precedente
if(prevClose>prevSMAVal && lastClose<SMAVal)
Apertura di un ordine di vendita a mercato utilizzando le variabili appropriate relative alla funzione MqlTradeRequest. request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result);
Di seguito è riportato il codice completo in un unico blocco per creare questo tipo di sistema di trading utilizzando la funzione OrderSend()
//+------------------------------------------------------------------+ //| OrderSend_Trading_system.mq5 | //+------------------------------------------------------------------+ int simpleMA; int barsTotal; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } void OnTick() { MqlRates priceArray[]; double mySMAArray[]; double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); 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 prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); request.sl = Ask-(500*_Point); request.tp = Ask+(1000*_Point); request.deviation = 50; OrderSend(request, result); } if(prevClose>prevSMAVal && lastClose<SMAVal) { request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_SELL; request.symbol = _Symbol; request.volume = 0.1; request.type_filling = ORDER_FILLING_FOK; request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID); request.sl = Bid+(500*_Point); request.tp = Bid-(1000*_Point); request.deviation = 50; OrderSend(request, result); } } }
Classe CTrade
Dopo aver appreso come piazzare gli ordini tramite la funzione OrderSend(), abbiamo un metodo semplice per accedere alle funzioni di trading. Possiamo utilizzare la classe CTrade già pronta fornita da MQL5, oppure possiamo creare la nostra classe per preferenze più personali. Ora, si parlerà di come utilizzare la classe CTrade già pronta in MQL5. Per ulteriori informazioni, è possibile consultare la classe CTrade dal riferimento MQL5.
Per prima cosa, possiamo trovare il file include della classe CTrade nella cartella Trade della cartella include nei file di installazione di MetaTrader 5. È sufficiente includere questo file nell'expert advisor per richiamare e utilizzare tutte le funzioni di trade, come di seguito indicato:
#include <Trade\Trade.mqh>
Creare un oggetto per la classe CTrade
CTrade trade;
In seguito saremo in grado di utilizzare tutte le funzioni di trade della classe CTrade, utilizzando trade prima del punto(.) e della funzione desiderata. Possiamo utilizzare tutte le funzioni per le operazioni con ordini, operazioni con posizioni, accesso ai parametri dell'ultima richiesta, accesso ai risultati della verifica dell'ultima richiesta, accesso ai risultati dell'esecuzione dell'ultima richiesta e altre ancora.
Citeremo alcune funzioni importanti come abbiamo fatto con OrderSend() per capire le differenze tra i due metodi. Capiremo come fare in base a quanto segue:
- Ordine a mercato
- Aggiunta di stop-loss e take-profit
- Ordine pendente
- Modifica di ordine pendente
- Rimuovere l'ordine pendente
Ordine a mercato:
Dopo aver creato il nostro oggetto trade, possiamo utilizzare la funzione PositionOpen per piazzare un ordine a mercato; i suoi parametri sono:
- symbol: per specificare il simbolo necessario
- order_type: per specificare il tipo di ordine per aprire una posizione
- volume: per specificare la dimensione del lotto
- price: per specificare il prezzo di apertura della posizione
- sl: per specificare il prezzo dello stop loss
- tp: per specificare il prezzo del take profit
- comment: per specificare un commento o NULL
Il seguente è un esempio di ciò:
trade.PositionOpen( _Symbol, //to be applied for the current symbol ORDER_TYPE_BUY, //to place buy order 0.1, //lot size or volume Ask, //opening price of the order - current ask Ask-(500*_Point), //sl Ask+(1000*_Point), //tp NULL //NULL );
Per aprire un ordine a mercato possiamo anche utilizzare i metodi aggiuntivi di CTrade come Buy, Sell invece di PositionOpen.
Aggiunta di stop-loss e take-profit:
È possibile modificare la posizione in base al simbolo o al numero del ticket utilizzando la funzione PositionModify. I suoi parametri sono:
- symbol o ticket: per specificare la posizione da modificare, se si modifica per simbolo si specifica il nome del simbolo o se si modifica per ticket si specifica il numero del ticket.
- sl: il nuovo prezzo dello stop loss
- tp: il nuovo prezzo di take profit
Esempio di modifica per simbolo:
trade.PositionModify( EURUSD, //the symbol name 1.06950, //the new sl 1.07100, //the new tp );
Esempio di modifica per ticket:
trade.PositionModify( ticket, //the ticket variable that holds the needed ticket number to modify 1.06950, //the new sl 1.07100, //the new tp );
Ordine pendente:
Se dobbiamo piazzare un ordine pendente utilizzando la classe CTrade, possiamo utilizzare la funzione OrderOpen. I suoi parametri sono:
- symbol: per determinare il nome del simbolo
- order_type: per determinare il tipo di ordine pendente
- volume: per specificare la dimensione del lotto
- limit_price: per specificare il prezzo stop limit
- price: per specificare il prezzo di esecuzione dell'ordine pendente
- sl: per specificare lo stop loss
- tp: per specificare il prezzo di take profit
- type_time: per specificare il tipo di scadenza
- expiration: per specificare la variabile datetime di scadenza
- comment: per specificare un commento, se necessario
L'esempio seguente riguarda l'inserimento di un ordine pendente buy limit utilizzando la funzione OrderOpen
trade.OrderOpen( "EURUSD", // symbol ORDER_TYPE_BUY_LIMIT, // order type 0.1, // order volume 0, // StopLimit price 1.07000, // execution price 1.06950, // Stop Loss price 1.07100, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration "" // comment );
Modifica dell’ordine pendente:
Se abbiamo bisogno di modificare l'ordine pendente piazzato, possiamo farlo utilizzando la classe CTrade tramite la funzione OrderModify. I suoi parametri sono:
- ticket: per specificare il ticket dell'ordine pendente da modificare
- price: il nuovo prezzo di esecuzione
- sl: il nuovo prezzo di stop loss
- tp: il nuovo prezzo di take profit
- type_time: per specificare il tipo di scadenza
- expiration: per specificare la variabile datatime di scadenza
- stoplimit: per determinare il prezzo dell'ordine limit
Di seguito è riportato un esempio di modifica di un ordine pendente
trade.OrderModify( ticket, // ticket number of the pending order to modify 1.07050, // execution price 1.07000, // Stop Loss price 1.07150, // Take Profit price ORDER_TIME_SPECIFIED, // type by expiration D'2023.08.31 00.00', // expiration 0, // StopLimit price );
Cancellare l'ordine pendente:
Se è necessario eliminare un ordine pendente, è possibile farlo utilizzando la funzione OrderDelete, che richiede il numero di ticket dell'ordine pendente da eliminare. Di seguito è riportato un esempio di tale funzione.
trade.OrderDelete(
ticket, // tick number of the pending order to delete
);
Applicazione della classe CTrade
Dobbiamo creare lo stesso sistema di trading creato con OrderSend(). Utilizzeremo la classe CTrade per capire le differenze di funzionamento delle funzioni di entrambe.
Di seguito sono riportati gli unici passaggi diversi per creare questo sistema di trading utilizzando la classe CTrade, mentre i restanti passaggi sono gli stessi già eseguiti in precedenza.
Includere il file include Trade utilizzando il preprocessore #include
#include <Trade\Trade.mqh>
Creare l'oggetto trade della classe CTrade
CTrade trade;
Quando la condizione di acquisto è soddisfatta, possiamo utilizzare PositionOpen e il tipo di ordine sarà ORDER_TYPE_BUY o il metodo aggiuntivo Buy, come il seguente codice
trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL);
Quando la condizione di vendita è soddisfatta, possiamo utilizzare PositionOpen con il tipo di ordine ORDER_TYPE_SELL o il metodo aggiuntivo Sell, come il seguente codice
trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL);
Di seguito è riportato il codice completo per creare il sistema di trading utilizzando la classe CTrade:
//+------------------------------------------------------------------+ //| CTrade_Trading_System.mq5 | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> int simpleMA; int barsTotal; CTrade trade; int OnInit() { simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE); barsTotal=iBars(_Symbol,PERIOD_H1); return(INIT_SUCCEEDED); } 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 prevClose=(priceArray[2].close); double SMAVal = NormalizeDouble(mySMAArray[1],_Digits); double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits); int bars=iBars(_Symbol,PERIOD_H1); if(barsTotal != bars) { barsTotal=bars; if(prevClose<prevSMAVal && lastClose>SMAVal) { trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL); } if(prevClose>prevSMAVal && lastClose<SMAVal) { trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL); } } }
Conclusioni
Se avete completato la lettura di questo articolo, si suppone che abbiate capito come funzionano gli ordini, le posizioni e le transazioni in MQL5. Oltre a capire come creare un sistema di trading senza problemi utilizzando i due metodi per le operazioni di trade, il metodo OrderSend e il metodo CTrade.
Abbiamo identificato il modo in cui piazziamo gli ordini a mercato e gli ordini pendenti, aggiunta di stop-loss e take-profit, modifica degli ordini pendenti e rimozione o cancellazione degli ordini pendenti utilizzando i due metodi.
Si presume che abbiate capito come applicare tutti i precedenti per creare un'applicazione, perché abbiamo fornito due semplici applicazioni per creare lo stesso sistema di trading con crossover della media mobile utilizzando i due metodi.
- OrderSend_Trading_System
- CTrade_Trading_System
L'obiettivo delle applicazioni citate è solo quello di capire le differenze tra di esse a livello pratico, quindi, fate attenzione, dovete testarle prima di utilizzarle in un conto live per assicurarvi che siano redditizie e adatte al vostro trading.
Credo che abbiate capito quanto sia facile usare la classe già pronta CTrade quando si lavora con le operazioni di trade, perché vi fa risparmiare molto tempo e fatica. Oltre ad altre caratteristiche, quando si utilizzano le classi nella programmazione in generale.
Se volete saperne di più su questo aspetto e sulla programmazione orientata agli oggetti in MQL5, potete leggere il mio precedente articolo Capire la programmazione orientata agli oggetti (OOP) in MQL5; spero che vi sia utile. MQL5 ha fatto un lavoro e uno sforzo molto apprezzati per fornirci gli strumenti per sviluppare e creare software di trading in modo semplice e agevole.
Spero che abbiate trovato utile questo articolo e che abbiate ottenuto molti spunti utili per capire e svolgere facilmente il vostro lavoro dopo questi approfondimenti. Se volete leggere altri miei articoli, potete consultare le mie pubblicazioni per trovare molti articoli su come creare sistemi di trading utilizzando gli indicatori tecnici più popolari e altro e spero che li troviate utili.
Tradotto dall’inglese da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/en/articles/13229
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.





- 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
ciao,
grande testo, tyvm.
Ho trovato un piccolo bug:
nella casella sottoTRADE_ACTION_SLTP avete scritto due volte request.sl, la seconda dovrebbe essere request.tp, come indicato nel commento alla fine della riga.
Cordiali saluti,
Gunther
Salve,
Grazie per il suo gentile commento. Hai ragione, è un errore e sarà preso in considerazione.
Saluti,
Utilizzando il tuo codice sto scrivendo un semplice ordine per uno strumento!
double price = 94500;
double stopLoss = prezzo - (500 * _Punto);
double takeProfit = prezzo + (1000 * _Point);
ulong ticket = trade.OrderOpen(
"SiM4", // simbolo
restituisce GetLastError() = 0 e l'ordine non viene piazzato e non c'è alcun accordo
È necessario specificare un token di accesso speciale quando si effettua un ordine dal broker?
restituisce GetLastError() = 0 e l'ordine non viene piazzato e non c'è alcuna transazione
È necessario specificare un token di accesso speciale quando si effettua un ordine dal broker?
Ciao Abdel Maaboud,
grazie per la gentilezza con cui hai scritto questo tutorial.
Questo tutorial fornisce solo il posizionamento degli ordini. C'è qualche codice per chiudere la posizione(take profit o cut loss) nel tuo articolo?
Cordiali saluti,
Ahmad Juniar