English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
preview
Eventi di Trade in MetaTrader 5

Eventi di Trade in MetaTrader 5

MetaTrader 5Trading | 9 dicembre 2021, 14:05
243 0
MetaQuotes
MetaQuotes

Introduzione

Tutti i comandi per eseguire operazioni di trading vengono passati al server di trading dal client terminal MetaTrader 5 tramite l'invio di richieste. Ogni richiesta deve essere correttamente compilata in base all'operazione richiesta; altrimenti non passerà la convalida primaria e non sarà accettata dal server per ulteriori elaborazioni.

Le richieste accettate dal server di trading vengono archiviate sotto forma di ordini che possono essere in sospeso o eseguiti istantaneamente dal prezzo di mercato. Gli ordini vengono archiviati sul server fino a quando non vengono evasi o annullati. Il risultato dell'esecuzione di un ordine è un deal.

Un del cambia la posizione di trading di un dato simbolo, può aprire, chiudere, aumentare, diminuire o invertire la posizione. Pertanto, una posizione aperta è sempre il risultato dell'esecuzione di uno o più deal. Informazioni più dettagliate sono fornite nell'articolo Ordini, Posizioni e Deal in MetaTrader 5.

Questo articolo descrive il concetto, i termini e i processi che fluiscono nel periodo dall'invio di una richiesta al suo spostamento nella cronologia di trading dopo che è stata elaborata.


Passaggio della Richiesta dal Client Terminal al Server di Trading.

Per eseguire un'operazione di trading, è necessario inviare un ordine al sistema di trading. Una richiesta viene sempre inviata al server di trading tramite l'invio di un ordine dal client terminal. La struttura di una richiesta deve essere compilata correttamente, indipendentemente da come fai trading, manualmente o utilizzando un programma MQL5.

Per eseguire manualmente un'operazione di trading, devi aprire la finestra di dialogo per compilare una richiesta di trading premendo il tasto F9. Quando si fa trading automaticamente tramite MQL5, le richieste vengono inviate utilizzando la funzione OrderSend(). Poiché molte richieste errate possono causare un sovraccarico indesiderato del server di trading, ogni richiesta deve essere verificata prima di essere inviata utilizzando la funzione OrderCheck(). Il risultato del controllo di una richiesta viene inserito in una variabile descritta dalla struttura MqlTradeCheckresult.

Importante: Ogni richiesta viene verificata per la correttezza nel client terminal prima di essere inviata al server di trading. Le richieste deliberatamente errate (per acquistare un milione di lotti o acquistare ad un prezzo negativo) non vengono passate al di fuori del client terminal. Ciò avviene per proteggere i server di trading da una massa di richieste errate causate da un errore in un programma MQL5.

Una volta che una richiesta arriva al trade server, passa il controllo primario:

  • se hai abbastanza risorse per eseguire l'operazione di trading.
  • se il prezzo specificato è corretto: prezzi di apertura, Stop Loss, Take Profit, ecc.
  • se il prezzo specificato è presente nel flusso del prezzo per l'esecuzione istantanea.
  • se i livelli di Stop Loss e Take Profit sono assenti nella modalità Market Execution.
  • se il volume è corretto: volume minimo e massimo, step, volume massimo della posizione (SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_MAX, SYMBOL_VOLUME_STEP e SYMBOL_VOLUME_LIMIT).
  • stato del simbolo: quotazione o sessione trade, possibilità di trading dal simbolo, una specifica modalità di trading (es. solo chiusura di posizioni), ecc.
  • stato dell’account di trading: limitazioni diverse per specifiche tipologie di account.
  • altri controlli, a seconda dell'operazione di trading richiesta.

Una richiesta errata che non supera il controllo primario sul server viene rifiutata. Il client terminal viene sempre informato dell'esito del controllo di una richiesta inviando una risposta. La risposta del server di trading può essere presa da una variabile di tipo MqlTradeResult che viene passata come secondo parametro nella funzione OrderSend() quando si invia una richiesta.

Invio di Richieste di Trading al Trade Server dal Client Terminal

Se una richiesta supera il controllo primario di correttezza, verrà inserita nella richiesta in attesa di essere elaborata. Come risultato dell'elaborazione di una richiesta, viene creato un ordine (comando per eseguire un'operazione di trading) nella base del server di trading. Tuttavia, esistono due tipi di richieste che non comportano la creazione di un ordine:

  1. una richiesta di modifica di una posizione (cambia il suo Stop Loss e/o Take Profit).
  2. una richiesta di modifica di un ordine in sospeso (i suoi livelli di prezzo e tempo di scadenza.

Il client terminal riceve un messaggio che la richiesta è stata accettata e inserita nel sottosistema di trading della piattaforma MetaTrader 5. Il server inserisce la richiesta accettata nella coda delle richieste per un'ulteriore elaborazione che può comportare:

  • piazzamento di un ordine in sospeso.
  • esecuzione di un ordine istantaneo dal prezzo di mercato.
  • modifica di un ordine o di una posizione.

La durata di una richiesta nella coda del server ha un limite di tre minuti. Una volta superato il periodo, la richiesta viene rimossa dalla coda delle richieste.


Invio di Eventi di Trading dal Trading Server al Client Terminal

Il modello di evento e le funzioni di gestione degli eventi sono implementati nel linguaggio MQL5. Significa che in risposta a qualsiasi evento predefinito l'ambiente di esecuzione MQL5 chiama la funzione appropriata - il gestore degli eventi. Per l'elaborazione degli eventi di trading c'è la funzione predefinita OnTrade(); al suo interno deve essere inserito il codice per lavorare con ordini, posizioni e deal. Questa funzione è chiamata solo per gli Expert Advisor, non verrà utilizzata negli indicatori e negli script anche se si aggiunge lì una funzione con lo stesso nome e tipo.

Gli eventi di trading sono generati dal server in caso di:

  • cambio di ordini attivi,
  • cambio di posizione,
  • cambio di deal,
  • cambiamento della storia di trading.

Si noti che un'operazione può causare il verificarsi di diversi eventi. Ad esempio, l'attivazione di un ordine in sospeso porta al verificarsi di due eventi:

  1. la comparsa di un deal che è scritto nella storia di trading.
  2. lo spostamento dell'ordine in sospeso dalla lista di quelli attivi alla lista degli ordini storici (l'ordine viene spostato nello storico).

Un altro esempio di più eventi è l'esecuzione di più operazioni sulla base di un unico ordine, nel caso in cui il volume richiesto non possa essere ottenuto da un'unica offerta opposta. Il server di trading crea e invia i messaggi su ciascun evento al client terminal. Ecco perché la funzione OnTrade() può essere chiamata più volte per un evento apparentemente singolo. Questo è un semplice esempio della procedura di elaborazione dell'ordine nel sottosistema di trading della piattaforma MetaTrader 5.

Ecco un esempio: mentre un ordine in sospeso per l'acquisto di 10 lotti di EURUSD attende di essere eseguito, compaiono offerte opposte per la vendita di 1, 4 e 5 lotti. Queste tre richieste insieme danno il volume richiesto di 10 lotti, quindi vengono eseguite una per una, se la politica di riempimento consente di eseguire operazioni di trading in parti.

A seguito dell'esecuzione di 4 ordini, il server eseguirà 3 operazioni di 1, 4 e 5 lotti sulla base delle richieste opposte esistenti. Quanti eventi di trading verranno generati in questo caso? La prima richiesta contraria di vendita di un lotto comporterà l'esecuzione dell'operazione di 1 lotto. Questo è il primo evento di Trading (1 lotto deal). Ma cambia anche l'ordine in sospeso per l'acquisto di 10 lotti; ora, è l'ordine per l'acquisto di 9 lotti di EURUSD. La variazione di volume dell'ordine in sospeso è il secondo evento di Trading (modifica del volume di un ordine in sospeso).

Generazione di Eventi di Trading

Per la seconda operazione di 4 lotti verranno generati gli altri due eventi Trade, su ciascuno di essi verrà inviato un messaggio al client terminal che ha avviato l'ordine iniziale in sospeso per l'acquisto di 10 lotti di EURUSD.

L'ultima offerta di 5 lotti porterà al verificarsi di tre eventi trade:

  1. il deal di 5 lotti,
  2. il cambio di volume,
  3. lo spostamento dell'ordine nella storia di trading.

Come risultato dell'esecuzione dell'operazione, il client terminal riceve 7 eventi Trade uno dopo l'altro (si presume che la connessione tra il client terminal e il server di trading sia stabile e nessun messaggio venga perso). Questi messaggi devono essere elaborati in un Expert Advisor utilizzando la funzione OnTrade().

Importante: Ogni messaggio su un evento di trading Trade può apparire come risultato di una o più richieste. Ogni richiesta può portare al verificarsi di più eventi trade. Non puoi fare affidamento sulla dichiarazione "Una richiesta - un evento Trade", poiché l'elaborazione degli eventi può essere eseguita in più fasi e ogni operazione può modificare lo stato degli ordini, delle posizioni e della cronologia di trading.


Elaborazione degli Ordini da parte del Server di Trading.

Tutti gli ordini che attendono la loro esecuzione verranno spostati nella cronologia alla fine: la condizione per la loro esecuzione sarà soddisfatta o verranno annullati. Esistono diverse varianti di annullamento dell'ordine:

  • esecuzione di un del sulla base dell'ordine.
  • rifiuto dell'ordine da parte di un dealer.
  • annullamento dell'ordine su richiesta del trader (richiesta manuale o automatica da programma MQL5).
  • scadenza dell'ordine, che è determinata dal trader al momento dell'invio della richiesta o dalle condizioni di trading del dato sistema di trading.
  • mancanza di risorse sull’account di trading per l'esecuzione dell'operazione nel momento in cui vengono soddisfatte le condizioni della sua esecuzione.
  • l'ordine viene annullato a causa della politica di riempimento (un ordine parzialmente evaso viene annullato).

Indipendentemente dal motivo per cui un ordine attivo viene spostato nella cronologia, il messaggio relativo alla modifica viene inviato al client terminal. I messaggi sull'evento trade non sono anche su tutti i client terminal, ma quelli associati al relativo account.


Importante: Il fatto di accettare una richiesta da parte del trade server non sempre porta all'esecuzione dell'operazione richiesta. Ciò significa che la richiesta ha superato la convalida dopo, quando è arrivata al server di trading.

Ecco perché la documentazione della funzione OrderSend() dice:

Valore restituito

In caso di successo del controllo di base di una richiesta, la funzione OrderSend() restituisce true - questo non è un segno di corretta esecuzione di un'operazione di trading. Per una descrizione più dettagliata del risultato dell'esecuzione della funzione, analizzare i campi della struttura MqlTradeResult.


Aggiornamento del Trade e della Cronologia nel Client Terminal

I messaggi sugli eventi trade e sui cambiamenti nella cronologia dei trade arrivano attraverso canali separati. Quando si invia una richiesta di acquisto utilizzando la funzione OrderSend(), è possibile ottenere il ticket dell'ordine, che viene creato a seguito della corretta convalida della richiesta. Allo stesso tempo, l'ordine stesso potrebbe non essere visualizzato nel client terminal e un tentativo di selezionarlo utilizzando OrderSelect() potrebbe non riuscire.

Tutti i messaggi dal server di trading arrivano al client terminal in modo indipendente

Nella figura sopra, puoi vedere come il server di trading comunica il ticket dell'ordine al programma MQL5, ma il messaggio sull'evento di trading Trade (comparsa di un nuovo ordine) non è ancora arrivato. Non è arrivato nemmeno il messaggio relativo al cambio della lista degli ordini attivi.

Ci può essere una situazione, quando il messaggio Trade sulla comparsa di un nuovo ordine arriva al programma quando un deal sulla sua base è già stato eseguito; quindi, l'ordine è già assente nell'elenco degli ordini attivi, è nella cronologia. Questa è una situazione reale, poiché la velocità di elaborazione delle richieste è molto più elevata rispetto all'attuale velocità di consegna di un messaggio attraverso una rete.


Gestione di Eventi Trade in MQL5

Tutte le operazioni sul server di trading e l'invio di messaggi sugli eventi trade vengono eseguite in modo asimmetrico. C'è solo un metodo sicuro per scoprire cosa è stato modificato esattamente sull’account di trading. Questo metodo consiste nel memorizzare lo stato del trading e la cronologia e,quindi, nel confrontarlo con il nuovo stato.

L'algoritmo di tracciamento degli eventi trade negli Expert Advisor è il seguente:

  1. dichiarare i contatori dell'ordine, delle posizioni e del deal nello scopo complessivo.
  2. determinare la profondità della cronologia di trading che verrà richiesta alla cache del programma MQL5. Più cronologia carichiamo nella cache, più risorse del terminale e del computer vengono consumate.
  3. inizializzare i contatori di ordini, posizioni e deal nella funzione OnInit.
  4. determinare le funzioni del gestore in cui richiederà la cronologia di trading alla cache.
  5. Lì, dopo aver caricato la cronologia di trading, scopriremo anche cosa è successo all’account di trading confrontando lo stato memorizzato e quello corrente.

Questo è l'algoritmo più semplice, permette di scoprire se il numero di posizioni aperte (ordine, deal) è stato modificato e qual è la direzione del cambiamento. Se ci sono cambiamenti, possiamo ottenere ulteriori informazioni più dettagliate. Se il numero di ordini non viene modificato, ma vengono modificati gli ordini stessi, è necessario un approccio diverso; pertanto, questa variante non viene trattata in questo articolo.

Le modifiche del contatore possono essere verificate nelle funzioni OnTrade() e OnTick() di un Expert Advisor.

Scriviamo un esempio di programma passo dopo passo.

1. Il contatore di ordini, del e posizioni in ambito globale.

int          orders;            // number of active orders
int          positions;         // number of open positions
int          deals;             // number of deals in the trade history cache
int          history_orders;    // number of orders in the trade history cache
bool         started=false;     // flag of initialization of the counters

2. La profondità della cronologia di trading da caricare nella cache è impostata nella variabile di input days (carica la cronologia dei trade per il numero di giorni specificato in questa variabile).

input    int days=7;            // depth of the trade history in days

//--- set the limit of the trade history on the global scope
datetime     start;             // start date of the trade history in cache
datetime     end;               // end date of the trade history in cache

3. Inizializzazione dei contatori e limiti della cronologia di trading. Porta l'inizializzazione dei contatori alla funzione InitCounters() per una migliore leggibilità del codice:

int OnInit()
  {
//---
   end=TimeCurrent();
   start=end-days*PeriodSeconds(PERIOD_D1);
   PrintFormat("Limits of the trade history to be loaded: start - %s, end - %s",
               TimeToString(start),TimeToString(end));
   InitCounters();
//---
   return(0);
  }

La funzione InitCounters() prova a caricare la cronologia dei trade nella cache e, in caso di successo, inizializza tutti i contatori. Inoltre, se la cronologia viene caricata correttamente, il valore della variabile globale 'started' è impostato su 'true', il che indica che i contatori sono stati inizializzati con successo.

//+------------------------------------------------------------------+
//|  initialization of the counters of positions, orders and deals   |
//+------------------------------------------------------------------+
void InitCounters()
  {
   ResetLastError();
//--- load history
   bool selected=HistorySelect(start,end);
   if(!selected)
     {
      PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d",
                  __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError());
      return;
     }
//--- get current values
   orders=OrdersTotal();
   positions=PositionsTotal();
   deals=HistoryDealsTotal();
   history_orders=HistoryOrdersTotal();
   started=true;
   Print("The counters of orders, positions and deals are successfully initialized");
  }

4. Il controllo delle modifiche allo stato dell’account di trading viene eseguito nei gestori OnTick() e OnTrade(). La variabile 'started' viene controllata per prima - se il suo valore è 'true' viene chiamata la funzione SimpleTradeProcessor(), altrimenti viene chiamata la funzione di inizializzazione dei contatori InitCounters().

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(started) SimpleTradeProcessor();
   else InitCounters();
  }
//+------------------------------------------------------------------+
//| called when the Trade event occurs                               |
//+------------------------------------------------------------------+
void OnTrade()
  {
   if(started) SimpleTradeProcessor();
   else InitCounters();
  }

5. La funzione SimpleTradeProcessor() verifica se il numero di ordini, operazioni e posizioni è stato modificato. Dopo aver eseguito tutti i controlli, chiamiamo la funzione CheckStartDateInTradeHistory() che sposta il valore 'start' più vicino al momento corrente se necessario.

//+------------------------------------------------------------------+
//| simple example of processing changes in trade and history        |
//+------------------------------------------------------------------+
void SimpleTradeProcessor()
  {
   end=TimeCurrent();
   ResetLastError();
//--- load history
   bool selected=HistorySelect(start,end);
   if(!selected)
     {
      PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d",
                  __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError());
      return;
     }

//--- get current values
   int curr_orders=OrdersTotal();
   int curr_positions=PositionsTotal();
   int curr_deals=HistoryDealsTotal();
   int curr_history_orders=HistoryOrdersTotal();

//--- check whether the number of active orders has been changed
   if(curr_orders!=orders)
     {
      //--- number of active orders is changed
      PrintFormat("Number of orders has been changed. Previous number is %d, current number is %d",
                  orders,curr_orders);
     /*
       other actions connected with changes of orders
     */
      //--- update value
      orders=curr_orders;
     }

//--- change in the number of open positions
   if(curr_positions!=positions)
     {
      //--- number of open positions has been changed
      PrintFormat("Number of positions has been changed. Previous number is %d, current number is %d",
                  positions,curr_positions);
      /*
      other actions connected with changes of positions
      */
      //--- update value
      positions=curr_positions;
     }

//--- change in the number of deals in the trade history cache
   if(curr_deals!=deals)
     {
      //--- number of deals in the trade history cache has been changed
      PrintFormat("Number of deals has been changed. Previous number is %d, current number is %d",
                  deals,curr_deals);
      /*
       other actions connected with change of the number of deals
       */
      //--- update value
      deals=curr_deals;
     }

//--- change in the number of history orders in the trade history cache
   if(curr_history_orders!=history_orders)
     {
      //--- the number of history orders in the trade history cache has been changed
      PrintFormat("Number of orders in the history has been changed. Previous number is %d, current number is %d",
                  history_orders,curr_history_orders);
     /*
       other actions connected with change of the number of order in the trade history cache
      */
     //--- update value
     history_orders=curr_history_orders;
     }
//--- check whether it is necessary to change the limits of trade history to be requested in cache
   CheckStartDateInTradeHistory();
  }

La funzione CheckStartDateInTradeHistory() calcola la data di inizio della richiesta della cronologia per il momento corrente (curr_start) e la confronta con la variabile 'start'. Se la differenza tra loro è maggiore di 1 giorno, allora viene corretto 'start' e vengono aggiornati i contatori degli ordini e dei deal della cronologia.

//+------------------------------------------------------------------+
//|  Changing start date for the request of trade history            |
//+------------------------------------------------------------------+
void CheckStartDateInTradeHistory()
  {
//--- initial interval, as if we started working right now
   datetime curr_start=TimeCurrent()-days*PeriodSeconds(PERIOD_D1);
//--- make sure that the start limit of the trade history period has not gone 
//--- more than 1 day over intended date
   if(curr_start-start>PeriodSeconds(PERIOD_D1))
     {
      //--- we need to correct the date of start of history loaded in the cache
      start=curr_start;
      PrintFormat("New start limit of the trade history to be loaded: start => %s",
                  TimeToString(start));

      //--- now load the trade history for the corrected interval again
      HistorySelect(start,end);

      //--- correct the counters of deals and orders in the history for further comparison
      history_orders=HistoryOrdersTotal();
      deals=HistoryDealsTotal();
     }
  }

Il codice completo dell'Expert Advisor DemoTradeEventProcessing.mq5 è allegato all'articolo.


Conclusione

Tutte le operazioni nella piattaforma di trading online MetaTrader 5 vengono eseguite in modo asincrono e i messaggi su tutte le modifiche su un account di trading vengono inviati indipendentemente l'uno dall'altro. Pertanto, non ha senso cercare di tenere traccia di singoli eventi in base alla regola "Una richiesta - un evento trade". Se hai bisogno di determinare con precisione cosa viene cambiato esattamente quando arriva anche un Trade, allora dovresti analizzare tutte le tue operazioni, posizioni e ordini ad ogni chiamata del gestore OnTrade confrontando il loro stato attuale con quello precedente.

Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/232

I Fondamenti dei Testing in MetaTrader 5 I Fondamenti dei Testing in MetaTrader 5
Quali sono le differenze tra le tre modalità di testing in MetaTrader 5 e cosa dovremmo cercare in particolare? Come si svolge il testing di un EA, facendo trading simultaneamente su più strumenti? Quando e in che modo vengono calcolati i valori degli indicatori durante il testing e in che modo vengono gestiti gli eventi? Come sincronizzare le barre di diversi strumenti durante il testing in modalità "solo prezzi di apertura"? Questo articolo si propone di fornire risposte a queste e a molte altre domande.
Ordini, Posizioni e Deal in MetaTrader 5 Ordini, Posizioni e Deal in MetaTrader 5
La creazione di un solido robot di trading non può essere eseguita senza una comprensione dei meccanismi del sistema di trading MetaTrader 5. Il client terminal riceve le informazioni su posizioni, ordini e deal dal server di trading. Per gestire correttamente questi dati utilizzando l'MQL5, è necessario avere una buona comprensione dell'interazione tra il programma MQL5 e il client terminal.
MQL5 Wizard: Nuova Versione MQL5 Wizard: Nuova Versione
L'articolo contiene le descrizioni delle nuove funzionalità disponibili in MQL5 Wizard aggiornato. L'architettura modificata dei segnali consente di creare robot di trading basati sulla combinazione di vari modelli di mercato. L'esempio contenuto nell'articolo spiega la procedura di creazione interattiva di un Expert Advisor.
Guida al Test all'Ottimizzazione degli Expert Advisor in MQL5 Guida al Test all'Ottimizzazione degli Expert Advisor in MQL5
Questo articolo spiega il processo step by step per identificare e risolvere gli errori di codice, nonché i passaggi per testare e ottimizzare i parametri di input dell’Expert Advisor. Imparerai come utilizzare lo Strategy Tester del client terminal MetaTrader 5 per trovare il miglior simbolo e set di parametri di input per il tuo Expert Advisor.