![El espectáculo debe continuar, o una vez más sobre el ZigZag](https://c.mql5.com/i/articles/overlay.png)
El espectáculo debe continuar, o una vez más sobre el ZigZag
Introducción
Una gran cantidad de versiones ZigZag prueban la existencia de un constante y persistente interés en este indicador. Un interés que merece bastante la pena. Este es quizás el único indicador que afecta directamente a las emociones del trader forzando las acciones inmediatas con su brillante y vívida representación gráfica de los principales movimientos del mercado. Aparentemente, esta puede ser la única explicación del fenómeno con un profundo conocimiento de la mayoría de que este indicador no tiene por finalidad la producción de señales de trading directas, no obstante estos intentan continuamente abordarlo al máximo en la situación actual del mercado. Observar el redibujado interminable de la última fractura de predicción es una ventaja dudosa, especialmente al percibirla.
Vamos a debatir un poco. Creámoslo o no, este es el comienzo de todo.
Letra de la canción
Todos nosotros que llegamos y nos QUEDAMOS en este mercado, tarde o temprano entendemos que no es tan simple como pensábamos al principio. Tan pronto como nos damos cuenta de ello, comenzamos a leer (aquellos que puede, claro). Pero, de alguna forma, percibimos lo que leemos de forma muy peculiar. En pocas palabras, elegimos las cosas más simples, no las correctas. En consecuencia, añadimos a nuestro arsenal solo las cosas más superficiales que son obvias de comprender y pueden traducirse fácilmente (y rápidamente) a un lenguaje algorítmico. Hay muchos ejemplos de ello. Este es uno, puede que no el mejor, pero vamos a aceptarlo como tal.
Todo el mundo sabe y recuerda que la tesis básica TA que todavía no ha sido desaprobada aún, pero tampoco ha sido estrictamente probada, no obstante:
El precio lo es todo
Tomando esto literalmente de frente, comenzamos a buscar, no los puntos de control del mercado, sino por todos los medios sus máximos y mínimos, ya que esto es más fácil y claro. Trazamos niveles de ayuda/resistencia con una regla, contamos niveles Fivo en ellos, contamos los ciclos en las barras, etc. De mal en peor, comenzamos a coger del sistema de trading de alguiensolo las cosas que son accesibles a nuestra comprensión sin prestar atención a las advertencias o para qué mercado es y el tiempo de creación de dicho sistema ….. Y lo que es peor, comenzamos a simplificar... simplificando Gaan, quien, según mi opinión, encontró (o estuvo muy cerca) la solución del problema del precio/tiempo...delirio...¿cómo es posible simplificar algo que todavía no ha sido completamente comprendido por nadie?
Y luego, cuando nos damos cuenta de que todo funciona mal de alguna forma, un poco mejor que a partes iguales, comenzamos a decir en alto que los gurús mienten, que sus métodos no funcionan, que los libros solo se escriben para sacar dinero, que la sección dorada no existe...etc. Y este es el resultado de nuestro olvido de que no es el sinónimo de minimax cuando miramos un extremo, sino en realidad este es un máximo o un mínimo, solo otra exhibición de su esencia interior que todavía necesitamos alcanzar. Por tanto, en base a esta visión superficial, intentamos predecir el futuro incluso sin intentar analizar qué hizo que este punto fuera el que está justo en este lugar en este momento.
Igual que nos gustaría ganar dinero, no nos afecta que algunas veces necesitemos parar y pensar un poco. Es algo muy útil, ya sabes. Comenzamos a percibir claramente la exactitud de que "el hombre es la única criatura viviente que hace lo mismo una y otra vez esperando resultados distintos". No estamos partiendo leña, ¿verdad? :)
Yo también me he dejado llevar por la euforia. Puede que debido a que se trata de mí, también. Es el momento de rematar. Vamos a comprender que no todos los gurús son gurús y que los que lo son nunca lo dirán todo...especialmente porque saben que lo que se da con cuchara no es sabroso ni es de mucha ayuda.
De vuelta al tema.
ZigZag fractal multimarco
Necesitaba un indicador que no solo representara los mínimos y los máximos, sino los puntos extremos del mercado guiados lógicamente por los movimientos del precio (LREP - ¿sería posible que esta abreviatura fuera más natural?) y, si es posible, que se confirmara. El problema de hacer que sea un generador de señales no se planteó inicialmente. En primer lugar, intenté jugar con el ZigZag estándar (no el incluido en MT4, sino el "estándar" en sentido general), pero había algo que me puso en alerta y me obligó a renunciar a esta idea:
- la uniformidad de todos los algoritmos a pesar de muchas discusiones en internet y una gran variedad de versiones (a propósito, quizás solo sea mi opinión, pero nunca me he encontrado con este algoritmo claramente decodificado en ningún sitio);
- la ausencia de un solo concepto sobre "qué" debería buscar;
- un desagradablemente frecuente y, lo que es peor, escasamente predecible redibujado;
- dependencia directa del periodo de tiempo y/o del paseo del precio previamente especificado;
En lo que respecta a mí, el último es el menos aceptable. No me seduce. Nada personal.
Recuerdo a Demark con estos puntos TD y a Williams con sus "fractales" (no sé quién pidió prestado a quién, pero son como dos gotas de agua). Parecían ser los "correctos", se argumentó al menos con los movimientos del precio anteriores y posteriores. Puede que no a todo el mundo le guste este tipo de enfoque en la elección de estos puntos. No obstante, nadie ha inventado nada más preciso y adecuado para su identificación inicial todavía, excepto para términos como "extremo valioso", "máximo local", etc., por supuesto.
Ninguno de los dos quizás son los mejores, pero seguro que son los más "familiares". Por esta razón no busco un código prestado y escribí mi propio indicador fractal sencillo, con más precisión, su parecido: las reglas de puntos que eligen ligeramente distinto se diferencian de las estándar. He intentado llamarlo con diferentes periodos de tiempo usando iCustom, pero entonces comprendí que sería más sensato calcular todo en el periodo de tiempo actual (el de trabajo). Además, la lógica de la programación lo advirtió todo: y sobre la construcción del módulo que se sugiere a sí mismo en el futuro y sobre el periodo de tiempo no estándar. Este es el resultado de lo que se obtuvo.
Las imágenes muestran su aspecto con los parámetros 1440, 360 y 60. El gráfico H1 se elije por su capacidad ilustrativa para que usted vea que la línea negra (60) no toma todos los puntos fractales y rechaza algunos de ellos. La primera imagen es para ver la punta, y la segunda solo se toma desde la zona central del gráfico.
El esquema de color no es el mejor, la imagen adjunta muestra mi visión al respecto.
Código
Vamos a ver cómo se implementa: ¿debemos actuar en un espectáculo de pantomimas? ;)
El indicador forma en el periodo de tiempo de trabajo una secuencia de nodos de ZigZag que se calculan en tres periodos de tiempo amulados más largos. Funciona en todos con todos los periodos de tiempo, incluidos los no estándar con las siguientes restricciones implementadas en el código:
- el periodo de tiempo más largo debe ser divisible por el de trabajo, ya que si no lo es, se establecen forzadamente los valores correctos más cercanos;
- el periodo de tiempo de trabajo no es mayor que el periodo de tiempo más grande;
- los periodos en los parámetros se especifican en minutos y deben establecerse en orden decreciente;
- el periodo del periodo de tiempo mayor no supera 43200 (un mes) - ese no es el límite, es posible uno mayor;
La función es que solo un búfer se usa para cada periodo de tiempo. No es necesario usar dos de ellos, ya que en la combinación lógica de periodos de tiempo, la probabilidad de >aparición de dos extremos dirigidos de forma distinta en una única barra del periodo de tiempo de trabajo es demasiado pequeña.
Este es el fragmento:
//----------------------------------------------------------------------- // MF_Fractal_ZZ_3in1.mq4 //----------------------------------------------------------------------- #property copyright "Copyright © 2008, BiViSi Corp." #property link "riderfin@bk.ru" #property link "ICQ 499949112" #property indicator_chart_window #property indicator_buffers 3 //---- style of the indicator line #property indicator_color1 Blue #property indicator_color2 Red #property indicator_color3 Yellow #property indicator_style1 0 #property indicator_style2 0 #property indicator_style3 0 #property indicator_width1 5 #property indicator_width2 3 #property indicator_width3 1 //---- INOUT PARAMETERS OF THE INDICATOR extern int VolExt=50; // VolExt+1" calculation of the last control points extern int TFLarge=1440; extern int TFMidle=240; extern int TFSmall=60; //---- Variables double Large[],Midle[],Small[]; // control points (indicator bufers) datetime PrevTimePer[4]; // the time of the last calculation of every TF datetime PrevTimeCalc=0; double P60,CP60; int CurPeriod, ErrorTF=0, NumberExt, Per, largelast=0, midlelast=0, smalllast=0; //----------------------------------------------------------------------- int init() { // initialization IndicatorBuffers(3); // for perspective" entry :) SetIndexBuffer(0,Large); SetIndexStyle(0,DRAW_SECTION); SetIndexEmptyValue(0,0.0); SetIndexBuffer(1,Midle); SetIndexStyle(1,DRAW_SECTION); SetIndexEmptyValue(1,0.0); SetIndexBuffer(2,Small); SetIndexStyle(2,DRAW_SECTION); SetIndexEmptyValue(2,0.0); ArrayInitialize(PrevTimePer,0); CurPeriod=Period(); CP60=CurPeriod*60; // restrictions: // control of TF and inputted parameters if (MathCeil(TFSmall/CurPeriod) != TFSmall/CurPeriod) TFSmall=MathCeil(TFSmall/CurPeriod)*CurPeriod; if (MathCeil(TFMidle/CurPeriod) != TFMidle/CurPeriod) TFMidle=MathCeil(TFMidle/CurPeriod)*CurPeriod; if (MathCeil(TFLarge/CurPeriod) != TFLarge/CurPeriod) TFLarge=MathCeil(TFLarge/CurPeriod)*CurPeriod; if (CurPeriod > TFSmall) {Alert ("The chart period must be less than or equal to ", TFSmall," min."); ErrorTF=1;return;} if (TFSmall >= TFMidle || TFMidle >= TFLarge || TFLarge>43200) {Alert ("Incorrect choice of timeframes for calulation!!!"); ErrorTF=1;return;} return; } //--------------------------------------------------------------------
El siguiente bloque es responsable de la búsqueda de los puntos de control, del cálculo de los nodos ZigZag y de escribirlos en las matrices del búfer del indicador.
La negativa a usar las construcciones del tipo int IC=IndicatorCounted(); y demás, depende del propio algoritmo de cálculo que proporciona la velocidad suficiente sin él (ver Force #1-3 en el código), este también puede aumentarse a propósito, un poco antes sobre este.
//-------------------------------------------------------------------- int start() { if ( ErrorTF==1 ) return; // incorrect timeframe FractalCalc(); return; } //====================================================================== // Searching of the 5 bar fractals and zigzag nodes claculation // on the emulation of the larger TF, deleting of the odd ones and representation on the current TF //====================================================================== void FractalCalc () { // Force №1 - caculation only on the fully formed bar of the working TF if (PrevTimeCalc == Time[0]) return; else PrevTimeCalc=Time[0]; int y, x, k, i, j, extr=0; // the time of the last bar of the current TF, that closes bar №1-5 of the larger TF int t1, t2, t3, t4, t5; // the number of the last bar of the cur. El periodo de tiempo que cierra la barra nº 1-5 del mayor periodo de tiempo int limit1, limit2, limit3, limit4, limit5; // the numver of bars of the cur. Periodo de tiempo con los picos y bases que corresponden a las barras 1-5 del mayor periodo de tiempo int up1,up2,up3,up4,up5,dn1,dn2,dn3,dn4,dn5; for (y=1; y<=3; y++) // cycle of the calculated TF { if (y==1) Per=TFLarge; if (y==2) Per=TFMidle; if (y==3) Per=TFSmall; P60=Per*60; // Force №2 - calculate the fissures only with the forming of the bar of the larger TF if (PrevTimePer[y] !=0) { if (Per<43200 && (Time[0] - PrevTimePer[y])<P60 )continue; if (Per==43200 && Month()==TimeMonth(PrevTimePer[y]))continue; } // Processing of bars absence // If linearly PrevTimePer[y]=Time[0], then in case of bar absence // the shift of whole calculation chain by the absence size will take place on the working TF PrevTimePer[y]=MathCeil(Time[0]/Per/60)*P60; NumberExt=0; extr=0; k=Per/CurPeriod; // limitation of cycle depending on currently calculated TF // and on the last fractal i=MathCeil(Bars/k)-5; // Force #3 - calculation starting with the last fissure if(y==1 && largelast !=0) i=largelast+k; if(y==2 && midlelast !=0) i=midlelast+k; if(y==3 && smalllast !=0) i=smalllast+k; for (x=1; x<=i; x++) { // find peaks and bases // the time of the beginning of the las bar of the cur. Periodo de tiempo que cierra la barra nº 1 del mayor periodo de tiempo if (PrevTimePer[y] !=0) t1=PrevTimePer[y]-x*P60+(k-1)*CP60; else t1=MathCeil(Time[0]/Per/60)*P60-x*P60+(k-1)*CP60; t2=t1-P60; t3=t2-P60; t4=t3-P60; t5=t4-P60; limit1=iBarShift(NULL,0,t1, false); limit2=iBarShift(NULL,0,t2, false); limit3=iBarShift(NULL,0,t3, false); limit4=iBarShift(NULL,0,t4, false); limit5=iBarShift(NULL,0,t5, false); up1=iHighest(NULL,0,MODE_HIGH,k,limit1); up2=iHighest(NULL,0,MODE_HIGH,k,limit2); up3=iHighest(NULL,0,MODE_HIGH,k,limit3); up4=iHighest(NULL,0,MODE_HIGH,k,limit4); up5=iHighest(NULL,0,MODE_HIGH,k,limit5); dn1=iLowest(NULL,0,MODE_LOW,k,limit1); dn2=iLowest(NULL,0,MODE_LOW,k,limit2); dn3=iLowest(NULL,0,MODE_LOW,k,limit3); dn4=iLowest(NULL,0,MODE_LOW,k,limit4); dn5=iLowest(NULL,0,MODE_LOW,k,limit5); // searching for control points if(High[up3]>High[up2] && High[up3]>High[up1] && High[up3]>=High[up4] && High[up3]>=High[up5]) { if (y==1){Large[up3]=High[up3];largelast=up3;} if (y==2){Midle[up3]=High[up3];midlelast=up3;} if (y==3){Small[up3]=High[up3];smalllast=up3;} NumberExt++; extr++; } if(Low[dn3]<Low[dn2] && Low[dn3]<Low[dn1] && Low[dn3]<=Low[dn4] && Low[dn3]<=Low[dn5]) { if (y==1){Large[dn3]=Low[dn3];largelast=dn3;} if (y==2){Midle[dn3]=Low[dn3];midlelast=dn3;} if (y==3){Small[dn3]=Low[dn3];smalllast=dn3;} NumberExt++; extr++; } if (NumberExt>VolExt) break; } }
Como ve, la mayor parte del código tiene por finalidad la optimización de los cálculos y la protección contra una posible situación inesperada: conexión perdida en el servidor y barras perdidas en el historial.
El siguiente bloque realiza una especie de "desbroce": el borrado de los extremos anormales (cuando aparecen varias bases entre dos picos y viceversa) para formar un ZigZag correcto: los máximos/mínimos se eligen de 2 o más picos/bases que vienen en sucesión y, en caso de igualdad, se elige el que tiene el último número... los anormales se establecen a cero. El algoritmo proporciona espacio para el argumento, por supuesto, y son posibles alternativas, pero decidí hacerlo por el momento.
El código contiene entradas comentadas que permiten deshacerse de la discordancia en picos/bases que aparecen en distintos periodos de tiempo, pero es necesario darle otro repaso, ya que no funciona correctamente en la forma actual. Ayudo en esta idea de forma temporal, pero usted puede hacerlo por sí mismo si está interesado.
El mismo fragmento tiene otra posibilidad de acelerar su funcionamiento si se usa la construcción if (NumberExt>VolExt) break; del cambio calculado anteriormente, pero lo he demorado por el momento.
Y una vez que hemos comenzado a hablar sobre la velocidad, el método más obvio y sencillo es disminuir VolExt en las entradas del indicador. Es difícil que alguien necesite más de 10-15 para el trading, no para el análisis, excepto para los auténticos glotones :).
if (extr==0) return; for (y=1; y<=3; y++) { if (y==1) j=ArraySize(Large);if (y==2)j=ArraySize(Midle); if (y==3)j=ArraySize(Small); int min=0, max=0, extmin=0, extmax=0; NumberExt=0; for (x=1;x<=j;x++) { if (y==1) { if (Large[x] == 0.0 ) continue; if (Large[x] == High[x]) { NumberExt++; extmax++; extmin=0; if (extmax==2) { if (Large[max]>=Large[x])Large[x]=0.0; else {Large[max]=0.0;max=x;} extmax--; } else max=x; } if (Large[x] == Low[x]) { NumberExt++; extmax=0; extmin++; if (extmin==2) { if (Large[min]<=Large[x])Large[x]=0.0; else {Large[min]=0.0;min=x;} extmin--; } else min=x; } } if (y==2) { if (Midle[x] == 0.0 ) continue; if (Midle[x] == High[x]) { NumberExt++; extmax++; extmin=0; if (extmax==2) { if (Midle[max]>=Midle[x])Midle[x]=0.0; else {Midle[max]=0.0;max=x;} extmax--; // it can be easier as the above one, but.... remove disagreements /* if (Midle[max]>Midle[x])Midle[x]=0.0; if (Midle[max]==Midle[x]) { if (Large[x] == High[x]) {Midle[max]=0.0;max=x;} else Midle[x]=0.0; } if (Midle[max]<Midle[x]){Midle[max]=0.0;max=x;} */ } else max=x; } if (Midle[x] == Low[x]) { NumberExt++; extmax=0; extmin++; if (extmin==2) { if (Midle[min]<=Midle[x])Midle[x]=0.0; else {Midle[min]=0.0;min=x;} extmin--; // it can be easier as the above one, but.... remove disagreements /* if (Midle[min]<Midle[x])Midle[x]=0.0; if (Midle[min]==Midle[x]) { if (Large[x] == Low[x]) {Midle[min]=0.0;min=x;} else Midle[x]=0.0; } if (Midle[min]>Midle[x]){Midle[min]=0.0;min=x;} */ } else min=x; } } if (y==3) { if (Small[x] == 0.0 ) continue; if (Small[x] == High[x]) { NumberExt++; extmax++; extmin=0; if (extmax==2) { if (Small[max]>=Small[x])Small[x]=0.0; else {Small[max]=0.0;max=x;} extmax--; // it can be easier as the above one, but.... remove disagreements /* if (Small[max]>Small[x])Small[x]=0.0; if (Small[max]==Small[x]) { if (Midle[x] == High[x]) {Small[max]=0.0;max=x;} else Small[x]=0.0; } if (Small[max]<Small[x]){Small[max]=0.0;max=x;} */ } else max=x; } if (Small[x] == Low[x]) { NumberExt++; extmax=0; extmin++; if (extmin==2) { if (Small[min]<=Small[x])Small[x]=0.0; else {Small[min]=0.0;min=x;} extmin--; // it can be easier as the above one, but.... remove diagreements /* if (Small[min]<Small[x])Small[x]=0.0; if (Small[min]==Small[x]) { if (Midle[x] == Low[x]) {Small[min]=0.0;min=x;} else Small[x]=0.0; } if (Small[min]>Small[x]){Small[min]=0.0;max=x;} */ } else min=x; } } if (NumberExt>VolExt) break; } } }
Conclusión
Como resultado, tenemos un indicador con un algoritmo que es quizás obvio, pero nunca ha sido usado por nadie antes, obtenido de algunas desventajas del ZigZag estándar y con las siguientes ventajas:
- los nodos se redibujan relativamente con menos frecuencia y el redibujado es razonable para el balanceo y para el movimiento del precio anterior. Al mismo tiempo, si estos coinciden en distintos periodos de tiempo, entonces hay una probabilidad del 90-95 % de que no se produzca ningún redibujado;
- la posibilidad de observar todo lo que ocurre en tres periodos de tiempo mayores en un único gráfico y, como resultado, la posibilidad de descubrir las principales tendencias sin usar ninguna construcción o herramienta adicional;
- el uso para cálculos ZigZag cualquier periodo de tiempo subestándar (desde M5 a MN1) cumpliendo cualquier requisito y necesidad;
- eficiencia, alta velocidad de cálculos, algoritmo y código claros que pueden corregirse y mejorarse fácilmente.
Puede que me pregunte por qué no hago esta corrección yo mismo de inmediato. Tengo suficiente con lo que tenemos por el momento... suficiente POR EL MOMENTO. :)
Y sé que un código eficiente terminado puede repasarse infinitamente. Es como sacar punta a un lápiz... puedes olvidarte de que lo que querías era dibujar con él. Me gustaría comenzar a dibujar. Tengo muchas ganas. :)
¿Qué será lo siguiente y qué debemos hacer al respecto? No hay una solución de antemano. Esto es solo una herramienta y lo que debe hacerse cuando se usa, un Pinocho o un taburete, lo decidirá por sí mismo cada Geppetto.
Solo puedo decir que el residuo seco contiene 5 búferes de indicador gratuitos, la posibilidad de añadir fácilmente algunos módulos nuevos y una respuesta bastante adecuada para llamar a través de iCustom().... ¡Fantasear!
Lo mejor que queda por hacer es dar mi AGRADECIMIENTO a:
ANG3110 - por lo más valioso - las ideas que, adecuadamente, me empujaron a escribir este indicador;
Korey - por su apoyo y ayuda en el diagnóstico de TimeCurrent y la optimización de los cálculos;
La gente del panel de anuncios, quienes de uno u otro modo, de forma consciente o no, algunas veces expresan sus ideas sobre las que me gusta meditar.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1531
![Integración del terminal de cliente de MetaTrader 4 con MS SQL Server](https://c.mql5.com/2/16/625_23.gif)
![Falacias, Parte 2. La estadística es una pseudociencia o la "crónica de la caída en picado de cada día"](https://c.mql5.com/2/16/617_41.gif)
![Indicadores de prueba de asesores expertos no de trading](https://c.mql5.com/2/16/627_11.gif)
![Modificación en dos etapas de posiciones abiertas](https://c.mql5.com/2/16/612_6.gif)
![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso