English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
I Principi del Calcolo Economico degli Indicatori

I Principi del Calcolo Economico degli Indicatori

MetaTrader 5Indicatori | 16 dicembre 2021, 10:42
85 0
Nikolay Kositsin
Nikolay Kositsin

Introduzione

L'idea di preservare le risorse in un segmento o nell'altro delle attività pratiche delle persone - è forse uno degli argomenti più significativi e urgenti sulla strada dello sviluppo umano e del progresso. A questo proposito, la programmazione in MQL5 non fa eccezione. Naturalmente, se la gamma di attività è limitata solo al visual trading, molti difetti della programmazione possono rimanere inosservati.

Ma tutto ciò che riguarda il trading automatizzato, inizialmente richiede una scrittura principalmente economica del codice, altrimenti, il processo di test e ottimizzazione dei robot di trading può essere esteso per un periodo di tempo così lungo che sarebbe praticamente impossibile attendere fino al loro completamento. L'idea di creare qualcosa di valore in questo tipo di situazione sembra abbastanza incerta.

Quindi, prima di intraprendere l'implementazione di strategie di trading, avrebbe senso familiarizzare meglio con quei dettagli della programmazione che hanno un effetto sul tempo di ottimizzazione e test degli Expert Advisor. E poiché la maggior parte degli Expert Advisor contiene chiamate agli indicatori dell'utente nei loro codici, allora suppongo che dovremmo iniziare con loro.

In generale, non ci sono molti punti rilevanti che devono essere tenuti a mente quando si costruiscono gli indicatori, quindi è più logico rivedere semplicemente ciascuno di essi in ordine.

Ricalcolo su ciascun indicatore tick di quelli che non sono ancora stati calcolati, barre appena emerse negli indicatori classici

L'essenza stessa degli indicatori classici, come RSI, ADX, ATR, CCI, ecc., è che sulle barre chiuse, il calcolo di questi indicatori può essere fatto solo una volta, e dopo di che, i calcoli possono essere fatti solo sulle barre appena emergenti. L'unica eccezione è l'attuale barra aperta, su cui il calcolo viene eseguito ripetutamente ad ogni segno di spunta, fino a quando questa barra non viene chiusa.

Il modo più semplice per scoprire se è ragionevole calcolare gli indicatori su barre non calcolate - è confrontare nello strategy tester i risultati dell'esecuzione di tali indicatori (ottimizzati) con gli indicatori calcolati su tutte le barre tutto il tempo (non ottimizzati).

Questo viene fatto abbastanza facilmente. Viene creato un Expert Advisor con la funzione vuota di OnInit () e OnTick (). Tutto quello che devi fare è scrivere la chiamata nell'Expert Advisor della versione richiesta dell'indicatore ottimizzato o non ottimizzato e ammirare i risultati delle esecuzioni nel tester di tali expert in entrambi i casi. Ad esempio, prenderò l'indicatore SMA.mq5 dal mio articolo "User Indicators in MQL5 for Beginners" nel quale farò una sostituzione di linea.  

   if (prev_calculated == 0) // if this is the first start, then make a recalculation of all existing bars
    first = MAPeriod - 1 + begin;
   else first = prev_calculated - 1; // on all subsequent starts, make calculations only on newly appeared bars

su 

   first = MAPeriod -  1  + Begin;  / / On all ticks the bars are being recalculated 

Di conseguenza, ottengo una versione non ottimizzata del codice di programmazione (SMA !!!!!!. mq5), che, a differenza dell'originale, ricalcola tutti i suoi valori su ogni tick. Per essere precisi, le versioni del codice esperto in entrambi i casi sono praticamente identiche, quindi ne fornirò solo una (SMA_Test.mq5)

//+------------------------------------------------------------------+
//|                                                     SMA_Test.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
int Handle;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//----+
   //----+ Obtaining the indicator handle
   Handle = iCustom(Symbol(), 0, "SMA");
   if (Handle == INVALID_HANDLE)
     Print(" Not able to obtain the indicator handle SMA");
//----+
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----+
    //--- Release the indicator handle
    IndicatorRelease(Handle);
//----+   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//----+
   double SMA[1];
   //----+ Using the indicator handle, copy the values of the indicator 
                   // buffer in a specially prepared for this statistical array
   CopyBuffer(Handle, 0, 0, 1, SMA);
//----+
  }
//+------------------------------------------------------------------+

Possiamo iniziare i test ora. Va notato che in tutti i test di questo articolo, utilizzeremo una modalità di simulazione delle modifiche alla barra, che è il più vicino possibile alla realtà -"Ogni tick"!

Fig.1 Configurazioni di test dell'Expert Advisor SMA_Test 

Ecco il risultato dell'esecuzione di un indicatore ottimizzato nel tester:

Fig.2 Il risultato del test dell'Expert Advisor SMA_Test 

Il colore rosso indica il tempo in cui il test è stato superato. Non posso dire che questo sia troppo! Ma per il completamento del test dell'indicatore SMA !!!!!!. mq5 abbiamo dovuto aspettare molto tempo!

Fig.3 Il risultato del test dell'Expert Advisor SMA !!!!!! _Test 

Fondamentalmente, il tempo di elaborazione del test in questo caso differisce dal test precedente di oltre 500 volte. E questo nonostante il fatto che sia stato selezionato un periodo di test sufficientemente breve. Ma mentre durante i test dell'Expert Advisor possiamo sopportare costi computazionali così elevati, è meglio dimenticare l'ottimizzazione dei loro parametri!

E quindi, questa è la prova più eloquente del fatto che un codice scritto economicamente - non è solo un passatempo per i professionisti nel campo della programmazione, ma piuttosto un approccio abbastanza attuale alla scrittura del proprio codice.

Su Internet c'è un intero sito web Overclockers.ru dedicato all'accelerazione dei personal computer al fine di massimizzarne le prestazioni. Il mezzo di base di questa pratica è l'uso di componenti del computer molto più costosi per aumentare la velocità di clock della CPU e della memoria RAM.

Dopo aver fatto questo, per questa CPU overcloccata viene utilizzato un sistema di raffreddamento ad acqua più costoso, o addirittura l'immersione in un processore di azoto liquido. Il risultato di tali atti è un aumento doppio o addirittura triplicato delle prestazioni del PC.

Una scrittura competente ed economica del codice può spesso aiutarci a ottenere molto, applicando pochissimo sforzo. Naturalmente, questo metodo non è in grado di trasformare un Celleron300A in un Core 2 Quad Q6600, tuttavia ci consente di far funzionare un normale PC con un budget standard in un modo che ci si aspetterebbe solo da un computer di alto livello!

Ricalcolo ripetuto dell'attuale barra chiusa in alcuni indicatori, non del tutto classici

E sarebbe tutto semplicemente fantastico se questo metodo di ottimizzazione del codice del programma fosse adatto indistintamente a tutti gli indicatori! Ma, ahimè, non è così. Esiste un intero gruppo di indicatori, che con tale approccio iniziano normalmente a calcolare solo una volta, durante il caricamento dell'indicatore su dati storici già esistenti.

E su tutte le barre emerse dopo aver caricato l'indicatore, i suoi valori risultano essere completamente errati. Il motivo principale per cui ciò accade è che alcune variabili del codice dell'indicatore dipendono da tali indicatori, che avevano le stesse variabili dopo il calcolo dell'indicatore sulla barra precedente. Ufficialmente, apparirà come segue:

                                                                                                                                                                                                                           

SomeVariable(bar) = Function(SomeVariable(bar - 1))

 

dove:

  • SomeVariable() — il valore di alcune variabili per alcune barre;
  • barra - numero di barra, su cui viene effettuato il calcolo.

Per ovvie ragioni, nel codice effettivo, tali dipendenze hanno una forma funzionale meno chiara. Ma l'essenza di questo non cambia, ad esempio, per lo spostamento di T3 (indicatore non ottimizzato - T3 !!!!!!. mq5) la parte del codice che a noi interessa, assomiglia a questa

   e1 = w1 * series + w2 * e1;
   e2 = w1 * e1 + w2 * e2;
   e3 = w1 * e2 + w2 * e3;
   e4 = w1 * e3 + w2 * e4;
   e5 = w1 * e4 + w2 * e5;
   e6 = w1 * e5 + w2 * e6;
   //----  
   T3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;

Le variabili e1, e2, e3, e4, e5, e6 hanno una propria dipendenza funzionale, che comporta l'uso di questo codice per il calcolo di ogni nuova barra una sola volta! Ma la barra corrente, attraverso un calcolo simile, verrà saltata ripetutamente fino a quando non sarà chiusa.

E i valori di queste variabili sulla barra corrente cambieranno continuamente, anche se per la barra corrente, prima di cambiarla, dovrebbero rimanere come erano dopo il calcolo sulla barra precedente!

E quindi, i valori di queste variabili sulla barra precedente (rispetto alla barra corrente) dovrebbero essere salvati nelle variabili statiche e trasferirli per essere riutilizzati fino al successivo cambio della barra, su cui i penultimi valori delle variabili dovrebbero essere nuovamente salvati e1, e2, e3, e4, e5 , e6.

Il codice aggiuntivo, che esegue manipolazioni simili con i valori, è abbastanza semplice. Prima di tutto, è necessario dichiarare le variabili statiche locali per la memorizzazione dei valori all'interno della funzione OnCalculate ()

   //---- declare the static variables for storing the valid values of the coefficients
   static double e1_, e2_, e3_, e4_, e5_, e6_;

Dopodiché, facendo la memorizzazione dei valori delle variabili nel ciclo sulla barra corrente prima di qualsiasi calcolo, nel momento in cui il numero di barre appena emerse è maggiore di zero:

     //---- memorize the values of variables before the run on the current bar
     if (rates_total != prev_calculated && bar == rates_total - 1)
      {
       e1_ = e1;
       e2_ = e2;
       e3_ = e3;
       e4_ = e4;
       e5_ = e5;
       e6_ = e6;
      }

E prima del blocco dell'operatore del ciclo, ripristinare i valori delle variabili mediante trasformazione inversa:

   //---- restore the values of the variables
   e1 = e1_;
   e2 = e2_;
   e3 = e3_;
   e4 = e4_;
   e5 = e5_;
   e6 = e6_;

Abbastanza naturalmente, l'inizializzazione avviata dei coefficienti calcolati viene ora eseguita una sola volta, al primo inizio della funzione OnCalculate (), e ora l'inizializzazione viene eseguita non dei coefficienti stessi, ma delle corrispondenti variabili statiche.

//---- calculating the starting number first for the cycle of recalculation of bars
   if (prev_calculated == 0) // verification of the first start of the indicator calculation
    {
     first = begin; // the starting number for calculating all of the bars
     //---- the starting initialization of calculated coefficients
     e1_ = price[first];
     e2_ = price[first];
     e3_ = price[first];
     e4_ = price[first];
     e5_ = price[first];
     e6_ = price[first];
    }

Di conseguenza, l'indicatore finale T3.mq5 ha iniziato a fare calcoli nel modo più economico. Tutto sarebbe niente, ma non accade spesso che dipendenze funzionali simili possano essere così facilmente identificate. In questo caso, i valori di tutte le variabili dell'indicatore possono essere memorizzati in variabili statiche e ripristinati allo stesso modo.

E solo dopo possiamo iniziare a capire quali variabili hanno davvero bisogno di essere recuperate e per quali non esiste tale necessità. Per fare ciò dobbiamo appendere sul grafico le versioni non ottimizzate e ottimizzate dell'indicatore e controllare il loro lavoro, rimuovendo gradualmente dall'elenco di recupero una variabile alla volta. Alla fine, ci rimangono solo quelle variabili, che hanno davvero bisogno di essere recuperate.

Naturalmente, ho fornito questa versione della logica per lavorare con il codice di programma degli indicatori normali, in cui c'è un ricalcolo della barra corrente e delle barre appena emergenti. Per gli indicatori, che ridipingono e guardano al futuro, non saremo in grado di creare un metodo analogo, molto standard e semplice di ottimizzazione del codice, a causa dei tratti unici di questi indicatori. E la maggior parte degli scrittori esperti di Expert Advisor non vede alcuna reale necessità per questo. Pertanto, è qui che possiamo considerare completa l’analisi dettagliata di questi indicatori.

Caratteristiche delle chiamate per gli indicatori, che possono rendere il codice MQL5 eccessivamente lento 

Sembrerebbe che l’obiettivo sia stato raggiunto, abbiamo un indicatore ottimizzato che conta le barre nel modo più economico e ora è sufficiente scrivere alcune righe di codice e richiamare questo indicatore nel codice dell'Expert Advisor o dell'indicatore per ottenere i valori calcolati dal buffer dell'indicatore.

Ma non è così facile come potrebbe sembrare se affrontato in una questione formale, senza preoccuparsi di capire che tipo di operazioni ci sono dietro queste poche righe di codice.

La specifica per ottenere i valori dall'utente e gli indicatori tecnici, proprio come dalle time-serie in MQL5, è che questo viene fatto attraverso la copia dei dati negli array di variabili degli utenti. Ciò può portare ad un accumulo di dati completamente inutili per i conti correnti.

E’ il modo più semplice per verificare tutto questo su una specifica amministrazione dei dati da qualche indicatore tecnico. Ad esempio, possiamo prendere iAMA in movimento e costruire, sulla base di questo indicatore tecnico, un indicatore personalizzato AMkA.

Per copiare i dati utilizzeremo la prima versione della funzione chiamata CopyBuffer(), con una richiesta alla posizione di partenza e il numero di elementi richiesti per la copia. Nell'indicatore AMkA, l'incremento in movimento sulla barra corrente viene elaborato utilizzando un indicatore tecnico Standard Deviazione, quindi, per ottenere i segnali di trading, questo incremento viene confrontato con il valore totale di deviazione standard elaborato.

Pertanto, nel caso più semplice per l'implementazione dell'indicatore AMkA, è necessario innanzitutto creare un indicatore, in cui il buffer dell'indicatore conteneva il valore dell'incremento in movimento (indicatore dAMA). Ed in seguito, in un altro indicatore, utilizzando l’handle dell'indicatore con incrementi AMA, otteniamo il valore risultante elaborato dall'indicatore di Standard Deviation.

Il processo di creazione di indicatori analoghi è già stato esaminato in dettaglio in vari articoli su questi argomenti, quindi non mi fermerò su di esso e analizzerò solo i dettagli dell'accesso ai buffer degli indicatori dell'indicatore chiamato nel codice di un altro indicatore.

Nella vasta risorsa di Internet, notiamo già l'emergere di esempi MQL5, in cui i loro autori copiano letteralmente l'intero contenuto dei buffer degli indicatori negli array intermedi e dinamici. E successivamente, tutti i valori, uno per uno, vengono trasferiti nei buffer degli indicatori finali da questi array intermedi utilizzando l'operatore del ciclo.

Per risolvere il nostro problema, questo approccio sembra estremamente semplice

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   ArrayCopy(AMA_Buffer, Array, 0, 0, WHOLE_ARRAY);

(Indicatore dAMA !!!!!!. mq5) O come questo 

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   
   for(bar = 0; bar < rates_total; bar++)
    {
     AMA_Buffer[bar] = Array[bar];
     /*
      here is the code of indicator calculations
    */     
    }

Ma qual è il prezzo per una soluzione senza così troppe pretese? In primo luogo, sarebbe meglio acquisire un po 'di conoscenza su quale sarebbe la linea d'azione particolarmente razionale. Prima di tutto, non vi è davvero alcuna necessità giustificata di utilizzare l'array intermedio Array [], e i dati devono essere copiati direttamente nel buffer dell'indicatore AMA [].

In secondo luogo, ad ogni segno di spunta dell'indicatore è necessario copiare i valori solo in tre casi:

  • dalle barre appena emerse
  • da barre chiuse,
  • dagli attuali barre aperte.

I valori rimanenti nel buffer dell'indicatore esistono già e non ha senso riscriverli più volte. 

//--- calculation of the required number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification for the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars

//--- copy the reappearing data into the indicator buffer AMA_Buffer[]
   if (CopyBuffer(AMA_Handle, 0, 0, to_copy, AMA_Buffer) <= 0)
    return(0); 

 È abbastanza naturale che il codice finale in questo caso sarà un po 'più complesso (Indicatore dAMA.mq5), ma ora possiamo usare la metodologia da me proposta all'inizio di questo articolo, per condurre test in entrambi i casi e trarre le conclusioni appropriate. Questa volta aumentiamo il periodo di test a un anno.

Fig.4 Configurazioni di test dell'Expert Advisor dAMA_Test
 

Infine, dopo aver superato il test nel journal dello Strategy Tester, otteniamo il tempo necessario per testare l'Expert Advisor dAMA_Test

Fig.5 Il risultato del test dell'Expert Advisor dAMA_Test

Il tempo risultante per superare il test in 43.937 ms è all'interno di un intervallo ragionevole. Cosa, purtroppo, non si può dire dell'analogo tempo risultante del superamento del test con l'Expert Advisor dAMA !!!!!! _ Test

Fig.6 Il risultato del superamento del test dell’expert dAMA !!!!!! _Test
  

Il tempo di superamento del test è di 960 625 ms, che è venti volte più lungo rispetto al caso precedente. La conclusione sembra abbastanza ovvia. Il codice dovrebbe essere scritto nel modo più economico, in modo che non esegua calcoli inutili!
L'indicatore AMkA, costruito sui principi sopra descritti, non dimostra nulla di nuovo, quindi mi concentrerò in questo caso solo sui dettagli della copia dei dati.

//---- declaring local arrays
   double dAMA_Array[], StdDev_Array[];
//---- indexation of elements in arrays just like in time series
   ArraySetAsSeries(dAMA_Array, true);
   ArraySetAsSeries(StdDev_Array, true);

//--- calculation of the number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification of the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars
   
//--- copy the newly appeared data into the indicator buffer and local dynamic arrays
   if(CopyBuffer(dAMAHandle,   1, 0, to_copy, AMABuffer   ) <= 0) return(0);
   if(CopyBuffer(dAMAHandle,   0, 0, to_copy, dAMA_Array  ) <= 0) return(0);
   if(CopyBuffer(StdDevHandle, 0, 0, to_copy, StdDev_Array) <= 0) return(0);

E’ fatto in modo del tutto analogo, tranne il fatto che adesso i dati vengono copiati in un singolo buffer di indicatori e due array dinamici dichiarati localmente per calcoli intermedi. 

L'implementazione di tutti i calcoli degli indicatori all'interno dell'indicatore, come uno dei modi per l'ottimizzazione 

Tutto questo è molto interessante, ma una struttura così complessa con chiamate successive di utenti e indicatori tecnici sembra un po’ troppo sospetta. E in qualche modo dovrebbe essere misurato. Ma per fare questo, non sarebbe male avere il codice dell'indicatore AMkA, che si trova all'interno dell'indicatore dell'utente e non utilizzerebbe le chiamate per altri indicatori.

Per un programmatore che ha compreso a fondo il processo di scrittura degli indicatori su MQL5, questo problema non richiede molto sforzo. Per prima cosa viene scritto il codice dell'indicatore dell'utente AMA.mq5, quindi vengono aggiunti gli elementi necessari del codice per l'implementazione dell'indicatore AMkA_.mq5. Riceviamo un altro secondo, ampio ciclo di calcolo dell'indicatore in cui l'array dell'utente viene caricato con l'incremento dell'indicatore AMA,

   //---- the main cycle of calculating the AMkA indicator
   for(bar = first; bar < rates_total; bar++)
    {
     //---- load the increments of the AMA indicator into the array for intermediate calculations
     for(iii = 0; iii < ama_period; iii++)
      dAMA[iii] = AMABuffer[bar - iii - 0] - AMABuffer[bar - iii - 1]; 

quindi questo array viene utilizzato per eseguire operazioni analoghe al calcolo dell'indicatore tecnico StDev basato sui dati dell'indicatore dAMA.mq5.

     //---- find the simple average of increments of AMA
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += dAMA[iii];
     SMAdif = Sum / ama_period;
     
     //---- find the sum of the square differences of increments and the average
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += MathPow(dAMA[iii] - SMAdif, 2);
     
     //---- determine the final value of the meansquare deviation of StDev from the increment of AMA
     StDev = MathSqrt(Sum / ama_period);

Il resto del codice è assolutamente analogo al codice dell'indicatore AMkA.mq5 e non ci interessa particolarmente. Ora possiamo iniziare a testare gli indicatori AMkA_.mq5 e AMkA.mq5 con l'aiuto di Expert Advisor AMkA__Test.mq5 e AMkA_Test.mq5.

Non ci sono difficoltà con il test dell'indicatore AMkA_.mq5 e il tempo del test è ben all'interno del quadro accettabile

Fig.7 Il risultato del superamento del test utilizzando l'Expert Advisor AMkA__Test
 

Ma l'indicatore AMkA.mq5 era incredibilmente lento

Fig.8 Il risultato del superamento del test utilizzando Expert Advisor AMkA_Test
 

Il suo risultato si è rivelato essere ben sette volte peggiore di quello di suo "fratello". Quali altri commenti possono esserci? La conclusione è abbastanza ovvia: costruire costruzioni così complesse, costituite da diverse chiamate consecutive di indicatori l'una dall'altra non è molto prudente ed è adatta solo per test preliminari!

Ovviamente, questi risultati sono stati ottenuti su una versione di prova del terminale client, ed è difficile dire in questo momento come sarà in futuro. Ma per quanto riguarda il prossimo campionato di robot di trading, si può affermare abbastanza chiaramente che questo è un argomento rilevante ed efficiente.

Alcune caratteristiche di richiamare gli indicatori dagli Expert Advisor

Tutto ciò che è correlato all'ottimizzazione dell'accesso ai dati dell'utente e agli indicatori tecnici nel codice di programmazione degli indicatori, è ugualmente applicabile all'ottimizzazione dell'accesso ai dati dell'utente e agli indicatori tecnici nel codice di programma degli Expert Advisor. Oltre alle situazioni già presentate, il codice Expert Advisor presenta un altro fattore che può influenzare in modo significativo il test e l'ottimizzazione dei sistemi di trading.

Un gran numero di Expert Advisor di solito elabora i dati dell'indicatore solo al momento del cambio di barra, e per questo motivo, in questi Expert Advisor non è necessario utilizzare la funzione CopyBuffer () per ogni tick.

In questa situazione, è necessario che gli Expert Advisor ottengano i dati dai buffer degli indicatori solo durante un cambio di barra. Pertanto, le chiamate degli indicatori dovrebbero essere posizionate nel blocco dietro le parentesi, il cui accesso è consentito solo una volta per ogni modifica della barra se tutti i dati necessari dal buffer dell'indicatore vengono copiati con successo negli array per i calcoli intermedi.

La cosa migliore che funge da tale filtro è una funzione utente, che restituisce un'unità logica al momento in cui si è svolta una modifica della barra corrente. Il file IsNewBar.mqh contiene la mia versione abbastanza universale di questa funzione:

bool IsNewBar
            (
             int Number, // Number of call to the function IsNewBar in the program code of the expert Advisor
             string symbol, // The chart symbol on which the data calculation is done
             ENUM_TIMEFRAMES timeframe // Timeframe of the chart on which the data calculation is done
            )

Quando si utilizza questa funzione nel codice di Expert Advisor, potrebbe essere simile a questa:

    //---- declaration of a static variable - array for storing the values of the AMA indicator
    static double AMA_Array[3];

    //---- calling up the AMA indicator for copying its values into the AMA_Array array
    if (IsNewBar(0, Symbol(), 0))
     {
      CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array); 
     }

Ma in questo caso è molto più logico agire in maniera diversa. Il fatto è che quando si richiama il CopyBuffer (), i dati nella matrice AMA_Array [] potrebbero non essere copiati e, in tal caso, sarà necessario richiamare questa funzione per ogni tick fino a quando non esiste un'opzione efficace per copiare i dati che viene implementata da una certa complicazione del filtro

   //---- declaration of a static variable - array for storing values of the AMA indicator
   static double AMA_Array[3];
    
   //---- declaration of the static variable for storing the results of copying the data from the AMA indicator
   static bool Recount;

   //---- calling up the AMA indicator for copying its values into the AMA_Array array
   if (IsNewBar(0, Symbol(), 0) || Recount)
     {
      if (CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array) < 0)
       {
        Recount = true; // attempt of data copying was unsuccessful 
        return; // exit the function OnTick()
       }
      
      //---- All operations of copying from the indicator buffers are successfully completed
           // there is no need for returning to this block until the next bar change
      Recount = false;
     }

Ora che sono chiari i dettagli della chiamata razionale della funzione della copia dei valori degli indicatori nel codice dell'Expert Advisor, è possibile testare i vantaggi dell'applicazione della funzione IsNewBar () negli Expert Advisor.

Quindi abbiamo due opzioni di Expert Advisor disponibili per essere testati nello Strategy Tester, il primo - AMA_Test.ex5. Copia i dati dal buffer dell'indicatore ad ogni tick.

Fig.9 Il risultato del superamento del test con l'Expert Advisor AMA_Test

Il secondo - IsNewBar_AMA_Test.mq5 copia i dati solo durante un cambio di barra.

Fig.10 Il risultato del superamento del test con l'Expert Advisor IsNewBar_AMA_Test

Sì! I risultati dei test sono alquanto deludenti. Si scopre che chiamare una funzione IsNewBar () su ogni tick è molto più costoso che copiare i dati in tre celle dell'array dell'utente! 

Qui vorrei attirare la vostra attenzione su un'altra parte importante, ma apparentemente poco appariscente dell'indicatore. Il fatto è che se otteniamo l’handler dell'indicatore nella funzione OnInit (), indipendentemente dal fatto che copiamo o meno i dati da questo indicatore all'interno della funzione OnTick (), i suoi calcoli su barre ancora non calcolate e correnti, verranno comunque eseguiti su ciascun tick.

Quindi, se il nostro Expert Advisor non richiede i valori degli indicatori contati dall'attuale open bar, allora è meglio, in termini di risparmio di tempo, disabilitare il calcolo di questi valori. Questo viene eseguito abbastanza facilmente - ridurre di uno il bordo destro del ciclo principale di riconteggio delle barre nell'indicatore Prima delle modifiche, questo ciclo nell'indicatore AMA.mq5 assomigliava a questo

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total; bar++)

E dopo il cambiamento, sarà simile a questo  

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total - 1; bar++)

Indicator AMA_Ex.mq5. Ora puoi testare questo indicatore (Expert Advisor AMA_Ex_Test.mq5)

Fig.11 Il risultato del superamento del test con l'Expert Advisor AMA_Ex_Test 

Certo, questo risultato è migliore del test dell'indicatore AMA del 21%, il che non è poi così male, ma se ci pensiamo, questo risultato potrebbe essere migliore.

Conclusione

In definitiva, l'efficienza del codice di un programma è un parametro abbastanza oggettivo. L'efficienza può essere misurata, analizzata logicamente e, in determinate situazioni, significativamente aumentata. I metodi con cui questo viene fatto non sono molto complicati. Tutto ciò che serve è un po’ di pazienza e fare di più di quelle pratiche che influenzano direttamente la redditività del sistema di trading automatizzato.

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

File allegati |
mql5.zip (23.38 KB)
L'Uso di ORDER_MAGIC per il Trading con Diversi Expert Advisor su un Singolo Strumento L'Uso di ORDER_MAGIC per il Trading con Diversi Expert Advisor su un Singolo Strumento
Questo articolo considera le questioni della codifica delle informazioni, utilizzando l'identificazione magica, nonché la divisione, l'assemblaggio e la sincronizzazione del trading automatico di diversi Expert Advisor. Questo articolo sarà interessante per i principianti, così come per i trader più esperti, perché affronta la questione delle posizioni virtuali, che possono essere utili nell'implementazione di complessi sistemi di sincronizzazione di Expert Advisor e varie strategie.
Test delle Prestazioni del Calcolo delle Medie Mobili in MQL5 Test delle Prestazioni del Calcolo delle Medie Mobili in MQL5
Dal momento della creazione del primo indicatore della media mobile, sono comparsi numerosi indicatori. Molti di loro utilizzano metodi di smoothing simili, ma non sono state studiate le prestazioni di diversi algoritmi di medie mobili. In questo articolo, prenderemo in considerazione i possibili modi d’utilizzo delle medie mobili in MQL5 e confronteremo le loro prestazioni.
Una Libreria per la Costruzione di un Grafico tramite l'API Google Chart Una Libreria per la Costruzione di un Grafico tramite l'API Google Chart
La costruzione di vari tipi di diagrammi è una parte essenziale nelle analisi della situazione del mercato e del test di un sistema di trading. Spesso, per costruire un diagramma di bell'aspetto, è necessario organizzare l'output dei dati in un file, dopo di che viene utilizzato in applicazioni come MS Excel. Questo non è molto conveniente e ci priva della possibilità di aggiornare dinamicamente i dati. L'API di Google Charts ha fornito i mezzi per creare grafici in modalità online, inviando una richiesta speciale al server. In questo articolo cercheremo di automatizzare il processo di creazione di tale richiesta e ottenere un grafico dal server di Google.
Creazione di un Expert Advisor, che fa Trading su una Serie di Strumenti Creazione di un Expert Advisor, che fa Trading su una Serie di Strumenti
Il concetto di diversificazione delle attività sui mercati finanziari è tranquillo e ha sempre attratto i trader principianti. In questo articolo, l'autore propone un approccio estremamente semplice alla costruzione di un Expert Advisor multi-valuta, per una prima introduzione a questa direzione delle strategie di trading.