L'implementazione dell'analisi automatica delle onde di Elliott in MQL5
Introduzione
Uno dei metodi più popolari di analisi di mercato è il principio dell'onda di Elliott. Tuttavia, questo processo è piuttosto complicato, il che ci porta all'uso di strumenti aggiuntivi. Uno di questi strumenti è il marcatore automatico.
Questo articolo descrive la creazione di un analizzatore automatico delle onde di Elliott nel linguaggio MQL5. Si presume che il lettore abbia già familiarità con la teoria delle onde, in caso contrario è necessario fare riferimento alle fonti appropriate.
1. Principio dell'onda di Elliott
Onde di Elliott - è un modello teorico del comportamento di mercato, sviluppato da Ralph Nelson Elliott, secondo il quale tutti i movimenti di prezzo sul mercato sono soggetti alla psicologia umana e sono un processo ciclico di cambiamenti delle onde impulsive, al correttivo e viceversa.
Le onde d'impulso sono una sequenza di cinque fluttuazioni di prezzo, onde correttive - una sequenza di tre o cinque fluttuazioni di prezzo. Le onde impulsive nella loro forma, struttura e regole ad esse applicabili sono dei seguenti tipi:
1. Impulsi: | |
---|---|
Figura 1. Impulso |
|
2. Diagonali principali: | |
Figura 2. Diagonale principale |
|
3. Diagonali: | |
Figura 3. Diagonale |
|
Le onde correttive sono classificate in: | |
4. Zigzag: | |
Figura 4. Zigzag |
|
5. Flat: | |
Figura 5. Flat |
|
6. Doppio Zigzag: | |
Figura 6. Doppio Zigzag |
|
7. Triplo Zigzag: | |
Figura 7. Triplo Zigzag |
|
8. Doppio Tre: | |
Figura 8. Doppio Tre |
|
9. Triplo Tre: | |
Figura 9. Triplo Tre |
|
10. Triangolo contratto: | |
Figura 10. Triangolo contratto |
|
11. Triangoli in espansione: | |
Figura 11. Triangolo in espansione |
|
I modelli e le regole d'onda, presentati sopra, corrispondono solo alla nozione classica dell'analisi delle onde.
C'è anche la sua concezione moderna, formata durante lo studio del mercato Forex. Ad esempio, viene trovato un nuovo modello di triangolo obliquo (scorrevole), vengono identificati gli impulsi con il triangolo nella seconda onda, ecc.
Come si può vedere dalle figure 1-11, ogni impulso o onda correttiva è costituito dallo stesso impulso e onde correttive (indicate dalla linea tratteggiata), ma in misura minore. Questo è il cosiddetto frattale (nidificazione) delle onde di Elliott: le onde di grado grande sono costituite da onde di grado minore, che a loro volta sono composte da onde di grado molto minore e così via.
Su questa nota possiamo completare la breve introduzione al principio delle onde di Elliott e passare all'argomento del mark-up automatico delle onde.
2. Algoritmo del mark-up automatico delle onde di Elliott
Come probabilmente avrai già capito, l'analisi delle onde di Elliott è un processo complesso e sfaccettato. Pertanto, le persone hanno iniziato fin dall'inizio a cercare e applicare strumenti che aiutassero ad alleggerirlo.
Uno di questi strumenti è diventato il meccanismo per il mark-up automatico delle onde di Elliott.
Possiamo distinguere due principi di mark-up automatici:
- Secondo la frattalità delle onde, l'analisi viene effettuata dall'alto verso il basso, dalle onde più grandi a quelle più piccole;
- L'analisi viene effettuata mediante un'enumerazione diretta di tutte le possibili opzioni.
Un diagramma a blocchi dell'analisi automatica delle onde di Elliott è mostrato nella Figura 12.
Figura 12. Un diagramma a blocchi dell'analisi automatica delle onde di Elliott
Considera l'algoritmo in modo più dettagliato sulla base dell'esempio del mark-up automatico dell'impulso (vedi Figura 13).
Nella prima fase, all'intervallo di tempo richiesto dal grafico dei prezzi, utilizzando lo "Zigzag", vengono evidenziati i punti necessari per effettuare il mark-up. Il numero di punti dipende dal tipo di onda che vogliamo analizzare. Quindi, per l'analisi dell'Impulso, sono richiesti sei punti: 5 vertici e un punto di inizio. Se stessimo analizzando lo Zigzag, il numero di punti richiesti sarebbe stato di 4 - 3 vertici e un punto di inizio.
Se lo "Zigzag" ha individuato sei punti sul grafico dei prezzi, allora possiamo immediatamente generare un mark-up dell'impulso: il primo punto, il punto di partenza della prima onda, il secondo punto, il vertice della prima onda, il terzo punto, il vertice della seconda onda, il quarto punto, il vertice della terza onda, il quinto punto, il vertice della quarta onda e il sesto punto, il vertice della quinta onda.
Tuttavia, nella Figura 13, lo "Zigzag" ha individuato 8 punti. In questo caso, sarà necessario enumerare in questi punti tutte le possibili opzioni e mark-up dell'onda. E ce ne saranno cinque (contrassegnati con colori diversi). E ogni versione del mark-up dovrà essere verificata secondo le regole.
Figura 13. Opzioni per contrassegnare il mark-up di un impulso
Dopo aver verificato le regole, nel caso in cui il mark-up dell'onda sia un impulso da tutti i parametri, tutte le sue sotto-onde vengono analizzate allo stesso modo.
Lo stesso vale per l'analisi di tutte le altre onde impulsive e correttive.
3. I tipi delle onde per il mark-up automatico
Come detto in precedenza, l'analisi sarà condotta dall'alto verso il basso, dando al programma le istruzioni per trovare qualche onda su un dato intervallo. Tuttavia, sull'intervallo più grande, è impossibile determinare lo stato dell'onda, il suo inizio e la sua fine. Chiameremo tale onda non iniziata e incompiuta.
Tutte le onde possono essere suddivise nei seguenti gruppi:
- Onde non iniziate:
- Onde con una prima onda non iniziata - 1-2-3-4-5 (ad esempio, un impulso con un'onda non iniziata 1, il numero di punti richiesto - 5) e 1-2-3 (ad esempio, uno Zigzag con un'onda non iniziata A; il numero richiesto di punti - 3);
- Onde con una seconda onda non iniziata - 2-3-4-5 (ad esempio, una diagonale con un'onda non iniziata 2, il numero di punti richiesto - 4) e 2-3 (ad esempio, un flat con un'onda non iniziata B ; il numero di punti richiesto -2);
- Onde con una terza onda non iniziata - 3-4-5 (ad esempio, un Triplo Zigzag con un'onda Y non iniziata; il numero richiesto di punti - 3);
- Onde con una quarta onda non iniziata - 4-5 (ad esempio, un triangolo con un'onda non iniziata D; il numero richiesto di punti -2);
- Onde con una quinta onda non iniziata - 5 (ad esempio, un impulso con un'onda non iniziata 5, il numero richiesto di punti - 1);
- Onde con una terza onda non iniziata - 3 (ad esempio, un doppio tre con un'onda Z non iniziata; il numero di punti richiesto - 1);
- Onde incompiute:
- Onde con una quinta onda incompiuta - 1-2-3-4-5 (ad esempio, un impulso con un'onda incompiuta 5; il numero richiesto di punti - 5);
- Onde con una quarta onda incompiuta - 1-2-3-4> (ad esempio, un triplo zigzag con un'onda XX incompiuta; il numero di punti richiesto - 4);
- Onde con una terza onda incompiuta - 1-2-3> (ad esempio, una diagonale principale dall'onda 3 incompiuta, il numero richiesto di punti -3);
- Onde con una seconda onda incompiuta - 1-2> (ad esempio, uno Zigzag con un'onda B incompiuta; il numero di punti richiesto -2);
- Onde con una prima onda incompiuta - 1> (ad esempio, un piatto con un'onda incompiuta A; il numero richiesto di punti -1);
- Onde non iniziate e non finite:
- Onde con una prima onda non iniziata e una seconda onda incompiuta -1-2> (ad esempio, uno Zigzag con un'onda non iniziata A e un'onda non terminata B; il numero di punti richiesto - 1);
- Onde con una seconda onda non iniziata e una terza onda incompiuta - 2-3>(ad esempio, uno Zigzag con un'onda B non iniziata e un'onda C incompiuta; il numero di punti richiesto - 1);
- Onde con una terza onda non iniziata e una quarta onda incompiuta - 3-4>< (ad esempio, un impulso con un'onda 3 non iniziata e un'onda 4 incompiuta, il numero di punti richiesto - 1);
- Onde con una quarta onda non iniziata e una quinta onda incompiuta - 4-5> (ad esempio, un impulso con un'onda non iniziata 4 e un'onda non terminata 5, il numero di punti richiesto - 1);
- Onde con una prima onda non iniziata e una terza onda incompiuta - 1-2-3>(ad esempio, il triplo tre con un'onda non iniziata W e un'onda incompiuta Y; il numero di punti richiesto - 2);
- Onde con una seconda onda non iniziata e una quarta onda incompiuta -2-3-4>(ad esempio, una diagonale principale con un'onda non iniziata 2 e un'onda non finita 4, il numero di punti richiesto - 2);
- Onde con una terza onda non iniziata e una quinta onda incompiuta - 3-4-5>(ad esempio, una diagonale con un'onda non iniziata 3 e un'onda incompiuta 5, il numero di punti richiesto - 2);
- Onde con un primo scarto non iniziato e con una quarta onda non terminata -1-2-3-4> (ad esempio, un triplo tre con un'onda W non iniziata e un'onda XX non terminata; il numero di punti richiesto - 3);
- Onde con una seconda onda non iniziata e una quinta onda incompiuta - 2-3-4-5 (ad esempio, un impulso con un'onda non iniziata 2 e un'onda non terminata 5; il numero richiesto di punti - 3);
- Onde con una prima onda non iniziata e una quinta onda incompiuta -1-2-3-4-5>(ad esempio, un triplo zigzag con un'onda W non iniziata e un'onda Z non terminata; il numero di punti richiesto - 4);
- Onde completate - 1-2-3-4-5 (il numero richiesto di punti - 6) e 1-2-3 (il numero richiesto di punti - 4).
Il segno "<" dopo il numero dell'onda indica che non è iniziata. Il segno ">" dopo il numero di un'onda indica che è incompleta.
Nella Figura 14 possiamo vedere le seguenti onde:
- Un'onda con una prima onda non iniziata A -A -BC;
- Un'onda con una prima W non iniziata e una seconda onda X incompiuta -W<-X>;
- Onde B e C completate;
Figura 14. Onde non iniziate e non finite
4. La descrizione delle strutture dati dell'analizzatore automatico delle onde di Elliott
Per scrivere l'analizzatore automatico delle onde di Elliott, avremo bisogno delle seguenti strutture dati:
4.1. La struttura della descrizione delle onde analizzate nel programma:
// The structure of the description of the analyzed waves in the program struct TWaveDescription { string NameWave; // name of the wave int NumWave; // number of sub-waves in a wave string Subwaves[6]; // the names of the possible sub-waves in the wave };
4.2. Una classe per memorizzare i parametri di un'onda specifica:
// A class for storing the parameters of a wave class TWave { public: string Name; // name of the wave string Formula; // the formula of the wave (1-2-3-4-5, <1-2-3 etc.) int Level; // the level of the wave double ValueVertex[6]; // the value of the top of the wave int IndexVertex[6]; // the indexes of the top of the waves };
4.3. Una classe per memorizzare i valori dei vertici e degli indici del vertice dello Zigzag:
// A class for storing the values of vertexes and indexes of the zigzag class TZigzag:public CObject { public: CArrayInt *IndexVertex; // indexes of the vertexes of the zigzag CArrayDouble *ValueVertex; // value of the vertexes of the zigzags };
4.4. Classe per rappresentare l'albero delle onde:
// A class for the presentation of the tree of the waves class TNode:public CObject { public: CArrayObj *Child; // the child of the given tree node TWave *Wave; // the wave, stored in the given tree node string Text; // text of the tree node TNode *Add(string Text,TWave *Wave=NULL) // the function of adding the node to the tree { TNode *Node=new TNode; Node.Child=new CArrayObj; Node.Text =Text; Node.Wave=Wave; Child.Add(Node); return(Node); } };
4.5. La struttura per memorizzare i punti, trovata dallo Zigzag:
// The structure for storing the points, found by the zigzag struct TPoints { double ValuePoints[]; // the values of the found points int IndexPoints[]; // the indexes of the found points int NumPoints; // the number of found points };
4.6. Una classe per memorizzare i parametri della sezione già analizzata del grafico:
// A class for storing the parameters of the already analyzed section, corresponding to the wave tree node class TNodeInfo:CObject { public: int IndexStart,IndexFinish; // the range of the already analyzed section double ValueStart,ValueFinish; // the edge value of the already analyzed section string Subwaves; // the name of the wave and the group of the waves TNode *Node; // the node, pointing to the already analyzed range of the chart };
4.7. Una classe per memorizzare la marcatura delle onde prima di posizionarla sulla carta:
// A class for storing the marking of waves before placing them on the chart class TLabel:public CObject { public: double Value; // the value of the vertex int Level; // the level of the wave string Text; // the marking of the wave };
5. La descrizione della funzione dell'analizzatore automatico delle onde di Elliott
Per scrivere l'analizzatore automatico delle onde di Elliott, avremo bisogno delle seguenti funzioni:
int Zigzag(intH,int Start,int Finish,CArrayInt *IndexVertex,CArrayDouble *ValueVertex)
Un elemento chiave nell'analizzatore automatico delle onde di Elliott è lo "Zigzag", mediante il quale verranno costruite le onde. Il calcolo dello "Zigzag" di qualsiasi parametro deve essere eseguito molto rapidamente.
Nel nostro analizzatore utilizzeremo lo "Zigzag", tratto dall'articolo "How to Write Fast Non-Redrawing ZigZags".
La funzione Zigzag calcola lo Zigzag con il parametro H nell'intervallo da Inizio a Fine, quindi registra gli indici trovati dei vertici e i valori dei vertici, rispettivamente, negli array IndexVertex e ValueVertex, i cui indirizzi sono passati a questa funzione.
La funzione Zigzag restituisce il numero di vertici trovati dello "Zigzag".
Funzione del riempimento di "Zigzag" e memorizzazione dei suoi parametri:
void FillZigzagArray(int Start,int Finish)
Come è stato mostrato prima, dobbiamo trovare il numero di punti necessario sul grafico dei prezzi per il mark-up dell'onda. E quindi avremo bisogno di avere un array di vertici dello "Zigzag", con parametri diversi, che itereremo poi per trovare questi punti.
La funzione FillZigzagArray calcola lo "Zigzag" sull'intervallo del grafico dall'inizio alla fine, con tutti i valori possibili del parametro H (fino a quando il numero di vertici dello "Zigzag" non diventerà uguale o inferiore a due), memorizza le informazioni sui vertici trovati negli oggetti della classe TZigzag, e registra questi oggetti nell'array globale ZigzagArray, il cui annuncio è il seguente:
CArrayObj *ZigzagArray;
La funzione di ricerca sull'intervallo dato richiede il numero di punti sul grafico dei prezzi:
bool FindPoints(int NumPoints,int IndexStart,int IndexFinish,double ValueStart,double ValueFinish,TPoints &Points)
La funzione FindPoints ricerca almeno tre NumPoints punti sul grafico dei prezzi, nell'intervallo richiesto, da IndexStart a IndexFinish, con i valori richiesti del primo e dell'ultimo punto ValueStart e ValueFinish, e li salva (cioè punti) nella struttura dei Punti, il cui collegamento viene passato a questa funzione.
La funzione FindPoints restituisce true, se viene trovato il numero di punti richiesto, altrimenti restituisce false.
5.4. NotStartedAndNotFinishedWaves
La funzione di analisi delle onde non iniziate e non finite:
void NotStartedAndNotFinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level)
La funzione NotStartedAndNotFinishedWaves analizza tutte le onde del terzo gruppo delle onde - non iniziate e non terminate. La funzione analizza l'onda NumWave (con un livello d'onda Level), le onde con il nome ParentWave.Name, che possono assumere la forma delle onde sub-onda (una forma di Zigzag, flat, Double zigzag e (o), ecc. .). L'onda analizzata NumWave verrà memorizzata nel nodo dell'albero delle onde, il nodo figlio Node.
Ad esempio, se ParentWave.Name = "Impulse", NumWave = 5, Subwaves = "Impulso, Diagonale e Livello = 2, allora possiamo dire che la funzione NotStartedAndNotFinishedWaves analizzerà la quinta onda dell'Impulso, che ha un'onda livello di due e può assumere la forma di un impulso o di una diagonale.
Ad esempio, utilizziamo un diagramma a blocchi dell'analisi dell'algoritmo delle onde non iniziate e non finite 1<-2-3> nella funzione NotStartedAndNotFinishedWaves:
<img alt="Figure 15. Il diagramma a blocchi dell'analisi delle onde con la formula "1"" title="Figure 15. Il diagramma a blocchi dell'analisi delle onde con la formula "1"" src="http://p.mql5.com/data/2/260/fig15.gif" style="vertical-align:middle;" height=" 1746" larghezza="750">
Figura 15. Il diagramma a blocchi dell'analisi delle onde con la formula "1<-2-3>"
Quando si utilizza la funzione NotStartedAndNotFinishedWaves, vengono chiamate le seguenti funzioni: NotStartedWaves, NotFinishedWaves e FinishedWaves.
La funzione per l'analisi delle onde non iniziate:
void NotStartedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level)
La funzione NotStartedWaves analizza tutte le onde del primo gruppo delle onde - le onde non iniziate. La funzione analizza l'onda NumWave (con il livello d'onda Level) dell'onda denominata ParentWave.Name, che può assumere la forma delle onde sub-onde. L'onda analizzata NumWave verrà memorizzata nel nodo dell'albero delle onde, il nodo figlio Node.
Quando la funzione NotStartedWaves è attiva, vengono chiamate le seguenti funzioni: NotStartedWaves e FinishedWaves.
Tutte le onde sono analizzate in modo simile al diagramma a blocchi nella figura 15.
L'analisi funzionale delle onde non finite:
void NotFinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level)
La funzione NotFinishedWaves analizza tutte le onde del secondo gruppo delle onde - onde non finite. La funzione analizza l'onda NumWave (con il livello d'onda Level) dell'onda denominata ParentWave.Name, che può assumere la forma delle onde sub-onda. L'onda analizzata NumWave verrà memorizzata nel nodo dell'albero delle onde, il nodo figlio Node.
Quando la funzione NotFinishedWaves è attiva, vengono chiamate le seguenti funzioni: NonFinishedWaves e FinishedWaves.
Tutte le onde sono analizzate in modo simile al diagramma a blocchi nella figura 15.
L'analisi funzionale delle onde completate (finite):
void FinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level)
La funzione FinishedWaves analizza tutte le onde del quarto gruppo, le onde completate. La funzione analizza l'onda NumWave (con un livello d'onda Level) dell'onda denominata ParentWave.Name, che può assumere la forma delle onde sub-onde. L'onda analizzata NumWave verrà memorizzata nel nodo dell'albero delle onde, il nodo figlio Node.
Quando la funzione FinishedWaves è attiva, viene chiamata la funzione FinishedWaves.
Tutte le onde sono analizzate in modo simile al diagramma a blocchi nella figura 15.
5.8. FindWaveInWaveDescription
La funzione di ricerca delle onde nella struttura dati WaveDescription:
int FindWaveInWaveDescription(string NameWave)
La funzione FindWaveInWaveDescription, dal nome dell'onda NameWave, passato come parametro, la ricerca nell'array di strutture WaveDescription e restituisce il numero di indice, corrispondente a questa onda.
L'array di strutture WaveDescription ha il seguente aspetto:
TWaveDescription WaveDescription[]= { { "Impulse",5, { "", "Impulse,Leading Diagonal,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Impulse,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Impulse,Diagonal," } } , { "Leading Diagonal",5, { "", "Impulse,Leading Diagonal,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Impulse,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Impulse,Diagonal," } } , { "Diagonal",5, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle," } } , { "Zigzag",3, { "", "Impulse,Leading Diagonal,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Impulse,Diagonal,", "", "" } } , { "Flat",3, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Impulse,Diagonal,", "", "" } } , { "Double Zigzag",3, { "", "Zigzag,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,", "", "" } } , { "Triple Zigzag",5, { "", "Zigzag,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag," } } , { "Double Three",3, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "", "" } } , { "Triple Three",5, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle," } } , { "Contracting Triangle",5, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle," } } , { "Expanding Triangle",5, { "", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle,", "Zigzag,Flat,Double Zigzag,Triple Zigzag,Double Three,Triple Three,Contracting Triangle,Expanding Triangle," } } };
La funzione FindWaveInWaveDescription viene utilizzata nell'analisi delle funzioni delle seguenti onde: NotStartedAndNotFinishedWaves, NotStartedWaves, NotFinishedWaves e FinishedWaves.
La funzione che verifica se la data sezione del grafico è già stata analizzata:
bool Already(TWave *Wave,int NumWave,TNode *Node,string Subwaves)
Poiché l'analisi automatica delle onde di Elliott avviene con il metodo dell'enumerazione, può verificarsi una situazione in cui la data sezione del grafico è già stata analizzata per la presenza di un'onda o di un gruppo delle onde. Per sapere questo, è necessario salvare il collegamento al nodo nell'albero delle onde dell'onda già analizzata e solo allora inserire il collegamento. Tutto questo accade nella funzione Already.
La funzione Already cerca un array globale NodeInfoArray, il quale memorizza gli oggetti della classe TNodeInfo, l'intervallo del grafico corrispondente all'onda NumWave, dell'onda denominata Wave. Name ha la forma delle onde sub-onde e registra nel Nodo l'indirizzo del nodo della sezione già marcata del grafico. Se questa sezione non esiste, viene creato e compilato un nuovo oggetto della classe TNodeInfo, che viene registrato nell'array NodeInfoArray.
La funzione restituisce true se l'intervallo del grafico è già stato analizzato, altrimenti restituisce false.
L'array NodeInfoArray viene dichiarato nel modo seguente:
CArrayObj NodeInfoArray;
5.10. Le funzioni di controllo delle onde per le regole
Include le funzioni VertexAAboveB, WaveAMMoreWaveB e WaveRules, da cui vengono chiamate le prime due funzioni. Durante il test, ricorda che le onde possono essere non iniziate e (o) incomplete e, ad esempio, per l'onda con la formula "1<-2-3>", non è possibile determinare se la quarta onda è andata oltre il territorio della prima onda perché non c'è ancora una quarta onda.
Funzione di controllo delle onde per le regole:
bool WaveRules(TWave *Wave)
La funzione WaveRules restituisce true se un'onda con il nome Wave.Name è "corretta", altrimenti restituisce false. Nella sua attività, la funzione WaveRules viene chiamata dalla funzione VertexAAboveVertexB e WaveAMMoreWaveB.
La funzione di controllare l'eccesso di un vertice su un altro vertice:
int VertexAAboveVertexB(int A,int B,bool InternalPoints)
La funzione VertexAAboveVertexB restituisce il numero > = 0 se la parte superiore dell'onda A supera la parte superiore dell'onda B, altrimenti restituisce -1. Se InternalPoints = true, allora i valori dei punti interni delle onde (massimo e/o minimo) sono presi in considerazione.
La funzione di controllare l'eccesso della lunghezza di un'onda rispetto alla lunghezza di un'altra:
int WaveAMoreWaveB(int A,int B)
La funzione WaveAMoreWaveB restituisce un numero >=0 se l'onda A è maggiore dell'onda B, altrimenti restituisce -1.
11. La funzione per cancellare la memoria
La funzione per cancellare l'albero delle onde con il nodo superiore Nodo:
void ClearTree(TNode *Node)
La funzione cancella l'array ClearNodeInfoArray:
void ClearNodeInfoArray()
La funzione per cancellare l'array ZigzagArray:
void ClearZigzagArray()
5.12. La funzione di bypassare le onde dell'albero e inviare i risultati dell'analisi al grafico
Dopo il completamento dell'analisi automatica delle onde di Elliott, abbiamo un albero delle onde.
Il suo esempio può essere presentato come nella figura seguente:
Figura 16. Un esempio di albero delle onde
Ora, per visualizzare i risultati dell'analisi sul grafico dobbiamo aggirare l'albero dato. Come mostrato nella figura 16, ci sono alcune opzioni silenziose (poiché ci sono diverse opzioni delle onde), e ogni opzione di un bypass porta a diversi mark-up.
Possiamo distinguere due tipi di nodi dell'albero.
Il primo tipo: nodi con i nomi delle onde ("Impulso", "Zigzag" ecc.). Il secondo tipo: nodi con numero d'onda ("1", "1<", "ecc.). Tutte le informazioni sui parametri dell'onda sono memorizzate nel primo tipo di nodi. Pertanto, quando visitiamo questi nodi, recupereremo e registreremo le informazioni sull'onda per poi visualizzarle sul grafico.
Per semplicità, ignoreremo l'albero, visitando solo le prime versioni delle onde.
Un esempio di bypass è mostrato in figura 17 ed è evidenziato in rosso.
Figura 17. Esempio di bypass di un albero delle onde
La funzione di bypassare un albero d'onda:
void FillLabelArray(TNode *Node)
La funzione FillLabelArray bypassa l'albero dell’onda con il nodo radice, passando solo per le prime versioni delle onde nell'albero, e riempie un array globale LabelArray i cui indici memorizzano un collegamento all'array di vertici (array di oggetti di classe TLabel) con l'indice dato sul grafico.
L'array LabelArray è definito come segue:
CArrayObj *LabelArray[];
La funzione di visualizzazione dei risultati dell'analisi sul grafico:
void CreateLabels()
La funzione CreateLabels crea gli oggetti grafici "Text", corrispondenti ai tag onda sul grafico. I tag delle onde vengono creati in base all'array LabelArray.
La funzione di aggiornamento (correzione) delle cime delle onde sul grafico:
void CorrectLabel()
La funzione CorrectLabel corregge i tag onda sul grafico quando viene fatto scorrere e/o durante la sua restrizione.
6. L'implementazione del partizionamento automatico delle onde di Elliott
6.1. La funzione Zigzag:
//+------------------------------------------------------------------+ //| The Zigzag function | //+------------------------------------------------------------------+ int Zigzag(int H,int Start,int Finish,CArrayInt *IndexVertex,CArrayDouble *ValueVertex) { bool Up=true; double dH=H*Point(); int j=0; int TempMaxBar = Start; int TempMinBar = Start; double TempMax = rates[Start].high; double TempMin = rates[Start].low; for(int i=Start+1;i<=Finish;i++) { // processing the case of a rising segment if(Up==true) { // check that the current maximum has not changed if(rates[i].high>TempMax) { // if it has, correct the corresponding variables TempMax=rates[i].high; TempMaxBar=i; } else if(rates[i].low<TempMax-dH) { // otherwise, if the lagged level is broken, fixate the maximum ValueVertex.Add(TempMax); IndexVertex.Add(TempMaxBar); j++; // correct the corresponding variables Up=false; TempMin=rates[i].low; TempMinBar=i; } } else { // processing the case of the descending segment // check that the current minimum hasn't changed if(rates[i].low<TempMin) { // if it has, correct the corresponding variables TempMin=rates[i].low; TempMinBar=i; } else if(rates[i].high>TempMin+dH) { // otherwise, if the lagged level is broken, fix the minimum ValueVertex.Add(TempMin); IndexVertex.Add(TempMinBar); j++; // correct the corresponding variables Up=true; TempMax=rates[i].high; TempMaxBar=i; } } } // return the number of zigzag tops return(j); }
6.2. La funzione FillZigzagArray:
CArrayObj *ZigzagArray; // declare the ZigzagArray global dynamic array //+------------------------------------------------------------------+ //| The FillZigzagArray function | //| search through the values of the parameter H zigzag | //| and fill the array ZigzagArray | //+------------------------------------------------------------------+ void FillZigzagArray(int Start,int Finish) { ZigzagArray=new CArrayObj; // create the dynamic array of zigzags CArrayInt *IndexVertex=new CArrayInt; // create the dynamic array of indexes of zigzag tops CArrayDouble *ValueVertex=new CArrayDouble; // create the dynamic array of values of the zigzag tops TZigzag *Zigzag; // declare the class for storing the indexes and values of the zigzag tops int H=1; int j=0; int n=Zigzag(H,Start,Finish,IndexVertex,ValueVertex);//find the tops of the zigzag with the parameter H=1 if(n>0) { // store the tops of the zigzag in the array ZigzagArray Zigzag=new TZigzag; // create the object for storing the found indexes and the zigzag tops, // fill it and store in the array ZigzagArray Zigzag.IndexVertex=IndexVertex; Zigzag.ValueVertex=ValueVertex; ZigzagArray.Add(Zigzag); j++; } H++; // loop of the H of the zigzag while(true) { IndexVertex=new CArrayInt; // create a dynamic array of indexes of zigzag tops ValueVertex=new CArrayDouble; // create a dynamic array of values of the zigzag tops n=Zigzag(H,Start,Finish,IndexVertex,ValueVertex); // find the tops of the zigzag if(n>0) { Zigzag=ZigzagArray.At(j-1); CArrayInt *PrevIndexVertex=Zigzag.IndexVertex; // get the array of indexes of the previous zigzag bool b=false; // check if there is a difference between the current zigzag and the previous zigzag for(int i=0; i<=n-1;i++) { if(PrevIndexVertex.At(i)!=IndexVertex.At(i)) { // if there is a difference, store the tops of a zigzag in the array ZigzagArray Zigzag=new TZigzag; Zigzag.IndexVertex=IndexVertex; Zigzag.ValueVertex=ValueVertex; ZigzagArray.Add(Zigzag); j++; b=true; break; } } if(b==false) { // otherwise, if there is no difference, release the memory delete IndexVertex; delete ValueVertex; } } // search for the tops of the zigzag until there is two or less of them if(n<=2) break; H++; } }
6.3. La funzione FindPoints:
//+------------------------------------------------------------------+ //| The FindPoints function | //| Fill the ValuePoints and IndexPoints arrays | //| of the Points structure | //+------------------------------------------------------------------+ bool FindPoints(int NumPoints,int IndexStart,int IndexFinish,double ValueStart,double ValueFinish,TPoints &Points) { int n=0; // fill the array ZigzagArray for(int i=ZigzagArray.Total()-1; i>=0;i--) { TZigzag *Zigzag=ZigzagArray.At(i); // the obtained i zigzag in the ZigzagArray CArrayInt *IndexVertex=Zigzag.IndexVertex; // get the array of the indexes of the tops of the i zigzags CArrayDouble *ValueVertex=Zigzag.ValueVertex; // get the array of values of the tops of the i zigzag int Index1=-1,Index2=-1; // search the index of the IndexVertex array, corresponding to the first point for(int j=0;j<IndexVertex.Total();j++) { if(IndexVertex.At(j)>=IndexStart) { Index1=j; break; } } // search the index of the IndexVertex array, corresponding to the last point for(int j=IndexVertex.Total()-1;j>=0;j--) { if(IndexVertex.At(j)<=IndexFinish) { Index2=j; break; } } // if the first and last points were found if((Index1!=-1) && (Index2!=-1)) { n=Index2-Index1+1; // find out how many points were found } // if the required number of points was found (equal or greater) if(n>=NumPoints) { // check that the first and last tops correspond with the required top values if(((ValueStart!=0) && (ValueVertex.At(Index1)!=ValueStart)) || ((ValueFinish!=0) && (ValueVertex.At(Index1+n-1)!=ValueFinish)))continue; // fill the Points structure, passed as a parameter Points.NumPoints=n; ArrayResize(Points.ValuePoints, n); ArrayResize(Points.IndexPoints, n); int k=0; // fill the ValuePoints and IndexPoints arrays of Points structure for(int j=Index1; j<Index1+n;j++) { Points.ValuePoints[k]=ValueVertex.At(j); Points.IndexPoints[k]=IndexVertex.At(j); k++; } return(true); }; }; return(false); };
6.4. La funzione NotStartedAndNotFinishedWaves:
//+------------------------------------------------------------------+ //| The NotStartedAndNotFinishedWaves function | //+------------------------------------------------------------------+ void NotStartedAndNotFinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level) { int v1,v2,v3,v4,I; TPoints Points; TNode *ParentNode,*ChildNode; int IndexWave; string NameWave; TWave *Wave; int i=0,pos=0,start=0; // Put the waves, which we will be analyzing to the ListNameWave array string ListNameWave[]; ArrayResize(ListNameWave,ArrayRange(WaveDescription,0)); while(pos!=StringLen(Subwaves)-1) { pos=StringFind(Subwaves,",",start); NameWave=StringSubstr(Subwaves,start,pos-start); ListNameWave[i++]=NameWave; start=pos+1; } int IndexStart=ParentWave.IndexVertex[NumWave-1]; int IndexFinish=ParentWave.IndexVertex[NumWave]; double ValueStart = ParentWave.ValueVertex[NumWave - 1]; double ValueFinish= ParentWave.ValueVertex[NumWave]; // find no less than two points on the price chart and put them into the structure Points // if they are not found, then exit the function if(FindPoints(2,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unbegun and incomplete waves with the formula "1<-2-3>" v1=0; while(v1<=Points.NumPoints-2) { v2=v1+1; while(v2<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the structure WaveDescription in order to // find out the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if((WaveDescription[IndexWave].NumWave==5) || (WaveDescription[IndexWave].NumWave==3)) { // create the object of TWave class and fill its fields - parameters of the analyzed waves Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2-3>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = IndexFinish; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if a wave passed the check by rules, add it into the wave tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create a third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release memory else delete Wave; } } v2=v2+2; } v1=v1+2; } // the loop of unbegun and unfinished waves with the formula "2<-3-4>" v2=0; while(v2<=Points.NumPoints-2) { v3=v2+1; while(v3<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its symbols and its names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="2<-3-4>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = IndexStart; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = IndexFinish; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check for rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=2; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in th waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by rules, release memory else delete Wave; } } v3=v3+2; } v2=v2+2; } // the loop of the unbegun and the incomplete waves with the formula "3<-4-5>" v3=0; while(v3<=Points.NumPoints-2) { v4=v3+1; while(v4<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to // find out the number of its symbols and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="3<-4-5>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = 0; Wave.IndexVertex[2] = IndexStart; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = IndexFinish; // check the wave for the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=3; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave has not passed the check by the rules, release the memory else delete Wave; } } v4=v4+2; } v3=v3+2; } // find no less than three points on the price chart and put them in the Points structure // if they were not found, then exit the function if(FindPoints(3,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false) return; // the loop of unbegun and unfinished waved with the formula "1<-2-3-4>" v1=0; while(v1<=Points.NumPoints-3) { v2=v1+1; while(v2<=Points.NumPoints-2) { v3=v2+1; while(v3<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create an object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2-3-4>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = IndexFinish; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waved tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave of the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v3=v3+2; } v2=v2+2; } v1=v1+2; } // the loop of unbegun and unfinished waves with the formula "2<-3-4-5>" v2=0; while(v2<=Points.NumPoints-3) { v3=v2+1; while(v3<=Points.NumPoints-2) { v4=v3+1; while(v4<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of the symbols and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="2<-3-4-5>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = IndexStart; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = IndexFinish; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=2; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waved tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave has not passed by the rules, release the memory else delete Wave; } } v4=v4+2; } v3=v3+2; } v2=v2+2; } // find no less than four point on the price chart and put them into the structure Points // if we didn't find any, then exit the function if(FindPoints(4,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false) return; // the loop of unbegun and unfinished waves with the formula "1<-2-3-4-5>" v1=0; while(v1<=Points.NumPoints-4) { v2=v1+1; while(v2<=Points.NumPoints-3) { v3=v2+1; while(v3<=Points.NumPoints-2) { v4=v3+1; while(v4<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2-3-4-5>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = IndexFinish; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waved tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the 5th sub-wave in the wave tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by the rules, release the memory else delete Wave; } } v4=v4+2; } v3=v3+2; } v2=v2+2; } v1=v1+2; } // find no less than one point on the price chart and record it into the structure Points // if we didn't find any, then exit the function if(FindPoints(1,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unbegun and unfinished waves with the formula "1<-2>" v1=0; while(v1<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5 || WaveDescription[IndexWave].NumWave==3) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = IndexFinish; Wave.IndexVertex[3] = 0; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waved tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by the rules, release the memory else delete Wave; } } v1=v1+1; } // loop the unbegun and unfinished waves with the formula "2<-3>" v2=0; while(v2<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the structure WaveDescription, in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5 || WaveDescription[IndexWave].NumWave==3) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="2<-3>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = IndexStart; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = IndexFinish; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=2; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waved tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v2=v2+1; } // the loop of unbegun and unfinished waves with the formula "3<-4>" v3=0; while(v3<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure on order to know the number of sub-waved and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="3<-4>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = 0; Wave.IndexVertex[2] = IndexStart; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = IndexFinish; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=3; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v3=v3+1; } // the loop of unbegun and unfinished waves with the formula "4<-5>" v4=0; while(v4<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of symbols and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="4<-5>"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = 0; Wave.IndexVertex[2] = 0; Wave.IndexVertex[3] = IndexStart; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = IndexFinish; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=4; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v4=v4+1; } }
6.5. La funzione NotStartedWaves:
//+------------------------------------------------------------------+ //| The function NotStartedWaves | //+------------------------------------------------------------------+ void NotStartedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level) { int v1,v2,v3,v4,v5,I; TPoints Points; TNode *ParentNode,*ChildNode; int IndexWave; string NameWave; TWave *Wave; int i=0,Pos=0,Start=0; // Put the waves, which we will be analyzing to the ListNameWave array string ListNameWave[]; ArrayResize(ListNameWave,ArrayRange(WaveDescription,0)); while(Pos!=StringLen(Subwaves)-1) { Pos=StringFind(Subwaves,",",Start); NameWave=StringSubstr(Subwaves,Start,Pos-Start); ListNameWave[i++]=NameWave; Start=Pos+1; } int IndexStart=ParentWave.IndexVertex[NumWave-1]; int IndexFinish=ParentWave.IndexVertex[NumWave]; double ValueStart = ParentWave.ValueVertex[NumWave - 1]; double ValueFinish= ParentWave.ValueVertex[NumWave]; // find no less than two points on the price chart and put them into the structure Points // if we didn't find any, then exit the function if(FindPoints(2,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // loop the unbegun waves with the formula "4<-5" v5=Points.NumPoints-1; v4=v5-1; while(v4>=0) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="4<-5"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = Points.ValuePoints[v5]; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = 0; Wave.IndexVertex[2] = 0; Wave.IndexVertex[3] = IndexStart; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = Points.IndexPoints[v5]; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=4; // create the fourth sub-wave in the wave tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create 5th sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by the rules, release the memory else delete Wave; } } v4=v4-2; } // loop the unbegun waves with the formula "2<-3" v3=Points.NumPoints-1; v2=v3-1; while(v2>=0) { int j=0; while(j<=i-1) { // in turn, from the ListNameWave, draw the name of the wave for analysis NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==3) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="2<-3"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = IndexStart; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=2; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v2=v2-2; } // find not less than three points on the price chart and put them into the structure Points // if we didn't find any, then exit the function if(FindPoints(3,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // loop the unbegun waves with the formula "3<-4-5" v5=Points.NumPoints-1; v4=v5-1; while(v4>=1) { v3=v4-1; while(v3>=0) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="3<-4-5"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = Points.ValuePoints[v5]; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = 0; Wave.IndexVertex[2] = IndexStart; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = Points.IndexPoints[v5]; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=3; // create the three sub-waves in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v3=v3-2; } v4=v4-2; } // the loop of the unbegun waves with the formula "1<-2-3" v3=Points.NumPoints-1; v2=v3-1; while(v2>=1) { v1=v2-1; while(v1>=0) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==3) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2-3"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); //if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); //if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v1=v1-2; } v2=v2-2; } // find no less than four points on the price chart and put them into the structure Points // if we didn't find any, then exit the function if(FindPoints(4,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unbegun waves with the formula "2<-3-4-5" v5=Points.NumPoints-1; v4=v5-1; while(v4>=2) { v3=v4-1; while(v3>=1) { v2=v3-1; while(v2>=0) { int j=0; while(j<=i-1) { // in turn, from the ListNameWave, draw the name of the wave for analysis NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="2<-3-4-5"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = Points.ValuePoints[v5]; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = IndexStart; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = Points.IndexPoints[v5]; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=2; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave has not passed the rules, release the memory else delete Wave; } } v2=v2-2; } v3=v3-2; } v4=v4-2; } // find no less than five points on the price chart and record it into the structure Points // if we didn't find any, then exit the function if(FindPoints(5,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unbegun waves with the formula "1<-2-3-4-5" v5=Points.NumPoints-1; v4=v5-1; while(v4>=3) { v3=v4-1; while(v3>=2) { v2=v3-1; while(v2>=1) { v1=v2-1; while(v1>=0) { int j=0; while(j<=i-1) { // in turn, from the ListNameWave, draw the name of the wave for analysis NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1<-2-3-4-5"; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = Points.ValuePoints[v5]; Wave.IndexVertex[0] = IndexStart; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = Points.IndexPoints[v5]; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotStartedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the chart, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v1=v1-2; } v2=v2-2; } v3=v3-2; } v4=v4-2; } }
6.6. La funzione NotFinishedWaves:
//+------------------------------------------------------------------+ //| The function FinishedWaves | //+------------------------------------------------------------------+ void NotFinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level) { int v0,v1,v2,v3,v4,I; TPoints Points; TNode *ParentNode,*ChildNode; int IndexWave; string NameWave; TWave *Wave; int i=0,Pos=0,Start=0; //we put the waves, which we will be analyzing in the array ListNameWaveg string ListNameWave[]; ArrayResize(ListNameWave,ArrayRange(WaveDescription,0)); while(Pos!=StringLen(Subwaves)-1) { Pos=StringFind(Subwaves,",",Start); NameWave=StringSubstr(Subwaves,Start,Pos-Start); ListNameWave[i++]=NameWave; Start=Pos+1; } int IndexStart=ParentWave.IndexVertex[NumWave-1]; int IndexFinish=ParentWave.IndexVertex[NumWave]; double ValueStart = ParentWave.ValueVertex[NumWave - 1]; double ValueFinish= ParentWave.ValueVertex[NumWave]; // find not less than two points on the price chart and record it into the structure Points // if we didn't find any, then exit the function if(FindPoints(2,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unfinished waves with the formula "1-2>" v0=0; v1=v0+1; while(v1<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from the ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if((WaveDescription[IndexWave].NumWave==5) || (WaveDescription[IndexWave].NumWave==3)) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1-2>"; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = 0; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = IndexFinish; Wave.IndexVertex[3] = 0; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v1=v1+2; } // find no less than three points on the price chart and put it into the Points structure // if none were found, then exit the function if(FindPoints(3,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unfinished waves with the formula "1-2-3>" v0=0; v1=v0+1; while(v1<=Points.NumPoints-2) { v2=v1+1; while(v2<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if((WaveDescription[IndexWave].NumWave==5) || (WaveDescription[IndexWave].NumWave==3)) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1-2-3>"; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = 0; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = IndexFinish; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, of the corresponding third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v2=v2+2; } v1=v1+2; } // find no less than four points on the price chart and record it into the Points structure // if none were found, then exit the function if(FindPoints(4,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false) return; // the loop of unfinished waves with the formula "1-2-3-4>" v0=0; v1=v0+1; while(v1<=Points.NumPoints-3) { v2=v1+1; while(v2<=Points.NumPoints-2) { v3=v2+1; while(v3<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in WaveDescription structure in order to know the number of sub-waves and the names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1-2-3-4>"; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = IndexFinish; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check for the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave didn't pass by the rules, release the memory else delete Wave; } } v3=v3+2; } v2=v2+2; } v1=v1+2; } // find no less than five points on the price chart and put them into the structure Points // if none were found, exit the function if(FindPoints(5,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of unfinished waves with the formula "1-2-3-4-5>" v0=0; v1=v0+1; while(v1<=Points.NumPoints-4) { v2=v1+1; while(v2<=Points.NumPoints-3) { v3=v2+1; while(v3<=Points.NumPoints-2) { v4=v3+1; while(v4<=Points.NumPoints-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of TWave class and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1-2-3-4-5>"; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = IndexFinish; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) NotFinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass by the rules, release the memory else delete Wave; } } v4=v4+2; } v3=v3+2; } v2=v2+2; } v1=v1+2; } }
6.7. La funzione FinishedWaves:
//+------------------------------------------------------------------+ //| The FinishedWaves function | //+------------------------------------------------------------------+ void FinishedWaves(TWave *ParentWave,int NumWave,TNode *Node,string Subwaves,int Level) { int v0,v1,v2,v3,v4,v5,I; TPoints Points; TNode *ParentNode,*ChildNode; int IndexWave; string NameWave; TWave *Wave; int i=0,Pos=0,Start=0; // Put the waves, which we will be analyzing to the ListNameWave array string ListNameWave[]; ArrayResize(ListNameWave,ArrayRange(WaveDescription,0)); while(Pos!=StringLen(Subwaves)-1) { Pos=StringFind(Subwaves,",",Start); NameWave=StringSubstr(Subwaves,Start,Pos-Start); ListNameWave[i++]=NameWave; Start=Pos+1; } int IndexStart=ParentWave.IndexVertex[NumWave-1]; int IndexFinish=ParentWave.IndexVertex[NumWave]; double ValueStart = ParentWave.ValueVertex[NumWave - 1]; double ValueFinish= ParentWave.ValueVertex[NumWave]; // find no less than four points on the price chart and put them into the structure Points // if none were found, then exit the function if(FindPoints(4,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false) return; // the loop of complete waves with the formula "1-2-3" v0 = 0; v1 = 1; v3 = Points.NumPoints - 1; while(v1<=v3-2) { v2=v1+1; while(v2<=v3-1) { int j=0; while(j<=i-1) { // in tuen, from ListNameWave, draw the name of the wave for analysis NameWave=ListNameWave[j++]; // find the index of the wave in the structure WaveDescription in order to know the number of sub-waves and its names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==3) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave;; Wave.Name=NameWave; Wave.Formula="1-2-3"; Wave.Level=Level; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = 0; Wave.ValueVertex[5] = 0; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = 0; Wave.IndexVertex[5] = 0; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(i)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(i)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by the rules, release the memory else delete Wave; } } v2=v2+2; } v1=v1+2; } // find no less than six points on the price chart and put them into the structure Points // if none were found, then exit the function if(FindPoints(6,IndexStart,IndexFinish,ValueStart,ValueFinish,Points)==false)return; // the loop of complete waves with the formula "1-2-3-4-5" v0 = 0; v1 = 1; v5 = Points.NumPoints - 1; while(v1<=v5-4) { v2=v1+1; while(v2<=v5-3) { v3=v2+1; while(v3<=v5-2) { v4=v3+1; while(v4<=v5-1) { int j=0; while(j<=i-1) { // get the name of the wave for analysis from ListNameWave NameWave=ListNameWave[j++]; // find the index of the wave in the WaveDescription structure in order to know the number of its sub-waves and their names IndexWave=FindWaveInWaveDescription(NameWave); if(WaveDescription[IndexWave].NumWave==5) { // create the object of class TWave and fill its fields - parameters of the analyzed wave Wave=new TWave; Wave.Name=NameWave; Wave.Level=Level; Wave.Formula="1-2-3-4-5"; Wave.ValueVertex[0] = Points.ValuePoints[v0]; Wave.ValueVertex[1] = Points.ValuePoints[v1]; Wave.ValueVertex[2] = Points.ValuePoints[v2]; Wave.ValueVertex[3] = Points.ValuePoints[v3]; Wave.ValueVertex[4] = Points.ValuePoints[v4]; Wave.ValueVertex[5] = Points.ValuePoints[v5]; Wave.IndexVertex[0] = Points.IndexPoints[v0]; Wave.IndexVertex[1] = Points.IndexPoints[v1]; Wave.IndexVertex[2] = Points.IndexPoints[v2]; Wave.IndexVertex[3] = Points.IndexPoints[v3]; Wave.IndexVertex[4] = Points.IndexPoints[v4]; Wave.IndexVertex[5] = Points.IndexPoints[v5]; // check the wave by the rules if(WaveRules(Wave)==true) { // if the wave passed the check by the rules, add it to the waves tree ParentNode=Node.Add(NameWave,Wave); I=1; // create the first sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the first sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the second sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the second sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the third sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the third sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fourth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fourth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); I++; // create the fifth sub-wave in the waves tree ChildNode=ParentNode.Add(IntegerToString(I)); // if the interval of the chart, corresponding to the fifth sub-wave, has not been analyzed, then analyze it if(Already(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I])==false) FinishedWaves(Wave,I,ChildNode,WaveDescription[IndexWave].Subwaves[I],Level+1); } // otherwise, if the wave did not pass the check by the rules, release the memory else delete Wave; } } v4=v4+2; } v3=v3+2; } v2=v2+2; } v1=v1+2; } }
6.8. La funzione FindWaveInWaveDescription:
//+------------------------------------------------------------------+ //| The FindWaveInWaveDescription function | //+------------------------------------------------------------------+ int FindWaveInWaveDescription(string NameWave) { for(int i=0;i<ArrayRange(WaveDescription,0);i++) if(WaveDescription[i].NameWave==NameWave)return(i); return(-1); }
6.9. La funzione Already:
//+------------------------------------------------------------------+ //| The Already function | //+------------------------------------------------------------------+ bool Already(TWave *Wave,int NumWave,TNode *Node,string Subwaves) { // obtain the necessary parameters of the wave or the group of waves int IndexStart=Wave.IndexVertex[NumWave-1]; int IndexFinish=Wave.IndexVertex[NumWave]; double ValueStart = Wave.ValueVertex[NumWave - 1]; double ValueFinish= Wave.ValueVertex[NumWave]; // in the loop, proceed the array NodeInfoArray for the search of the marked-up section of the chart for(int i=NodeInfoArray.Total()-1; i>=0;i--) { TNodeInfo *NodeInfo=NodeInfoArray.At(i); // if the required section has already been marked-up if(NodeInfo.Subwaves==Subwaves && (NodeInfo.ValueStart==ValueStart) && (NodeInfo.ValueFinish==ValueFinish) && (NodeInfo.IndexStart==IndexStart) && (NodeInfo.IndexFinish==IndexFinish)) { // add the child nodes of the found node into the child nodes of the new node for(int j=0;j<NodeInfo.Node.Child.Total();j++) Node.Child.Add(NodeInfo.Node.Child.At(j)); return(true); // exit the function } } // if the interval has not been marked-up earlier, then record its data into the array NodeInfoArray TNodeInfo *NodeInfo=new TNodeInfo; NodeInfo.IndexStart=IndexStart; NodeInfo.IndexFinish=IndexFinish; NodeInfo.ValueStart=ValueStart; NodeInfo.ValueFinish=ValueFinish; NodeInfo.Subwaves=Subwaves; NodeInfo.Node=Node; NodeInfoArray.Add(NodeInfo); return(false); }
6.10. La funzione WaveRules:
int IndexVertex[6]; // the indexes of the tops of the wave double ValueVertex[6],Maximum[6],Minimum[6]; // the balues of the tops of the wave, as well as the maximum and minimum values of the wave string Trend; // direction of the trend - "Up" or "Down" string Formula; // the formula of the wave - "1<2-3>" or "1-2-3>" etc. int FixedVertex[6]; // information about the tops of the wave, whether or not they have been fixed //+------------------------------------------------------------------+ //| The function WaveRules | //+------------------------------------------------------------------+ bool WaveRules(TWave *Wave) { Formula=Wave.Formula; bool Result=false; // fill the array IndexVertex and ValueVertex - indexes of the tops and values of the tops of the wave for(int i=0;i<=5;i++) { IndexVertex[i]=Wave.IndexVertex[i]; ValueVertex[i]=Wave.ValueVertex[i]; FixedVertex[i]=-1; } // fill the array FixedVertex, the balues of which indicate whether or not the top of the wave is fixed int Pos1=StringFind(Formula,"<"); string Str; if(Pos1>0) { Str=ShortToString(StringGetCharacter(Formula,Pos1-1)); FixedVertex[StringToInteger(Str)]=1; FixedVertex[StringToInteger(Str)-1]=0; Pos1=StringToInteger(Str)+1; } else Pos1=0; int Pos2=StringFind(Formula,">"); if(Pos2>0) { Str=ShortToString(StringGetCharacter(Formula,Pos2-1)); FixedVertex[StringToInteger(Str)]=0; Pos2=StringToInteger(Str)-1; } else { Pos2=StringLen(Formula); Str=ShortToString(StringGetCharacter(Formula,Pos2-1)); Pos2=StringToInteger(Str); } for(int i=Pos1;i<=Pos2;i++) FixedVertex[i]=1; double High[],Low[]; ArrayResize(High,ArrayRange(rates,0)); ArrayResize(Low,ArrayRange(rates,0)); // find the maximums and minimums of the waves for(int i=1; i<=5; i++) { Maximum[i]=rates[IndexVertex[i]].high; Minimum[i]=rates[IndexVertex[i-1]].low; for(int j=IndexVertex[i-1];j<=IndexVertex[i];j++) { if(rates[j].high>Maximum[i])Maximum[i]=rates[j].high; if(rates[j].low<Minimum[i])Minimum[i]=rates[j].low; } } // find out the trend if((FixedVertex[0]==1 && ValueVertex[0]==rates[IndexVertex[0]].low) || (FixedVertex[1]==1 && ValueVertex[1]==rates[IndexVertex[1]].high) || (FixedVertex[2]==1 && ValueVertex[2]==rates[IndexVertex[2]].low) || (FixedVertex[3]==1 && ValueVertex[3]==rates[IndexVertex[3]].high) || (FixedVertex[4]==1 && ValueVertex[4]==rates[IndexVertex[4]].low) || (FixedVertex[5]==1 && ValueVertex[5]==rates[IndexVertex[5]].high)) Trend="Up"; else Trend="Down"; // check the required wave by the rules if(Wave.Name=="Impulse") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0 && VertexAAboveVertexB(4,1,true)>=0 && VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,true)>=0 && (WaveAMoreWaveB(3,1)>=0 || WaveAMoreWaveB(3,5)>=0)) Result=true; } else if(Wave.Name=="Leading Diagonal") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0 && VertexAAboveVertexB(4,2,true)>=0 && VertexAAboveVertexB(1,4,false)>=0 && VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,true)>=0&& (WaveAMoreWaveB(3,1)>=0 || WaveAMoreWaveB(3,5)>=0)) Result=true; } else if(Wave.Name=="Diagonal") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0 && VertexAAboveVertexB(4,2,true)>=0 && VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,true)>=0&& (WaveAMoreWaveB(3,1)>=0 || WaveAMoreWaveB(3,5)>=0)) Result=true; } else if(Wave.Name=="Zigzag") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0) Result=true; } else if(Wave.Name=="Flat") { if(VertexAAboveVertexB(1,0,false)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0) Result=true; } else if(Wave.Name=="Double Zigzag") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0) Result=true; } else if(Wave.Name=="Double Three") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,false)>=0) Result=true; } else if(Wave.Name=="Triple Zigzag") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(2,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,true)>=0 && VertexAAboveVertexB(3,1,false)>=0 && VertexAAboveVertexB(5,3,false) && VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,true)>=0) Result=true; } else if(Wave.Name=="Triple Three") { if(VertexAAboveVertexB(1,0,true)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,false)>=0 && VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,false)>=0) Result=true; } else if(Wave.Name=="Contracting Triangle") { if(VertexAAboveVertexB(1,0,false)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,false)>= 0&& VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,false)>=0 && WaveAMoreWaveB(2,3)>=0 && WaveAMoreWaveB(3,4)>=0 && WaveAMoreWaveB(4,5)>=0) Result=true; } else if(Wave.Name=="Expanding Triangle") { if(VertexAAboveVertexB(1,0,false)>=0 && VertexAAboveVertexB(1,2,false)>=0 && VertexAAboveVertexB(3,2,false)>= 0&& VertexAAboveVertexB(3,4,false)>=0 && VertexAAboveVertexB(5,4,false)>=0 && WaveAMoreWaveB(3,2)>=0 && WaveAMoreWaveB(3,2)>=0) Result=true; } return(Result); }
6.11. La funzioneVertexAAboveVertexB:
//+-------------------------------------------------------------------------------------+ //| The function VertexAAboveVertexB checks whether or not the top A is higher than top B, | //| transferred as the parameters of the given function | //| this check can be performed only if the tops A and B - are fixed, | //| or the top A - is not fixed and prime, while the top B - is fixed, | //| or the top A - is fixed, while the top B - is not fixed and odd, | //| or the top A - is not fixed and prime, and the top B - is not fixed and odd | //+-------------------------------------------------------------------------------------+ int VertexAAboveVertexB(int A,int B,bool InternalPoints) { double VA=0,VB=0,VC=0; int IA=0,IB=0; int Result=0; if(A>=B) { IA = A; IB = B; } else if(A<B) { IA = B; IB = A; } // if the internal points of the wave must be taken into consideration if(InternalPoints==true) { if((Trend=="Up") && ((IA%2==0) || ((IA-IB==1) && (IB%2==0)))) { VA=Minimum[IA]; IA=IA-IA%2; } else if((Trend=="Down") && ((IA%2==0) || ((IA-IB==1) && (IB%2==0)))) { VA=Maximum[IA]; IA=IA-IA%2; } else if((Trend=="Up") && ((IA%2==1) || ((IA-IB==1) && (IB%2==1)))) { VA=Maximum[IA]; IA=IA -(1-IA%2); } else if((Trend=="Down") && (IA%2==1) || ((IA-IB==1) && (IB%2==1))) { VA=Minimum[IA]; IA=IA -(1-IA%2); } VB=ValueVertex[IB]; } else { VA = ValueVertex[IA]; VB = ValueVertex[IB]; } if(A>B) { A = IA; B = IB; } else if(A<B) { A = IB; B = IA; VC = VA; VA = VB; VB = VC; } if(((FixedVertex[A]==1) && (FixedVertex[B]==1)) || ((FixedVertex[A] == 0) &&(A % 2 == 0) && (FixedVertex[B] == 1)) || ((FixedVertex[A] == 1) && (FixedVertex[B] == 0) && (B %2 == 1)) || ((FixedVertex[A] == 0) & (A %2 == 0) && (FixedVertex[B] == 0) && (B % 2== 1))) { if(((Trend=="Up") && (VA>=VB)) || ((Trend=="Down") && (VA<=VB))) Result=1; else Result=-1; } return(Result); }
6.12. La funzione WaveAMoreWaveB:
//+-----------------------------------------------------------------------+ //| The function WaveAMoreWaveB checks whether or not the wave A is larger than the wave B, | //| transferred as the parameters of the given function | //| this check can be performed only if wave A - is complete, | //| and wave B - is incomplete or incomplete and unbegun | //+-----------------------------------------------------------------------+ int WaveAMoreWaveB(int A,int B) { int Result=0; double LengthWaveA=0,LengthWaveB=0; if(FixedVertex[A]==1 && FixedVertex[A-1]==1 && (FixedVertex[B]==1 || FixedVertex[B-1]==1)) { LengthWaveA=MathAbs(ValueVertex[A]-ValueVertex[A-1]); if(FixedVertex[B]==1 && FixedVertex[B-1]==1) LengthWaveB=MathAbs(ValueVertex[B]-ValueVertex[B-1]); else if(FixedVertex[B]==1 && FixedVertex[B-1]==0) { if(Trend=="Up") LengthWaveB=MathAbs(ValueVertex[B]-Minimum[B]); else LengthWaveB=MathAbs(ValueVertex[B]-Maximum[B]); } else if(FixedVertex[B]==0 && FixedVertex[B-1]==1) { if(Trend=="Up")LengthWaveB=MathAbs(ValueVertex[B-1]-Minimum[B-1]); else LengthWaveB=MathAbs(ValueVertex[B-1]-Maximum[B-1]); } if(LengthWaveA>LengthWaveB) Result=1; else Result=-1; } return(Result); }
6.13. La funzione ClearTree:
//+------------------------------------------------------------------+ //| The function of clearing the waves tree with the top node Node | //+------------------------------------------------------------------+ void ClearTree(TNode *Node) { if(CheckPointer(Node)!=POINTER_INVALID) { for(int i=0; i<Node.Child.Total();i++) ClearTree(Node.Child.At(i)); delete Node.Child; if(CheckPointer(Node.Wave)!=POINTER_INVALID)delete Node.Wave; delete Node; } }
6.14. La funzione ClearNodeInfoArray:
//+------------------------------------------------------------------+ //| The function of clearing the NodeInfoArray array | //+------------------------------------------------------------------+ void ClearNodeInfoArray() { for(int i=NodeInfoArray.Total()-1; i>=0;i--) { TNodeInfo *NodeInfo=NodeInfoArray.At(i); if(CheckPointer(NodeInfo.Node)!=POINTER_INVALID)delete NodeInfo.Node; delete NodeInfo; } NodeInfoArray.Clear(); }
6.15. La funzione ClearZigzagArray:
//+------------------------------------------------------------------+ //| The function of clearing the ZigzagArray array | //+------------------------------------------------------------------+ void ClearZigzagArray() { for(int i=0;i<ZigzagArray.Total();i++) { TZigzag *Zigzag=ZigzagArray.At(i); delete Zigzag.IndexVertex; delete Zigzag.ValueVertex; delete Zigzag; } ZigzagArray.Clear(); }
6.16. La funzione FillLabelArray:
CArrayObj *LabelArray[]; int LevelMax=0; //+------------------------------------------------------------------+ //| The FillLabelArray function | //+------------------------------------------------------------------+ void FillLabelArray(TNode *Node) { if(Node.Child.Total()>0) { // obtain the first node TNode *ChildNode=Node.Child.At(0); // obtain the structure, in which the information about the wave is stored TWave *Wave=ChildNode.Wave; string Text; // if there is a first top if(Wave.ValueVertex[1]>0) { // mark the top according to the wave if(Wave.Name=="Impulse" || Wave.Name=="Leading Diagonal" || Wave.Name=="Diagonal") Text="1"; else if(Wave.Name=="Zigzag" || Wave.Name=="Flat" || Wave.Name=="Expanding Triangle" || Wave.Name=="Contracting Triangle") Text="A"; else if(Wave.Name=="Double Zigzag" || Wave.Name=="Double Three" || Wave.Name=="Triple Zigzag" || Wave.Name=="Triple Three") Text="W"; // obtain the array of the ArrayObj tops, which have the index Wave.IndexVertex[1] on the price chart CArrayObj *ArrayObj=LabelArray[Wave.IndexVertex[1]]; if(CheckPointer(ArrayObj)==POINTER_INVALID) { ArrayObj=new CArrayObj; LabelArray[Wave.IndexVertex[1]]=ArrayObj; } // put the information about the top with the index Wave.IndexVertex[1] into the array ArrayObj TLabel *Label=new TLabel; Label.Text=Text; Label.Level=Wave.Level; if(Wave.Level>LevelMax)LevelMax=Wave.Level; Label.Value=Wave.ValueVertex[1]; ArrayObj.Add(Label); } if(Wave.ValueVertex[2]>0) { if(Wave.Name=="Impulse" || Wave.Name=="Leading Diagonal" || Wave.Name=="Diagonal") Text="2"; else if(Wave.Name=="Zigzag" || Wave.Name=="Flat" || Wave.Name=="Expanding Triangle" || Wave.Name=="Contracting Triangle") Text="B"; else if(Wave.Name=="Double Zigzag" || Wave.Name=="Double Three" || Wave.Name=="Triple Zigzag" || Wave.Name=="Triple Three") Text="X"; CArrayObj *ArrayObj=LabelArray[Wave.IndexVertex[2]]; if(CheckPointer(ArrayObj)==POINTER_INVALID) { ArrayObj=new CArrayObj; LabelArray[Wave.IndexVertex[2]]=ArrayObj; } TLabel *Label=new TLabel; Label.Text=Text; Label.Level=Wave.Level; if(Wave.Level>LevelMax)LevelMax=Wave.Level; Label.Value=Wave.ValueVertex[2]; ArrayObj.Add(Label); } if(Wave.ValueVertex[3]>0) { if(Wave.Name=="Impulse" || Wave.Name=="Leading Diagonal" || Wave.Name=="Diagonal") Text="3"; else if(Wave.Name=="Zigzag" || Wave.Name=="Flat" || Wave.Name=="Expanding Triangle" || Wave.Name=="Contracting Triangle") Text="C"; else if(Wave.Name=="Double Zigzag" || Wave.Name=="Double Three" || Wave.Name=="Triple Zigzag" || Wave.Name=="Triple Three") Text="Y"; CArrayObj *ArrayObj=LabelArray[Wave.IndexVertex[3]]; if(CheckPointer(ArrayObj)==POINTER_INVALID) { ArrayObj=new CArrayObj; LabelArray[Wave.IndexVertex[3]]=ArrayObj; } TLabel *Label=new TLabel; Label.Text=Text; Label.Level=Wave.Level; if(Wave.Level>LevelMax)LevelMax=Wave.Level; Label.Value=Wave.ValueVertex[3]; ArrayObj.Add(Label); } if(Wave.ValueVertex[4]>0) { if(Wave.Name=="Impulse" || Wave.Name=="Leading Diagonal" || Wave.Name=="Diagonal") Text="4"; else if(Wave.Name=="Expanding Triangle" || Wave.Name=="Contracting Triangle") Text="D"; else if(Wave.Name=="Triple zigzag" || Wave.Name=="Triple Three") Text="XX"; CArrayObj *ArrayObj=LabelArray[Wave.IndexVertex[4]]; if(CheckPointer(ArrayObj)==POINTER_INVALID) { ArrayObj=new CArrayObj; LabelArray[Wave.IndexVertex[4]]=ArrayObj; } TLabel *Label=new TLabel; Label.Text=Text; Label.Level=Wave.Level; if(Wave.Level>LevelMax)LevelMax=Wave.Level; Label.Value=Wave.ValueVertex[4]; ArrayObj.Add(Label); } if(Wave.ValueVertex[5]>0) { if(Wave.Name=="Impulse" || Wave.Name=="Leading Diagonal" || Wave.Name=="Diagonal") Text="5"; else if(Wave.Name=="Expanding Triangle" || Wave.Name=="Contracting Triangle") Text="E"; else if(Wave.Name=="Triple Zigzag" || Wave.Name=="Triple Three") Text="Z"; CArrayObj *ArrayObj=LabelArray[Wave.IndexVertex[5]]; if(CheckPointer(ArrayObj)==POINTER_INVALID) { ArrayObj=new CArrayObj; LabelArray[Wave.IndexVertex[5]]=ArrayObj; } TLabel *Label=new TLabel; Label.Text=Text; Label.Level=Wave.Level; if(Wave.Level>LevelMax)LevelMax=Wave.Level; Label.Value=Wave.ValueVertex[5]; ArrayObj.Add(Label); } // proceed the child nodes of the current node for(int j=0;j<ChildNode.Child.Total();j++) FillLabelArray(ChildNode.Child.At(j)); } }
6.17. La funzione CreateLabels:
double PriceInPixels; CArrayObj ObjTextArray; // declare the array, which will store the graphical objects of "Text" type //+------------------------------------------------------------------+ //| The function CreateLabels | //+------------------------------------------------------------------+ void CreateLabels() { double PriceMax =ChartGetDouble(0,CHART_PRICE_MAX,0); double PriceMin = ChartGetDouble(0,CHART_PRICE_MIN); int WindowHeight=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); PriceInPixels=(PriceMax-PriceMin)/WindowHeight; int n=0; // loop the LabelArray array for(int i=0;i<ArrayRange(LabelArray,0);i++) { // if there are tops with the same index i if(CheckPointer(LabelArray[i])!=POINTER_INVALID) { // obtain the tops with the same indexes i CArrayObj *ArrayObj=LabelArray[i]; // loop the tops and display them on the chart for(int j=ArrayObj.Total()-1;j>=0;j--) { TLabel *Label=ArrayObj.At(j); int Level=LevelMax-Label.Level; string Text=Label.Text; double Value=Label.Value; color Color; int Size=8; if((Level/3)%2==0) { if(Text=="1") Text="i"; else if(Text == "2") Text = "ii"; else if(Text == "3") Text = "iii"; else if(Text == "4") Text = "iv"; else if(Text == "5") Text = "v"; else if(Text == "A") Text = "a"; else if(Text == "B") Text = "b"; else if(Text == "C") Text = "c"; else if(Text == "D") Text = "d"; else if(Text == "E") Text = "e"; else if(Text == "W") Text = "w"; else if(Text=="X") Text="x"; else if(Text == "XX") Text = "xx"; else if(Text == "Y") Text = "y"; else if(Text == "Z") Text = "z"; } if(Level%3==2) { Color=Green; Text="["+Text+"]"; } if(Level%3==1) { Color=Blue; Text="("+Text+")"; } if(Level%3==0) Color=Red; int Anchor; if(Value==rates[i].high) { for(int k=ArrayObj.Total()-j-1;k>=0;k--) Value=Value+15*PriceInPixels; Anchor=ANCHOR_UPPER; } else if(Value==rates[i].low) { for(int k=ArrayObj.Total()-j-1;k>=0;k--) Value=Value-15*PriceInPixels; Anchor=ANCHOR_LOWER; } CChartObjectText *ObjText=new CChartObjectText; ObjText.Create(0,"wave"+IntegerToString(n),0,rates[i].time,Value); ObjText.Description(Text); ObjText.Color(Color); ObjText.SetInteger(OBJPROP_ANCHOR,Anchor); ObjText.FontSize(8); ObjText.Selectable(true); ObjTextArray.Add(ObjText); n++; } } } ChartRedraw(); }
6.18. La funzione CorrectLabel:
//+------------------------------------------------------------------+ //| The CorrectLabel function | //+------------------------------------------------------------------+ void CorrectLabel() { double PriceMax=ChartGetDouble(0,CHART_PRICE_MAX,0); double PriceMin = ChartGetDouble(0,CHART_PRICE_MIN); int WindowHeight=ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); double CurrentPriceInPixels=(PriceMax-PriceMin)/WindowHeight; // loop all of the text objects (wave tops) and change their price size for(int i=0;i<ObjTextArray.Total();i++) { CChartObjectText *ObjText=ObjTextArray.At(i); double PriceValue=ObjText.Price(0); datetime PriceTime=ObjText.Time(0); int j; for(j=0;j<ArrayRange(rates,0);j++) { if(rates[j].time==PriceTime) break; } double OffsetInPixels; if(rates[j].low>=PriceValue) { OffsetInPixels=(rates[j].low-PriceValue)/PriceInPixels; ObjText.Price(0,rates[j].low-OffsetInPixels*CurrentPriceInPixels); } else if(rates[j].high<=PriceValue) { OffsetInPixels=(PriceValue-rates[j].high)/PriceInPixels; ObjText.Price(0,rates[j].high+OffsetInPixels*CurrentPriceInPixels); } } PriceInPixels=CurrentPriceInPixels; }
7. La funzione di inizializzazione, de-approvvigionamento ed elaborazione degli eventi
Nella funzione OnInit vengono creati i pulsanti di controllo dell'analizzatore automatico delle onde di Elliott.
Vengono creati i seguenti pulsanti:
- "Avvia analisi": si verifica un'analisi automatica delle onde
- "Mostra risultati": si verifica la visualizzazione dei segni dell'onda sul grafico,
- "Cancella grafico": si verifica una cancellazione della memoria e la cancellazione dei segni d'onda dal grafico,
- "Correggi i segni": corregge i segni delle onde sulla carta.
L'elaborazione della pressione di questi pulsanti avviene in funzione dell'elaborazione dell'evento OnChartEvent.
Nella funzione OnDeinit tutti gli oggetti grafici vengono rimossi dal grafico, inclusi i pulsanti di controllo.
#include <Object.mqh> #include <Arrays\List.mqh> #include <Arrays\ArrayObj.mqh> #include <Arrays\ArrayInt.mqh> #include <Arrays\ArrayDouble.mqh> #include <Arrays\ArrayString.mqh> #include <ChartObjects\ChartObjectsTxtControls.mqh> #include <Elliott wave\Data structures.mqh> #include <Elliott wave\Analysis functions.mqh> #include <Elliott wave\Rules functions.mqh> CChartObjectButton *ButtonStart,*ButtonShow,*ButtonClear,*ButtonCorrect; int State; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { State=0; // create control buttons ButtonStart=new CChartObjectButton; ButtonStart.Create(0,"Begin analysis",0,0,0,150,20); ButtonStart.Description("Begin analysis"); ButtonShow=new CChartObjectButton; ButtonShow.Create(0,"Show results",0,150,0,150,20); ButtonShow.Description("Show results"); ButtonClear=new CChartObjectButton; ButtonClear.Create(0,"Clear chart",0,300,0,150,20); ButtonClear.Description("Clear chart"); ButtonCorrect=new CChartObjectButton; ButtonCorrect.Create(0,"Correct the marks",0,450,0,150,20); ButtonCorrect.Description("Correct the marks"); ChartRedraw(); return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //clear waves tree ClearTree(FirstNode); //clear NodeInfoArray ClearNodeInfoArray(); //clear ZigzagArray ClearZigzagArray(); //clear LabelArray for(int i=0;i<ArrayRange(LabelArray,0);i++) { CArrayObj *ArrayObj=LabelArray[i]; if(CheckPointer(ArrayObj)!=POINTER_INVALID) { for(int j=0;j<ArrayObj.Total();j++) { TLabel *Label=ArrayObj.At(j); delete Label; } ArrayObj.Clear(); delete ArrayObj; } } //delete all of the graphical elements from the chart for(int i=ObjTextArray.Total()-1;i>=0;i--) { CChartObjectText *ObjText=ObjTextArray.At(i); delete ObjText; } ObjTextArray.Clear(); delete ButtonStart; delete ButtonShow; delete ButtonClear; delete ButtonCorrect; ChartRedraw(); } MqlRates rates[]; TNode *FirstNode; //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Begin analysis" && State!=0) MessageBox("First press the button \"Clear char\""); if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Show results" && State!=1) MessageBox("First press the button \"Begin analysis\""); if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Clear chart" && State!=2) MessageBox("First press the button \"Show results\""); if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Correct the mark" && State!=2) MessageBox("First press the button \"Show results\""); //if the "Begin analysis" is pressed if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Begin analysis" && State==0) { //fill the rates array CopyRates(NULL,0,0,Bars(_Symbol,_Period),rates); //fill the array ZigzagArray FillZigzagArray(0,Bars(_Symbol,_Period)-1); //create the first node TWave *Wave=new TWave; Wave.IndexVertex[0] = 0; Wave.IndexVertex[1] = Bars(_Symbol,_Period)-1; Wave.ValueVertex[0] = 0; Wave.ValueVertex[1] = 0; FirstNode=new TNode; FirstNode.Child=new CArrayObj; FirstNode.Wave=Wave; FirstNode.Text="First node"; string NameWaves="Impulse,Leading Diagonal,Diagonal,Zigzag,Flat,Double Zigzag,Triple Zigzag, Double Three,Triple Three,Contracting Triangle,Expanding triangle"; //call the search for unbegun and incomplete waves function NotStartedAndNotFinishedWaves(Wave,1,FirstNode,NameWaves,0); MessageBox("Analysis is complete"); State=1; ButtonStart.State(false); ChartRedraw(); } // if "Show results" is pressed if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Show results" && State==1) { ArrayResize(LabelArray,ArrayRange(rates,0)); //fill the LabelArray array FillLabelArray(FirstNode); //show the mark-up of the waves on the chart CreateLabels(); State=2; ButtonShow.State(false); ChartRedraw(); } //if "Clear chart" is pressed" if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Clear chart" && State==2) { //clear the waves tree ClearTree(FirstNode); //clear the NodeInfoArray array ClearNodeInfoArray(); //clear the ZigzagArray array ClearZigzagArray(); //clear LabelArray for(int i=0;i<ArrayRange(LabelArray,0);i++) { CArrayObj *ArrayObj=LabelArray[i]; if(CheckPointer(ArrayObj)!=POINTER_INVALID) { for(int j=0;j<ArrayObj.Total();j++) { TLabel *Label=ArrayObj.At(j); delete Label; } ArrayObj.Clear(); delete ArrayObj; } } // delete mark-up from the chart for(int i=ObjTextArray.Total()-1;i>=0;i--) { CChartObjectText *ObjText=ObjTextArray.At(i); ObjText.Delete(); } ObjTextArray.Clear(); State=0; ButtonClear.State(false); ChartRedraw(); } if(id==CHARTEVENT_OBJECT_CLICK && sparam=="Correct the marks" && State==2) { CorrectLabel(); ButtonCorrect.State(false); ChartRedraw(); } }
Abbiamo esaminato tutte le funzioni dell'analizzatore automatico delle onde di Elliott.
8. Modi per migliorare il programma
Il markup automatico del programma onde di Elliott, scritto in MQL5, presenta diversi difetti:
- Un sistema imperfetto di controllo delle regole di markup. Ad esempio, quando si controlla secondo le regole, le relazioni di Fibonacci tra le onde non vengono prese in considerazione, sia per tempo che per prezzo.
- La presenza di sezioni non partizionate sul grafico (lacune nel mark-up). Ciò significa che non è possibile costruire un'onda corretta in base ai punti presi dal dato intervallo di tempo. La via d'uscita da questa situazione è aumentare il numero di punti per identificare una particolare onda. Ad esempio, per trovare l'impulso, cerca 8 o più punti, anziché 6.
- I risultati del mark-up non mostrano alcuna informazione aggiuntiva. Ad esempio, i canali non vengono costruiti automaticamente, gli obiettivi non vengono valutati, ecc.
- L'implementazione dell'utilizzo dell'albero delle onde non è fornita in questo articolo (non è possibile selezionare una versione specifica del mark-up), pertanto il grafico visualizza solo una delle tante opzioni per un mark-up (la prima versione del mark-up).
- Indipendentemente dal fatto che la carta visualizzi solo una variante delle onde, tutte le altre opzioni vengono salvate in memoria e ne occupano lo spazio.
- Il programma si concentra sul mark-up dei grafici Monthly to Daily, poiché l'operazione è molto lenta quando c'è un numero elevato di barre (potrebbero essere necessarie ore per contrassegnare un grafico orario). Un esempio di mark-up di un grafico mensile di EURUSD è mostrato nella figura 18.
Figura 18. Onde di Elliott identificate dall'analizzatore automatico in MQL5
Conclusione
Questo articolo ha esaminato un algoritmo dell'analisi automatica delle onde di Elliott. Questo algoritmo è stato implementato nel linguaggio MQL5.
Il programma ha una serie di carenze, discusse sopra, e dà ragione della loro ulteriore eliminazione. Spero che questo problema interessi i fan delle onde di Elliott e presto appariranno molti programmi con l'analisi automatica delle onde.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/260
- 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