![Come Scrivere un Indicatore sulla Base di un Altro Indicatore](https://c.mql5.com/i/articles/overlay.png)
Come Scrivere un Indicatore sulla Base di un Altro Indicatore
Introduzione
In MQL5,oltre a creare un nuovo indicatore personalizzato ex novo come descritto nell’articolo "MQL5: Crea il Tuo Indicatore puoi scriverne uno sulla base di un altro indicatore, integrato nel client terminal o uno personalizzato. Ci sono due modi: il primo è migliorare un indicatore, aggiungere nuovi calcoli e plot (questa variante si applica solo agli indicatori personalizzati che hanno codice open source). Il secondo modo è utilizzare un indicatore integrato nel terminale o utilizzare un indicatore personalizzato esistente tramite le funzioni iCustom() o IndicatorCreate().
Primo Modo Aggiunta di un Plot.
Consideriamo questo modo di creare un indicatore in dettaglio sull'esempio di miglioramento dell’ True_Strength_Index_ver3 dall'articolo "Applicazione di Un Indicatore ad un Altro". Aggiungiamo una linea di segnale con la possibilità di scegliere il tipo e il periodo di adattamento all'indicatore. L'intero processo è composto da 8 fasi.
1. Creazione di una Copia del File
Aprire l'indicatore True_Strength_Index_ver3 in MetaEditor e salvarlo con un nuovo nome, ad esempio TSI. Il nuovo file deve essere salvato nella directory MQL5/Indicators della cartella root del terminale.
2. Modifica delle Proprietà dell'Indicatore
Cerca le proprietà indicator_buffers e indicator_plots nel codice dell'indicatore. La proprietà indicator_buffers determina il numero totale di buffer indicatori utilizzati nell'indicatore, la proprietà indicator_plots - numero di buffer visualizzati su un grafico. Attualmente, nell'indicatore vengono utilizzati otto buffer; uno di questi viene mostrato su un grafico. Dobbiamo aggiungere un altro buffer che dovrebbe essere visualizzato su un grafico. Aumenta di uno i valori indicator_buffers e indicator_plots.
#property indicator_buffers 8 #property indicator_plots 2
3. Determinare le Proprietà di Visualizzazione del Nuovo Buffer
Impostare le proprietà di visualizzazione del nuovo buffer. Utilizzare il codice già preparato da questo indicatore. Utilizzando il mouse, copia tutto il codice che determina le proprietà di visualizzazione della prima riga dell'indicatore.
//---- plot TSI #property indicator_label1 "TSI" #property indicator_type1 DRAW_LINE #property indicator_color1 Blue #property indicator_style1 STYLE_SOLID #property indicator_width1 1
Inseriscilo sotto le proprietà della prima riga e modificalo.
//---- plot TSI Signal #property indicator_label2 "TSISignal" // Line name that is displayed in a pop up help when the mouse cursor is put over the line #property indicator_type2 DRAW_LINE // Type of buffer #property indicator_color2 Red // Color of the line #property indicator_style2 STYLE_SOLID // Style #property indicator_width2 1 // Thickness of the line
Innanzitutto, modifica il numero di proprietà da 1 a 2,in quanto è la proprietà per il secondo buffer. Modifica la proprietà indicator_label2 in TSISignal - è il nome della riga che viene mostrato in una guida pop-up quando il cursore del mouse viene posizionato sopra la riga come quello visualizzato nella finestra dei dati. La proprietà indicator_type2 non deve essere modificata, mentre il buffer dovrebbe essere visualizzato come una riga. Modifica la proprietà indicator_color2 in Red - la nuova riga sarà di colore rosso. La proprietà indicator_style2 rimane la stessa: la riga del segnale è solida come quella principale. Anche la proprietà indicator_width2 dovrebbe rimanere la stessa: la nuova riga avrà uno spessore di 1 pixel.
4. Dichiarazione delle Variabili Esterne
Le variabili esterne che possono essere modificate attraverso l'indicatore (linee che iniziano con la parola "input") si trovano sotto le proprietà delle righe nel codice. Anche la linea del segnale dovrebbe avere i suoi parametri: periodo e tipo di adattamento.
Dichiarare una variabile esterna del tipo int con valore 5 e denominata "sp" (smoothing period) e una variabile con il tipo di ENUM_MA_METHOD denominato "sm" (smoothing method) che ha valore MODE_EMA (la linea del segnale avrà il periodo di smoothing 5 e il tipo esponenziale di smoothing di default). Ora, la sezione del codice che contiene le variabili esterne è simile alla seguente:
input int r=25; input int s=13; input int sp=5; input ENUM_MA_METHOD sm=MODE_EMA;
5. Dichiarare un Array per un Nuovo Buffer
Dichiariamo un array che verrà utilizzato dal buffer dell'indicatore. Cerca la funzione OnInit() nel codice e trova dove sono collocare le chiamate della funzione SetIndexBuffer() per guidarti attraverso array di buffer di indicatori già esistenti nell'indicatore. Nell'indicatore True_Strength_Index_ver3 tali matrici sono TSIBuffer, MTMBuffer, AbsMTMBuffer, EMA_MTMBuffer, EMA2_MTMBuffer, EMA_AbsMTMBuffer EMA2_AbsMTMBuffer.
La funzione SetIndexBuffer() dell'array TSIBuffer viene chiamata con il parametro INDICATOR_DATA: significa che il buffer viene visualizzato su un grafico. Tutti gli altri array vengono chiamati con il parametro INDICATOR_CALCULATIONS. Ciò significa che gli array sono ausiliari e vengono utilizzati per calcoli intermedi.
Il nuovo buffer dovrebbe essere visualizzato su un grafico, quindi dichiariamolo dopo la dichiarazione dell'array TSIBuffer per mantenere l'ordine logico e per un più facile orientamento nel codice in caso di ulteriore miglioramento dell'indicatore.
Pertanto, in primo luogo, dichiariamo due array per i buffer visualizzati in un grafico e, successivamente, gli array per i buffer utilizzati per i calcoli intermedi.
//--- indicator buffers double TSIBuffer[]; double TSISigBuffer[]; // Array for new buffer of the signal line double MTMBuffer[]; double AbsMTMBuffer[]; double EMA_MTMBuffer[]; double EMA2_MTMBuffer[]; double EMA_AbsMTMBuffer[]; double EMA2_AbsMTMBuffer[];
6. Associazione di un Array ad un Buffer
Questa è una fase piuttosto importante che richiede una maggiore attenzione e cura - associazione di un array ad un buffer di indicatori. L'associazione viene eseguita utilizzando la funzione SetIndexBuffer(). Il primo parametro nella chiamata di funzione è l'indice di array. Il secondo è il nome dell'array, mentre il terzo è l’ identificatore che indica lo scopo del buffer. I buffer si trovano nel tab "Colors" della finestra delle proprietà dell'indicatore in base all'indice (il primo parametro), nello stesso ordine in cui vengono disegnati su un grafico, il primo è il buffer 0, poi il buffer 1 su di esso, ecc.
Non è necessario che la funzione SetIndexBuffer() venga chiamata in sequenza per i buffer con indici 0, 1, 2...; tuttavia, manteniamo l'ordine delle chiamate delle funzioni SetIndexBuffer(). Eseguire la chiamata dell'array TSISigBuffer dopo aver chiamato la funzione per l'array TSIBuffer. Il buffer della linea principale (l'array TSIBuffer) ha l'indice 0. Ciò significa che il buffer successivo (l'array TSISigBuffer) dovrebbe avere indice 1.
Il terzo parametro di chiamata della funzione SetIndexBuffer() per la matrice TSISigBuffer è la costante INDICATOR_DATA (il buffer viene visualizzato su un grafico).
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);
Re-indicizza il resto dei buffer per la funzione SetIndexBuffer() da chiamare con un valore aumentato sequenzialmente del primo parametro.
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA); SetIndexBuffer(2,MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(4,EMA_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(5,EMA2_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(6,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(7,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);
Per questa specifica situazione, si consiglia di mantenere la sequenza di chiamata della funzione SetIndexBufer() in base agli indici crescenti. Pertanto, in caso di ulteriori miglioramenti non occorrerà molta attenzione o molto lavoro.
Ora abbiamo otto buffer, due dei quali vengono visualizzati su un grafico. Assicurati che gli stessi valori siano specificati nelle proprietà degli indicatori indicator_buffers e indicator_plots (fase 2).
7. Calcolo dei Valori della Linea di Segnale
La linea del segnale rappresenta una media mobile disegnata sui dati della linea principale dell'indicatore. Non abbiamo bisogno di eseguire dei calcoli per questo; il client terminal delivery include una libreria per il calcolo delle medie mobili su un array di informazioni (file MovingAverages.mqh). A proposito, è già incluso nel codice dell'indicatore (riga 14):
#include <MovingAverages.mqh>
L'unica cosa che ci resta da fare è usare le sue funzionalità.
Nella funzione OnCalculate() trova un punto in cui sono terminati i calcoli della linea principale dell'indicatore (l'array TSIBuffer). Usiamo la funzione di ricerca. Seleziona il nome dell'array TSIBuffer, ad esempio, nella parte del codice in cui è dichiarato (fig. 1). Quindi, esegui il comando "Menu principale" - "Modifica" - "Trova e sostituisci" - "Trova" o utilizzare la combinazione di tasti Ctrl + F.
Fig. 1. Nome selezionato dell’array
La parola "TSIBuffer" sarà già digitata nel campo "Trova" della finestra "Trova" aperta. Seleziona "Up" nella sezione "Direzione". Ora, quando la finestra "Trova" è aperta, metti il cursore subito dopo la funzione OnCalculate(), premi subito il pulsante "Trova successivo" e troverai subito il punto in cui i calcoli dell'array TSIBuffer sono finiti. I calcoli vengono eseguiti nel ciclo "for". Aggiungeremo il codice per il calcolo della linea di segnale subito dopo questo ciclo. (fig. 2).
calcoli è contrassegnato con la cornice rossa.calcoli è contrassegnato con la cornice rossa.
Fig. 2. Ultima posizione trovata di calcolo del valore TSIBuffer (freccia rossa). Il ciclo in cui vengono eseguiti i calcoli è contrassegnato con la cornice rossa.
Le funzioni per il calcolo di tutti i quattro principali tipi di medie mobili sono incluse nella libreria MovingAverages.mqh:
- per quella semplice - SimpleMAOnBuffer(),
- per quella esponenziale - ExponentialMAOnBuffer(),
- per quella lineare ponderata - LinearWeightedMAOnBuffer(),
- per quella adattiva - SmoothedMAOnBuffer().
Tutte queste funzioni hanno lo stesso set di parametri:
const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[],double& buffer[]
Il parametro price[] della funzione determina un array con i dati iniziali su cui verrà eseguito il calcolo di una media mobile. Il parametro buffer è l’array che memorizzerà i valori della media mobile. I parametri rates_total e prev_calculated sono gli stessi dei parametri rates_total e prev_calculated della funzione onCalculate(); essi determinano la dimensione dell'array price[] e il numero di elementi già elaborati dell'array. Il parametro begin è l'indice di un elemento dell’array da cui partono i dati significativi.
Considerando le peculiarità degli algoritmi di calcolo delle medie mobili nella libreria MovingAverages.mqh (queste caratteristiche non sono pertinenti con l'argomento di questo articolo); abbiamo bisogno di un approccio attento all'impostazione del parametro begin.
In ogni caso, questo parametro non deve essere impostato su un elemento dell'array precedente rispetto a quello da cui partono i valori dei dati di origine (l'array TSIBuffer). È consentito specificare un elemento successivo se non porta a errori di calcolo.
Per determinare un valore accettabile di begin, prestare attenzione ai parametri del ciclo, for in cui vengono calcolati i valori dell'array TSIBuffer - il ciclo inizia dal valore della variabile di start. Dobbiamo scoprire il valore della variabile start che aveva durante il primo calcolo dell'indicatore (quando il valore prev_calculated è uguale a 0). Il valore della variabile "start" viene calcolato subito prima del ciclo, quando prev_calculated=0; il calcolo viene eseguito utilizzando la seguente formula:
start=begin+r+s-1;
Il valore della variabile start che viene passato alla funzione di calcolo delle medie mobili deve essere uguale a quel valore.
Dopo il ciclo di calcolo dell'array TSIBuffer, dichiarare la variabile begin2 e assegnarle il valore begin+r+s-1.
int begin2=begin+r+s-1;
Per dare la possibilità di utilizzare diverse funzioni di adattamento a seconda del valore del parametro esterno "sm", utilizzare l'operatore di switch . Per ogni variante di valore della variabile sm scrivere la chiamata della funzione corrispondente.
switch(sm) { case MODE_EMA: ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_LWMA: LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMA: SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMMA: SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; }
Dopodiché, possiamo vedere l'indicatore con la linea del segnale. Premere il pulsante "Compila", aprire il client terminal e associare l'indicatore ad un grafico (fig. 3).
Fig. 3. Indicatore STI, blu - linea principale, rosso - nuovo, linea di segnale.
8. Tagliare l’Inizio del Disegno del Buffer
Se scorri un grafico con l'indicatore sul bordo sinistro, vedrai che l'indicatore disegna linee nella parte per la quale i valori non sono stati calcolati. Non è una cosa bella (fig. 4).
Fig. 4. Disegno dell'indicatore nella parte in cui il calcolo non è stato eseguito.
Utilizzando la funzione PlotIndexSetInteger() chiamata con l'identificatore PLOT_DRAW_BEGIN, determinare il numero di prime barre in cui il buffer non viene disegnato. La chiamata della funzione deve essere eseguita dall'interno della funzione OnInit() dell'indicatore. Aggiungi la chiamata della funzione alla fine di OnInit(), ma prima della chiamata di ritorno(0), come è ovvio che sia.
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);
Premi nuovamente il pulsante "Compila" e ottieni l'inizio corretto del disegno dell'indicatore (fig. 5).
Fig. 5. Inizio corretto del disegno dell'indicatore.
Secondo Modo. Creazione di un Nuovo Indicatore sulla Base di quello Esistente
Considereremo questo modo utilizzando un esempio di creazione di un indicatore di convergenza e divergenza delle linee principali e di segnale dell'indicatore TSI. L'indicatore verrà disegnato come istogramma e avrà due colori come gli indicatori AO, AC. Se il valore dell'indicatore aumenta, l'istogramma sarà di colore verde; se diminuisce, l'istogramma sarà di colore rosso. Come già accennato in precedenza nell'introduzione, per fare riferimento ad un altro indicatore è possibile utilizzare la funzione iCustom() o IndicatorCreate(). All'inizio, diamo un'occhiata alla creazione di un indicatore utilizzando la funzione iCustom().
Creazione di un Indicatore Mediante la Funzione iCustom()
1. Creazione di Nuovo Indicatore
Creiamo un nuovo indicatore. Per creare un nuovo indicatore in MetaEditor è necessario eseguire il comando "Menu principale" - "File" - "Nuovo" - "Indicatore personalizzato" o premere la combinazione di tasti "Ctrl + N". Nel campo "Nome" della finestra che è comparsa, specifica il nome del nuovo indicatore - TSIsCDiCust, poi premi il pulsante "Aggiungi". Aggiungere un parametro esterno, il suo nome non è importante quanto la determinazione di una parte per i parametri esterni nel codice; inoltre, sarà più facile copiare tutti i parametri esterni dall'indicatore TSI (fig. 6).
Fig. 6. Primo passaggio della creazione di un indicatore personalizzato in un wizard
Premere il pulsante "Avanti".
Nella finestra successiva, specifica che l'indicatore verrà disegnato in una finestra separata. Non definire minimo e massimo. Premi il pulsante "Aggiungi" e comparirà un nuovo buffer nell'elenco dei buffer degli indicatori; specifica il suo nome - TSIsCD (verrà visualizzato in una guida pop-up se si posiziona il cursore del mouse sulla linea dell'indicatore e nella finestra dei dati) e il suo tipo - Istogramma a Colori.
Dopodiché, compariranno diversi esempi di colore nel campo "Colore". Specificare il colore verde Green per il primo esempio, il colore Red (rosso) per il secondo e lasciare gli altri senza effettuare modifiche. Aggiungere altri due buffer denominati Tsi e TsiSignal, che verranno utilizzati per ricevere e memorizzare i valori dell'indicatore TSI (fig. 7).
Fig. 7. Secondo passaggio della creazione di un indicatore personalizzato nel wizard.
Premi il pulsante "Fine" e il modello del nuovo indicatore verrà aperto in MetaEditor.
2. Modifica delle Proprietà dell'Indicatore e dei Buffer dell'Indicatore
Al passaggio 1 abbiamo determinato 3 buffer; tuttavia, il valore di #property indicator_buffers è pari a 4. Il fatto è che un istogramma colorato utilizza due buffer: uno viene visualizzato su un grafico ed è destinato ai valori di un indicatore, mentre il secondo è destinato a determinare il colore di visualizzazione del primo buffer. Lascia il valore #property indicator_buffers senza apportare modifiche. Modifica il valore #property indicator_plots a 1 - in un grafico deve essere visualizzato un solo buffer.
I buffer Tsi e TsiSignal non dovrebbero essere visualizzati su un grafico, ecco perché vanno eliminate tutte le loro proprietà (tutte le proprietà dell'indicatore che terminano con 2 e 3).
//--- plot Tsi #property indicator_label2 "Tsi" #property indicator_type2 DRAW_LINE #property indicator_color2 Red #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- plot TsiSignal #property indicator_label3 "TsiSignal" #property indicator_type3 DRAW_LINE #property indicator_color3 Red #property indicator_style3 STYLE_SOLID #property indicator_width3 1Nella funzione OnInit() trovare le chiamate della funzione SetIndexBuffer() per questi buffer (i nomi degli array sono TsiBuffer e TsiSignalBuffer), modificare il valore del terzo parametro da INDICATOR_DATA a INDICATOR_CALCULATIONS.
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);
Modifica la proprietà indicator_color1 - lascia solo i primi due colori.
#property indicator_color1 Green,Red
3. Dichiarazione dei Parametri Esterni
Aprire l'indicatore TSI in MetaEditor e copiare tutte le variabili esterne da esso, sostituire la variabile esterna correnteInput1 con questi parametri.
//--- input parameters input int r=25; input int s=13; input int sp=5; // Smoothing period input ENUM_MA_METHOD sm=MODE_EMA; // Smoothing type
4. Dichiarazione di una Variabile per l'Handle dell'indicatore e Chiamata dell'Indicatore
Nella sezione comune dell'indicatore, dichiara una variabile del tipo int e nominala Handle. Chiamata della funzione iCustom() nella parte inferiore di OnInit(). La funzione restituisce l’ handle dell'indicatore creato; ne abbiamo bisogno per ricevere i valori dell'indicatore. Assegna il valore restituito dalla funzione alla variabile Handle.
I primi due parametri della funzione iCustom() determinano un simbolo e un intervallo in cui i dati verranno utilizzati per il calcolo dell'indicatore. Specifichiamo un simbolo e un intervallo a cui è associato l'indicatore: _Symbol e PERIOD_CURRENT. Il terzo parametro è il nome di un indicatore personalizzato; in questo caso, si tratta del TSI. Tutti i parametri esterni dell'indicatore chiamato sono elencati più avanti:
Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);
5. Preparazione della funzione OnCalculate()
Passiamo alla funzione OnCalculate(). L'indicatore TSI viene calcolato su un buffer di dati, quindi useremo la prima forma della funzione OnCalculate(). Modifica la seconda forma esistente della funzione OnCalculate() nel modello con la prima.
int OnCalculate(const int rates_total, // size of the price[] array const int prev_calculated, // bars processed during the previous call const int begin, // from where the significant data begin const double &price[] // array for calculation ) { return(rates_total); }
L'ulteriore lavoro sull'indicatore verrà eseguito all'interno di questa funzione.
6. Determinazione dei Limiti di Calcolo dell'Indicatore
La massima priorità e importanza nello sviluppo di qualsiasi indicatore è quella di determinare i limiti del range di barre elaborate. All'inizio dell'indicatore, dovremmo eseguire il calcolo dell'indicatore per ogni barra, durante il suo funzionamento - solo per una che è attualmente formata. È possibile rilevare il momento di avvio dell'indicatore attraverso il valore della variabile prev_calculated. Se questo valore è uguale a zero, questa è la prima esecuzione della funzione OnCalculate() dall'inizio dell'indicatore.
Alla prima esecuzione della funzione OnCalculate(), è necessario determinare l'indice della prima barra da cui devono essere avviati i calcoli. Il suo valore è determinato dal numero di barre necessarie per il calcolo del valore dell'indicatore (l'indicizzazione viene eseguita da sinistra a destra).
L'inclinazione della linea dell'indicatore è determinata da due barre, quindi abbiamo bisogno di un'altra barra precedente. Indice di una barra, i dati significativi dell'array price[] partono da, come è noto, dal valore della variabile begin; quindi, iniziamo il calcolo delle barre dalla barra start=begin+1.
Inoltre, durante il funzionamento dell'indicatore, l'indice di una barra da cui parte il calcolo è determinato dal valore della variabile prev_calculated - questa variabile contiene il numero di barre già elaborate. Pertanto, per scoprire l'indice dell'ultima barra per cui sono stati eseguiti i calcoli, è necessario sottrarre 1 da prev_calculated.
L'ultima delle barre già elaborate verrà nuovamente considerata nei calcoli perché può essere una barra di formazione. Il limite di calcolo è determinato dalla dimensione dell’array price[] - la variabile rates_total. L'indice dell'ultima barra per cui vengono eseguiti i calcoli è uguale a rates_total-1 (è inferiore alla dimensione dell'array per uno).
Poiché l'indicatore utilizza i dati di un altro indicatore per il suo calcolo, dovremmo ottenere questi dati. È possibile ottenere i dati di un altro indicatore utilizzando la funzione CopyBuffer(). Nel primo parametro della funzione è necessario specificare l’handle di un indicatore, i cui dati devono essere copiati (handle viene ottenuto nella fase 4); nel secondo parametro, specifica un indice del buffer copiato (il valore necessario può essere determinato mediante il tab "Color" delle proprietà dell'indicatore copiato, il conteggio parte da zero).
Il terzo parametro è l'indice di una barra dalla quale viene iniziata la copia; in questo caso, l'indicizzazione viene eseguita da destra a sinistra e,quindi, la barra più a destra è quella zero. Il quarto parametro è il numero di elementi dell’array da copiare. È necessario prestare attenzione nel determinare il numero degli elementi copiati tanto quanto nel determinare il range delle barre considerate nel calcolo. Questo influisce sulle prestazioni dell'indicatore. L'indice di una barra da cui parte il calcolo dell'indicatore è determinato preliminarmente, quindi il numero di elementi copiati viene calcolato come rates_total-start. Durante il processo di lavoro, quando l'indicatore viene calcolato solo per la barra di formazione, viene copiato un solo elemento dell'array.
Se le funzioni CopyBuffer() restituiscono -1 nel tentativo di copiare le informazioni, significa che i dati non possono essere copiati. Dunque, non ha senso eseguire i calcoli. Questo errore deve essere gestito. All'inizio del CopyBuffer() dichiara una variabile statica del tipo bool e nominala "error". Se si verifica un errore durante il processo di calcolo dell'indicatore, in particolare l'errore di copiatura dei dati dell'indicatore, assegna il valore True a questa variabile e termina l'esecuzione della funzione OnCalculate().
Ricalcola nuovamente l'intero indicatore al tick successivo se il valore di errore indica che è stato commesso un errore durante la precedente esecuzione della funzione OnCalculate(). Pertanto, l'inizio della funzione OnCalculate() sarà il seguente:
static bool error=true; int start; if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start { error=true; // Set the value True for the indicator to be calculated for all bars } if(error) // If value of error=true, then it is the first execution of the function after // the start of the indicator, or there was an error of copying of data at the previous start { start=begin+1; error=false; } else { start=prev_calculated-1; } if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // Copying data of main line of the indicator { error=true; // Failed to copy data, set the value True for the error variable to recalculate the whole // indicator at the next call of OnCalculate() return(0); // End working of the function } if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // Copy data of the signal line of the indicator { error=true; // Failed to copy data, set the value true for the error variable to recalculate the whole // indicator at the next call of the OnCalculate() function return(0); // End working of the function }
I limiti di calcolo dell'indicatore sono determinati, fai un ciclo di calcoli in questo range di barre.
for(int i=start;i<rates_total;i++) { }
Calcola il valore dell'indicatore (il codice si trova all'interno del ciclo appena creato).
TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];
Ora, passiamo alla cosa più interessante: colorare il buffer. In precedenza nella fase 1, abbiamo determinato l'uso di un istogramma a colori per il buffer dell'indicatore. Questo tipo di disegno richiede due buffer: uno è per il valore dell'indicatore e l'altro è per il colore. L'elenco dei colori è impostato nella proprietà indicator_color1. Quando il valore 0 è impostato per l'elemento buffer, l'indicatore viene visualizzato con il colore verde; quando è impostato il valore 1, l'indicatore è rosso (in base alla loro posizione nella indicator_color1 nell'elenco; la numerazione inizia da zero).
È impossibile evitare una situazione in cui i valori dell'indicatore sono uguali a due barre adiacenti; in questo caso, l'indicatore dovrebbe essere visualizzato con il colore precedente (perché abbiamo solo due colori per i movimenti su e giù). Quindi, all'inizio dei calcoli copieremo il valore del buffer TsiCDColors sulla barra precedente:
TsiCDColors[i]=TsiCDColors[i-1];
Quando ci si sposta verso l'alto, colorare l'indicatore con il colore: Verde
if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;
Quando ci si sposta verso il basso colorare l'indicatore con il colore Rosso:
if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;
Questo ci porta quasi alla fine del lavoro sull'indicatore; viene lasciato per determinare l'inizio del disegno dell'indicatore.
7. Completamento del Lavoro sull’Indicatore
Nonostante la variabile begin venga utilizzata per determinare il calcolo dell'indicatore, ciò non significa che i dati dell'indicatore partano dalla barra identificata con la variabilebegin. Se l'algoritmo di un indicatore personalizzato non è noto, è quasi impossibile rilevare il numero di barre necessarie per il calcolo dell'indicatore. Ecco perché possiamo saltare questa fase o è possibile individuare un valore sulla base dell'esperienza. Tuttavia, conosciamo l'algoritmo dell'indicatore TSI, quindi possiamo individuare esattamente l'inizio dell'indicatore. Aggiungi la chiamata della funzione PlotIndexSetInteger() con l'identificatore PLOT_DRAW_BEGIN alla funzione OnInit().
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);
L'indicatore TSI visualizza valori precisi a due cifre decimali; imposta la stessa precisione utilizzando la funzione IndicatorSetInteger() con l'identificatore INDICATOR_DIGITS:
IndicatorSetInteger(INDICATOR_DIGITS,2);
Compila l'indicatore e associalo ad un grafico (fig. 8).
Fig. 8. Indicatore TSIsDiCust.
Creazione di un Indicatore Mediante la Funzione IndicatorCreate()
La creazione di un indicatore utilizzando la funzione IndicatorCreate() è la stessa della sua creazione utilizzando la funzione iCustom(), ad eccezione del passaggio 4 - la funzione IndicatorCreate() viene utilizzata al posto di iCustom().
1. Salva una copia dell'indicatore TSIsCDiCust con il nome TSIsCDiCreate.
2. Trova dove viene chiamata la funzione iCustom() nel codice. D'ora in poi, verrà eseguita la chiamata della funzione IndicatorCreate() al posto di iCustom(). Analogamente a iCustom(), i primi due parametri della funzione IndicatorCreate() determinano un simbolo e un intervallo che verranno utilizzati per il calcolo dell'indicatore. Il terzo parametro è un identifier del tipo di indicatore, per un indicatore personalizzato è IND_CUSTOM. I parametri dell'indicatore di creazione vengono passati alla funzione utilizzando l’array delle strutture MqlParam.
Il MqlParam contiene quattro variabili - tre di esse sono variabili di diversi tipi utilizzati per i valori: double_value, integer_value e string_value; e un altra è type, cioè determina il tipo di variabile utilizzata. L'indicatore TSI possiede quattro parametri esterni. Poiché l'indicatore è quello personalizzato, il primo elemento dell'array determina il nome dell'indicatore personalizzato, quindi l'array deve contenere cinque elementi. Dichiara un array delle strutture (il codice si trova dove è stato chiamato iCustom():
MqlParam Params[5];
Compila l'array con i valori:
Params[0].type=TYPE_STRING; Params[0].string_value="TSIs"; // Specify name of the called custom indicator in the first parameter Params[1].type=TYPE_INT; Params[1].integer_value=r; Params[2].type=TYPE_INT; Params[2].integer_value=s; Params[3].type=TYPE_INT; Params[3].integer_value=sp; Params[4].type=TYPE_INT; Params[4].integer_value=sm;
Abbiamo già trattato i primi tre parametri passati alla funzione IndicatorCreate(). La dimensione dell’array di parametri viene passata attraverso il quarto parametro; l'ultimo è l'array con i parametri stessi:
Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);
Non ci resta che premere il pulsante "Compila " e controllare l'indicatore nel client terminal.
Conclusione
Ripetiamo brevemente le idee principali a cui dovresti prestare attenzione durante la creazione di un indicatore personalizzato sulla base di un altro indicatore.
Quando si migliora un indicatore, è necessario specificare correttamente il numero di buffer e il numero di buffer da disegnare (le proprietà indicator_buffers, indicator_plots ); è necessario determinare le proprietà dei nuovi buffer (le proprietà indicator_label , indicator_type , indicator_color , indicator_style , indicator_width). Quando si chiama la funzione SetIndexBufer() per i nuovi buffer, è necessario specificare il valore corretto del terzo parametro (INDICATOR_DATA o INDICATOR_CALCULATIONS); inoltre, bisogna specificare correttamente i valori del primo parametro (indice del buffer); eseguire la re-indicizzazione dei buffer, se necessario.
Quando si crea un nuovo indicatore utilizzando un altro indicatore personalizzato, è necessario passare correttamente i parametri alla funzione iCustom(); e compilare la struttura dei parametri quando si utilizza la funzione IndicatorCreate(). Qui dovresti prestare attenzione anche alla corretta specifica dei parametri quando chiami la funzione SetIndexBuffer(). La cosa più importante è non dimenticare di eseguire la chiamata della funzione SetIndexBuffer() per i nuovi buffer.
Ogni volta che si lavora con gli indicatori, è necessario prestare attenzione nel determinare un intervallo di calcolo delle barre: utilizzare i valori delle variabili prev_calculated, rates_total, begin. MetaEditor ti aiuterà a gestire gli altri errori che possono verificarsi durante la programmazione (i messaggi di errore che compaiono durante la compilazione vengono visualizzati tab "Errors").
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/127
![20 Segnali di Trading in MQL5](https://c.mql5.com/2/0/20_Trading_Signals_MQL5__1.png)
![Funzioni di Money Management in un Expert Advisor](https://c.mql5.com/2/0/money_management_MQL5__1.png)
![Il Prototipo di Robot di Trading](https://c.mql5.com/2/0/Prototype_Expert_Advisor_MQL5.png)
![Creazione di una Information Board utilizzando le Standard Library Classes e Google Chart API](https://c.mql5.com/2/0/info_panel_MQL5.png)
![MQL5 - Linguaggio delle strategie di trading integrato nel client terminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso