English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Limitazioni e Verifiche sugli Expert Advisors

Limitazioni e Verifiche sugli Expert Advisors

MetaTrader 5Esempi | 8 dicembre 2021, 17:07
253 0
MetaQuotes
MetaQuotes

Introduzione

Quando crei un algoritmo per il trading automatizzato dovresti essere in grado non solo di elaborare i prezzi per creare segnali di trading, ma di essere in grado di ottenere molte informazioni ausiliarie sulle limitazioni imposte al funzionamento degli Expert Advisor. Questo articolo ti dirà come:

  • ottenere informazioni sulle sessioni di trading;
  • controllare se hai abbastanza risorse per aprire una posizione;
  • imporre una limitazione al volume totale di trading con un simbolo;
  • Imporre una limitazione al numero totale di ordini;
  • calcolare la perdita potenziale tra il prezzo di entrata e lo Stop Loss;
  • Controlla se c'è una nuova barra.

Sessioni di Trading e Quotazione

Per ricevere le informazioni sulle sessioni di trading, è necessario utilizzare la funzione SymbolInfoSessionTrade(), per le sessioni di quotazione utilizzare la funzione SymbolInfoSessionQuote() corrispondente. Entrambe le funzioni operano nello stesso modo: se esiste una sessione con l'indice specificato per il giorno della settimana specificato (l'indicizzazione delle sessioni inizia da zero), la funzione restituisce true. L'ora di inizio e fine di una sessione viene scritta al quarto e quinto parametro passati dal collegamento.

//--- check if there is a quotation session with the number session_index
bool session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);
Per scoprire tutta la sessione del giorno specificato, chiamare questa funzione in un ciclo fino a quando non restituisce false.
//+------------------------------------------------------------------+
//|  Display information about quotation sessions                    |
//+------------------------------------------------------------------+
void PrintInfoForQuoteSessions(string symbol,ENUM_DAY_OF_WEEK day)
  {
//--- start and end of session
   datetime start,finish;
   uint session_index=0;
   bool session_exist=true;

//--- go over all sessions of this day
   while(session_exist)
     {
      //--- check if there is a quotation session with the number session_index
      session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);

      //--- if there is such session
      if(session_exist)
        {
         //--- display the day of week, the session number and the time of start and end
         Print(DayToString(day),": session index=",session_index,"  start=",
               TimeToString(start,TIME_MINUTES),"    finish=",TimeToString(finish-1,TIME_MINUTES|TIME_SECONDS));
        }
      //--- increase the counter of sessions
      session_index++;
     }
  }

Il giorno della settimana viene visualizzato nel formato stringa utilizzando la funzione personalizzata DayToString() che riceve il valore dell'enumerazione ENUM_DAY_OF_WEEK come parametro.

//+------------------------------------------------------------------+
//| Receive the string representation of a day of week               |
//+------------------------------------------------------------------+
string DayToString(ENUM_DAY_OF_WEEK day)
  {
   switch(day)
     {
      case SUNDAY:    return "Sunday";
      case MONDAY:    return "Monday";
      case TUESDAY:   return "Tuesday";
      case WEDNESDAY: return "Wednesday";
      case THURSDAY:  return "Thursday";
      case FRIDAY:    return "Friday";
      case SATURDAY:  return "Saturday";
      default:        return "Unknown day of week";
     }
   return "";
  }

Il codice finale dello script SymbolInfoSession.mq5 è allegato alla fine dell'articolo. Qui, mostriamo solo la sua parte principale.

void OnStart()
  {
//--- the array where the days of week are stored
   ENUM_DAY_OF_WEEK days[]={SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY};
   int size=ArraySize(days);

//---
   Print("Quotation sessions");
//--- go over all the days of week
   for(int d=0;d<size;d++)
     {
      PrintInfoForQuoteSessions(Symbol(),days[d]);
     }

//---
   Print("Trading sessions");
//--- go over all the days of week
   for(int d=0;d<size;d++)
     {
      PrintInfoForTradeSessions(Symbol(),days[d]);
     }
  }


Controllo del Margine

Per scoprire la quantità di margine necessaria per aprire o aumentare una posizione, è possibile utilizzare la funzione OrderCalcMargin(); il primo parametro che gli viene passato è un valore dell'enumerazione ENUM_ORDER_TYPE. Per un'operazione di acquisto dovresti chiamarla con il parametro ORDER_TYPE_BUY; per vendere, usa il parametroORDER_TYPE_SELL . La funzione restituisce l'importo del margine in base al numero di lotti e al prezzo di apertura.

void OnStart()
  {
//--- the variable to receive the value of margin
   double margin;
//--- to receive information about the last tick
   MqlTick last_tick;
//--- try to receive the value from the last tick
   if(SymbolInfoTick(Symbol(),last_tick))
     {
      //--- reset the last error code
      ResetLastError();
      //--- calculate margin value
      bool check=OrderCalcMargin(type,Symbol(),lots,last_tick.ask,margin);
      if(check)
        {
         PrintFormat("For the operation %s  %s %.2f lot at %G required margin is %.2f %s",OrderTypeToString(type),
                     Symbol(),lots,last_tick.ask,margin,AccountInfoString(ACCOUNT_CURRENCY));
        }
     }
   else
     {
      Print("Unsuccessful execution of the SymbolInfoTick() function, error ",GetLastError());
     }
  }

Va notato che la funzione OrderCalcMargin() consente di calcolare il valore del margine non solo per gli ordini di mercato, ma anche per gli ordini in sospeso. È possibile controllare i valori restituiti per tutti i tipi di ordini utilizzando lo script Check_Money.mq5.

La funzione OrderCalcMargin() è concepita per il calcolo della dimensione del margine degli ordini in sospeso, poiché in alcuni sistemi di trading potrebbe essere richiesto un rimborso monetario anche per gli ordini in sospeso. Di solito, la dimensione del margine degli ordini in sospeso viene calcolata attraverso un coefficiente per la dimensione del margine per le posizioni lunghe e corte.

Identificatore

Descrizione

Tipo di Property

SYMBOL_MARGIN_LONG

Tasso di addebito del margine su posizioni lunghe

doppio

SYMBOL_MARGIN_SHORT

Tasso di addebito del margine su posizioni corte

doppio

SYMBOL_MARGIN_LIMIT

Tasso di addebito del margine su ordini Limit

doppio

SYMBOL_MARGIN_STOP

Tasso di addebito del margine su ordini Stop

doppio

SYMBOL_MARGIN_STOPLIMIT

Tasso di addebito del margine su ordini Stop Limit

doppio


È possibile ottenere i valori di tali coefficienti utilizzando il codice semplice:

//--- Calculate the rates of margin charging for different types of orders
   PrintFormat("Rate of margin charging on long positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LONG));
   PrintFormat("Rate of margin charging on short positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_SHORT));
   PrintFormat("Rate of margin charging on Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LIMIT));
   PrintFormat("Rate of margin charging on Stop orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOP));
   PrintFormat("Rate of margin charging on Stop Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOPLIMIT));

Per i simboli Forex, i tassi di addebito del margine per gli ordini in sospeso sono solitamente uguali a 0, cioè non ci sono requisiti di margine per loro.

I risultati dell'esecuzione dello script Check_Money.mq5.

I risultati dell'esecuzione dello script Check_Money.mq5.

A seconda del modo di addebitare il margine, il sistema di gestione del denaro può cambiare, così come il sistema di trading stesso può subire alcune limitazioni se è richiesto un margine per gli ordini in sospeso. Ecco perché questi parametri possono anche essere limiti naturali del funzionamento di un Expert Advisor.

Contabilizzazione di Possibili Profitti e Perdite

Quando si posiziona uno stop level protettivo, è necessario essere pronti per il suo innesco. Il rischio di perdite potenziali dovrebbe essere preso in considerazione in termini di denaro; e OrderCalcProfit() è inteso a questo scopo. È molto simile alla già considerata funzione OrderCalcMargin(), ma richiede prezzi sia di apertura che di chiusura per i calcoli.

Specificare uno dei due valori dell'enumerazione ENUM_ORDER_TYPE come primo parametro, ORDER_TYPE_BUY o ORDER_TYPE_SELL; altri tipi di ordini genereranno un errore. Nell'ultimo parametro, è necessario passare una variabile utilizzando il riferimento, a cui la funzione OrderCalcProfit() scriverà il valore del profitto/perdita in caso di esecuzione riuscita.

L'esempio di utilizzo della funzione CalculateProfitOneLot() che calcola il profitto o la perdita quando si chiude una posizione lunga con livelli specificati in entrata e in uscita:

//+------------------------------------------------------------------+
//| Calculate potential profit/loss for buying 1 lot                 |
//+------------------------------------------------------------------+
double CalculateProfitOneLot(double entry_price,double exit_price)
  {
//--- receive the value of profit to this variable
   double profit=0;
   if(!OrderCalcProfit(ORDER_TYPE_BUY,Symbol(),1.0,entry_price,exit_price,profit))
     {
      Print(__FUNCTION__,"  Failed to calculate OrderCalcProfit(). Error ",GetLastError());
     }
//---
   return(profit);
  }

Il risultato del calcolo di questa funzione viene mostrato nella figura.

Esempio di calcolo e visualizzazione della perdita potenziale sul grafico utilizzando la funzione OrderCalcProfit().

L'intero codice è disponibile nell'allegato Expert Advisor CalculateProfit_EA.mq5.

Verifica della Presenza di una Nuova Barra

Lo sviluppo di molti sistemi di trading presuppone che i segnali di trading siano calcolati solo quando appare una nuova barra; tutte le azioni di trading vengono eseguite una sola volta. La modalità "Solo prezzi aperti" del tester di strategia nel client terminal MetaTrader 5 è utile per controllare questi sistemi di trading automatizzati.

Nella modalità "Solo prezzi aperti", tutti i calcoli degli indicatori e la chiamata della funzione OnTick() nell’Expert Advisor vengono eseguiti solo una volta per barra durante il test. È la modalità di trading più veloce e, di regola, il modo più tollerante alle oscillazioni di prezzo insignificanti di creare sistemi di trading. Allo stesso tempo, ovviamente, gli indicatori utilizzati in un Expert Advisor dovrebbero essere scritti correttamente e non dovrebbero distorcere i loro valori quando arriva una nuova barra.

Lo strategy tester in modalità "Solo prezzi aperti" consento di sollevarti dalla preoccupazione di lanciare l'Expert Advisor solo una volta per barra: è molto conveniente. Tuttavia, mentre lavora in modalità tempo reale su una demo o su un account reale, un trader dovrebbe controllare l'attività del proprio Expert Advisor per fare eseguire una sola operazione di trading per ciascun segnale ricevuto. Il modo più semplice per questo scopo, è il monitoraggio dell'apertura della barra non formata corrente.

Per ottenere l'orario di apertura dell'ultima barra, è necessario utilizzare la funzione SeriesInfoInteger() con il nome specificato del simbolo, l'intervallo e la proprietà SERIES_LASTBAR_DATE. Confrontando costantemente il tempo di apertura della barra corrente con quello della barra memorizzata in una variabile, è possibile rilevare facilmente il momento in cui appare una nuova barra. Permette di creare la funzione personalizzata isNewBar() che può apparire come segue:

//+------------------------------------------------------------------+
//| Return true if a new bar appears for the symbol/period pair      |
//+------------------------------------------------------------------+
bool isNewBar()
  {
//--- remember the time of opening of the last bar in the static variable
   static datetime last_time=0;
//--- current time
   datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);

//--- if it is the first call of the function
   if(last_time==0)
     {
      //--- set time and exit
      last_time=lastbar_time;
      return(false);
     }

//--- if the time is different
   if(last_time!=lastbar_time)
     {
      //--- memorize time and return true
      last_time=lastbar_time;
      return(true);
     }
//--- if we pass to this line then the bar is not new, return false
   return(false);
  }

Un esempio di utilizzo della funzione è fornito nell'allegato Expert Advisor CheckLastBar.mq5 .

I messaggi di CheckLastBar Expert Advisor sulla visualizzazione di nuove barre sull'intervallo M1.

I messaggi di CheckLastBar Expert Advisor sulla comparsa di nuove barre sull'intervallo M1.

Limitazione del Numero di Ordini in Sospeso

Se è necessario limitare il numero di ordini in sospeso attivi che possono essere inseriti contemporaneamente in un account, è possibile scrivere la propria funzione personalizzata. Nominiamolo IsNewOrderAllowed(); controllerà se è consentito effettuare un altro ordine in sospeso. Scriviamolo per rispettare le regole dell'Automated Trading Championship.

//+------------------------------------------------------------------+
//| Checks if it is allowed to place another order                   |
//+------------------------------------------------------------------+
bool IsNewOrderAllowed()
  {
//--- get the allowed number of pending orders on an account
   int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);

//--- if there is no limitations, return true; you can send an order
   if(max_allowed_orders==0) return(true);

//--- if we pass to this line, then there are limitations; detect how many orders are already active
   int orders=OrdersTotal();

//--- return the result of comparing
   return(orders<max_allowed_orders);
  }

La funzione è semplice: ottenere il numero consentito di ordini alla variabile max_allowed_orders; se il suo valore non è uguale a zero, confrontare con il numero corrente di ordini . Tuttavia, questa funzione non considera un'altra possibile limitazione: la limitazione del volume totale consentito di posizioni aperte e ordini in sospeso da parte di un simbolo specifico.

Limitazione del Numero di Lotti con un Simbolo Specifico

Per ottenere la dimensione della posizione aperta da un simbolo specifico, prima di tutto, è necessario selezionare una posizione utilizzando la funzione PositionSelect(). Solo dopo, puoi richiedere il volume della posizione aperta utilizzando PositionGetDouble(); restituisce varie proprietà della posizione selezionata che hanno il doppio tipo. Scriviamo la funzione PostionVolume() per ottenere il volume di posizione da un dato simbolo.

//+------------------------------------------------------------------+
//| Returns the size of position by a specific symbol                |
//+------------------------------------------------------------------+
double PositionVolume(string symbol)
  {
//--- try to select a positions by a symbol
   bool selected=PositionSelect(symbol);
//--- the position exists
   if(selected)
      //--- return the position volume
      return(PositionGetDouble(POSITION_VOLUME));
   else
     {
      //--- report about the unsuccessful attempt to select the position
      Print(__FUNCTION__," Failed to execute PositionSelect() for the symbol ",
            symbol," Error ",GetLastError());
      return(-1);
     }
  }

Prima di effettuare una richiesta di trading per effettuare un ordine in sospeso con un simbolo, è necessario verificare la limitazione del volume totale della posizione aperta e degli ordini in sospeso da parte di quel simbolo - SYMBOL_VOLUME_LIMIT. Se non vi è alcuna limitazione, il volume di un ordine in sospeso non può superare il volume massimo consentito che può essere ricevuto utilizzando il volume SymbolInfoDouble().

double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
if(max_volume==0) volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);

Tuttavia, questo approccio non considera il volume degli ordini in sospeso correnti per il simbolo specificato. Scriviamo una funzione che calcola questo valore:

//+------------------------------------------------------------------+
//| Returns the size of position by a specified symbol               |
//+------------------------------------------------------------------+
double PositionVolume(string symbol)
  {
//--- try to select a position by a symbol
   bool selected=PositionSelect(symbol);
//--- the position exist
   if(selected)
      //--- return the position volume
      return(PositionGetDouble(POSITION_VOLUME));
   else
     {
      //--- return zero if there is no position
      return(0);
     }
  }

Considerando il volume della posizione aperta e del volume degli ordini in sospeso, il controllo finale apparirà come segue:

//+------------------------------------------------------------------+
//|  Returns maximum allowed volume for an order by a symbol         |
//+------------------------------------------------------------------+
double NewOrderAllowedVolume(string symbol)
  {
   double allowed_volume=0;
//--- get the limitation on the maximum volume of an order
   double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
//--- get the limitation of volume by a symbol
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);

//--- get the volume of open position by a symbol
   double opened_volume=PositionVolume(symbol);
   if(opened_volume>=0)
     {
      //--- if we already used available volume
      if(max_volume-opened_volume<=0)
         return(0);

      //--- volume of the open position doen't exceed max_volume
      double orders_volume_on_symbol=PendingsVolume(symbol);
      allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
      if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
     }
   return(allowed_volume);
  }

L'intero codice dell'Expert Advisor Check_Order_And_Volume_Limits.mq5 che contiene le funzioni, menzionate in questa sezione, è allegato all'articolo.

Esempio di controllo utilizzando il Check_Order_And_Volume_Limits Expert Advisor sull’account di un partecipante dell'Automated Trading Championship 2010.

Esempio di controllo utilizzando il Check_Order_And_Volume_Limits Expert Advisor sull’account di un partecipante dell'Automated Trading Championship 2010.

Verifica della Correttezza del Volume

Una parte significativa di qualsiasi robot di trading è la capacità di scegliere un volume corretto per eseguire un'operazione di trading. Qui, non parleremo dei sistemi di gestione del denaro e della gestione del rischio, ma del volume da correggere in base alle relative proprietà di un simbolo.

Identificatore

Descrizione

Tipo di Property

SYMBOL_VOLUME_MIN

Volume minimo per una posizione

doppio

SYMBOL_VOLUME_MAX

Volume massimo per una posizione

doppio

SYMBOL_VOLUME_STEP

Cambio di step minimo per l'esecuzione della posizione

doppio


Per eseguire tale verifica, possiamo scrivere la funzione personalizzata CheckVolumeValue():

//+------------------------------------------------------------------+
//|  Check the correctness of volume of an order                     |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &description)
  {
//--- Minimum allowed volume for trade operations
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      description=StringFormat("Volume is less than the minimum allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- Maximum allowed volume for trade opertations
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      description=StringFormat("Volume is greater than the maximum allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get the minimal volume change step
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      description=StringFormat("Volume is not a multiple of minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                               volume_step,ratio*volume_step);
      return(false);
     }
   description="Correct value of volume ";
   return(true);
  }

È possibile verificare l’operatività di questa funzione utilizzando lo script CheckVolumeValue.mq5 allegato all'articolo.

Messaggi di CheckVolumeValue.mq5 che verificano la correttezza del volume.

Messaggi di CheckVolumeValue.mq5 che verificano la correttezza del volume.

Conclusione

L'articolo descrive le verifiche di base per eventuali limitazioni al funzionamento di un Expert Advisor che possono essere affrontate quando si crea il proprio sistema di trading automatizzato. Questi esempi non includono tutte le possibili condizioni che dovrebbero essere controllate durante il funzionamento di un Expert Advisor su un account di trading. Tuttavia, spero che questi esempi aiuteranno i neofiti a capire come implementare le verifiche più popolari nel linguaggio MQL5.

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

L'Ordine di Creazione e Distruzione dell'oggetto in MQL5 L'Ordine di Creazione e Distruzione dell'oggetto in MQL5
Ogni oggetto, sia esso un oggetto personalizzato, un array dinamico o un array di oggetti, viene creato ed eliminato nel programma MQL5 nel suo modo particolare. Spesso, alcuni oggetti fanno parte di altri oggetti e l'ordine di eliminazione dell'oggetto durante la reinizializzazione diventa particolarmente importante. Questo articolo fornisce alcuni esempi che illustrano i meccanismi di utilizzo degli oggetti.
Applicazione di un Indicatore ad un Altro Applicazione di un Indicatore ad un Altro
Quando si scrive un indicatore che utilizza la forma abbreviata della chiamata di funzione OnCalculate(), potresti non considerare il fatto che un indicatore può essere calcolato non solo dai dati di prezzo, ma anche dai dati di un altro indicatore (indipendentemente dal fatto che sia integrato o uno personalizzato). Vuoi migliorare un indicatore per la sua corretta applicazione ai dati dell'altro indicatore? In questo articolo, esamineremo tutti i passaggi necessari per tale modifica.
MQL5 per Principianti Guida all'Utilizzo degli Indicatori Tecnici negli Expert Advisor MQL5 per Principianti Guida all'Utilizzo degli Indicatori Tecnici negli Expert Advisor
Per ottenere i valori di un indicatore integrato o personalizzato in un Expert Advisor, innanzitutto il suo handle deve essere creato utilizzando la funzione corrispondente. Gli esempi nell'articolo mostrano come utilizzare questo o quell'indicatore tecnico durante la creazione dei propri programmi. L'articolo descrive gli indicatori creati nel linguaggio MQL5. È destinato a coloro che non hanno molta esperienza nello sviluppo di strategie di trading e offre modi semplici e chiari di lavorare con gli indicatori utilizzando la libreria di funzioni offerta.
MQL5: Crea il tuo Indicatore MQL5: Crea il tuo Indicatore
Cos'è un indicatore? È un insieme di valori calcolati che vogliamo siano visualizzati sullo schermo in un modo pratico. Gli insiemi di valori sono rappresentati nei programmi, come array. Pertanto, la creazione di un indicatore equivale alla scrittura di un algoritmo che gestisce alcuni array (matrici di prezzo) e registra i risultati della gestione su altri array (valori dell'indicatore). Descrivendo la creazione del True Strength Index, l'autore mostra come scrivere indicatori in MQL5.