English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Passi su Nuovi Binari: Indicatori Personalizzati in MQL5

Passi su Nuovi Binari: Indicatori Personalizzati in MQL5

MetaTrader 5Esempi | 8 dicembre 2021, 16:57
200 0
TheXpert
TheXpert

Introduzione

Finalmente abbiamo l'opportunità di provare il nuovo trading terminal - MetaTrader 5. Senza dubbio, è degno di nota e ha molte nuove funzionalità rispetto al suo predecessore. I vantaggi importanti di questa piattaforma, tra gli altri, sono:

  • Linguaggio sostanzialmente modificato che consente ora di utilizzare la programmazione orientata agli oggetti, consentendo comunque di utilizzare i ricchi vantaggi della programmazione strutturale.
  • La velocità di esecuzione del codice che ora è molto più veloce rispetto a MetaTrader 4.
  • Indispensabile aumento delle possibilità di visualizzazione delle informazioni necessarie.

Non elencherò tutte le nuove possibilità e caratteristiche del nuovo terminale e del linguaggio. Sono numerose e alcune novità meritano la trattazione in un articolo a parte. Inoltre non c'è codice qui, scritto con programmazione orientata agli oggetti, è un argomento troppo serio per essere semplicemente menzionato in un contesto come i vantaggi aggiuntivi per gli sviluppatori.

In questo articolo, considereremo gli indicatori, la loro struttura, disegno, tipologie e loro dettagli di programmazione rispetto a MQL4.

Non c'è nulla di complicato in questo articolo; inoltre, qualsiasi cosa qui considerata può essere verificata direttamente nel terminale utilizzando i file allegati.

Spero che questo articolo sia utile sia per i principianti che per gli sviluppatori esperti, forse alcuni di loro qui troveranno qualcosa di nuovo.

 

La Struttura Generale

La struttura generale dell'indicatore rispetto a MQL4 non è cambiata.

Come prima, ci sono tre funzioni: per l'inizializzazione, per l'elaborazione dei dati e per la reinizializzazione dell'indicatore.

Come prima, molti parametri dell'indicatore possono essere definiti dalle proprietà (parola chiave #property). La maggior parte di essi è progettata specificamente per gli indicatori. Le proprietà e i parametri di input, come prima, sono definiti in un contesto globale.

Ad esempio, consideriamo l'implementazione della colorazione personalizzata per l'indicatore RSI. Ecco la versione troncata, quella completa si trova nel file Color_RSI.mq5.

Consideriamo le parti del codice.

//--- group of data properties
#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"
#property version   "1.00"
//--- description of the indicator should not exceed 511 symbols in total
//--- including newline symbols
#property description "      "
#property description "Demonstration of the indicator creation"
#property description "by the example of RSI coloring"

Le proprietà sopra specificate vengono visualizzate nel pannello delle informazioni dell'indicatore (il tab "Common" delle proprietà). Appare così:

//--- indicator properties
#property indicator_separate_window // the indicator will be displayed in a separate subwindow
#property indicator_buffers 2       // number of used buffers
#property indicator_plots   1       // number of displayed buffers
//--- plot 1
#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors
#property indicator_type1  DRAW_COLOR_LINE               // and the special color display type

Queste proprietà sono le proprietà dell'indicatore. La descrizione delle altre proprietà si trova nella guida.

//---- buffers
double Values[];                 // buffer of values
double ValuesPainting[];         // buffer of color indices
//--- indicator input parameters
input string             _1           = "RSI parameters";
input int                RSIPeriod    = 5;
input int                SmoothPeriod = 5;
input ENUM_APPLIED_PRICE AppliedPrice = PRICE_CLOSE;
input string             _2           = "Color settings";
input color              Down         = clrDarkSalmon;
input color              Up           = clrDeepSkyBlue;
//--- variable for storing the indicator handle
int RSIHandle;

Ecco i parametri di input dell'indicatore e le variabili globali (da non confondere con le variabili globali del client terminal). I parametri di input dell'indicatore sono specificati con l'identificatore di input.

Ora, è possibile impostare l'enumerazione per il parametro di input, a volte è utile per evitare la scelta errata dei parametri.

Ad esempio, il parametro AppliedPrice verrà visualizzato in un elenco a cascata con possibili valori validi.

Quindi, tutte le enumerazioni, inclusa quella definita dall'utente, verranno visualizzate nello stesso elenco a cascata. Ad esempio, il seguente parametro

//...
enum DayOfWeek
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

input DayOfWeek Day;

//...

verrà visualizzato come segue:

int OnInit()
  {
//--- bind indicator buffers
//--- Values serves as a display buffer
   SetIndexBuffer(0,Values,INDICATOR_DATA);
//--- ValuesPainting serves as the buffer for storing colors
   SetIndexBuffer(1,ValuesPainting,INDICATOR_COLOR_INDEX);
//--- Set the start of drawing Values buffer
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,RSIPeriod);
//--- Set the indicator name
   IndicatorSetString(INDICATOR_SHORTNAME,"Color RSI("+string(RSIPeriod)+")");
//--- Set an empty value for plots
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//--- Set buffer colors
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Down);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,Up);
//--- Receive indicator handles
   RSIHandle=iRSI(NULL,0,RSIPeriod,AppliedPrice);
//--- Set the sequence of buffer indexation
   ArraySetAsSeries(Values,true);
   ArraySetAsSeries(ValuesPainting,true);
//--- successful execution
   return(0);
  }

OnInit è la funzione di inizializzazione dell’indicatore. Qui configuriamo i buffer degli indicatori e le loro proprietà e definiamo le variabili dell'indicatore che non possono essere definite nelle proprietà o devono essere impostate dinamicamente. Inoltre, c'è un'inizializzazione iniziale dei dati, inclusa l'assegnazione degli handle necessari per gli indicatori.

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//--- number of bars for calculation
   int toCount=(int)MathMin(rates_total,rates_total-prev_calculated+1);
//--- try to copy iRSI indicator data
   if(CopyBuffer(RSIHandle,0,0,toCount,Values)==-1)
     {
      Print("Data copy error, №",GetLastError());
      //--- return command for recalculation of the indicator values
      return(0);
     }
//--- coloring. Yer, now it has become that easy
   for(int i=toCount-2;i>=0;--i)
     {
      //--- coloring the first line
      if(Values[i+1]!=EMPTY_VALUE && Values[i]>Values[i+1])
         ValuesPainting[i]=1;
      else
         ValuesPainting[i]=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

OnCalculate è la funzione per il calcolo dei dati. Questa funzione può essere di due tipi. Ecco la sua forma standard. I dettagli sono riportati di seguito.

Funzione:

//--- this function usage in not obligatory
/*
void OnDeinit()
{

}
*/

OnDeinit è la funzione di reinizializzazione dell'indicatore. Spesso è necessario rilasciare le risorse, ad esempio gli handle di file. Per gli altri casi, questa funzione non è necessaria.

 

Due Concetti degli Indicatori

Il primo è standard, lo stesso a cui ci siamo abituati in MQL4, ma in una forma leggermente modificata. La funzione OnCalculate viene utilizzata al posto della funzione Start.

Per il modulo standard appare come segue:

int OnCalculate(const int rates_total,      // Arrays size
                const int prev_calculated,  // Bars processed on the previous call
                const datetime& time[],     // Data for the current chart and timeframe...
                const double& open[],
                const double& high[],       
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
{
   return rates_total;
}

Per ridurre la quantità di codice destinato alla copia dei dati, i dati del grafico vengono trasmessi direttamente come array ai parametri della funzione. Inoltre, il numero di barre disponibili viene trasmesso come primo parametro della funzione, il numero di barre elaborare dopo l'ultima chiamata o 0 (zero) viene trasmesso come secondo parametro.

Il valore 0 (zero) può essere trasmesso alla prima chiamata dell'indicatore, nonché durante il caricamento di dati nuovi o mancanti. Questo parametro è un sostituto (alternativa o equivalente - dipende da te) dell’ IndicatorCounted() che è scomodo per molti sviluppatori.

Il secondo concetto è la sostituzione e l'espansione delle funzioni simili a i<…>OnArray di MQL4. C'è un indicatore di questo tipo negli esempi di terminale - Media Mobile Personalizzata. Questo tipo di indicatori è destinato all'elaborazione dei dati in base alla scelta dell'utente, inclusi gli indicatori personalizzati.

La funzione per l'elaborazione dei dati per gli indicatori di questo tipo si presenta così:

int OnCalculate (const int rates_total,      // the size of the price[] array
                 const int prev_calculated,  // bars calculated in the previous call
                 const int begin,            // where notional data start from
                 const double& price[]       // data array for calculation
                 )
  {
   return rates_total;
  }

L’ ultimo parametro della funzione sono i dati selezionati dall'utente per l’elaborazione. Se vuoi applicare un indicatore con molti buffer, il primo buffer indicatore verrà trasmesso per l'elaborazione dei dati.

I Dati del Primo Indicatore stanno a significare che l'indicatore verrà applicato all'indicatore collegato per primo alla finestra selezionata del grafico.

I Dati dell'Indicatore Precedente indicano che quell'indicatore verrà applicato all'ultimo indicatore collegato alla finestra selezionata del grafico.

Questi indicatori possono essere utilizzati per assemblare l'intero stack. Ad esempio, utilizzando l'indicatore della Media Mobile Personalizzata è possibile ottenere il triplo smoothing. imponendo il primo indicatore ai dati necessari, il secondo al primo e il terzo al secondo:

Ci sono molti indicatori standard che attuano questo particolare concetto. Pertanto, quando viene visualizzato il prompt per il parametro della funzioneapplied_price_or_handle:

indica che l'indicatore è implementato nel modo in cui può essere calcolato sui dati dell'utente - l'handle di questi dati deve essere trasmesso come parametro applied_price_or_handle.

Allo stesso modo, è possibile organizzare l'elaborazione dei dati direttamente nel codice dell’indicatore:

  {
   //...
   RSIHandle = iRSI(NULL, 0, RSIPeriod, AppliedPrice);
   SmoothHandle = iMA(NULL, 0, SmoothPeriod, 0, MODE_EMA, RSIHandle);
   //...
  }

C'è un'altra nuova applicazione di questo concetto: la capacità di scrivere indicatori di servizio universale. Un esempio di tale indicatore è allegato nel file Direction_Brush.mq5.

I risultati vengono presentati nel grafico sopra. La colorazione della direzione in questo caso è separata come entità indipendente e implementata nell'altro indicatore.

Certamente, la loro universalità è limitata, poiché sono applicabili solo per il buffer zero dell'indicatore. Tuttavia, penso che indicatori di questo tipo potrebbero essere utili.

D’altro canto, quando scrivi un indicatore personalizzato, dovresti tenerne conto, perché la principale elaborazione delle informazioni nel buffer zero consentirà di evitare l'implementazione di una macchina multifunzionale in un indicatore. Molte delle altre azioni possono essere eseguite ed eseguite negli indicatori di servizio esterno. Tutto quello che dovrai fare è allegare il servizio degli indicatori con la funzionalità richiesta alla tua personalizzazione.

Il campo di applicazione non è così ristretto come potrebbe sembrare a prima vista:

  • colorare le caratteristiche dell'indicatore (picchi, direzioni, livelli, segmenti, ecc.), compresa la visualizzazione del tono;
  • segnali diversi in condizioni diverse;
  • raccolta e visualizzazione di statistiche - ad esempio, la distribuzione dei dati;
  • costruzione di indicatori universali che possono essere calcolati per un buffer, ad esempio medie mobili, zigzag.

Le caratteristiche sopra menzionate non sono l'elenco esaustivo dell'implementazione del concetto. Penso che molte altre implementazioni efficaci verranno trovate in seguito.

 

Accesso ai Dati

I principi di accesso ai dati sono cambiati in MQL5. Adesso, il lavoro avviene direttamente negli array e, di conseguenza, la velocità di calcolo è aumentato in modo significativo. Ora non è necessario creare un array e chiamare la funzione iCustom per ogni valore. Invece è possibile ottenere il conteggio dei dati necessario chiamando una funzione e, quindi, utilizzare direttamente i dati richiesti copiati in un array locale specificato.

La copia dei dati viene implementata utilizzando la funzione di sistema CopyBuffer. Puoi trovare la descrizione della funzione nella guida.

Il numero massimo di dati da copiare per l'indicatore e gli array statici (con una dimensione predefinita), viene determinato dalla dimensione dell'array. La dimensione dell'array dinamico può essere modificato se il numero di dati copiati supera la sua dimensione.

Sono inoltre presenti funzioni speciali per l'accesso ai dati storici:

Funzione Descrizione
CopyBuffer Ottiene dati di un buffer specificato di un certo indicatore nella quantità necessaria.
CopyRates Ottiene i dati storici della struttura MqlRates di un determinato simbolo-periodo nella quantità specificata nell'array rates_array.
CopyTime La funzione ottiene in time_array i dati storici dei prezzi di apertura delle barre per la coppia simbolo-periodo selezionata nella quantità specificata.
CopyOpen La funzione ottiene in open_array i dati storici dei prezzi della barra open per la coppia simbolo-periodo selezionata nella quantità specificata.
CopyHigh La funzione ottiene in high_array i dati storici dei prezzi più alti della barra per la coppia simbolo-periodo selezionata nella quantità specificata.
CopyLow La funzione ottiene in low_array i dati storici dei prezzi più bassi della barra per la coppia simbolo-periodo selezionati nella quantità specificata.
CopyClose La funzione ottiene in close_array i dati storici dei prezzi della barra close per la coppia simbolo-periodo selezionata nella quantità specificata.
CopyTickVolume La funzione ottiene in volume_array i dati storici dei volumi tick per la coppia simbolo-periodo selezionata nella quantità specificata.
CopyRealVolume La funzione ottiene in volume_array i dati storici dei volumi trade per la coppia simbolo-periodo selezionata nella quantità specificata.
CopySpread La funzione ottiene in spread_array i dati storici dei valori spread per la coppia simbolo-periodo selezionata nella quantità specificata.

Ulteriori dettagli sono disponibili nella guida.

Questi dati vengono trasmessi solo in una forma dell'indicatore, per l'altra dovrebbero ottenere la propria.

Poiché il tipo di array dei dati storici non è necessariamente doppio, si consiglia di utilizzare solo buffer dinamici non indicatori per la loro archiviazione.

Inoltre, c'è un altro dettaglio non documentato: se il conteggio dei dati copiati è uguale a 0 (zero), la funzione CopyBuffer genererà un errore con il codice №4003, quindi il conteggio dei dati da copiare non deve essere inferiore a 1 (uno) elemento.

 

Buffer Indicatore

Il conteggio dei buffer non è limitato.

Adesso, non devi pensare a come inserire correttamente le informazioni, come eseguire i calcoli intermedi in modo efficiente, lavorando alla creazione dell'indicatore cluster.

Ma non dobbiamo dimenticare che l'archiviazione dei buffer richiede memoria. Pertanto, se specifichi una profondità della cronologia del terminale di circa 1.000.000 di barre e colleghi l'indicatore del cluster "thick" al grafico dei minuti, non sorprendersi se il terminale consuma Gb di memoria.

Anche l'essenza del buffer ha subito alcune modifiche. La quantità dei buffer utilizzati è specificata nella proprietà in.

#property indicator_buffers 2       // buffers used

Questo valore dovrebbe corrispondere al conteggio totale dei buffer.

Il numero di buffer visualizzati è definito dalla proprietà:

#property indicator_plots 1         // buffers displeyed

Ecco qualche dettaglio. La maggior parte degli stili di disegno richiede solo un buffer INDICATOR_DATA per il disegno. Tuttavia, ci sono alcuni stili che richiedono diversi buffer indicatori per il disegno.

Intendiamo i seguenti stili di disegno:

  • DRAW_HISTOGRAM2 - richiede due buffer indicatori (HistogramSample.mq5)

  • DRAW_FILLING - richiede due buffer indicatori (CrossMa.mq5)

  • DRAW_CANDLES - richiede quattro buffer indicatori (CandleSample.mq5)

  • DRAW_BARS - richiede quattro buffer indicatori (BarsSample.mq5)

Tutti i tipi di cui sopra tranne lo stile DRAW_FILLING (non può essere colorato), hanno analoghi colorati.

Tutti i buffer indicatori sono ora suddivisi in 3 tipi:

  • INDICATOR_DATA - buffer, i cui dati vengono visualizzati sul grafico. Questi buffer sono pensati per disegnare e per lavorare con iCustom. Dovrebbero essere registrati prima. In caso di loro ordine arbitrario (sbagliato), il codice verrà compilato con successo e sarà disegnato quando applicato a un grafico, tuttavia, molto probabilmente, in modo errato.

  • INDICATOR_COLOR_INDEX - buffer per l'archiviazione dei colori. Sono necessari per memorizzare gli indici del buffer di colore di tipo INDICATOR_DATA, aventi uno dei tipi di colore speciali (#property Indicator_typeN). Tale buffer (che chiamiamo il suo buffer di colore) dovrebbe essere registrato subito dopo il buffer principale che lo utilizza.

  • INDICATOR_CALCULATIONS - buffer di questo tipo sono destinati alla memorizzazione dei risultati dei calcoli ausiliari. Non vengono visualizzati sul grafico.

int OnInit()
{
   // ...
   SetIndexBuffer(0, V2, INDICATOR_DATA);
   SetIndexBuffer(1, V2C,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, V4, INDICATOR_DATA);
   SetIndexBuffer(3, V4C,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4, V1, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, V3, INDICATOR_CALCULATIONS);

   // ...
   return 0;
}

Ci sono anche alcune funzionalità quando si fa riferimento agli indicatori tramite iCustom.

  • I buffer per il disegno (quelli che vengono visualizzati sul grafico) sono disponibili per la lettura. Il numero del buffer (indice) deve corrispondere a quello per cui il buffer è registrato.
  • I buffer per l'archiviazione dei colori possono essere disponibili per la lettura, ma non sempre. Ad esempio, nel codice sopra il buffer V2C può leggere e ottenere i valori necessari, ma il buffer V4C non è disponibile.
  • I buffer per i calcoli intermedi non sono disponibili, come invece accadeva in MQL4. Se vuoi avere accesso garantito al buffer di dati esterno, dichiararlo come INDICATOR_DATA.

In caso di richiesta al buffer inaccessibile, verrà generato l'errore 4806 ("Il dato richiesto non è stato trovato").

Consideriamo in dettaglio i buffer di colore.

In MQL4, per ogni colore era necessario creare un buffer separato, ma ora utilizzando gli stili di colore è possibile specificare fino a 63 colori per un buffer. In qualche caso, consentirà di ottimizzare il numero dei buffer utilizzati e, quindi, di risparmiare l'utilizzo della memoria. Apre anche nuove possibilità per scrivere indicatori, in particolare, l'uso della visualizzazione del tono.

Inoltre, questa innovazione, in alcuni casi, semplifica notevolmente la logica dell'applicazione di più colori rispetto a MQL4. L’ esempio più ovvio: separazione delle tendenze in base ai colori. In MQL4 per il caso di implementazione molto economico (dai casi corretti) ha richiesto tre (3) buffer e una programmazione non banale.

Ora è più facile che mai. Ecco gli esempi di codice, l'implementazione completa si trova nel file Color_RSI.mq5.

#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors
#property indicator_type1  DRAW_COLOR_LINE               // and the special color display type
//---- buffers
double Values[];                 // buffer of values
double ValuesPainting[];         // buffer of color indices
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- bind indicator buffers
//--- Values serves as a display buffer
   SetIndexBuffer(0,Values,INDICATOR_DATA);
//--- ValuesPainting serves as the buffer for storing colors
   SetIndexBuffer(1,ValuesPainting,INDICATOR_COLOR_INDEX);
//...
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(/*...*/)
  {
//--- number of bars for calculation
   int toCount=(int)MathMin(rates_total,rates_total-prev_calculated+1);
//--- try to copy iRSI indicator data
   if(CopyBuffer(RSIHandle,0,0,toCount,Values)==-1)
     {
      Print("Data copy error, №",GetLastError());
      //--- return command for recalculation of the indicator values
      return(0);
     }
//--- coloring. Yer, now it has become that easy
   for(int i=toCount-2;i>=0;--i)
     {
      //--- coloring the first line
      if(Values[i+1]!=EMPTY_VALUE && Values[i]>Values[i+1])
         ValuesPainting[i]=1;
      else
         ValuesPainting[i]=0;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Ancora un po' di codice e otteniamo quanto segue:

Dovresti notare alcuni dettagli quando usi i tipi di colore per il disegno.

Per i buffer di colore, quando si utilizza uno schema di definizione del colore dinamico, il conteggio dei colori massimo è limitato dal conteggio dei colori definito nella proprietà Indicator_colorN. Ad esempio,

#property indicator_color1 clrDarkSalmon, clrDeepSkyBlue // use 2 colors

la combinazione di colori del buffer conterrà un massimo di due colori, anche se configurerai dinamicamente un numero maggiore di colori (usando PlotIndexSetInteger).

Perciò, il numero richiesto di colori deve essere scritto in una riga - riga di definizione della proprietà. Il colore può essere modificato dinamicamente. Il colore più corto che ho trovato - "Rosso". Tuttavia, puoi sempre fare quanto segue:

Invece di

#property indicator_color1  clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, clrRed, //…

potresti scrivere:

#define C clrRed
#property indicator_color1  C, C, C, C, C, C, C, C, C, C, C, C, C, C, //…

Il numero massimo di colori per un buffer è 63. Quando il numero di colore è maggiore del buffer massimo (definito dalla proprietà Indicator_colorN) non verrà visualizzato.

Ecco un esempio di visualizzazione dei toni, utilizzando il numero massimo di colori:

In generale, le opportunità di disegno sono notevolmente aumentate e questa è una cosa fantastica.

 

Array

Durante il riferimento diretto ai dati dell'array tramite gli indici, è necessario indicare il tipo di ordinamento dei dati - proprietà AsSeries. Non può essere definito per alcuni tipi di array.

Questo flag non può essere impostato per gli array multidimensionali e statici. Per i tipi di array che vengono trasmessi alla funzione OnCalculate, è possibile impostare tale flag.

La copia dei dati tramite la funzione CopyBuffer non dipende dalla proprietà AsSeries, ma la sua implementazione è diversa per i diversi buffer.

Per i buffer indicatori è necessario copiare l'intera profondità della cronologia disponibile. Ricordalo bene.

Per gli array dinamici e statici (con una dimensione predefinita) la copia dei dati viene eseguita dal presente al passato.

La funzione CopyBuffer cambia la dimensione dei buffer per i buffer dinamici (eccetto quelli dell'indicatore) per la dimensione necessaria.

Non è consigliabile utilizzare gli array statici per la copia dei dati.

In generale, ti consiglio di controllare sempre come copi i dati e come li gestisci. Il modo più semplice e sicuro è:

  • impostare la proprietà AsSeries per tutti i buffer utilizzati per l'archiviazione dei dati storici.
  • tenere conto delle strutture dei buffer per i diversi buffer.
  • controllare sempre il valore della variabile _LastError (ultimo codice errore).

Inoltre, ti consiglio vivamente di studiare la guida della funzione CopyBuffer e per tutte le funzioni legate alla proprietà AsSeries.

 

IndicatorCounted

Ora, i dibattiti sulla necessità della funzione IndicatorCounted cadranno nell’ oblio, perché questo valore è definito direttamente da noi come valore di ritorno della precedente chiamata di funzione.

int OnCalculate(const int rates_total,      // array size
                const int prev_calculated,  // bars processed after last call
                //...)
  {
   return rates_total;
  }

Più spesso è sufficiente restituire il valore rates_total che contiene il conteggio delle barre della chiamata di funzione corrente.

Tuttavia, se i dati del prezzo sono stati modificati dall'ultima chiamata OnCalculate() (ad esempio, sono stati caricati i dati della cronologia o sono stati riempiti gli spazi vuoti dei dati della cronologia), allora il valore del parametro di input prev_calculated

sarà impostato su 0 (zero) dal client terminal.

Inoltre, se la funzione OnCalculate restituisce zero, allora i valori dell'indicatore non sono mostrati nella DataWindow del client terminal. Pertanto, se vuoi vedere l'indicatore ed eseguire il ricalcolo completo durante il processo di caricamento della cronologia o dopo il fallimento della connessione, restituisce 1 invece di 0.

L'altra caratteristica utile che è stata aggiunta è determinare quante barre sono state calcolate per l’ indicatore È più utile per gli Expert Advisor che eseguono calcoli su dati di grandi dimensioni. La funzione è BarsCalculated, i suoi dettagli possono essere trovati nella guida.

Questa funzione ha un'altra applicazione utile. Se l'indicatore non è stato caricato, il suo caricamento potrebbe richiedere del tempo: il tempo tra la creazione dell'handle dell'indicatore e il suo utilizzo per i calcoli.

Questo tempo è necessario per l'inizializzazione e il suo calcolo preliminare iniziale. Dipende dalla velocità di calcolo e dai dettagli dell'indicatore.

Durante questo tempo, la chiamata per la funzione CopyBuffer genera l'errore 4806 - "I dati richiesti non sono stati trovati".

La funzione BarsCalculated può essere utilizzata per determinare la disponibilità dei dati dell'indicatore per la copia:

//--- number of bars for calculation
   int toCount=rates_total-(int)MathMax(prev_calculated-1,0);
//--- try to copy iWPR indicator data
   int copied=CopyBuffer(WPRHandle,0,0,toCount,Values);
   int err=GetLastError();
//--- check coying result
   if(copied==-1)
     {
      //--- if error number is 4806, the data simply have not been uploaded yet
      if(err==4806)
        {
         //--- wait till the data is uploaded
         for(int i=0;i<1000;++i)
            if(BarsCalculated(WPRHandle)>0)
               break;
         //--- try to copy iWPR indicator data again
         copied=CopyBuffer(WPRHandle,0,0,rates_total,Values);
         err=GetLastError();
        }
     }
//--- check coying result
   if(copied==-1)
     {
      Print("Error when trying to get WPR values, last error is ",err," bars ",rates_total);
      return(0);
     }
//...

 

Riepilogo

In conclusione, vorrei dire che in questo articolo sono stati considerati solo alcuni dettagli. Tuttavia, spero che gli aspetti fondamentali siano presentati qui.

Sarebbe bello se questo articolo fosse un utile riferimento sull'argomento, dove tu puoi sempre cercare e trovare informazioni sui dettagli.

Se hai trovato degli errori in questo articolo o hai scoperto qualcosa di importante, ti prego di informarmi e cercherò di correggerlo e migliorare l'articolo il prima possibile.

Sto progettando di delineare i recenti cambiamenti ma, a parte questo, spero che alcune delle informazioni utili appaiano nei commenti.

Questo è il motivo per leggerli attentamente.

 

Appendice

  • Color.mqh - include file, copia questo file nella cartella MQL5/Include. Questo file è necessario per l'indicatore Toned_WPR.
  • Color.mq5 - library, copia questo file nella cartella MQL5/Libraries. Questo file è necessario per l'indicatore Toned_WPR.

Tutti i file sopra sono degli indicatori.

 

Ringraziamenti

Ancora una volta, vorrei ringraziare il Sig. Victor Rustamov (granit77) per la lettura del manoscritto, le discussioni utili e i consigli utili.


Tradotto dall’inglese da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/en/articles/5

File allegati |
crossma.mq5 (2.47 KB)
candlesample.mq5 (2.31 KB)
barssample.mq5 (2.3 KB)
color.mq5 (4.28 KB)
color.mqh (0.99 KB)
toned_wpr.mq5 (4.65 KB)
color_rsi.mq5 (5.57 KB)
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.
Arriva il Nuovo MetaTrader 5 e MQL5 Arriva il Nuovo MetaTrader 5 e MQL5
Questa è solo una panoramica di MetaTrader 5. Non posso descrivere tutte le nuove funzionalità del sistema per un periodo di tempo così breve: i test sono iniziati il 09.09.2009. Questa è una data simbolica e sono sicuro che sarà un numero fortunato. Sono passati alcuni giorni da quando ho ricevuto la versione beta del terminale MetaTrader 5 e MQL5. Non sono riuscito a provare tutte le sue funzionalità, ma sono già sorpreso.
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.
Utilizza i canali MQL5.community e le chat di gruppo Utilizza i canali MQL5.community e le chat di gruppo
Il sito web MQL5.com riunisce trader di tutto il mondo. Gli utenti pubblicano articoli, condividono codici gratuiti, vendono prodotti nel Market, offrono servizi da freelance e copiano segnali di trading. Puoi comunicare con loro sul Forum, nelle chat dei trader e nei canali MetaTrader.