
L'indicatore ZigZag: Nuovo approccio e nuove soluzioni
Introduzione
Ogni trader conosce sicuramente l'indicatore ZigZag destinato all'analisi dei movimenti di prezzo di una certa o maggiore ampiezza. Una linea ZigZag è una linea spezzata i cui nodi si trovano ai massimi e ai minimi del grafico dei prezzi.
Esistono molte varianti di questo indicatore: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16. Tuttavia, molti sviluppatori di programmi MQL5 sono desiderosi di creare il proprio ZigZag "ideale". I principali svantaggi dell'indicatore ZigZag sono ritardi, contrassegni errati di nodi discutibili (barra esterna) e prestazioni insoddisfacenti.
Secondo me, l'implementazione ZigZag più elegante è stata proposta da Yuri Kulikov (Yurich). Inoltre, ci sono alcuni ottimi articoli MQL4, come "Layman's Notes: ZigZag..." e "Show Must Go On, or Once Again about ZigZag". L'argomento sembra essere stato ampiamente esplorato, con un gran numero di pubblicazioni disponibili. Eppure c'è qualcosa di magnetizzante in questo. Ora ha catturato anche il mio interesse, in particolare per la possibilità di creare un indicatore ZigZag avanzato.
Questo articolo descrive un metodo per creare uno ZigZag avanzato utilizzando l'indicatore Inviluppo. Si presume di poter trovare una certa combinazione di parametri di input per una serie di inviluppo, per cui la maggior parte dei nodi ZigZag si trova all'interno dei confini delle bande di Envelopes (inviluppo).
Un metodo per creare un indicatore ZigZag avanzato
Stabiliremo un obiettivo: trovare le coordinate di due nodi: il nodo corrente e il nodo previsto (Fig. 1). Il nodo corrente è un nodo non ancora completato le cui coordinate sono ancora in fase di ricerca o regolazione. Inoltre, è sempre sulla barra corrente (zero). Pur essendo nel futuro, un nodo previsto deve mostrare il livello stimato del prossimo nodo ZigZag.
Fig. 1. Previsione di nuovi nodi ZigZag: il nodo corrente e il nodo successivo.
Quindi l'obiettivo è fissato e abbiamo un'idea di come utilizzare le inviluppo a media mobile come base per costruire un indicatore avanzato (Fig. 2). Cercheremo le inviluppo la cui deviazione dai nodi ZigZag è minima. Sembra abbastanza logico che le inviluppo per i picchi e gli avvallamenti ZigZag debbano essere cercati separatamente.
Fig. 2. Indicatori ZigZag e inviluppo a media mobile.
Per aumentare la significatività statistica della previsione, invece di utilizzare solo uno o anche 10 indicatori Inviluppo, dovremmo utilizzare un pool di 100 o più indicatori con dati di input diversi. Differiranno nel periodo di media della linea dell'indicatore principale e nel prezzo utilizzato (Alto per i picchi e Basso per i minimi). Introduciamo le seguenti notazioni e formule:
- ZZ- l'indicatore ZigZag;
- ENV - la linea principale dell'indicatore Inviluppo (coincide con l'indicatore iMA);
- Inviluppo(i) - valore della riga principale dell'indicatore Inviluppo sulla i-esima barra;
- ZZ(High) - Valore di picco ZigZag;
- ZZ(Low) - Valore minimo ZigZag;
- ENV(High) - valore della linea principale dell'indicatore Inviluppo corrispondente ad un picco ZigZag;
- ENV(Low) - valore della linea principale dell'indicatore Inviluppo corrispondente ad un avvallamento ZigZag;
- n_high - numero di picchi ZigZag;
- n_low - numero di depressioni ZigZag.
Abbiamo due gruppi di indicatori: uno per i picchi e l'altro per i minimi (circa 100 indicatori in ciascuno). Calcoleremo la deviazione dei nodi ZigZag dalla linea principale dell'indicatore Envelopes per ciascun indicatore nel pool e troveremo la media aritmetica delle deviazioni per ciascun indicatore del pool utilizzando le formule di cui sopra. La figura seguente mostra un diagramma delle deviazioni rispetto ai nodi identificati ZZ dalla linea principale ENV per un indicatore.
Fig. 3. Diagramma delle deviazioni dei nodi ZZ da ENV.
La media aritmetica delle deviazioni verrà utilizzata per determinare il livello a cui deve essere spostata la linea principale dell'indicatore inviluppo per tracciare le bande delle Envelopes (inviluppo). Quindi, avremo bisogno della media aritmetica delle deviazioni dai picchi ZigZag per disegnare la linea superiore e della media aritmetica delle deviazioni dai minimi per disegnare la linea inferiore dell'indicatore delle inviluppo.
Sono le linee superiori e inferiori delle inviluppo che useremo per trovare punti caratteristici e prevedere i nodi ZigZag. Ancora una volta, siamo interessati al pool di inviluppo costituito da un insieme di indicatori Inviluppo. Per ogni indicatore viene calcolata la media aritmetica delle deviazioni dei nodi ZigZag dalla linea principale di un dato Envelopes (inviluppo). Dopo aver tracciato le linee risultanti (la linea superiore e inferiore) del pool nel grafico, saremo in grado di vedere quanto segue:
Fig. 4. Le linee di inviluppo sull'aereo.
Se assumiamo che ogni linea si trovi su un piano separato, mentre tutte insieme creano una superficie, la figura sopra mostra solo la proiezione di ciascun indicatore sul piano del grafico dei prezzi. Un'immagine 3D di queste linee sarà approssimativamente la seguente:
Fig. 5. Le linee di inviluppo in 3D.
Diamo ora una rapida lezione di geometria. Immagina che il pool di linee dell'indicatore Envelopes sia una superficie 3D. Prendi un piano perpendicolare al grafico dei prezzi e taglia la superficie in corrispondenza della barra corrente (zero).
Di conseguenza, otteniamo una sezione trasversale della superficie che rappresenta una curva (le figure sopra mostrano un caso speciale in cui la curva è una linea retta). Per fare la previsione è sufficiente avere le coordinate di ogni punto sulla curva che verranno ulteriormente utilizzate nei calcoli.
Avremo bisogno delle seguenti caratteristiche della sezione trasversale: punto massimo e minimo, nonché il baricentro della sezione trasversale (la media aritmetica di tutti i valori dei punti). I punti caratteristici ottenuti verranno proiettati sulla barra corrente (zero), con i relativi dati memorizzati nella cronologia. Questi punti caratteristici serviranno come base per i nodi ZigZag attuali e successivi.
Poiché la ricerca delle bande di Envelopes (inviluppo) viene eseguita separatamente per picchi e avvallamenti, di conseguenza dovremmo ottenere due sezioni d'urto: una per i picchi e l'altra per gli avvallamenti.
Per ottenere la previsione, utilizzeremo il punto caratteristico più vicino. Ad esempio, durante la ricerca di un picco ZigZag, prendiamo i punti caratteristici della sezione trasversale risultanti dall'intersezione della superficie delle linee superiori dell'indicatore Inviluppo con un piano di taglio. Viceversa, per trovare un avvallamento si prendono i punti caratteristici della sezione risultante dall'intersezione della superficie delle linee inferiori dell'indicatore Inviluppo con un piano di taglio.
Test del nuovo indicatore
Ora che abbiamo definito il metodo, creiamo l'indicatore. Per prima cosa troveremo gli ultimi nodi dell'indicatore ZigZag e li disegneremo nel grafico. A questo scopo, utilizzeremo la classe AdvancedZigZag scritta per il compito in questione:
//+------------------------------------------------------------------+ //| AdvancedZigZag.mqh | //| Copyright 2013, DC2008 | //| https://www.mql5.com/ru/users/DC2008 | //+------------------------------------------------------------------+ #property copyright "Copyright 2013, DC2008" #property link "https://www.mql5.com/ru/users/DC2008" #property version "1.00" //+------------------------------------------------------------------+ //| GetExtremums.mqh | //+------------------------------------------------------------------+ #include <GetExtremums.mqh> // author of the code Yurich #property copyright "Copyright 2012, Yurich" #property link "https://www.mql5.com/ru/users/Yurich" //+------------------------------------------------------------------+ //| ZigZag node structure | //+------------------------------------------------------------------+ struct MqlZigZag { double price; // Node coordinate datetime t; // Time }; //+------------------------------------------------------------------+ //| The AdvancedZigZag class | //+------------------------------------------------------------------+ class AdvancedZigZag { private: MqlRates rt[]; dextremum zz[]; int history; double amplitude; public: dextremum zHL[]; MqlZigZag zzH[],zzL[]; int Count(const double range); int Read(const int nodes); AdvancedZigZag(const int bars); ~AdvancedZigZag(); }; //+------------------------------------------------------------------+ //| Class constructor | //+------------------------------------------------------------------+ AdvancedZigZag::AdvancedZigZag(const int bars) { history=bars; amplitude=0; } //+------------------------------------------------------------------+ //| The Read method of the class | //+------------------------------------------------------------------+ int AdvancedZigZag::Read(const int nodes) { CopyRates(NULL,0,TimeCurrent(),history,rt); int cnt=GetExtremums(amplitude,rt,zHL,nodes); return(cnt); } //+------------------------------------------------------------------+ //| The Count method of the class | //+------------------------------------------------------------------+ int AdvancedZigZag::Count(const double range) { amplitude=range; CopyRates(NULL,0,TimeCurrent(),history,rt); int cnt=GetExtremums(amplitude,rt,zz); ArrayResize(zzH,cnt); ArrayResize(zzL,cnt); int h=0; int l=0; for(int i=0; i<cnt; i++) { if(zz[i].type>0) { zzH[h]=(MqlZigZag)zz[i]; h++; } else { zzL[l]=(MqlZigZag)zz[i]; l++; } } ArrayResize(zzH,h); ArrayResize(zzL,l); return(cnt); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ AdvancedZigZag::~AdvancedZigZag() { }
Ci sono due metodi in totale:
- Il metodo Count trova tutti i nodi ZigZag in un determinato periodo di tempo (numero di barre) e li salva in vari array, separando i picchi dai minimi. In questo modo sarà più semplice fare l'analisi e il calcolo delle inviluppo;
- Il metodo Read trova gli ultimi nodi e li salva in un singolo array. Abbiamo bisogno di questo metodo per la visualizzazione dell'indicatore ZigZag;
La libreria GetExtremums (di Yury Kulikov) sarà necessaria anche nella ricerca dei nodi.
Mettiamo l'indicatore in esame in un Expert Advisor. Perché un Expert Advisor e non un indicatore? Questa è ovviamente una questione di gusti, ma mi sembra che sia più efficiente in questo modo. Le funzionalità grafiche di Expert Advisor sono indubbiamente più deboli, ma guadagniamo in termini di prestazioni poiché gli indicatori dello stesso simbolo operano in un unico flusso, mentre ogni EA opera nel proprio flusso separato. Diamo un'occhiata al codice:
//+------------------------------------------------------------------+ //| two_Comets.mq5 | //| Copyright 2013, DC2008 | //| https://www.mql5.com/ru/users/DC2008 | //+------------------------------------------------------------------+ #property copyright "Copyright 2013, DC2008" #property link "https://www.mql5.com/ru/users/DC2008" #property version "1.00" #include <AdvancedZigZag.mqh> //--- Depth of history for the indicator calculation input int depth_stories=5000; // Depth stories for calculating the indicator [bars] //--- Minimum ZigZag amplitude value input int amplitude=100; // The minimum value of the amplitude of the indicator [points] //--- Declaring the class AdvancedZigZag Azz(depth_stories); //--- #define NUMBER_MA 227 #define START_MA 5 //--- macros #define SIZE(i) (double)i*0.3<1?1:(int)(i*0.25) #define ObjF1 ObjectSetString(0,name,OBJPROP_FONT,"Wingdings") #define ObjF2 ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_CENTER) #define ObjF3(T) ObjectSetInteger(0,name,OBJPROP_TIME,T) #define ObjF4(P) ObjectSetDouble(0,name,OBJPROP_PRICE,P) #define ObjF5(size) ObjectSetInteger(0,name,OBJPROP_FONTSIZE,size) #define ObjF6(code) ObjectSetString(0,name,OBJPROP_TEXT,CharToString(code)) #define ObjF7(clr) ObjectSetInteger(0,name,OBJPROP_COLOR,clr) #define ObjF8 ObjectSetInteger(0,name,OBJPROP_COLOR,clrMagenta) #define ObjF9 ObjectSetInteger(0,name,OBJPROP_WIDTH,3) #define ObjF10 ObjectSetInteger(0,name,OBJPROP_BACK,true) #define ObjFont ObjF1;ObjF2; #define ObjCoordinates(T,P) ObjF3(T);ObjF4(P); #define ObjProperty(size,code,clr) ObjF5(size);ObjF6(code);ObjF7(clr); #define ObjZZ ObjF8;ObjF9;ObjF10; //--- double MA[1],sumHi[NUMBER_MA],sumLo[NUMBER_MA]; int handle_MA_H[NUMBER_MA],handle_MA_L[NUMBER_MA]; datetime t[1]; int H,L; int t_min,t_max; int err=-1; double sumH[2],maxH[2],minH[2]; double sumL[2],maxL[2],minL[2]; string name; int count; int shift; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { shift=PeriodSeconds()/30; //--- calculation of ZigZag nodes using historical data Azz.Count(amplitude*Point()); H=ArraySize(Azz.zzH); L=ArraySize(Azz.zzL); if(H<30 || L<30) { Print("Not enough data to calculate ZigZag nodes: "+ "increase the depth of history; "+ "or decrease the amplitude value."); return(-1); } //--- for(int i=0; i<NUMBER_MA; i++) { handle_MA_H[i]=iMA(NULL,0,i+START_MA,0,MODE_SMA,PRICE_HIGH); handle_MA_L[i]=iMA(NULL,0,i+START_MA,0,MODE_SMA,PRICE_LOW); } //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(0,-1,-1); for(int i=0; i<NUMBER_MA; i++) { IndicatorRelease(handle_MA_H[i]); IndicatorRelease(handle_MA_L[i]); } //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get the current bar's opening time value CopyTime(NULL,0,0,1,t); //--- ZigZag: last 7 nodes count=Azz.Read(7); for(int i=1; i<count; i++) { name="ZZ"+(string)i; ObjectCreate(0,name,OBJ_TREND,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,clrRed); ObjectSetInteger(0,name,OBJPROP_WIDTH,10); ObjectSetInteger(0,name,OBJPROP_BACK,true); ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[i-1].value); ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[i-1].time); ObjectSetDouble(0,name,OBJPROP_PRICE,1,Azz.zHL[i].value); ObjectSetInteger(0,name,OBJPROP_TIME,1,Azz.zHL[i].time); } //--- check for integrity of preliminary calculations if(err<0) { //--- calculate the sums of deviations of the nodes from MA for ZigZag peaks ArrayInitialize(sumHi,0.0); for(int j=H-1; j>=0; j--) { for(int i=0; i<NUMBER_MA; i++) { err=CopyBuffer(handle_MA_H[i],0,Azz.zzH[j].t,1,MA); if(err<0) return; sumHi[i]+=Azz.zzH[j].price-MA[0]; } } //--- calculate the sums of deviations of the nodes from MA for ZigZag troughs ArrayInitialize(sumLo,0.0); for(int j=L-1; j>=0; j--) { for(int i=0; i<NUMBER_MA; i++) { err=CopyBuffer(handle_MA_L[i],0,Azz.zzL[j].t,1,MA); if(err<0) return; sumLo[i]+=MA[0]-Azz.zzL[j].price; } } } } //+------------------------------------------------------------------+
Dobbiamo chiarire alcune cose qui:
- L'indicatore iEnvelopes viene sostituito dall'indicatore iMA. Non c'è nulla di falso o fuorviante in esso. Il fatto è che la linea principale di iEnvelopes coincide con iMA! È quindi più conveniente utilizzare l'indicatore della media mobile.
- Usiamo due pool di medie mobili, composti da 227 linee ciascuno, per un totale di 454 indicatori iMA! È molto o poco? Fondamentalmente, è un numero grande. Ma, prima di tutto, possiamo cambiare il numero di indicatori, se necessario, e in secondo luogo, abbiamo bisogno delle statistiche. Qual è il punto nella ricerca di inviluppo per una dozzina di nodi? Ne servono almeno un centinaio.
- I valori degli indicatori vengono caricati nel blocco OnTick() anziché OnInit(). Se il blocco di caricamento dei dati viene posizionato in OnInit(), è molto probabile che alcuni dati possano essere caricati in ritardo e gli indicatori di conseguenza non verranno calcolati in modo accurato e completo. Dopo aver ottenuto tutti i dati per i calcoli, il valore della variabile err diventerà positivo e questo blocco verrà escluso dall'operazione.
Quindi, l'indicatore risultante traccia gli ultimi sette nodi ZigZag e calcola le coordinate di tutti gli altri nodi in una data cronologia (Fig. 6). Il calcolo viene eseguito solo una volta e utilizziamo ulteriormente i dati calcolati. Puoi ovviamente implementarlo in modo tale da consentire un aggiornamento regolare dei dati ma in questo articolo lo terremo per un solo passaggio.
Fig. 6. L'indicatore ZigZag (7 nodi).
Tracciamo inoltre le sezioni trasversali delle superfici degli indicatori delle inviluppo. Per fare ciò, aggiungeremo quanto segue al metodo OnTick():
//--- PEAKS sumH[0]=0.0; maxH[0]=0.0; minH[0]=0.0; for(int i=0; i<NUMBER_MA; i++) { CopyBuffer(handle_MA_H[i],0,t[0],1,MA); double envelope=MA[0]+sumHi[i]/H; if(i==0 || envelope<minH[0]) { minH[0]=envelope; t_min=SIZE(i); } if(envelope>maxH[0]) { maxH[0]=envelope; t_max=SIZE(i); } sumH[0]+=envelope; name="H"+(string)i; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0]-(NUMBER_MA-i*2)*shift,envelope) ObjProperty(SIZE(i),158,clrBlue) } //--- TROUGHS sumL[0]=0.0; maxL[0]=0.0; minL[0]=0.0; for(int i=0; i<NUMBER_MA; i++) { CopyBuffer(handle_MA_L[i],0,t[0],1,MA); double envelope=MA[0]-sumLo[i]/L; if(i==0 || envelope<minL[0]) { minL[0]=envelope; t_min=SIZE(i); } if(envelope>maxL[0]) { maxL[0]=envelope; t_max=SIZE(i); } sumL[0]+=envelope; name="L"+(string)i; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0]+(NUMBER_MA-i*2)*shift,envelope) ObjProperty(SIZE(i),158,clrGold) }
Per discernere i punti di sezione della superficie formata dalle linee delle inviluppo, i punti variano di dimensione: maggiore è il periodo medio della linea principale degli indicatori delle inviluppo, più grandi sono i punti (Fig. 7). Inoltre, le sezioni trasversali vengono ruotate attorno ad un asse verticale passante per la barra corrente (zero) in diverse direzioni: i picchi sono a 90 gradi a destra e gli avvallamenti sono a 90 gradi a sinistra.
Ora possono essere visti nel piano del grafico dei prezzi. Inizialmente giacevano sul piano di taglio (Fig. 5) e non potevano essere osservati. Potevamo solo immaginarli a noi stessi, senza avere alcuna idea della loro forma. Le linee di sezione si sono rivelate di una forma molto particolare. Questo viene fatto anche per comodità di analisi grafica. Visivamente le sezioni trasversali assomigliano a due comete volanti:
Fig. 7. Sezione trasversale del pool di indicatori Inviluppo.
Procediamo al calcolo delle caratteristiche della sezione d'urto: la massima e la minima, nonché il baricentro (media aritmetica). I valori risultanti verranno visualizzati come punti sulla barra corrente, con la dimensione in punti corrispondente alla dimensione della relativa caratteristica. Inoltre, li salveremo nella cronologia per ulteriori analisi. Quindi, aggiungeremo quanto segue al codice esistente:
//--- PEAKS ... //--- midi string str=(string)t[0]; name="Hmidi"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],sumH[0]/NUMBER_MA) ObjProperty(10,119,clrBlue) //--- max name="Hmax"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],maxH[0]) ObjProperty(t_max,158,clrBlue) //--- min name="Hmin"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],minH[0]) ObjProperty(t_min,158,clrBlue) ... //--- TROUGHS ... //--- midi name="Lmidi"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],sumL[0]/NUMBER_MA) ObjProperty(10,119,clrGold) //--- max name="Lmax"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],maxL[0]) ObjProperty(t_max,158,clrGold) //--- min name="Lmin"+str; ObjectCreate(0,name,OBJ_TEXT,0,0,0); ObjFont ObjCoordinates(t[0],minL[0]) ObjProperty(t_min,158,clrGold)
Ora vediamo come appare quando viene rappresentato graficamente:
Fig. 8. Caratteristiche della sezione trasversale: il massimo e il minimo, nonché il baricentro tracciato separatamente per picchi e avvallamenti.
Abbiamo solo bisogno di aggiungere l'ultimo tocco finale trovando e tracciando i nodi ZigZag avanzati. Miglioriamo il codice aggiungendo quanto segue:
//--- ZigZag: advanced nodes if(Azz.zHL[0].type>0) // peak { ObjectDelete(0,"MIN"); ObjectDelete(0,"MINfuture"); name="MAX"; ObjectCreate(0,name,OBJ_TREND,0,0,0); ObjZZ ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[1].value); ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[1].time); ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]); double price=minH[0]; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); if(Azz.zHL[0].value>minH[0]) { price=sumH[0]/NUMBER_MA; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); } if(Azz.zHL[0].value>sumH[0]/NUMBER_MA) { price=maxH[0]; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); } //--- into the future name="MAXfuture"; ObjectCreate(0,name,OBJ_TREND,0,0,0); ObjZZ ObjectSetDouble(0,name,OBJPROP_PRICE,0,price); ObjectSetInteger(0,name,OBJPROP_TIME,0,t[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,maxL[0]); ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]+NUMBER_MA*shift); if(price<maxL[0]) ObjectSetDouble(0,name,OBJPROP_PRICE,1,sumL[0]/NUMBER_MA); if(price<sumL[0]/NUMBER_MA) ObjectSetDouble(0,name,OBJPROP_PRICE,1,minL[0]); } if(Azz.zHL[0].type<0) // trough { ObjectDelete(0,"MAX"); ObjectDelete(0,"MAXfuture"); name="MIN"; ObjectCreate(0,name,OBJ_TREND,0,0,0); ObjZZ ObjectSetDouble(0,name,OBJPROP_PRICE,0,Azz.zHL[1].value); ObjectSetInteger(0,name,OBJPROP_TIME,0,Azz.zHL[1].time); ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]); double price=maxL[0]; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); if(Azz.zHL[0].value<maxL[0]) { price=sumL[0]/NUMBER_MA; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); } if(Azz.zHL[0].value<sumL[0]/NUMBER_MA) { price=minL[0]; ObjectSetDouble(0,name,OBJPROP_PRICE,1,price); } //--- into the future name="MINfuture"; ObjectCreate(0,name,OBJ_TREND,0,0,0); ObjZZ ObjectSetDouble(0,name,OBJPROP_PRICE,0,price); ObjectSetInteger(0,name,OBJPROP_TIME,0,t[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,minH[0]); ObjectSetInteger(0,name,OBJPROP_TIME,1,t[0]+NUMBER_MA*shift); if(price>minH[0]) ObjectSetDouble(0,name,OBJPROP_PRICE,1,sumH[0]/NUMBER_MA); if(price>sumH[0]/NUMBER_MA) ObjectSetDouble(0,name,OBJPROP_PRICE,1,maxH[0]); }
Quindi, abbiamo il nuovo indicatore ZigZag avanzato che prevede la posizione di nuovi nodi (Fig. 9). I nodi stessi si trovano nei punti caratteristici della sezione trasversale: il massimo, il minimo e il baricentro. Il titolo provvisorio dell'indicatore è "Due comete".
Va notato che il tempo di completamento del nodo successivo, che è futuro, è rimasto sconosciuto. Fondamentalmente, possiamo prevedere solo una coordinata del nodo: il prezzo.
Fig. 9. L'indicatore ZigZag avanzato prevede i nodi: quello attuale e quello successivo.
Analisi dei risultati e raccomandazioni per gli sviluppatori
Le osservazioni degli indicatori hanno mostrato che:
- Le deviazioni delle coordinate del nodo ZigZag dai nodi previsti sono all'interno della regione di tolleranza. Il vasto numero di nodi giace nell'ombra della corrispondente sezione trasversale. Questa è certamente solo una valutazione qualitativa. Risultati più accurati seguiranno nei prossimi articoli.
- Le sezioni trasversali delle linee delle inviluppo dimostrano il comportamento del mercato e l'andamento dei prezzi previsto! Prestare attenzione alla coda della cometa che è composta da punti con il periodo medio più piccolo (il più piccolo per dimensione). È diretto nella direzione del prezzo. La coda della cometa si piega nei modi più intricati e più è girata nella direzione opposta, maggiori sono le possibilità di vedere il cambiamento di tendenza. Basta guardare il comportamento dell'indicatore su diversi intervalli di tempo con diverse ampiezze. Questo è estremamente interessante!
- I punti caratteristici delle sezioni trasversali formano linee che possono presentare una forte resistenza al movimento dei prezzi. Pertanto possono essere considerati come linee di supporto e resistenza.
- Quando i punti del baricentro della sezione lo superano (come i picchi in Fig. 9), questo è indice della presenza della tendenza al rialzo.
Quindi quello che abbiamo ottenuto è un indicatore molto interessante che può essere provato in una strategia di trading!
Conclusione
- Il metodo per prevedere i nodi dell'indicatore ZigZag esaminato nell'articolo ci ha permesso di creare il nuovo indicatore - "Due comete".
- Lo ZigZag avanzato mostra le possibili coordinate di nuovi nodi, anche se questa è solo una previsione.
- L'algoritmo considerato nell'articolo può essere utilizzato per tracciare indicatori avanzati simili, non necessariamente indicatori ZigZag, ad esempio frattali o indicatori semaforici.
- I programmatori MQL5 alle prime armi possono trovare interessante vedere come possono creare macro nei loro programmi per ridurre la quantità di codice ripetuto.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/646





- 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