Testare Strategie di Trading

L'idea di trading automatico è attraente per il fatto che il robot di trading è in grado di lavorare ininterrottamente per 24 ore al giorno, sette giorni alla settimana. Il robot non si stanca, non ha dubbi o paure, è totalmente esente da problemi psicologici. E' sufficiente formalizzare in modo chiaro le regole di trading e la loro attuazione negli algoritmi, ed il robot è pronto a lavorare senza sosta. Ma prima, è necessario assicurarsi che le seguenti due condizioni importanti siano soddisfatte:

  • L'Expert Advisor esegue operazioni di trading secondo le regole del sistema di trading;
  • La strategia di trading, implementata nell'EA, dimostra un profitto sulla cronistoria.

Per avere risposte a queste domande, ci rivolgiamo allo Strategy Tester, incluso nel terminale client MetaTrader 5.

Questa sezione illustra le caratteristiche del programma di testing ed ottimizzazione nello strategy tester:

 

Limiti di memoria e spazio su disco nella MQL5 Cloud Network

La seguente limitazione si applica alle ottimizzazioni eseguite nella MQL5 Cloud Network: l'Expert Advisor non deve scrivere su disco più di 4GB di informazioni o utilizzare più di 4GB di RAM. Se il limite viene superato, l'agente di rete non sarà in grado di completare correttamente il calcolo e non riceverai il risultato. Tuttavia, ti verrà addebitato tutto il tempo speso per i calcoli.

Se hai bisogno di ottenere informazioni da ogni passaggio di ottimizzazione, invia dei frames senza scrivere sul disco. Per evitare di utilizzare operazioni con i file negli Expert Advisors durante i calcoli nella rete cloud MQL5, è possibile utilizzare il seguente controllo:

   int handle=INVALID_HANDLE;
   bool file_operations_allowed=true;
   if(MQLInfoInteger(MQL_OPTIMIZATION) || MQLInfoInteger(MQL_FORWARD))
      file_operations_allowed=false;
 
   if(file_operations_allowed)
     {
      ...
      handle=FileOpen(...);
      ...
     }

 

Limiti di Funzione nel Tester di Strategia #

Esistono limiti operativi per alcune funzioni nello Strategy Tester del terminale client.

Le funzioni Comment(), Print() e PrintFormat() #

Per aumentare le prestazioni, le funzioni Comment(), Print() e PrintFormat() non vengono eseguite durante l'ottimizzazione dei parametri del robot di trading. L'eccezione è l'uso di queste funzioni all'interno dell handler OnInit(). Questo ti permette di trovare facilmente la causa degli errori quando si verificano.

Le funzioni Alert(), MessageBox(), PlaySound(), SendFTP, SendMail(), SendNotification(), WebRequest() #

Le funzioni Alert(), MessageBox(), PlaySound(), SendFTP(), SendMail(), SendNotification() e WebRequest() progettate per l'interazione con il "mondo esterno" non vengono eseguite nel tester di strategia.

 

Modalità Generazione Tick #

Un Expert Advisor è un programma, scritto in MQL5, che viene eseguito ogni volta in risposta ad alcuni eventi esterni. La EA ha una corrispondente funzione (event handler) per ogni evento predefinito.

L'evento NewTick (variazione di prezzo) è l'evento principale per l'EA e, di conseguenza, abbiamo bisogno di generare una sequenza di tick per testare l' EA. Ci sono 3 modalità di generazione tick implementate nello Strategy Tester del terminale client di MetaTrader 5:

  • Ogni tick
  • 1 minuto OHLC (prezzi OHLC con barre minuto)
  • Solo prezzi di apertura

La modalità base e la più dettagliata è la modalità "Ogni tick", le altre due modalità sono le semplificazioni della base, e verranno descritte rispetto alla modalità "Ogni tick". Considerate tutte le tre modalità, al fine di capire le differenze tra di loro.

"Every Tick"

I dati storici di quotazioni di strumenti finanziari vengono trasferiti dal trade server al terminale client MetaTrader 5 sotto forma di barre minutamente impacchettate . Informazioni dettagliate sulla presenza delle richieste e la costruzione del timeframe richiesto può essere ottenuta dal capitolo Organizzare Dati di Accesso nel manuale di riferimento MQL5.

L'elemento minimo dello storico dei prezzo è la barra minuta, da cui è possibile ottenere informazioni sui quattro valori del prezzo:

  • Open - il prezzo al quale è stata aperta la barra minuta;
  • High - il massimo che è stato raggiunto nel corso di questa barra minuta;
  • Low - il minimo che è stato raggiunto nel corso di questa barra minuta;
  • Close - il prezzo di chiusura della barra.

La nuova barra dei minuti non viene aperta nel momento in cui inizia il nuovo minuto (il numero di secondi diventa uguale a 0), ma quando si verifica un tick - un cambio di prezzo di almeno un punto. La figura mostra la barra primo minuto della nuova settimana di trading, che ha orario di apertura 2011.01.10 00:00. Il divario di prezzo tra Venerdì e Lunedì, che vediamo sul chart, è comune, poiché i tassi di cambio fluttuano anche nei fine settimana in risposta alle notizie in arrivo.

Il divario di prezzo tra Venerdì e Lunedi

Per questa barra, si sa solo che la barra minuta è stata aperta il 10 gennaio 2011 alle 00 ore 00 minuti, ma non sappiamo nulla circa i secondi. Avrebbe potuto essere aperta alle 00:00:12 o 00:00:36 (12 o 36 secondi dopo l'inizio di un nuovo giorno) o qualsiasi altro momento entro tale minuto. Ma sappiamo che il prezzo di apertura di EURUSD era a 1.28940 al tempo di apertura della barra del nuovo minuto.

Non sappiamo anche, in un secondo, quando il tick corrispondente al prezzo di chiusura della barra minuto considerata, è stato ricevuto. Sappiamo solo una cosa - l'ultimo prezzo Close della barra minuto. Per questo minuto, il prezzo era 1,28958. Il tempo di comparsa di prezzi High e Low è sconosciuto anche, ma sappiamo che i prezzi Minimi(Low) e Massimi(High) sono stati a livello di 1,28958 e 1,28940, rispettivamente.

Per testare la strategia di trading, abbiamo bisogno di una sequenza di ticks, in cui il lavoro dell' Expert Advisor verrà simulato. Così, per ogni barra minuto, sappiamo che i 4 punti di controllo, dove il prezzo vi è stato sicuramente. Se un bar ha solo 4 ticks, allora ciò è un informazione sufficiente per effettuare un testing, ma di solito il volume di ticke è superiore a 4.

Quindi, vi è la necessità di generare punti di controllo supplementari per i ticks, che si sono verificati tra i prezzi Open, High, Low e Close. Il principio della generazione ticks modalità "Ogni tick" è descritto L'algoritmo di Generazione Ticks all'interno dello Strategia Tester del Terminale MetaTrader 5 del quale una figura è presentata di seguito.

Algoritmo di generazione dei Ticks

Durante il testing in modalità "Ogni Tick", la funzione OnTick() dell' EA verrà chiamata ad ogni punto di controllo. Ogni punto di controllo è un tick da una sequenza generata. L' EA riceverà l'orario ed il prezzo del tick simulato, così come sarebbe quando si lavora online.

Importante: la modalità testing "Ogni tick" è la più precisa, ma al tempo stesso, quella che richiede più tempo. Per un test iniziale della maggioranza delle strategie di trading, è generalmente sufficiente utilizzare una delle altre due modalità di test.

"1 Minuto OHLC"

La modalità "Ogni tick" è la più accurata delle tre modalità, ma al tempo stesso, è la più lenta. La gestione dell'handler OnTick() si verifica ad ogni tick, mentre il volume tick può essere molto grande. Per una strategia, in cui la sequenza ticks dei movimenti dei prezzi in attraverso tutta la barra, non ha importanza, vi è una modalità di simulazione più rapida e più grezza - "1 Minuto OHLC".

Nella modalità "1 minuto OHLC", la sequenza ticks è costruita solo dai prezzi OHLC delle barre minuto; il numero dei punti di controllo generati è significativamente ridotto - quindi, e di conseguenza è ridotto il tempo di testing. Il lancio della funzione onTick() viene eseguito su tutti i punti di controllo, che sono costruiti dai prezzi delle barre OHLC minuto.

Il rifiuto di generare ulteriori ticks intermedi tra i prezzi Open, High, Low e Close, porta ad un aspetto di rigido determinismo nello sviluppo dei prezzi, dal momento che viene determinato il prezzo di apertura. Ciò permette di creare un "Testing Graal", che mostra un grafico piacevole di rialzo del saldo testing.

Un esempio di tale Graal è presentato nel Code Base - Grr-al.

L'expert Advisor Grr-al, utilizza le peculiarità dei prezzi OHLC

La figura mostra un grafico molto interessante di questo EA testing. Come è stato ottenuto? Conosciamo 4 prezzi per una barra minuto, e sappiamo anche che il primo è il prezzo di apertura, e l'ultimo è il prezzo di chiusura. Abbiamo i prezzi Alti e Bassi tra loro, e la sequenza del loro verificarsi è sconosciuta, ma è noto, che il prezzo High(alto) è maggiore o uguale al prezzo di Apertura(Open), ed il prezzo Low(basso) è minore o uguale al prezzo Open.

E' sufficiente per determinare il momento di ricezione del prezzo di apertura(Open), e quindi analizzare il tick successivo al fine di determinare quale prezzo abbiamo in questo momento - sia l'Alto o il Basso. Se il prezzo è inferiore al prezzo Open, allora abbiamo un prezzo Low ed il buy in questo tick; il tick successivo corrisponderà al prezzo High, al quale noi chiudiamo il buy e apririamo per sell. Il tick successivo è l'ultimo, questo è il prezzo Close, e chiudiamo la vendita su di esso.

Se dopo il prezzo, riceviamo un tick con un prezzo superiore al prezzo di apertura, allora la sequenza di affari è invertita. Elabora una barra minuto in questo modo "cheat", ed attende il prossimo.

Durante il testing di questo EA sullo storico, tutto va liscio, ma una volta che lo lanciamo on-line, la verità comincia a rivelarsi - la linea di bilancio rimane costante, ma punta in giù. Per esporre questo trucco, dobbiamo semplicemente eseguire l'EA nella modalità "Ogni tick".

Nota: Se i risultati dell' EA nelle modalità di testing grezze ("OHLC 1 minuto" e "Solo Prezzi di Apertura") sembrano troppo buoni, assicuratevi di provarlo in modalità "Ogni Tick".

"Solo Prezzi di Apertura"

In questa modalità i ticks vengono generati sulla base dei prezzi OHLC del timeframe selezionato per il testing. La funzione OnTick() dell' Expert Advisor gira solo all'inizio della barra al prezzo Open. Grazie a questa caratteristica, i livelli di stop e pendenti, possono innescare un prezzo che differisce da quello specificato (soprattutto nel testing su timeframes superiori). Invece, abbiamo la possibilità di eseguire rapidamente un test di valutazione dell'Expert Advisor.

I periodi W1 e MN1 sono le eccezioni in modalità di generazione ticks "Open Price Only": per questi timeframes i ticks vengono generati per i prezzi OHLC di ogni giorno, non prezzi OHLC della settimana o del mese.

Supponiamo di provare un Expert Advisor su EURUSD H1 nella modalità "Solo Prezzi di Apertura". In questo caso, il numero totale di ticks (punti di controllo) sarà non più di 4*numero di barre un-ora all'interno dell'intervallo testato. Ma l' handler OnTick() viene chiamato solo all'apertura della barra un-ora. I controlli richiesti per una analisi corretta si verificano sul resto dei ticks (che sono "nascosti" dalla EA).

  • Il calcolo dei requisiti di margine;
  • L'innesco di Stop Loss e Take Profit;
  • L'innesco di ordini pendenti;
  • La rimozione di ordini pendenti espirati.

Se non ci sono posizioni aperte o ordini in sospeso, non abbiamo bisogno di effettuare tali controlli sui ticks nascosti, e l'incremento della velocità può essere sostanzialmente tranquillo. Questa modalità "Solo Prezzi di Apertura" è ben adatta per le strategie di testing, il quale procedimento riguarda solo l'apertura della barra e non utilizza gli ordini pendenti, così come gli ordini StopLoss e TakeProfit. Per la classe di tali strategie, l'accuratezza necessaria del testing viene preservata.

Usiamo l' Expert Advisor Moving Average dal pacchetto astandard, come un esempio di EA, che può essere testato in qualsiasi modalità. La logica di questo EA è costruita in modo tale che tutte le decisioni vengono prese all' apertura della barra, e gli affari vengono eseguiti immediatamente, senza l'uso di ordini pendenti.

Esegue un testing di EA su EURUSD H1 su un intervallo dal 2010.09.01 al 2010.12.31, e confronta i grafici. La figura mostra il grafico saldo dal rapporto di test per tutte le tre modalità.

Il grafico del testing dell' EA Moving Average.mq5 dal pacchetto standard non dipende dalla modalità di testing

Come si può vedere, i grafici su diverse modalità di testing sono esattamente gli stessi per l'EA Moving Average dal pacchetto standard.

Ci sono alcune limitazioni sulla modalità "Solo Prezzi di Apertura":

  • Non è possibile utilizzare la modalità di esecuzione Random Delay(_* Ritardo Casuale).
  • Nella Expert Advisor testato, non è possibile accedere ai dati del timeframe inferiore a quello utilizzato per il testing/ottimizzazione. Ad esempio, se si esegue il testing/ottimizzazione sul periodo H1, è possibile accedere ai dati di H2, H3, H4, ecc., ma non M30, M20, M10, ecc. Inoltre, i timeframes superiori a cui si accede, devono essere multipli del timeframe di testing. Ad esempio, se si esegue il testing in M20, non è possibile accedere ai dati di M30, ma è possibile accedere ad H1. Queste limitazioni sono connesse all'impossibilità di ottenere dati di timeframes inferiori o non multipli su barre generate durante il testing/ottimizzazione.
  • Le limitazioni per l'accesso ai dati di altri timeframes si applicano anche ad altri simboli i cui dati vengono utilizzati dall'Expert Advisor. In questo caso la limitazione per ogni simbolo dipende dal timeframe a cui si accede durante il testing/ottimizzazione. Supponiamo che, durante le prove su EURUSD H1, un Expert Advisor accede ai dati di GBPUSD M20. In questo caso l' Expert Advisor sarà in grado di utilizzare ulteriori dati di EURUSD H1, H2, ecc., nonché GBPUSD M20, H1, H2 ecc.

Nota: La modalità "Solo Prezzi di Apertura" ha il più veloce tempo di testing, ma non è adatto per tutte le strategie di trading. Selezionare la modalità di testing desiderata in base alle caratteristiche del sistema di trading.

Per concludere la sezione sulle modalità di generazione dei ticks, consideriamo un confronto visivo delle diverse modalità di generazione di ticks per EURUSD, per due barre M15 su un intervallo da 2011.01.11 21:00:00 - 2011.01.11 21:30:00..

I ticks sono stati salvati in file diversi utilizzando l'EA WriteTicksFromTester.mq5 e la fine di questi nomi file sono specificati in filenameEveryTick, filenameOHLC e filenameOpenPrice (parametri di input).

Siamo in grado di specificare le date di partenza e e di fine dei ticks (le variabili start ed end) per l'Expert Advisor WriteTicksFromTester

Per ottenere tre file con tre sequenze di tick (per ciascuna delle seguenti modalità "Ogni Tick", "1 minuto OHLC" e "Solo Prezzi di Apertura"), l'EA è stato lanciato per tre volte nei modi corrispondenti, in runs singole. Quindi, i dati provenienti da questi tre file sono stati visualizzati sul grafico con l'indicatore TicksFromTester.mq5. Il codice dell' indicatore è allegato a questo articolo.

La sequenza dei tick nello Strategy Tester del terminale MetaTrader 5 in tre diverse modalità di testing

Per default, tutte le operazioni sui file nel linguaggio MQL5 vengono realizzate all'interno del "file sandbox", e durante il testing l'EA ha accesso solo alla propria "sandbox file". Affinché l'indicatore e l' EA possano lavorare con i file da una cartella durante la prova, abbiamo usato il flag FILE_COMMON. Un esempio di codice dall' EA:

//--- apre il file
   file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,";");
//--- controlla l'handle del file
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Errore nell'apertura del file %s per la scrittura. Error code=%d",filename,GetLastError());
      return;
     }
   else
     {
      PrintFormat("Il file verrà creato nella cartella %s ",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Per leggere i dati dell'indicatore, abbiamo usato anche il flag FILE_COMMON. Questo ci ha permesso di evitare di trasferire manualmente i file necessari da una cartella ad un'altra.

//--- apre il file
   int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,";");
//--- controlla l'handle del file
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Errore nell'apertura del file %s per la lettura. Error code=%d",fname,GetLastError());
      return;
     }
   else
     {
      PrintFormat("Il file verrà aperto da %s",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Simulazione dello spread #

La differenza di prezzo tra i prezzi Bid ed Ask si chiama spread. Durante il testing, lo spread non viene modellato, ma è tratto da dati storici. Se lo spread è minore o uguale a zero nei dati storici, allora dall' agente di testing viene utilizzato l'ultimo spread noto (al momento della generazione).

Nello Strategy Tester, lo spread è sempre considerato come fluttuante. Che è SymbolInfoInteger(symobl, SYMBOL_SPREAD_FLOAT) e restituisce sempre true.

Inoltre, i dati dello storico contengono i valori dei tick ed i volumi di trading. Per lo stoccaggio ed il recupero dei dati si usa una speciale struttura MqlRates:

struct MqlRates
  {
   datetime time;         // Orario di inizio del periodo
   double   open;         // Prezzo di Apertura(Open)
   double   high;         // Il prezzo Massimo del periodo
   double   low;          // Il prezzo Minimo del periodo
   double   close;        // Prezzo di Chiusura(Close)
   long     tick_volume;  // Volume Tickv
   int      spread;       // Spread
   long     real_volume;  // Volume Trade
  };

Utilizzare ticks reali durante un test #

Test e ottimizzazione su ticks reali sono il più vicino possibile alle condizioni reali. Invece di ticks generati sulla base dei dati minute, è possibile utilizzare i ticks reali accumulati da un broker. Questi sono i ticks da scambi e fornitori di liquidità.

Per garantire la massima precisione di test, barre minuti vengono utilizzate anche nella modalità ticks reali. Le barre vengono applicate per controllare e correggere i dati tick. Questo permette anche di evitare la divergenza dei charts nel tester e nel terminale client.

Il tester confronta i dati tick con i parametri barra minuto: un tick non dovrebbe superare i livelli Alto/Basso della barra, anche, i ticks iniziali e finali, dovrebbero coincidere con i prezzi Apertura/Chiusura della barra. Il volume viene confrontato pure. Se viene rilevata una mancata corrispondenza, tutti i ticks corrispondenti a tale barra minuto vengono scartati. Vengono invece utilizzati ticks generati(come nella modalità "Ogni tick").

Se uno storico del simbolo ha una barra minuto senza i dati tick per essa, il tester genera ticks in modalità "Ogni tick". Questo permette tracciare un chart corretto nel tester in caso i dati tick di un broker siano insufficienti. Se uno storico del simbolo non dispone di una barra minuto, ma i dati tick appropriati per il minuto sono presenti, i dati possono essere utilizzati nel tester. Ad esempio, le coppie di simboli di scambio vengono formate usando gli Ultimi prezzi. Se solo i ticks con prezzi Bid/Ask, senza l'Ultimo prezzo (Last), arrivano dal server, la barra non viene generata. Il tester utilizza questi dati tick dal momento che non contraddicono quelli al minuto.

I ​​dati tick potrebbero non coincidere con barre minuto per varie ragioni, per esempio a causa di perdite di connessione o altri errori durante la trasmissione dei dati da una sorgente al terminale client. I dati minuto vengono considerati più affidabile durante i test.

Tenete a mente le seguenti caratteristiche durante il test sui ticks reali:

  • Quando si lancia un test, i dati aggiornati sul simbolo vengono sincronizzati con quelli tick.
  • I tick vengono memorizzati nella cache simbolo dello strategy tester. La dimensione della cache non supera i 128000 ticks. Quando i nuovi ticks arrivano, i dati più vecchi vengono rimossi dalla cache. Tuttavia, la funzione CopyTicks permette la ricezione di ticks fuori della cache (solo quando si fa il test su tick reali). In tal caso, i dati vengono richiesti dal database tick tester che è completamente simile al database terminale client corrispondente. Non vengono implementate correzioni barra minulo a questa base. Pertanto, i ticks possono essere diversi da quelli memorizzati nella cache.

Le variabili globali del Terminale Client #

Durante il testing, le variabili globali del terminale client vengono emulate anche, ma non sono collegate alle correnti variabili globali del terminale, che possono essere viste nel terminale utilizzando il tasto F3. Ciò significa che tutte le operazioni con le variabili globali del terminale, durante i testing, hanno luogo al di fuori del terminale client (nell'agente di test).

Il Calcolo degli Indicatori durante il Testing #

Nella modalità in tempo reale, i valori dell'indicatore vengono calcolati ad ogni tick.

Nel Tester di strategia, gli indicatori vengono calcolati solo quando si accede ai dati, cioè quando vengono richiesti i valori del buffer dell'indicatore. Le uniche eccezioni sono gli indicatori personalizzati con il #property tester_everytick_calculate specificato. In questo caso, il ricalcolo viene eseguito su ogni tick.

Nella modalità di test visivo, tutti gli indicatori vengono ricalcolati incondizionatamente all'arrivo di un nuovo tick per essere visualizzati correttamente sul grafico di test visivo.

L'indicatore viene calcolato una volta per ogni tick. Tutte le successive richieste di dati dell'indicatore non portano al ricalcolo fino all'arrivo di un nuovo tick. Pertanto, se il timer è abilitato in un EA tramite la funzione EventSetTimer(), i dati dell'indicatore vengono richiesti dall'ultimo tick prima di ogni chiamata del gestore OnTimer(). Se l'indicatore non è stato ancora calcolato sull'ultimo tick, i calcoli dei valori dell'indicatorevengono avviati. Se i dati sono già stati preparati, vengono forniti senza un nuovo ricalcolo.

Pertanto, tutti i calcoli dell'indicatore vengono eseguiti nel modo più efficiente in termini di risorse — se l'indicatore è già stato calcolato a un dato tick, i suoi dati vengono forniti "così come sono". Non viene avviato alcun ricalcolo.

Caricamento dello Storico durante il Testing #

Lo storico di un simbolo da testare è sincronizzato e caricato dal terminale, dal trade server prima di avviare il processo di testing. Durante la prima volta, il terminale carica tutto lo storico a disposizione di un simbolo per non richiederlo in un secondo momento. Inoltre solo i nuovi dati vengono caricati.

Un agente di testing riceve lo storico di un simbolo da testare dal terminale client subito dopo l'inizio del testing. Se i dati di altri strumenti vengono utilizzati nel processo di testing (ad esempio, è un Expert Advisor multivaluta), gli agenti di testing richiedono lo storico dal terminale client durante la prima chiamata a tali dati. Se i dati storici sono disponibili nel terminale, vengono immediatamente passati all'agente di testing. Se i dati non sono disponibili, il terminale li richiede e scarica dal server, e poi li passa all'agente di testing.

I dati di strumenti finanziari aggiuntivi sono anche necessari per il calcolo dei cross-rates per le operazioni di trade. Per esempio, quando si fa il testing di una strategia EURCHF con la valuta di deposito in USD, prima di elaborare la prima operazione di trading, l'agente di testing richiede i dati storici di EURUSD e USDCHF dal terminale client, anche se la strategia non contiene la chiamata diretta di uso di questi simboli.

Prima di testare una strategia multi-valuta, si consiglia di scaricare tutti i dati storici necessari nel terminale client. Ciò contribuirà ad evitare ritardi nel testing/ottimizzazione associato con il download dei dati richiesti. È possibile scaricare lo storico, per esempio, aprendo i grafici appropriati e facendo scorrimento verso l'inizio dello storico. Un esempio di caricamento forzato dello storico nel terminale è disponibile nella sezione Organizzare l'Accesso ai Dati dell' MQL5 Reference.

Agenti di testing, a loro volta, ricevono lo storico dal terminale in una forma impacchettata. Durante il testing successivo, il tester non carica lo storico dal terminale, in quanto i dati richiesti sono disponibili dalla precedente esecuzione del tester.

  • Il terminale carica lo storico da un trade server sola volta, la prima volta l'agente richiede lo storico di un simbolo da essere testato dal terminale. Lo storico viene caricato in forma impacchettata per ridurre il traffico.
  • I ticks non vengono inviati attraverso la rete, sono generati sugli agenti di testing.

Testing Multi-valuta #

Lo strategy tester ci permette di eseguire un test di strategie, facendo trading su più simboli. Tali EA sono convenzionalmente indicati come Expert Advisor multi-valuta, dal momento che in origine, nelle piattaforme precedenti, il testing veniva effettuato solo per un unico simbolo. Nello Strategy Tester del terminale MetaTrader 5, possiamo modellare il trading per tutti i simboli disponibili.

Il tester carica lo storico dei simboli utilizzati dal terminale client (non dal trade server!) automaticamente durante la prima chiamata dei dati del simbolo.

L'agente di testing scarica solo lo storico mancante, con un piccolo margine per fornire i dati necessari sullo storico, per il calcolo degli indicatori al momento di avvio del testing. Per i limiti temporali di D1 e minori, il volume minimo dello storico scaricato è di un anno.

Pertanto, se si esegue un test su un intervallo 2010.11.01-2010.12.01 (testing per un intervallo di un mese) con un periodo di M15 (ciascuna barra è pari a 15 minuti), il terminale verrà richiesto per lo storico dello strumento finanziario per l'intero anno del 2010. Per il timeframe settimanale, ci verrà richiesta una storia di 100 barre, che è di circa due anni (un anno ha 52 settimane). Per il testing su un timeframe settimanale l'agente chiederà lo storico di 8 anni (12 mesi x 8 anni = 96 mesi).

Se non vi sono le barre necessarie, la data di inizio del testing verrà automaticamente slittata dal passato al presente per fornire la necessaria riserva di barre prima del testing.

Durante il testing, il "Market Watch" viene emulato anche, dal quale si possono ottenere informazioni sui simboli.

Per default, all'inizio del testing, c'è solo un simbolo nel "Market Watch" dello Strategy Tester - il simbolo su cui gira il testing. Tutti i simboli necessari sono collegati al "Market Watch" dello Strategy Tester (non al terminale!) automaticamente quando vi si riferiscono.

Prima di iniziare il testing di un Expert-Advisor multi-valuta, è necessario selezionare i simboli necessari per il testing "Market Watch" del terminale e caricare i dati richiesti. Durante la prima chiamata di un simbolo "straniero", il suo storico verrà automaticamente sincronizzato tra l'agente di testing ed il terminale cliente. Un simbolo "estraneo" è il simbolo diverso da quello su cui testing è in esecuzione.

Il riferimento ai dati di un "altro" simbolo si verificano nei seguenti casi:

  • Richiesta della timeseries di un simbolo/timeframe utilizzando le seguenti funzioni:

Al momento della prima chiamata ad un "altro" simbolo, il processo di testing viene interrotto e lo storico viene scaricato per il simbolo/timefreame, dal terminale per l'agente di testing. Allo stesso tempo viene fatta la generazione della sequenza dei tick per questo simbolo.

Una sequenza individuale di tick viene generata per ogni simbolo, secondo il modo selezionato di generazione tick. È anche possibile richiedere lo storico in modo esplicito per i simboli desiderati chiamando SymbolSelect() nell'handler OnInit() - il download dello storico sarà effettuato immediatamente prima del testing dell' Expert Advisor.

Pertanto, non richiede alcuno sforzo supplementare eseguire testing multi-valuta nel terminale client MetaTrader 5 . Basta aprire i grafici dei simboli appropriati del terminale cliente. Lo storico sarà caricato automaticamente dal trade server per tutti i simboli necessari, purché contenga questi dati.

Simulazione del Tempo nello Strategy Tester #

Durante il testing, l'ora locale TimeLocal() è sempre uguale all'ora del server TimeTradeServer(). A sua volta, l'orario del server è sempre uguale all'orario corrispondente al tempo GMT - TimeGMT(). In questo modo, tutte queste funzioni visualizzano lo stesso orario durante il testing.

La mancanza di una differenza tra l'orario GMT, locale, server nello Strategy Tester viene fatta deliberatamente in caso non vi è alcuna connessione con il server. I risultati del test devono essere sempre gli stessi, indipendentemente dal fatto che vi sia un collegamento. Le informazioni sull'ora del server non vengono memorizzate localmente, ed sono prese dal server.

Gli Oggetti Grafici nel Testing #

Durante il testing/ottimizzazione gli oggetti grafici non vengono tracciati. Così, quando ci si riferisce alle proprietà di un oggetto creato durante il testing/ottimizzazione, un Expert Advisor riceverà i valori zero.

Questa limitazione non si applica al testing in modalità visuale.

La funzone OnTimer() nello Strategy Tester #

MQL5 offre l'opportunità per l'handling degli eventi timer. La chiamata dell'handler OnTimer() avviene indipendentemente dalla modalità di testing. Ciò significa che se un test è in esecuzione in modalità "Solo prezzi di apertura" per il periodo H4, e l' EA ha un timer impostato ad una chiamata al secondo, allora all' apertura di ogni barra H4, l'handler OnTick() sarà chiamato una sola volta, e l'handler OnTimer() sarà chiamato 14400 volte (3600 secondi * 4 ore). La quantità per cui il tempo di testing dell' EA sarà aumentata dipende dalla logica della EA.

Per verificare la dipendenza del tempo di testing dalla data frequenza del timer, abbiamo creato un EA semplice senza operazioni di trading.

//--- parametri di input
input int      timer=1;              // valore timer, sec
input bool     timer_switch_on=true; // timer on
//+--------------------------------------------------------------------------------+
//| Funzione di inizializzazione dell' Expert                                      |
//+--------------------------------------------------------------------------------+
int OnInit()
  {
//--- esegue il timer se timer_switch_on==true
   if(timer_switch_on)
     {
      EventSetTimer(timer);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+--------------------------------------------------------------------------------+
//| Funzione deinizializzazione Expert                                             |
//+--------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- ferma il timer
   EventKillTimer();
  }
//+--------------------------------------------------------------------------------+
//| Funzione Timer                                                                 |
//+--------------------------------------------------------------------------------+
void OnTimer()
  {
//---
// non viene eseguita alcuna azione, il corpo dell'handler è vuoto
  }
//+--------------------------------------------------------------------------------+

Misure del tempo di testing sono state prese da diversi valori del parametro timer (periodicità dell'evento Timer). Sui dati ottenuti, abbiamo tracciato un tempo di testing in funzione del periodo di Timer.

Il tempo di testing in funzione del periodo di Timer

Si vede chiaramente che il più piccolo è il parametro di timer, durante l'inizializzazione della funzione EventSetTimer(Timer), più piccolo è il periodo (Period) tra le chiamate dell'handler OnTimer(), e più grande è il tempo T di testing, alle stesse condizioni di altri.

La funzione Sleep() nello Strategy Tester #

La funzione Sleep() consente all' EA o script di sospendere l'esecuzione del programma MQL5 per un po', quando si lavora sul grafico. Questo può essere utile per la richiesta di dati, che non sono pronti al momento della richiesta ed è necessario attendere che siano pronti. Un esempio dettagliato di utilizzo della funzione Sleep() possono essere trovati nella sezione Arrangiamento Accesso ai Dati.

Il processo di testing non è attardato dalla chiamata Sleep(). Quando si chiama Sleep(), i ticks generati vengono sono "giocati" entro un termine specificato, che può provocare l'innesco di ordini pendenti, stops, ecc. Dopo una chiamata Sleep(), il tempo simulato nello Strategy Tester aumenta di un intervallo, specificato nel parametro della funzione Sleep.

Se, a seguito della esecuzione della funzione Sleep(), l'ora corrente nello Strategy Tester ha superato il periodo di testing, allora si riceverà un errore di "Ciclo si Sleep infinito rilevato durante il testing". Se si riceve questo errore, i risultati del testing non vengono respinti, tutti i calcoli vengono eseguiti nel loro pieno volume (numero di affari, subsidenza, ecc), ed i risultati di questo test vengono trasmessi al terminale.

La funzione Sleep() non funziona in OnDeinit(), dal momento che dopo che viene chiamata, il tempo di testing sarà garantito a superare il range dell' intervallo di testing.

Lo schema di utilizzo della funzione Sleep() nello Strategy Tester del terminale MetaTrader 5

Utilizzo dello Strategy Tester per i Problemi di Ottimizzazione in Calcoli Matematici #

Il tester nel terminale MetaTrader 5 può essere utilizzato non solo per testare strategie di trading, ma anche per i calcoli matematici. Per utilizzarlo, è necessario selezionare la modalità "Calcoli Matematici":

math_calculations

In questo caso, solo tre funzioni verranno chiamate: OnInit(), OnTester(), OnDeinit(). In modalità "Calcoli matematici" lo Strategy Tester non genera alcun tick e download dello storico.

Lo Strategy Tester funziona in modalità "Calcoli matematici" anche se si specifica la data di inizio maggiore di quella di chiusura.

Quando si utilizza il tester per risolvere problemi matematici, il caricamento dello storico e la generazione di ticks non si verifica.

Un tipico problema matematico da risolvere nello Strategy Tester MetaTrader 5 - la ricerca di un estremo di una funzione con molte variabili.

Per risolverlo abbiamo bisogno di:

  • Il calcolo del valore della funzione deve essere collocato nella funzione OnTester();
  • I parametri della funzione devono essere definiti come variabili di input- dell' Expert Advisor;

Compilare l'EA, aprire la finestra "Strategy Tester". Nel campo "Parametri di Input", selezionare le variabili di input richieste, e definire l'insieme dei valori dei parametri specificando i valori di avvio, di arresto e di step per ognuna delle variabili della funzione.

Selezionare il tipo di ottimizzazione - "Algoritmo Completo lento" (ricerca completa dello spazio parametri) o "Algoritmo veloce a base genetica". Per una semplice ricerca di estremo della funzione, è meglio scegliere una ottimizzazione veloce, ma se si desidera calcolare i valori per l'intero set di variabili, allora è meglio usare l'ottimizzazione lenta.

Selezionare la modalità "Calcoli matematici" ed utilizzare il bottone "Start", per eseguire la procedura di ottimizzazione. Notare che durante l'ottimizzazione lo Strategy Tester ricerca i valori massimi della funzione OnTester. Per trovare un minimo locale, restituire l'inverso del valore della funzione calcolata dalla funzione OnTester:

return(1/function_value);

È necessario controllare che function_value non è uguale a zero, altrimenti si può ottenere un errore critico di divisione per zero.

C'è un altro modo, è più conveniente e non distorce i risultati dell'ottimizzazione, è stato suggerito dai lettori di questo articolo:

return(-function_value);

Questa opzione non richiede il controllo del function_value_ per essere uguale a zero, e la superficie dei risultati di ottimizzazione in una rappresentazione 3D ha la stessa forma, ma si specchia all'originale.

Come esempio, forniamo la funzione sink():

sink_formula

Il codice della EA per trovare l'estremo di questa funzione è inserito nell' OnTester():

//+--------------------------------------------------------------------------------+
//|                                                                       Sink.mq5 |
//|                                      Copyright 2011, MetaQuotes Software Corp. |
//|                                                           https://www.mql5.com |
//+--------------------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- parametri di input
input double   x=-3.0; // start=-3, step=0.05, stop=3
input double   y=-3.0; // start=-3, step=0.05, stop=3
//+--------------------------------------------------------------------------------+
//| Tester function                                                                |
//+--------------------------------------------------------------------------------+
double OnTester()
  {
//---
   double sink=MathSin(x*x+y*y);
//---
   return(sink);
  }
//+--------------------------------------------------------------------------------+

Eseguie l'ottimizzazione e vede i risultati dell'ottimizzazione sottoforma di un grafico 2D.

I risultati dell'ottimizzazione completa della funzione sink (x*x+y*y) come funzione 2D-graph

Migliore è il valore di una data coppia di parametri (x, y), più è saturo il colore. Come era atteso dalla vista della forma della formula sink(), i suoi valori formano cerchi concentrici con centro in (0,0). Si può vedere nel grafico-3D, che la funzione sink() non ha un estremo unico globale:

Grafico 3D della funzione Sink

La sincronizzazione delle Barre nella modalità "Solo prezzi di apertura" #

Il tester nel terminale client MetaTrader 5 ci permette di controllare il cosiddetto "EA multi-valuta". Un EA multi-valuta - è un EA che fa il trade su due o più simboli.

Il testing di strategie, che sono tradate su più simboli, impone alcuni requisiti tecnici complementari sul tester:

  • La generazione di ticks per questi simboli;
  • Il calcolo dei valori degli indicatori per questi simboli;
  • Il calcolo dei requisiti di margine per questi simboli;
  • La sincronizzazione di sequenze tick generate per tutti i simboli di trading.

Lo Strategy Tester genera e riproduce una sequenza tick per ogni strumento secondo la modalità trading selezionata. Al tempo stesso, viene aperta una nuova barra per ogni simbolo, indipendentemente da come la barra viene aperta su un altro simbolo. Ciò significa che quando si testa un EA multi-valuta, può verificarsi una situazione (e spesso accade), quando per uno strumento una nuova barra è già aperta, e per l'altro non. Così, durante il testing, tutto avviene proprio come nella realtà.

Questa simulazione autentica dello storico nel tester non causa alcun problema, basta che vengono utilizzate le moddalità di testing "Ogni tick" e "1 minuto OHLC". Per queste modalità, sufficienti ticks vengono generati per una candela, per poter attendere fino a che avviene la sincronizzazione di barre da diversi. Ma come facciamo a testare strategie di un EA multi-valuta in modalità "Solo prezzi di Apertura", se la sincronizzazione delle barre degli strumenti di trading è obbligatoria? In questa modalità, l'EA viene chiamato solo su un tick, che corrisponde al tempo di apertura delle barre.

Noi lo illustrano in un esempio: se stiamo testando un EA su EURUSD, ed una nuova candela oraria è aperta su EURUSD, allora si può facilmente riconoscere questo fatto - nei test in modalità "Solo Prezzi di apertura", l' evento NewTick corrisponde al momento dell'apertura barra sul periodo di testing. Ma non vi è alcuna garanzia che la nuova candela aperta sul simbolo USDJPY, viene utilizzata nella EA.

In circostanze normali, è sufficiente completare il lavoro della funzione OnTick() e verificare la comparsa di una nuova barra sull'emersione di una nuova barra su USDJPY al prossimo tick. Ma, durante il testing in la modalità "Solo prezzi di Apertura", non ci sarà nessun altro tick, e così può sembrare che questa modalità non è adatta per il testing di EA multi-valuta. Ma non è così - non dimenticate che il tester in MetaTrader 5 si comporta proprio come farebbe nella vita reale. È possibile attendere una nuova barra si apre su un altro dei simboli utilizzando la funzione del Sleep() !

Il codice di EA Synchronize_Bars_Use_Sleep.mq5, che mostra un esempio di sincronizzazione di barre in modalità "Solo Prezzi di Apertura":

//+--------------------------------------------------------------------------------+
//|                                                 Synchronize_Bars_Use_Sleep.mq5 |
//|                                      Copyright 2011, MetaQuotes Software Corp. |
//|                                                           https://www.mql5.com |
//+--------------------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- parametri di input
input string   other_symbol="USDJPY";
//+--------------------------------------------------------------------------------+
//| Funzione di inizializzazione dell' Expert                                      |
//+--------------------------------------------------------------------------------+
int OnInit()
  {
//--- controllo il simbolo
   if(_Symbol==other_symbol)
     {
      PrintFormat("Devi specificare l'altro simbolo nei parametri di input o selezionare altro simbolo nello Strategy Tester!");
      //--- arresto testing forzato
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+--------------------------------------------------------------------------------+
//| Funzione tick dell'Expert                                                      |
//+--------------------------------------------------------------------------------+
void OnTick()
  {
//--- variabile statica, utilizzata per il salvataggio del tempo dell'ultima barra
   static datetime last_bar_time=0;
//--- sync flag
   static bool synchonized=false;
//--- se variabile statica non viene inizializzata
   if(last_bar_time==0)
     {
      //--- è la prima chiamata, salva il tempo bar ed esce
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
      PrintFormat("La variabile last_bar_time è inizializzata con valore %s",TimeToString(last_bar_time));
     }
//--- ottiene il tempo di apertura dell'ultima barra del simbolo del grafico
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//--- se gli orari non sono uguali
   if(curr_time!=last_bar_time)
     {
      //--- salva l'orario di apertura della barra alla variabile statica
      last_bar_time=curr_time;
      //--- non sincronizzato
      synchonized=false;
      //--- stampa messaggio
      PrintFormat("Una nuova barra è apparsa sul simbolo %s at %s",_Symbol,TimeToString(TimeCurrent()));
     }
//--- prezzo di apertura della barra dell'altro simbolo
   datetime other_time;
//--- loop fino al tempo di apertura di un altro simbolo diventa uguale a curr_time
   while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
     {
      PrintFormat("Aspetta 5 secondi..");
      //--- aspetta 5 secondi e chima SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)
      Sleep(5000);
     }
//--- le barre sono sincronizzate
   synchonized=true;
   PrintFormat("Orario di aperturara della barra del simbolo del grafico %s: is %s",_Symbol,TimeToString(last_bar_time));
   PrintFormat("Oerario di apertura della barra del simbolo %s: is %s",other_symbol,TimeToString(other_time));
//--- TimeCurrent() non è utile, utilizzare TimeTradeServer()
   Print("Le barre sono sincronizzate a ",TimeToString(TimeTradeServer(),TIME_SECONDS));
  }
//+--------------------------------------------------------------------------------+

Si noti l'ultima riga dell' EA, che visualizza l'ora corrente quando il fatto della sincronizzazione è stato stabilito:

   Print("Le barre sono sincronizzate a ",TimeToString(TimeTradeServer(),TIME_SECONDS));

Per visualizzare l'ora corrente abbiamo usato la funzione TimeTradeServer() piuttosto che TimeCurrent(). TimeCurrent() restituisce l'orario dell'ultimo tick, che non cambia dopo l'utilizzo di Sleep(). Esegui l'EA in modalità "Solo Prezzi di Apertura", e vedrai un messaggio riguardo la sincronizzazione delle barre.

Synchronize_Bars_Use_Sleep_EA

Usiamo la funzione TimeTradeServer() al posto di TimeCurrent(), se è necessario per ottenere l'ora corrente del server, e non il tempo di arrivo dell'ultimo tick.

C'è un altro modo per sincronizzare le barre - utilizzando un timer. Un esempio di tale EA è Synchronize_Bars_Use_OnTimer.mq5, che è allegato in questo articolo.

La funzione IndicatorRelease() nella Tester #

Dopo aver completato un testing singolo, viene aperto automaticamente un grafico dello strumento, che visualizza le offerte completate e gli indicatori utilizzati per l'EA. Questo aiuta a controllare visivamente i punti di entrata ed uscita, e confrontarli con i valori degli indicatori.  

Nota: indicatori, visualizzati sul grafico, che si aprono automaticamente dopo il completamento del test, vengono calcolati nuovamente dopo il completamento del test. Anche se questi indicatori sono stati utilizzati nell' EA testato.

Ma in alcuni casi, il programmatore può decidere di nascondere le informazioni su cui sono stati coinvolti gli indicatori negli algoritmi di trading. Ad esempio, il codice della EA è in affitto o venduto come un file eseguibile, senza la fornitura del codice sorgente. A questo scopo, la funzione IndicatorRelease() è adatta.

Se il terminale imposta un modello con il nome tester.tpl nella directory /profiles/templates del terminale client, allora sarà applicato al grafico aperto. In sua assenza, viene applicato il modello predefinito. (default.tpl).

La funzione IndicatorRelease() è originariamente prevista per rilasciare la porzione di calcolo dell'indicatore, se non è più necessaria. Questo vi permette di salvare sia la memoria che le risorse della CPU, perché ogni tick richiede un calcolo dell'indicatore. Il suo secondo obiettivo - è quello di vietare la visualizzazione di un indicatore sul grafico di testing, dopo una test run singola.

Per proibire la visualizzazione dell'indicatore sul grafico dopo il testing, chiamare IndicatorRelease() con l'handle dell'indicatore nell'handler OnDeinit(). La funzione OnDeinit() viene sempre chiamata dopo il completamento e prima della visualizzazione del grafico di prova.

//+--------------------------------------------------------------------------------+
//| Funzione deinizializzazione Expert                                             |
//+--------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   bool hidden=IndicatorRelease(handle_ind);
   if(hidden) Print("IndicatorRelease() completato con successo");
   else Print("IndicatorRelease() ha restituito false. Error code ",GetLastError());
  }

Al fine di proibire che si mostri l'indicatore sul grafico, dopo il completamento di un singolo test, utilizzare la funzione IndicatorRelease() nell'handler OnDeinit().

Event Handling nel Tester #

La presenza dell' handler OnTick() nell' EA non è obbligatoria per per essere sottoposta a testing su dati storici nel tester MetaTrader 5. È sufficiente che l' EA contenga almeno uno dei seguenti handler-funzione:

  • OnTick() - Event handler di arrivo di un nuovo tick;
  • OnTrade() - Event handler di trading;
  • OnTimer() - Event handler dell'arrivo di un segnale dal timer;
  • OnChartEvent() - un handler per gli eventi del client.

Durante il testing in un EA, siamo in grado di gestire gli eventi personalizzati utilizzando la funzione OnChartEvent(), ma negli indicatori, questa funzione non può essere chiamata nel tester. Anche se l'indicatore ha l'event handler OnChartEvent() e questo indicatore è utilizzato nella EA testato, l'indicatore stesso non riceverà alcun evento personalizzato.

Durante il testing, un Indicatore può generare eventi personalizzati utilizzando la funzione EventChartCustom(), e l'EA può elaborare questo evento nell' OnChartEvent().

In aggiunta a questi eventi, eventi speciali associati al processo di testing ed ottimizzazione vengono generati nello strategy tester:

  • Tester - questo evento viene generato dopo il completamento del testing dell'Expert Advisor sui dati storici. L'evento Tester viene gestito utilizzando la funzione OnTester(). Questa funzione può essere utilizzata solo quando si fa il testing dell'Expert Advisorè ed destinata principalmente per il calcolo di un valore utilizzato come criterio Custom max per l'ottimizzazione genetica dei parametri di input.
  • TesterInit - questo evento viene generato durante l'avvio di ottimizzazione nello strategy tester prima del vero primo passo. L'evento TesterInit viene gestito utilizzando la funzione OnTesterInit(). Durante l'inizio dell' ottimizzazione, un Expert Advisor con questo gestore viene caricato automaticamente in un grafico del terminale separato, con simbolo e periodo specificati nel tester, e riceve l'evento TesterInit. La funzione viene utilizzata per avviare un Expert Advisor prima dell'inizio dell' ottimizzazione per ulteriore elaborazione dei risultati di ottimizzazione.
  • TesterPass - questo evento viene generato quando un nuovo frame di dati viene ricevuto. L'evento TesterPass è gestito utilizzando la funzione OnTesterPass(). Un Expert Advisor con questo handler viene caricato automaticamente in un grafico terminale separato con il simbolo/periodo specificati per il testing, e ricevono l'evento TesterPass quando un frame viene ricevuto durante l'ottimizzazione. La funzione viene utilizzata per la gestione dinamica dei risultati di ottimizzazione "sul posto", senza attendere il suo completamento. I frame vengono aggiunti utilizzando la funzione FrameAdd(), che può essere chiamata dopo la fine di un singolo passaggio nell' handler OnTester().
  • TesterDeinit - questo evento viene generato dopo la fine della ottimizzazione Expert Advisor nello Strategy Tester. L'evento TesterDeinit è gestito utilizzando la funzione OnTesterDeinit(). Un Expert Advisor con questo handler viene caricato automaticamente in un grafico all'inizio dell' ottimizzazione, e riceve TesterDeinit dopo il suo completamento. La funzione viene utilizzata per la lavorazione finale di tutti i risultati dell'ottimizzazione.

Agenti Testing #

Il testing nel terminale MetaTrader 5 viene effettuato utilizzando agenti di test. Agenti locali vengono creati e attivati ​​automaticamente. Il numero predefinito di agenti locali corrisponde al numero di core in un computer.

Ogni agente di testing ha la propria copia delle variabili globali, che non è correlata al terminale client. Il terminale stesso è il dispensatore, che distribuisce i compiti agli agenti locali e remoti. Dopo l'esecuzione di un compito sul testing di un EA, con i parametri specificati, l'agente restituisce i risultati al terminale. Con un singolo test, un solo agente viene utilizzato.

L'agente memorizza lo storico, ricevuto dal terminale, in cartelle separate, dal nome dello strumento, in modo che lo storico per EURUSD è memorizzato in una cartella denominata EURUSD. Inoltre, la storia degli strumenti è separata dalle loro fonti. La struttura per memorizzare lo storico assomiglia al seguente modo:

tester_catalog\Agent-IPaddress-Port\bases\name_source\history\symbol_name

Ad esempio, lo storico per EURUSD dal server MetaQuotes-Demo può essere memorizzato nella cartella tester_catalog\Agent-127.0.0.1-3000\bases\MetaQuotes-Demo\EURUSD.

Un agente locale, dopo il completamento del testing, entra in una modalità di stand-by, in attesa di una nuova attività per altri 5 minuti, in modo da non perdere tempo per avviare per la chiamata successiva. Solo dopo che il periodo di attesa è finito, l'agente locale si spegne e si decarica dalla memoria della CPU.

In caso di un precoce completamento del testing, da parte dell'utente (il pulsante "Annulla"), nonché con la chiusura del terminale client, tutti gli agenti locali interrompono immediatamente il loro lavoro e vengono decaricati dalla memoria.

Lo Scambio di Dati tra il Terminale e l'Agente #

Quando si esegue un test, il terminale client si prepara per inviare all'agente un certo numero di blocchi di parametri:

  • I parametri di input per il testing (modalità di simulazione, l'intervallo di test, strumenti, criteri di ottimizzazione, ecc.)
  • L'elenco dei simboli selezionati nel "Market Watch"
  • La specifica del simbolo di testing (la dimensione del contratto, i margini consentiti dal mercato per l'impostazione di un StopLoss e Takeprofit, ecc)
  • L'Expert Advisor da essere testato e i valori dei suoi parametri di input
  • Informazioni su file aggiuntivi (librerie, indicatori, file di dati - # property tester_ ...)

tester_indicator

string

Nome di un indicatore personalizzato nel formato "nome_indicatore.ex5". Indicatori che richiedono il testing vengono definiti automaticamente dalla chiamata della funzione iCustom(), se il parametro corrispondente viene impostato tramite una stringa costante. Per tutti gli altri casi (utilizzo della funzione IndicatorCreate() o uso di una stringa non costante nel parametro che imposta il nome dell' indicatore) questa proprietà è obbligatoria

tester_file

string

Nome file per un tester con l'indicazione di estensione, tra virgolette (come una stringa costante). Il file specificato verrà passato al tester. File di input da testare, se ci sono quelli necessari, deve sempre essere specificato.

tester_library

string

Nome libreria con l'estensione, tra virgolette. Una libreria può avere estensione DLL o EX5. Librerie che richiedono testing vengono definite automaticamente. Tuttavia, se una delle librerie viene utilizzata da un indicatore personalizzto, questa proprietà è necessaria

Per ogni blocco di parametri, un'impronta digitale in forma di hash-MD5 viene creata, e viene inviata all'agente. MD5-hash è univoca per ciascun set, il suo volume è molte volte più piccolo della quantità di informazioni sulla quale viene calcolato.

L'agente riceve un hash di blocchi e li confronta con quelli che ha già. Se l'impronta digitale del blocco parametri dato non è presente nell'agente, o l'hash ricevuto è diverso da quello esistente, l'agente richiede questo blocco di parametri. Questo riduce il traffico tra il terminale e l'agente.

Dopo il testing, l'agente restituisce al terminale di tutti i risultati della run, che sono indicati nella scheda "Risultati del Test" e "Risultati Ottimizzazione": il profitto ricevuto, il numero di affari, il coefficiente Sharpe, il risultato della funzione OnTester(), ecc

Durante l'ottimizzazione, le terminale spedisce i compiti di testing agli agenti in piccoli pacchetti, ogni pacchetto contenente diversi compiti (per ogni compito si intende ogni attività di test singolo con una serie di parametri di input). Questo riduce il tempo di scambio tra il terminale e l'agente.

Gli agenti non registrano mai sull'hard disk i files EX5, ottenuti dal terminale (EA, indicatori, librere, ecc) per motivi di sicurezza, di modo che un computer con un agente in esecuzione non può utilizzare i dati inviati. Tutti gli altri file, tra cui DLL, sono registrate nella sandbox. In agenti remoti non si possono testare EA utilizzando DLL.

I risultati dei testing sono sommate dal terminale in una cache speciale dei risultati (i risultati della cache), per un accesso rapido ad essi quando sono necessari. Per ogni insieme di parametri, il terminale ricerca la i risultati della cache già disponibili dalle run precedenti, al fine di evitare repliche. Se il risultato con un insieme di parametri non viene trovato, all'agente viene dato il compito di eseguire il testing.

Tutto il traffico tra il terminale e l'agente è crittografato.

I ticks non vengono inviati attraverso la rete, sono generati sugli agenti di testing.

Uso della Cartella Condivisa di tutti i Terminali Client #

Tutti gli agenti di testing sono isolati gli uni dagli altri e dal terminale client: ogni agente ha una propria cartella in cui sono iscritti i suoi log. Inoltre, tutte le operazioni di file durante il testing dell'agente si verificano nella cartella agent_name/MQL5/Files. Tuttavia, siamo in grado di realizzare l'interazione tra gli agenti locali ed il terminale client tramite una cartella condivisa per tutti i terminali client, se durante l'apertura del file si specifica la flag FILE_COMMON:

//+--------------------------------------------------------------------------------+
//| Funzione di inizializzazione dell' Expert                                      |
//+--------------------------------------------------------------------------------+
int OnInit()
  {
//--- la cartella condivisa per tutti i terminali client
   common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//--- tira fuori il nome di questa cartella
   PrintFormat("Apre il file nella cartella condivisa dei terminali client %s", common_folder);
//--- apre il file nella cartella condivisa (indicato dal flag FILE_COMMON)
   handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
  ... ulteriori azioni
//---
   return(INIT_SUCCEEDED);
  }

Utilizzo di DLLs #

Per accelerare l'ottimizzazione è possibile utilizzare non solo agenti locali, ma anche agenti remoti. In questo caso, ci sono alcune limitazioni per agenti remoti. Prima di tutto, gli agenti remoti non mostrano nei loro log i risultati dell'esecuzione della funzione Print(), messaggi sulla apertura e la chiusura delle posizioni. Un minimo di informazioni vengono visualizzate nel registro per evitare che EA erroneamente scritti facciano immondizia nel computer , su cui l'agente di rimozione è in funzione, con i messaggi.

Una seconda limitazione - il divieto di utilizzo di DLL durante il testing degli EA. Le chiamate DLL sono assolutamente vietate su agenti remoti per motivi di sicurezza. In agenti locale, le chiamate DLL negli EA testati sono ammesse solo con l'autorizzazione appropriata "Consenti Importazione DLL".

L'opzione "Consenti Importazione DLL" in programmi MQL5

Nota: Quando si utilizza la riceziona da EA (script, indicatori) che richiedono il permesso di chiamate DLL, si deve essere consapevoli dei rischi che si assumono quando si consente questa opzione nelle impostazioni del terminale. Indipendentemente da come la EA sarà utilizzato - per il testing o per l'esecuzione su un grafico.