![20 Segnali di Trading in MQL5](https://c.mql5.com/i/articles/overlay.png)
20 Segnali di Trading in MQL5
Introduzione
I trader cercano di trovare regolarità nel comportamento dei prezzi, si sforzano di formare regole usando le quali avranno una buona possibilità di determinare un momento favorevole per l'acquisto o la vendita. Per creare un sistema completamente automatico, è necessario imparare come informare sull'arrivo di tali momenti - segnali di trading.
I segnali informano i trader sui potenziali punti di inserimento di una posizione, tuttavia non tutti sono da eseguire obbligatoriamente. Dei criteri aggiuntivi possono filtrare anche la maggior parte dei segnali, ma per noi non è significativo. L'argomento dell'articolo è come programmare i segnali di trading più popolari in MQL5.
1. Quali Segnali Conosciamo?
Tutti i metodi per determinare i momenti di ingresso nel mercato possono essere suddivisi in diversi tipi:
- intersezione di medie mobili
- rottura di un range
- uscita dalla zona di overbuying/overselling sulla base di tassi stocastici
- bounce dai bordi di un canale
- rottura dei bordi di un canale
- cambiamento di tendenza
2. Come Codificarlo Meglio?
Esistono molti modi per scrivere un codice; può essere scritto all'interno di OnStart(), OnTick() e delle altre funzioni. Puoi trovare informazioni più dettagliate su di esse nella documentazione su questo sito Web o nella guida per l'utente integrata nel MetaEditor;tuttavia, questo metodo non è efficace e talvolta è necessario scrivere più volte le stesse parti del codice. Questo è il caso in cui considereremo un altro modo: useremo funzioni personalizzate che possono essere chiamate da qualsiasi parte del codice del nostro programma.
Per comodità di utilizzo delle funzioni create, combiniamole in un gruppo separato come include file esterno e nominiamolo SignalTrade; verrà memorizzato nella directory ...\MQL5\Include. Permetterà di collegare facilmente questo modulo a qualsiasi programma.
Nonostante tutti i segnali sembrino diversi, essi hanno molte cose in comune. Esistono tre varianti che possono essere ricevute da una funzione che genera i segnali:
- segnale di acquisto
- segnale di vendita
- nessun segnale
Quindi, creiamo un'enumerazione che corrisponda a questi segnali.
- 1 - segnale di acquisto
- -1 - segnale di vendita
- 0 - nessun segnale
Scriviamo un prototipo della funzione che restituisce un segnale. Dividere la nostra funzione in più parti nelle quali verrà eseguita l'una o l'altra operazione. Le variabili necessarie per l'archiviazione dei dati vengono dichiarate e inizializzate al principio della funzione. Il caricamento e il controllo delle informazioni necessarie dall'indicatore creato verranno eseguiti in seguito. Il controllo delle informazioni è essenziale per evitare conseguenze impreviste nel lavorare con i dati e del programma nel suo complesso.
Una volta caricate e controllate le informazioni, vai a formare un segnale. Non appena si forma un segnale, esci dalla funzione e restituisci il segnale ottenuto ad esso come uno dei valori descritti sopra.
int TradeSignal() { //--- zero means absence of signal int sig=0; //--- check the handles of indicators //--- if all the handles are invalid, create them //--- if the handles are valid, copy the values from indicators //--- check the copied data //--- in case of an error of copying, exit from the function //--- perform the indexation of the array as a timeseries //--- in case of an indexation error, exit from the function //--- check conditions and set the value for sig //--- return the trade signal return(sig); }
3. Esempi dei 20 Segnali di Trading.
Useremo diversi indicatori per ottenere i segnali di trading. In MQL5 gli indicatori sono chiamati utilizzando le funzioni speciali, ad esempio iMA, iAC, iMACD, iIchimoku, ecc.; esse creanouna copia dell'indicatore tecnico corrispondente nella cache globale del client terminal. Se esiste già una copia dell'indicatore con tali parametri, la nuova copia non viene creata ed il contatore dei riferimenti alle attuali copie aumenta.
Queste funzioni restituiscono l'handle della copia corrispondente dell'indicatore. Inoltre, con questo handle, è possibile ricevere i dati calcolati dall' indicatore corrispondente. I dati del buffer corrispondente (gli indicatori tecnici contengono i dati calcolati nei loro buffer interni; il loro numero può variare da 1 a 5, a seconda del tipo di indicatore) possono essere copiati in un programma MQL5 utilizzando la funzione CopyBuffer().
È impossibile utilizzare i dati di un indicatore subito dopo la sua creazione, poiché è necessario un po’ di tempo per calcolare i valori dell'indicatore; quindi, il modo migliore, è creare gli handle all'interno di OnInit(). La funzione iCustom() crea l'indicatore personalizzato corrispondente e, se la creazione ha esito positivo, restituisce l'handle dell'indicatore. Gli indicatori personalizzati possono contenere fino a 512 buffer di indicatori, il cui contenuto si può ottenere anche utilizzando la funzione CopyBuffer() e l'handle ottenuto.
Per ogni segnale, creiamo una funzione in base al nostro prototipo TradeSignal() e numeriamoli nel seguente ordine: TradeSignal_01() - TradeSignal_20(). Analizziamo in dettaglio la struttura della funzione per formare un segnale usando l'esempio di un segnale basato sull'intersezione di medie mobili; quindi, scriveremo le funzioni per gli altri segnali in modo simile.
3.1. Intersezione delle Medie Mobili
Figura 1. L'intersezione di due medie mobili
Usando la funzione TradeSignal_01(), otterremo un segnale sull'intersezione di due Medie Mobili (МА): quella veloce con periodo 8 e quella lenta con periodo 16.
Nella nostra funzione, fisseremo solo il fatto dell'intersezione e restituiremo il valore del segnale corrispondente alla funzione. Secondo le nostre regole e il prototipo, la funzione sarà simile:
int TradeSignal_01() { //--- zero means that there is no signal int sig=0; //--- check the handles of indicators if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid { //--- create is again h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE); //--- exit from the function return(0); } else //--- if the handle is valid { //--- copy value of the indicator to the array if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if the array of data is less than required //--- exit from the function return(0); //--- set the indexation in the array as in a timeseries if(!ArraySetAsSeries(ma1_buffer,true)) //--- in case of an indexation error, exit from the function return(0); } if(h_ma2==INVALID_HANDLE)//--- if the handle is invalid { //--- create it again h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE); //--- exit from the function return(0); } else //--- if the handle is valid { //--- copy values of the indicator to the array if(CopyBuffer(h_ma2,0,0,2,ma2_buffer)<2) //--- if there is less data than required //--- exit from the function return(0); //--- set the indexation in the array as in a timeseries if(!ArraySetAsSeries(ma1_buffer,true)) //--- in case of an indexation error, exit from the function return(0); } //--- check the condition and set a value for the sig if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1]) sig=1; else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
Ora diamo uno sguardo più dettagliato a ciascuna parte del codice. All'inizio della funzione, dichiariamo una variabile locale che memorizzerà il tipo di segnale e la inizializziamo con zero che indica assenza di segnale.
int sig=0;
Inoltre, controlliamo la validità dell’nandle; se l’handle non è valido, lo creiamo e usciamo dalla funzione, perché il calcolo dell'indicatore richiede del tempo. Viene implementato per evitare l'errore di copiare i dati dal buffer dell'indicatore.
if(h_ma1==INVALID_HANDLE)//--- if the handle is invalid { //--- create it again h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE); //--- exit from the function return(0); }
Se l'handle è valido, copiare i dati nell’array. Per analizzare la situazione, è sufficiente copiare i dati delle ultime tre barre della MA veloce e due barre di quella lenta. A tale scopo, utilizzare la seguente funzione :
int CopyBuffer( int indicator_handle, // handle of an indicator int buffer_num, // number of buffer of an indicator int start_pos, // where to start from int count, // amount to be copied double buffer[] // an array to copy data to );
Controllali: se ci sono meno dati del necessario, significa che si è verificato un errore di copia; di conseguenza, l’array in cui i dati avrebbero dovuto essere memorizzati determinerà un errore. Per evitarlo, usciamo dalla funzione. Inoltre abbiamo bisogno di impostare l’indicizzazione nell'array come in una timeserie; la seguente funzione è destinata a questo:
bool ArraySetAsSeries( void array[], // array by a link bool set // true means that the indexation order is reversed );
Se si è verificato un errore durante l'indicizzazione dell'array, esci dalla funzione, altrimenti possiamo ottenere risultati errati.
else //--- if the handle is valid { //--- copy values of the indicator to the array if(CopyBuffer(h_ma1,0,0,3,ma1_buffer)<3) //--- if there is less data than required //--- exit from the function return(0); //--- set the indexation in the array like in a timeseries if(!ArraySetAsSeries(ma1_buffer,true)) //--- in case of an indexation error, exit from the function return(0); }
Ora, man mano che gli indicatori vengono creati e si ottengono tutte le informazioni necessarie, procediamo alla fase principale: la formazione di un segnale.
Per eliminare l’oscillazione del segnale nella barra corrente, analizza solo le barre chiuse 1-st e 2-nd.
Forma il segnale per acquistare. A tale scopo, prendi il valore della MA veloce alla 2a barra e confrontalo con il valore della MA lenta a 1 barra; confronta il valore della MA veloce alla barra 1-st con il valore della MA lenta alla barra 1-st. Se il valore della MA veloce nella barra 2-nd è inferiore al valore della MA lenta nella barra 1-st, e il valore della MA veloce nella barra 1-st è maggiore del valore della MA lenta nella barra 1-st, significa che la MA veloce ha attraversato quella lenta verso l'alto; questo è il nostro segnale per comprare. Se la nostra condizione è vera, scrivi 1 nella variabile sig.
Il segnale per vendere si forma in modo simile. Se la MA veloce nella barra 2-nd è maggiore della MA lenta nella barra 1-st, e se la MA veloce nella barra 1-st è inferiore alla MA lenta nella barra 1-st, significa incrocio top-down della MA lenta da parte della MA veloce. Se la nostra condizione è vera, scrivi il valore -1 nella variabile sig. Se entrambe le condizioni sono false, significa che non c'è segnale, quindi scriviamo il valore 0 nella variabile sig. Ora i segnali si formano, restituiscono il tipo di segnale ottenuto alla nostra funzione TradeSignal_01()
//--- check the condition and set a value for the sig if(ma1_buffer[2]<ma2_buffer[1] && ma1_buffer[1]>ma2_buffer[1]) sig=1; else if(ma1_buffer[2]>ma2_buffer[1] && ma1_buffer[1]<ma2_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig);
3.2. Intersezione della Linea Principale e di Segnale del MACD
Figura 2. L'intersezione della linea principale e del segnale dell'indicatore MACD
Nella funzione TradeSignal_02() otterremo il segnale sull'intersezione del segnale e la linea principale di MACD. Se la linea del segnale attraversa quella principale dall'alto verso il basso, è il segnale per acquistare. Se la linea del segnale attraversa quella principale dal basso verso l'alto, è il segnale per vendere. Altri casi verranno considerati come assenza di segnale.
int TradeSignal_02() { int sig=0; if(h_macd==INVALID_HANDLE) { h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE); return(0); } else { if(CopyBuffer(h_macd,0,0,2,macd1_buffer)<2) return(0); if(CopyBuffer(h_macd,1,0,3,macd2_buffer)<3) return(0); if(!ArraySetAsSeries(macd1_buffer,true)) return(0); if(!ArraySetAsSeries(macd2_buffer,true)) return(0); } //--- check the condition and set a value for sig if(macd2_buffer[2]>macd1_buffer[1] && macd2_buffer[1]<macd1_buffer[1]) sig=1; else if(macd2_buffer[2]<macd1_buffer[1] && macd2_buffer[1]>macd1_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.3. Rottura del Range del Canale di Prezzo
Figura 3. Rottura dei bordi inferiore e superiore del Canale di Prezzo
Nella funzione TradeSignal_03() riceveremo il segnale di una rottura dei bordi superiore o inferiore del Canale di Prezzo.
Se il prezzo buca il bordo superiore del Canale di Prezzo e il prezzo è fissato al di sopra di questo bordo, è il segnale per acquistare. Se il prezzo buca il bordo inferiore del Canale di Prezzo e il prezzo è fissato al di sotto di questo bordo, allora è il segnale per vendere. Altri casi, vengono considerati come assenza di segnale.
A differenza di due funzioni precedenti, qui abbiamo bisogno di un array per memorizzare i prezzi di chiusura. per ottenerli, utilizza la seguente funzione :
int CopyClose( string symbol_name, // symbol name ENUM_TIMEFRAMES timeframe, // period int start_pos, // where to start from int count, // amount to be copied double close_array[] // array for copying close prices to );
int TradeSignal_03() { int sig=0; if(h_pc==INVALID_HANDLE) { h_pc=iCustom(Symbol(),Period(),"Price Channel",22); return(0); } else { if(CopyBuffer(h_pc,0,0,3,pc1_buffer)<3) return(0); if(CopyBuffer(h_pc,1,0,3,pc2_buffer)<3) return(0); if(CopyClose(Symbol(),Period(),0,2,Close)<2) return(0); if(!ArraySetAsSeries(pc1_buffer,true)) return(0); if(!ArraySetAsSeries(pc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the conditions and set a value for sig if(Close[1]>pc1_buffer[2]) sig=1; else if(Close[1]<pc2_buffer[2]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.4. Rottura del Range dei Canali Adattivi ADX
Figura 4. La rottura dei bordi superiore e inferiore del canale adattivo ADX.
Usando la funzione TradeSignal_04(), otterremo il segnale di rottura dei bordi superiore o inferiore del canale adattivo ADX.
Se il prezzo buca il bordo superiore del canale adattivo ADX e il prezzo di chiusura è fissato al di sopra di questo bordo, è il segnale per acquistare. Se il prezzo buca il bordo inferiore del Canale di Prezzo e il prezzo di chiusura è fissato al di sotto di questo confine, è il segnale per vendere. Altri casi, vengono considerati come assenza di segnale.
int TradeSignal_04() { int sig=0; if(h_acadx==INVALID_HANDLE) { h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14); return(0); } else { if(CopyBuffer(h_acadx,0,0,2,acadx1_buffer)<2) return(0); if(CopyBuffer(h_acadx,1,0,2,acadx2_buffer)<2) return(0); if(CopyClose(Symbol(),Period(),0,2,Close)<2) return(0); if(!ArraySetAsSeries(acadx1_buffer,true)) return(0); if(!ArraySetAsSeries(acadx2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for the sig if(Close[1]>acadx1_buffer[1]) sig=1; else if(Close[1]<acadx2_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.5. Esci dalle zone di Overbuying/Overselling di Stochastic
Figura 5. Attraversamento dei livelli di overbuying e overselling da parte dello stocastico.
Usando il TradeSignal_05() otterremo il segnale di uscita dello stocastico dalle zone dioverbuying/overselling;i livelli di tali zone saranno livelli con valori 80 e 20.
Compriamo, poiché l'oscillatore (%K o %D) scende al di sotto di un certo livello (di solito, è 20) e poi sale al di sopra. Vendiamo, poiché l'oscillatore sale più in alto di un certo livello (di solito, è 80) e poi scende al di sotto.
int TradeSignal_05() { int sig=0; if(h_stoh==INVALID_HANDLE) { h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH); return(0); } else { if(CopyBuffer(h_stoh,0,0,3,stoh_buffer)<3) return(0); if(!ArraySetAsSeries(stoh_buffer,true)) return(0); } //--- check the condition and set a value for sig if(stoh_buffer[2]<20 && stoh_buffer[1]>20) sig=1; else if(stoh_buffer[2]>80 && stoh_buffer[1]<80) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.6. Uscita dalle zone Overbuying/Overselling dell’RSI
Figura 6. Incrocio dei livelli di overbuying e overselling da parte dell'indicatore RSI
Utilizzando la funzione TradeSignal_06() otterremo il segnale sull'uscita dell'indicatore RSI dalle zone di overbuying/overselling; i livelli per queste zone sono i livelli con i valori 70 e 30.
Compriamo, poiché l'RSI scende al di sotto di un certo livello (di solito, è 30) e poi sale al di sopra. Vendiamo, poiché l'RSI sale più in alto di un certo livello (di solito, è 70) e poi scende al di sotto .
int TradeSignal_06() { int sig=0; if(h_rsi==INVALID_HANDLE) { h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE); return(0); } else { if(CopyBuffer(h_rsi,0,0,3,rsi_buffer)<3) return(0); if(!ArraySetAsSeries(rsi_buffer,true)) return(0); } //--- check the condition and set a value for sig if(rsi_buffer[2]<30 && rsi_buffer[1]>30) sig=1; else if(rsi_buffer[2]>70 && rsi_buffer[1]<70) sig=-1; else sig=0; //--- return the trade signal return(sig);3.7. Esci dalle zone Overbuying/Overselling del CCI
Figura 7. Incrocio dei livelli di overbuying e overselling da parte dell'indicatore CCI
Usando il TradeSignal_07() otterremo il segnale di uscita dell'indicatore CCI dalle zone di overbuying/overselling; i livelli per tali zone sono i livelli con i valori 100 e -100.
Compriamo, poiché ilCCI scende più in basso del livello -100 e poi sale al di sopra. Vendiamo, poiché il CCI sale al di sopra dellivello 100 e poi scende al di sotto.
int TradeSignal_07() { int sig=0; if(h_cci==INVALID_HANDLE) { h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL); return(0); } else { if(CopyBuffer(h_cci,0,0,3,cci_buffer)<3) return(0); if(!ArraySetAsSeries(cci_buffer,true)) return(0); } //--- check the condition and set a value for sig if(cci_buffer[2]<-100 && cci_buffer[1]>-100) sig=1; else if(cci_buffer[2]>100 && cci_buffer[1]<100) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.8. Uscita dalle zone Overbuying/Overselling di Williams %
Figura 8. Incrocio dei livelli di overbuying e overselling da parte dell'indicatore Williams %
Utilizzando la funzione TradeSignal_08() otterremo il segnale di uscita dell'indicatore Williams % dalle zone di overbuying/overselling; i livelli per tali zone sono i livelli con valori -20 e -80.
Compriamo, poiché Williams % scende al di sotto del livello -80 e poi sale al di sopra di esso. Vendiamo, poiché Williams % sale al di sopra del livello -20 e poi scende al di sotto di esso.
int TradeSignal_08() { int sig=0; if(h_wpr==INVALID_HANDLE) { h_wpr=iWPR(Symbol(),Period(),14); return(0); } else { if(CopyBuffer(h_wpr,0,0,3,wpr_buffer)<3) return(0); if(!ArraySetAsSeries(wpr_buffer,true)) return(0); } //--- check the condition and set a value for sig if(wpr_buffer[2]<-80 && wpr_buffer[1]>-80) sig=1; else if(wpr_buffer[2]>-20 && wpr_buffer[1]<-20) sig=-1; else sig=0; //--- return the trade signal return(sig); }3.9. Bounce dai Bordi del Canale Bollinger
Figura 9. Bounce del prezzo dal bordo del Canale Bollinger
Usando la funzione TradeSignal_09() otterremo il segnale quando il prezzo rimbalza dai bordi del canale Bollinger.
Se il prezzo buca o tocca il bordo superiore del Bollinger e poi ritorna indietro, è il segnale per vendere. Se il prezzo buca o tocca il bordo inferiore del Bollinger, allora è il segnale per acquistare.
int TradeSignal_09() { int sig=0; if(h_bb==INVALID_HANDLE) { h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE); return(0); } else { if(CopyBuffer(h_bb,1,0,2,bb1_buffer)<2) return(0); if(CopyBuffer(h_bb,2,0,2,bb2_buffer)<2) return(0); if(CopyClose(Symbol(),Period(),0,3,Close)<3) return(0); if(!ArraySetAsSeries(bb1_buffer,true)) return(0); if(!ArraySetAsSeries(bb2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[2]<=bb2_buffer[1] && Close[1]>bb2_buffer[1]) sig=1; else if(Close[2]>=bb1_buffer[1] && Close[1]<bb1_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.10. Bounce dai Bordi del Canale di Deviazione Standard
Figura 10. Bounce del prezzo dai bordi del canale di deviazione standard
Usando la funzione TradeSignal_10(), otterremo il segnale se il prezzo rimbalza dai bordi del canale di deviazione standard.
Se il prezzo buca o tocca il bordo superiore del canale di deviazione standard e poi ritorna indietro, è il segnale per vendere. Se il prezzo buca o tocca il bordo inferiore del canale di deviazione standard, allora è il segnale per acquistare.
int TradeSignal_10() { int sig=0; if(h_sdc==INVALID_HANDLE) { h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0); return(0); } else { if(CopyBuffer(h_sdc,0,0,2,sdc1_buffer)<2) return(0); if(CopyBuffer(h_sdc,1,0,2,sdc2_buffer)<2) return(0); if(CopyClose(Symbol(),Period(),0,3,Close)<3) return(0); if(!ArraySetAsSeries(sdc1_buffer,true)) return(0); if(!ArraySetAsSeries(sdc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[2]<=sdc2_buffer[1] && Close[1]>sdc2_buffer[1]) sig=1; else if(Close[2]>=sdc1_buffer[1] && Close[1]<sdc1_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.11. Bounce dai Bordi del Canale di Prezzo
Figura 11. Il bounce del prezzo dai bordi del Canale di Prezzo
Usando la funzione TradeSignal_11() otterremo il segnale se il prezzo rimbalza dai bordi del Canale di Prezzo.
Se il prezzo buca o tocca il bordo superiore del canale di prezzo e poi ritorna indietro, è il segnale per vendere. Se il prezzo buca o tocca il bordo inferiore del Canale di Prezzo, allora è il segnale per acquistare.
int TradeSignal_11() { int sig=0; if(h_pc==INVALID_HANDLE) { h_pc=iCustom(Symbol(),Period(),"Price Channel",22); return(0); } else { if(CopyBuffer(h_pc,0,0,4,pc1_buffer)<4) return(0); if(CopyBuffer(h_pc,1,0,4,pc2_buffer)<4) return(0); if(CopyClose(Symbol(),Period(),0,3,Close)<3) return(0); if(!ArraySetAsSeries(pc1_buffer,true)) return(0); if(!ArraySetAsSeries(pc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[1]>pc2_buffer[2] && Close[2]<=pc2_buffer[3]) sig=1; else if(Close[1]<pc1_buffer[2] && Close[2]>=pc1_buffer[3]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.12. Bounce dai Bordi del Canale Envelopes
Figura 12. Il bounce del prezzo dai bordi del canale Envelopes
Usando la funzione TradeSignal_12(), otterremo il segnale se il prezzo rimbalza dai bordi del canale Envelopes.
Se il prezzo buca o tocca il bordo superiore del canale Envelopes e poi ritorna indietro, è il segnale per vendere. Se il prezzo buca o tocca il bordo inferiore del canale Envelopes, è il segnale per acquistare.
int TradeSignal_12() { int sig=0; if(h_env==INVALID_HANDLE) { h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1); return(0); } else { if(CopyBuffer(h_env,0,0,2,env1_buffer)<2) return(0); if(CopyBuffer(h_env,1,0,2,env2_buffer)<2) return(0); if(CopyClose(Symbol(),Period(),0,3,Close)<3) return(0); if(!ArraySetAsSeries(env1_buffer,true)) return(0); if(!ArraySetAsSeries(env2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[2]<=env2_buffer[1] && Close[1]>env2_buffer[1]) sig=1; else if(Close[2]>=env1_buffer[1] && Close[1]<env1_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.13. Rottura del Canale Donchian
Figura 13. Rottura dei bordi del Canale Donchian
Nella funzione TradeSignal_13(), otterremo il segnale quando il prezzo buca i bordi del canale Donchian.
Se il prezzo buca il bordo superiore del canale Donchian e il prezzo di chiusura è fissato al di sopra quel bordo, è il segnale per acquistare. Se il prezzo buca il bordo inferiore del canale Donchian e il prezzo di chiusura è fissato al di sotto di questo bordo, è il segnale per vendere.
int TradeSignal_13() { int sig=0; if(h_dc==INVALID_HANDLE) { h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2); return(0); } else { if(CopyBuffer(h_dc,0,0,3,dc1_buffer)<3) return(0); if(CopyBuffer(h_dc,1,0,3,dc2_buffer)<3) return(0); if(CopyClose(Symbol(),Period(),0,2,Close)<2) return(0); if(!ArraySetAsSeries(dc1_buffer,true)) return(0); if(!ArraySetAsSeries(dc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[1]>dc1_buffer[2]) sig=1; else if(Close[1]<dc2_buffer[2]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.14. Rottura del Silver-Channel
Figura 14. Rottura dei bordi del Silver-Channel
Nella funzione TradeSignal_14(), otterremo il segnale quando il prezzo buca i bordi del Silver-Channel. L'indicatore Silver-Channel disegna 8 bordi che possono fungere anche da livelli di supporto e resistenza. Per ottenere il segnale, useremo 2 bordi centrali.
Se il prezzo buca il bordo superiore del Silver-Channel e il prezzo di chiusura è fissato al di sopra di questo bordo, è il segnale per acquistare. Se il prezzo buca il bordo inferiore del Silver-Channel e il prezzo di chiusura è fissato al di sotto di questo bordo, è il segnale per vendere.
int TradeSignal_14() { int sig=0; if(h_sc==INVALID_HANDLE) { h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8); return(0); } else { if(CopyBuffer(h_sc,0,0,2,sc1_buffer)<2) return(0); if(CopyBuffer(h_sc,1,0,2,sc2_buffer)<2) return(0); if(CopyClose(Symbol(),Period(),0,3,Close)<3) return(0); if(!ArraySetAsSeries(sc1_buffer,true)) return(0); if(!ArraySetAsSeries(sc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[2]<sc1_buffer[1] && Close[1]>sc1_buffer[1]) sig=1; else if(Close[2]>sc2_buffer[1] && Close[1]<sc2_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.15. Rottura del Canale Gallagher
Figura 15. Rottura dei bordi del canale Gallagher
Nel canale TradeSignal_15(), otterremo il segnale quando il prezzo buca i bordi del canale Gallagher. L'indicatore del canale Gallagher è disegnato da massimi e minimi per 10 giorni.
Se il prezzo buca il bordo superiore del canale Gallagher e il prezzo di chiusura è fissato al di sopra di questo bordo, è il segnale per acquistare. Se il prezzo buca il bordo inferiore del canale Gallagher e il prezzo di chiusura è fissato al di sotto di questo bordo, è il segnale per vendere.
int TradeSignal_15() { int sig=0; if(h_gc==INVALID_HANDLE) { h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher"); return(0); } else { if(CopyBuffer(h_gc,0,0,3,gc1_buffer)<3) return(0); if(CopyBuffer(h_gc,1,0,3,gc2_buffer)<3) return(0); if(CopyClose(Symbol(),Period(),0,2,Close)<2) return(0); if(!ArraySetAsSeries(gc1_buffer,true)) return(0); if(!ArraySetAsSeries(gc2_buffer,true)) return(0); if(!ArraySetAsSeries(Close,true)) return(0); } //--- check the condition and set a value for sig if(Close[1]>gc1_buffer[2]) sig=1; else if(Close[1]<gc2_buffer[2]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.16. Cambio di tendenza da parte dell’NRTR
Figura 16. Identificazione di un cambiamento di tendenza utilizzando l'indicatore NRTR
Nella funzione TradeSignal_16(), otterremo il segnale quando cambia la tendenza dell’NRTR.
Se l'indicatore NRTR mostra una tendenza al rialzo, è il segnale per acquistare. Se l’NRTR mostra una tendenza al ribasso, è il segnale per vendere.
int TradeSignal_16() { int sig=0; if(h_nrtr==INVALID_HANDLE) { h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0); return(0); } else { if(CopyBuffer(h_nrtr,0,0,2,nrtr1_buffer)<2) return(0); if(CopyBuffer(h_nrtr,1,0,2,nrtr2_buffer)<2) return(0); if(!ArraySetAsSeries(nrtr1_buffer,true)) return(0); if(!ArraySetAsSeries(nrtr2_buffer,true)) return(0); } //--- check the condition and set a value for sig if(nrtr1_buffer[1]>0) sig=1; else if(nrtr2_buffer[1]>0) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.17. Cambiamento di Tendenza da parte di Alligator
Figura 17. Cambiamento della Tendenza da parte di Alligator
Nella funzione TradeSignal_17(), otterremo il segnale quando Alligator cambia la tendenza.
Se Jaw, Teeth e Lips sono chiusi e attorcigliati, l'Alligator sta andando a dormire o sta già dormendo. Quando dorme, la sua fame cresce; e più dorme, più è affamato quando si sveglia. La prima cosa che fa quando si sveglia è aprire la bocca e sbadigliare. Poi inizia a sentire l'odore del cibo - la carne di un toro o di un orso, e poi inizia a cacciarlo. Quando Alligator ha mangiato abbastanza, perde il suo interesse per il prezzo del cibo (le Balance Lines convergono); è il momento di fissare il profitto.
int TradeSignal_17() { int sig=0; if(h_al==INVALID_HANDLE) { h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN); return(0); } else { if(CopyBuffer(h_al,0,0,2,al1_buffer)<2) return(0); if(CopyBuffer(h_al,1,0,2,al2_buffer)<2) return(0); if(CopyBuffer(h_al,2,0,2,al3_buffer)<2) return(0); if(!ArraySetAsSeries(al1_buffer,true)) return(0); if(!ArraySetAsSeries(al2_buffer,true)) return(0); if(!ArraySetAsSeries(al3_buffer,true)) return(0); } //--- check the condition and set a value for sig if(al3_buffer[1]>al2_buffer[1] && al2_buffer[1]>al1_buffer[1]) sig=1; else if(al3_buffer[1]<al2_buffer[1] && al2_buffer[1]<al1_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.18. Cambiamento di Tendenza da parte dell’AMA
Figura 18. Cambiamento di tendenza da parte dell’AMA
Nella funzione TradeSignal_18(), otterremo il segnale quando cambia la tendenza dell’AMA.
Se l'indicatore AMA è diretto verso l'alto, è il segnale per acquistare. Se l'AMA è diretto verso il basso, allora è il segnale per vendere.
int TradeSignal_18() { int sig=0; if(h_ama==INVALID_HANDLE) { h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE); return(0); } else { if(CopyBuffer(h_ama,0,0,3,ama_buffer)<3) return(0); if(!ArraySetAsSeries(ama_buffer,true)) return(0); } //--- check the condition and set a value for sig if(ama_buffer[2]<ama_buffer[1]) sig=1; else if(ama_buffer[2]>ama_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.19. Cambio di Colore dell'Awesome Oscillator
Figura 19. Identificazione di un cambiamento di tendenza utilizzando l'indicatore Awesome Oscillator
Nella funzione TradeSignal_19(), otterremo il segnale quando cambia il colore dell'istogramma Awesome Oscillator.
Una delle caratteristiche di MQL5 è la possibilità di creare buffer per indicatori, in cui è possibile memorizzare indici del colore delle linee impostate nelle proprietà #property indicator_colorN. Quando il colore dell'istogramma Awesome Oscillator è verde, è il segnale per acquistare. Se il suo colore diventa rosso, è il segnale per vendere.
int TradeSignal_19() { int sig=0; if(h_ao==INVALID_HANDLE) { h_ao=iAO(Symbol(),Period()); return(0); } else { if(CopyBuffer(h_ao,1,0,20,ao_buffer)<20) return(0); if(!ArraySetAsSeries(ao_buffer,true)) return(0); } //--- check the condition and set a value for sig if(ao_buffer[1]==0) sig=1; else if(ao_buffer[1]==1) sig=-1; else sig=0; //--- return the trade signal return(sig); }
3.20. Cambiamento di Tendenza da parte di Ichimoku
Figura 20. Identificazione di un cambiamento di tendenza utilizzando l'indicatore Ichimoku
Nella funzione TradeSignal_20(), otterremo il segnale quando cambia la tendenza di Ichimoku. A tale scopo, analizzeremo l'intersezione delle linee Tenkan-sen e Kijun-sen.
Il segnale di acquisto viene generato quando la linea Tenkan-sen attraversa il kijun-sen bottom-up. L'incrocio top-down è il segnale per vendere.
int TradeSignal_20() { int sig=0; if(h_ich==INVALID_HANDLE) { h_ich=iIchimoku(Symbol(),Period(),9,26,52); return(0); } else { if(CopyBuffer(h_ich,0,0,2,ich1_buffer)<2) return(0); if(CopyBuffer(h_ich,1,0,2,ich2_buffer)<2) return(0); if(!ArraySetAsSeries(ich1_buffer,true)) return(0); if(!ArraySetAsSeries(ich2_buffer,true)) return(0); } //--- check the condition and set a value for sig if(ich1_buffer[1]>ich2_buffer[1]) sig=1; else if(ich1_buffer[1]<ich2_buffer[1]) sig=-1; else sig=0; //--- return the trade signal return(sig); }
4. Rendilo un Indicatore
Ora, poiché abbiamo i blocchi di indicatori già pronti, possiamo iniziare a scrivere un indicatore che mostri i segnali sulla base di tutti i metodi selezionati. Utilizzando il modello creato, possiamo implementare la ricezione del segnale da qualsiasi indicatore; è sufficiente formulare correttamente una condizione di segnale e aggiungerla al codice.
Scriviamo un indicatore con parametri inflessibili integrati. I segnali degli indicatori saranno disegnati sotto forma di frecce (freccia in su -ma, giù - vendere, una croce - nessun segnale) sulla parte destra del grafico. Prendiamo il carattere standard Wingdings per disegnare le frecce. Inoltre, abbiamo bisogno di creare diverse altre funzioni per visualizzare le informazioni sui segnali sul grafico di un simbolo. Li combineremo in un blocco separato come una libreria che può essere utilizzata per scrivere i propri programmi aggiungendo nuove funzioni ad esso. Nominiamo LibFunctions questa libreria.
Nell'intestazione del nostro indicatore futuro, scrivi il collegamento del file con le funzioni per la generazione del segnale e la funzione di importazione necessarie per la visualizzazione grafica del segnale, oltre a dichiarare le variabili sul global scape che memorizzerà il tipo di segnale ricevuto dall'indicatore.
//--- Connect necessary libraries of functions #include <SignalTrade.mqh> //--- Import of functions from the LibFunctions library #import "LibFunctions.ex5" void SetLabel(string nm,string tx,ENUM_BASE_CORNER cn,ENUM_ANCHOR_POINT cr,int xd,int yd,string fn,int fs,double yg,color ct); string arrow(int sig); color Colorarrow(int sig); #import //+------------------------------------------------------------------+ //| Declare variables for storing signals of indicators | //+------------------------------------------------------------------+ int SignalMA; int SignalMACD; int SignalPC; int SignalACADX; int SignalST; int SignalRSI; int SignalCCI; int SignalWPR; int SignalBB; int SignalSDC; int SignalPC2; int SignalENV; int SignalDC; int SignalSC; int SignalGC; int SignalNRTR; int SignalAL; int SignalAMA; int SignalAO; int SignalICH;
Come accennato in precedenza, gli indicatori vengono caricati sul terminale una sola volta e vengono creati i puntatori (handle) per tali indicatori; ecco perché implementiamo la loro creazione nella funzione OnInit(), poiché questa funzione viene eseguita solo una volta all'avvio del programma.
int OnInit() { //--- create indicator handles h_ma1=iMA(Symbol(),Period(),8,0,MODE_SMA,PRICE_CLOSE); h_ma2=iMA(Symbol(),Period(),16,0,MODE_SMA,PRICE_CLOSE); h_macd=iMACD(Symbol(),Period(),12,26,9,PRICE_CLOSE); h_pc=iCustom(Symbol(),Period(),"Price Channel",22); h_acadx=iCustom(Symbol(),Period(),"AdaptiveChannelADX",14); h_stoh=iStochastic(Symbol(),Period(),5,3,3,MODE_SMA,STO_LOWHIGH); h_rsi=iRSI(Symbol(),Period(),14,PRICE_CLOSE); h_cci=iCCI(Symbol(),Period(),14,PRICE_TYPICAL); h_wpr=iWPR(Symbol(),Period(),14); h_bb=iBands(Symbol(),Period(),20,0,2,PRICE_CLOSE); h_sdc=iCustom(Symbol(),Period(),"StandardDeviationChannel",14,0,MODE_SMA,PRICE_CLOSE,2.0); h_env=iEnvelopes(Symbol(),Period(),28,0,MODE_SMA,PRICE_CLOSE,0.1); h_dc=iCustom(Symbol(),Period(),"Donchian Channels",24,3,-2); h_sc=iCustom(Symbol(),Period(),"Silver-channels",26,38.2,23.6,0,61.8); h_gc=iCustom(Symbol(),Period(),"PriceChannelGalaher"); h_nrtr=iCustom(Symbol(),Period(),"NRTR",40,2.0); h_al=iAlligator(Symbol(),Period(),13,0,8,0,5,0,MODE_SMMA,PRICE_MEDIAN); h_ama=iAMA(Symbol(),Period(),9,2,30,0,PRICE_CLOSE); h_ao=iAO(Symbol(),Period()); h_ich=iIchimoku(Symbol(),Period(),9,26,52); return(0); }
Tutti i calcoli principali vengono eseguiti nella funzione OnCalculate(); lì, inseriremo il resto del codice dell'indicatore.
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[]) { //---assign the signal value to the variable SignalMA = TradeSignal_01(); SignalMACD = TradeSignal_02(); SignalPC = TradeSignal_03(); SignalACADX = TradeSignal_04(); SignalST = TradeSignal_05(); SignalRSI = TradeSignal_06(); SignalCCI = TradeSignal_07(); SignalWPR = TradeSignal_08(); SignalBB = TradeSignal_09(); SignalSDC = TradeSignal_10(); SignalPC2 = TradeSignal_11(); SignalENV = TradeSignal_12(); SignalDC = TradeSignal_13(); SignalSC = TradeSignal_14(); SignalGC = TradeSignal_15(); SignalNRTR = TradeSignal_16(); SignalAL = TradeSignal_17(); SignalAMA = TradeSignal_18(); SignalAO = TradeSignal_19(); SignalICH = TradeSignal_20(); //--- draw graphical objects on the chart in the upper left corner int size=((int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS)/22); int i=0; int x=10; int y=0; int fz=size-4; y+=size; SetLabel("arrow"+(string)i,arrow(SignalMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMA)); x+=size; SetLabel("label"+(string)i,"Moving Average",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalMACD),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalMACD)); x+=size; SetLabel("label"+(string)i,"MACD",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalPC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC)); x+=size; SetLabel("label"+(string)i,"Price Channell",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalACADX),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalACADX)); x+=size; SetLabel("label"+(string)i,"Adaptive Channel ADX",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalST),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalST)); x+=size; SetLabel("label"+(string)i,"Stochastic Oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalRSI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalRSI)); x+=size; SetLabel("label"+(string)i,"RSI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalCCI),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalCCI)); x+=size; SetLabel("label"+(string)i,"CCI",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalWPR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalWPR)); x+=size; SetLabel("label"+(string)i,"WPR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalBB),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalBB)); x+=size; SetLabel("label"+(string)i,"Bollinger Bands",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalSDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSDC)); x+=size; SetLabel("label"+(string)i,"StDevChannel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalPC2),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalPC2)); x+=size; SetLabel("label"+(string)i,"Price Channell 2",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalENV),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalENV)); x+=size; SetLabel("label"+(string)i,"Envelopes",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalDC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalDC)); x+=size; SetLabel("label"+(string)i,"Donchian Channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalSC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalSC)); x+=size; SetLabel("label"+(string)i,"Silver-channels",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalGC),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalGC)); x+=size; SetLabel("label"+(string)i,"Galaher Channel",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalNRTR),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalNRTR)); x+=size; SetLabel("label"+(string)i,"NRTR",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalAL),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAL)); x+=size; SetLabel("label"+(string)i,"Alligator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalAMA),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAMA)); x+=size; SetLabel("label"+(string)i,"AMA",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalAO),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalAO)); x+=size; SetLabel("label"+(string)i,"Awesome oscillator",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); i++;y+=size;x=10; SetLabel("arrow"+(string)i,arrow(SignalICH),CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y+4,"Wingdings",fz-2,0,Colorarrow(SignalICH)); x+=size; SetLabel("label"+(string)i,"Ichimoku Kinko Hyo",CORNER_RIGHT_UPPER,ANCHOR_RIGHT_UPPER,x,y,"Arial",fz,0,BlueViolet); return(rates_total); }
Bene, il nostro indicatore è pronto. Alla fine, avremo la seguente immagine sul grafico.
5. Rendilo un Expert Advisor
Allo stesso modo, possiamo scrivere un Expert Advisor che mostra il segnale dell'indicatore sul grafico. Implementiamo un sistema informativo con gli elementi di controllo grafico. È possibile scegliere un indicatore necessario e impostarne i parametri attraverso l'interfaccia grafica.
Qui non parleremo dell'implementazione dell'interfaccia grafica; puoi trovare le informazioni al riguardo nell'articolo Creazione di Pannelli di Controllo Attivi in MQL5 per il Trading.
Per modificare le impostazioni degli indicatori attraverso la nostra interfaccia grafica, miglioriamo la nostra libreria SignalTrade.mqh e la nominiamo SignalTradeExp.mqh.
Innanzitutto, abbiamo bisogno di variabili aggiuntive per memorizzare le impostazioni degli indicatori.
//--- input parameters Moving Average int periodma1=8; int periodma2=16; ENUM_MA_METHOD MAmethod=MODE_SMA; ENUM_APPLIED_PRICE MAprice=PRICE_CLOSE; //--- input parameters MACD int FastMACD=12; int SlowMACD=26; int MACDSMA=9; ENUM_APPLIED_PRICE MACDprice=PRICE_CLOSE; //--- input parameters Price Channel int PCPeriod=22; //--- input parameters Adaptive Channel ADX int ADXPeriod=14; //--- input parameters Stochastic Oscillator int SOPeriodK=5; int SOPeriodD=3; int SOslowing=3; ENUM_MA_METHOD SOmethod=MODE_SMA; ENUM_STO_PRICE SOpricefield=STO_LOWHIGH; //--- input parameters RSI int RSIPeriod=14; ENUM_APPLIED_PRICE RSIprice=PRICE_CLOSE; //--- input parameters CCI int CCIPeriod=14; ENUM_APPLIED_PRICE CCIprice=PRICE_TYPICAL; //--- input parameters WPR int WPRPeriod=14; //--- input parameters Bollinger Bands int BBPeriod=20; double BBdeviation=2.0; ENUM_APPLIED_PRICE BBprice=PRICE_CLOSE; //--- input parameters Standard Deviation Channel int SDCPeriod=14; double SDCdeviation=2.0; ENUM_APPLIED_PRICE SDCprice=PRICE_CLOSE; ENUM_MA_METHOD SDCmethod=MODE_SMA; //--- input parameters Price Channel 2 int PC2Period=22; //--- input parameters Envelopes int ENVPeriod=14; double ENVdeviation=0.1; ENUM_APPLIED_PRICE ENVprice=PRICE_CLOSE; ENUM_MA_METHOD ENVmethod=MODE_SMA; //--- input parameters Donchian Channels int DCPeriod=24; int DCExtremes=3; int DCMargins=-2; //--- input parameters Silver-channels int SCPeriod=26; double SCSilvCh=38.2; double SCSkyCh=23.6; double SCFutCh=61.8; //--- input parameters NRTR int NRTRPeriod = 40; double NRTRK = 2.0; //--- input parameters Alligator int ALjawperiod=13; int ALteethperiod=8; int ALlipsperiod=5; ENUM_MA_METHOD ALmethod=MODE_SMMA; ENUM_APPLIED_PRICE ALprice=PRICE_MEDIAN; //--- input parameters AMA int AMAperiod=9; int AMAfastperiod=2; int AMAslowperiod=30; ENUM_APPLIED_PRICE AMAprice=PRICE_CLOSE; //--- input parameters Ichimoku Kinko Hyo int IKHtenkansen=9; int IKHkijunsen=26; int IKHsenkouspanb=52;
Sostituire i valori costanti degli indicatori con le variabili. Altre cose dovrebbero essere lasciate invariate.
h_ma1=iMA(Symbol(),Period(),periodma1,0,MAmethod,MAprice);
Un punto significativo è l'uso economico della memoria del computer; quando si modificano le impostazioni, è necessario scaricare la copia dell'indicatore con le vecchie impostazioni e caricarne una nuova. Questo si può fare usando la seguente funzione:
bool IndicatorRelease( int indicator_handle, // indicator handle );
if(id==CHARTEVENT_OBJECT_ENDEDIT && sparam=="PIPSetEditMA2") { periodma2=(int)ObjectGetString(0,"PIPSetEditMA2",OBJPROP_TEXT); ObjectSetString(0,"PIPSetEditMA2",OBJPROP_TEXT,(string)periodma2); //--- unload old copy of the indicator IndicatorRelease(h_ma2); //--- create new copy of the indicator h_ma2=iMA(Symbol(),Period(),periodma2,0,MAmethod,MAprice); ChartRedraw(); }
Conclusione
Pertanto, abbiamo imparato come leggere le informazioni dagli indicatori e come passarle all’Expert Advisor. In tal modo, è possibile ottenere segnali da qualsiasi indicatore.
Nota
- I file degli indicatori SignalTrade.mq5, AdaptiveChannelADX.mq5, Donchian Channels.mq5, NRTR.mq5, Price Channel.mq5, PriceChannelGalaher.mq5, Silver-channels.mq5, StandardDeviationChannel.mq5 devono essere copiati nella cartella ...\MQL5\Indicators.
- SignalTrade.mqh e SignalTradeExp.mqh include files devono essere copiati nella cartella ...\MQL5\Include.
- La libreria di funzioni LibFunctions.mq5 deve essere copiata nella cartella ...\MQL5\Libraries.
- ExpSignalTrade.mq5 Expert Advisor deve essere copiato in ...\MQL5\Experts.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/130
![Il Prototipo di Robot di Trading](https://c.mql5.com/2/0/Prototype_Expert_Advisor_MQL5.png)
![Come Scrivere un Indicatore sulla Base di un Altro Indicatore](https://c.mql5.com/2/0/indicator_based_on_other_MQL5__1.png)
![Come creare il Tuo Trailing Stop](https://c.mql5.com/2/0/Trailing_Stop_MQL5.png)
![Funzioni di Money Management in un Expert Advisor](https://c.mql5.com/2/0/money_management_MQL5__1.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