
De lo básico a intermedio: Indicador (III)
En el artículo anterior, "Del básico al intermedio: Indicador (II)", nos lo pasamos muy bien y aprendimos mucho, ya que se demostró cómo implementar una media móvil de forma muy simple, práctica y perfectamente funcional. Sin embargo, aquello que se mostró puede considerarse solo una breve introducción al mundo de la programación MQL5, ya que el material es bastante básico, simple y directo. Sin embargo, podemos hacer mucho más.
Así que, querido lector, intenta comprender los conceptos que se exponen aquí. No intentes simplemente copiar el código ni pienses que, solo porque tú no consigues hacerlo, nadie más sabe cómo hacer esto o aquello. Entender el concepto es más importante que entender el propio código, ya que este puede cambiar dependiendo de quién lo escriba. El concepto, sin embargo, siempre se mantendrá. Comenzaremos con algo muy sencillo, ya que lo que se verá puede llegar a ser muy complicado si aplicamos ciertas funcionalidades de repente.
Un indicador y múltiples representaciones gráficas
Probablemente ya hayas visto a alguien programar o incluso hayas intentado crear algún sistema o configuración operativa para ganar dinero en el mercado de capitales. No es raro que muchos de estos sistemas hagan uso de diversas medias móviles, que en muchos casos se utilizan de forma contraria. Además, existen sistemas de canales, como las famosas bandas de Bollinger, que se basan en dos medias móviles: una que representaría la banda superior y otra que representaría la banda inferior. Pero no estoy aquí para explicar cómo se podría utilizar este sistema para operar en el mercado. Mi objetivo aquí es mostrar cómo podríamos hacer algo similar de manera simple y práctica.
En el caso de las bandas de Bollinger, que estoy utilizando como ejemplo, pero podría ser cualquier otra cosa, tenemos dos líneas representadas gráficamente, a veces tres, donde una representaría la media interna del canal. Pero simplificaremos las cosas a dos líneas para que puedas entender cómo implementar cualquier cantidad de líneas. Para comenzar, utilizaremos el código que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buffer[]; 11. //+------------------------------------------------------------------+ 12. int OnInit() 13. { 14. SetIndexBuffer(0, gl_buffer, INDICATOR_DATA); 15. 16. return INIT_SUCCEEDED; 17. }; 18. //+------------------------------------------------------------------+ 19. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 20. { 21. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 22. gl_buffer[c] = High[c]; 23. 24. return rates_total; 25. }; 26. //+------------------------------------------------------------------+
Código 01
Muy bien, creo que no es necesario mostrar lo que hará este código cuando se ejecute y se coloque en un gráfico, ya que esto se explicó con detalle en los dos artículos anteriores. Todo lo que necesitamos hacer es observar lo que se está haciendo en la función de tratamiento de eventos, en este caso, la función OnCalculate. Puedes ver que allí claramente estamos utilizando el valor máximo. Es decir, tendremos una línea de representación gráfica que seguirá la máxima de cada barra, ya que no estamos efectuando ningún tipo de cálculo de suavización. Y sí, mi querido lector, los cálculos de media móvil tienen precisamente el objetivo de suavizar la curva que se representará gráficamente en la pantalla, creando así un valor medio entre tantos valores que se han utilizado en el cálculo. Pero esto implica explicar material matemático, algo que escapa al propósito de este artículo.
Muy bien, este indicador, que se ve en el código 01, funciona perfectamente. Observa que estamos utilizando la versión extendida de la función OnCalculate. El motivo se verá ahora. Ahora tengo una pregunta para ti, querido y estimado lector: ¿cómo podrías añadir una segunda línea de representación gráfica al gráfico? El objetivo sería representar, por ejemplo, los mínimos de cada barra. Podrías decirme que bastaría con crear un nuevo indicador y modificar el código de la línea 22 para que, en lugar de usar High, usáramos Low. Estarías en lo cierto. En ningún caso esta idea es errónea, ya que funciona.
Esto complica las cosas, ya que habría dos indicadores en el gráfico. Detalle: cada indicador trabajaría con una de las líneas de representación gráfica. Sin embargo, podemos hacer algo mejor, ya que podemos unir estos dos indicadores en un único código. Mostrarte cómo hacerlo es el objetivo de este tema. Sé que puede parecer complicado al principio, pero si entiendes lo que se muestra, podrás crear cualquier tipo de indicador con múltiples líneas de representación gráfica. Recordemos que, en este momento, vamos a ver la forma más simple de hacerlo. Después, si quieres, te mostraré una forma más elaborada.
De acuerdo, entonces, basándonos en el código 01, lo modificaremos para crear una segunda línea de representación gráfica. Lo haremos paso a paso para que todos puedan seguirlo y entender cómo hacerlo.
Lo primero que debemos hacer es crear un nuevo buffer para contener los nuevos datos de representación gráfica. Recordemos que el tipo DRAW_LINE, que es el que estamos utilizando, necesita un buffer para cada pieza de información de representación gráfica. Así obtendremos lo que se muestra justo abajo.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ . . .
Código 02
Este código 02 es un fragmento del contenido que vamos a implementar, ya que lo haremos paso a paso; así es más sencillo. Observa que he cambiado el nombre del buffer en la línea 10 y he añadido uno nuevo en la línea 11. Con esto, comenzamos a implementar nuestra segunda línea de representación gráfica. El siguiente paso lo haremos más rápido, para garantizar que todo se está haciendo correctamente. Entonces, obtendremos el código que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 1 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ 13. int OnInit() 14. { 15. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 16. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 17. 18. return INIT_SUCCEEDED; 19. }; 20. //+------------------------------------------------------------------+ 21. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 22. { 23. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 24. { 25. gl_buff_max[c] = High[c]; 26. gl_buff_min[c] = Low[c]; 27. } 28. 29. return rates_total; 30. }; 31. //+------------------------------------------------------------------+
Código 03
Bien, esta es la parte básica. Sin embargo, este código tiene un pequeño problema que aún debemos resolver. Pero antes de eso, necesitamos entender cuál es el problema y por qué aparece. Fíjate en que, en la línea 16, estoy creando un nuevo indexador. Cada buffer utilizado en el indicador, que MetaTrader 5 tendrá que mantener y observar, necesita un indexador único. Una vez definida la línea 16, ya podremos utilizar el buffer como se muestra en la línea 26.
Este buffer, utilizado en el sistema de representación gráfica, puede tener diferentes funciones. Por ahora, solo vamos a utilizar el tipo que tiene como objetivo contener los datos que se van a utilizar para representar algo en el gráfico. Muy bien, este código 03 puede compilarse. Sin embargo, al aplicarlo al gráfico, el resultado es el que vemos justo debajo.
Imagen 01
¿Pero qué pasó aquí? No lo entiendo. ¿Por qué solo vemos la línea de representación gráfica de los valores mínimos? El motivo, querido lector, es que le estamos diciendo a MetaTrader 5 que el indicador solo contiene un buffer de representación gráfica y una información para representar. Puedes verlo en las líneas siete y ocho. Como en realidad tenemos dos buffers y dos líneas, todo lo que necesitamos hacer es modificar la información mencionada en las líneas siete y ocho. Siendo así, vamos a modificar el código, como se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrBlack 06. //+----------------+ 07. #property indicator_buffers 2 08. #property indicator_plots 2 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ . . .
Código 04
Observa que solo hemos cambiado las líneas mencionadas anteriormente. Sin embargo, al aplicar el indicador al gráfico, el resultado es lo que podemos ver justo debajo.
Imagen 02
¿Otra vez esto? Ahora sí que no lo entiendo. ¿No era para que el código representara gráficamente dos líneas? ¿Por qué solo veo una? Con calma, querido lector. Con calma. Tranquilo, mi querido lector, tranquilo. El motivo por el que solo ves una línea es que no se está aplicando ningún color a la segunda línea. Para aclararlo, observa cómo se configura el indicador.
Animación 01
Observa que NO EXISTE NINGÚN COLOR PARA LA SEGUNDA LÍNEA. E incluso intentando atribuirle un valor de color, esta no aparece. Para resolverlo, necesitamos indicarle al compilador que reserve y cree la segunda línea. Esto se consigue modificando el código una vez más, como se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_LINE 05. #property indicator_color1 clrRed 06. //+----------------+ 07. #property indicator_type2 DRAW_LINE 08. #property indicator_color2 clrGreen 09. //+----------------+ 10. #property indicator_buffers 2 11. #property indicator_plots 2 12. //+----------------+ 13. double gl_buff_max[], 14. gl_buff_min[]; 15. //+------------------------------------------------------------------+ . . .
Código 05
Observa lo que se ha añadido al código, que se puede ver aquí en el código 05. Para hacerlo más evidente, he utilizado colores diferentes. Así, cuando coloques el indicador en el gráfico, podrás ver lo que se muestra justo debajo.
Imagen 03
¿Ves lo sencillo que es implementar diversas líneas de representación gráfica en un mismo indicador? Todo lo que tienes que hacer es ir agregando elementos poco a poco, sabiendo lo que estás haciendo. Como aquí no estamos efectuando ningún cálculo, las líneas nunca se cruzarán. Sería más o menos lo que ocurriría si estuviéramos implementando un indicador de bandas. La diferencia es que una de las líneas recibiría valores de una banda y la otra, de la otra banda, creando algo similar a las famosas bandas de Bollinger. Es un tema muy interesante, ¿no crees?
Creo que ahora ya serás capaz de crear diversos tipos y estilos de indicadores basándote únicamente en estos conocimientos. Pero, antes de profundizar aún más en este asunto, ya que esta parte de la programación es muy interesante y divertida, ¿qué te parece si modificamos el indicador de la imagen 03 para que las líneas aparezcan coloreadas? Hum, esto parece complicado. Pero, ¿realmente es complicado o es que aún no sabes cómo proceder? Bien, veamos. Para ello, abordaremos un nuevo tema.
Líneas de representación gráfica coloreadas
Una de las cosas que más llaman la atención y entusiasman a la gente es ver un indicador con líneas que cambian de color. Hasta ahora, hemos creado un sistema muy sencillo en el que podíamos usar un color u otro, pero ¿y cambiar de color? Parece muy difícil de hacer e implementar, sobre todo para mí, que apenas estoy empezando a aprender programación MQL5. Está bien, mi querido lector. Pero el hecho de que digas que apenas estás comenzando no significa que no puedas interesarte por lo que se mostrará. Y NO, hacer un indicador cuyas líneas se representen gráficamente en varios colores no es complicado, solo es diferente.
Para que te hagas una idea de lo que estoy hablando, vamos a tomar el código implementado en el tema anterior. Para mostrar el resultado de la imagen 03, necesita contener un contenido muy parecido al que se muestra a continuación.
//+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed //+----------------+ #property indicator_type2 DRAW_LINE #property indicator_color2 clrGreen //+----------------+ #property indicator_buffers 2 #property indicator_plots 2 //+----------------+ double gl_buff_max[], gl_buff_min[]; //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); return INIT_SUCCEEDED; }; //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) { for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) { gl_buff_max[c] = High[c]; gl_buff_min[c] = Low[c]; } return rates_total; }; //+------------------------------------------------------------------+
Código 06
Este código 06 es el resultado de todas las modificaciones realizadas a partir del código 01 hasta que pudimos representar dos líneas en el gráfico. Ahora, para hacer que esas mismas líneas sean multicolores, solo tenemos que seguir los pasos que se indican a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_COLOR_LINE 05. #property indicator_color1 clrMaroon, clrTomato, clrBlue 06. //+----------------+ 07. #property indicator_type2 DRAW_COLOR_LINE 08. #property indicator_color2 clrGreen, clrPaleGreen 09. //+----------------+ . . .
Código 07
Ahora, compara el código 06 con el código 07. Observa que hemos cambiado el tipo de objeto que se utiliza en la representación gráfica, pasando del tipo DRAW_LINE al tipo DRAW_COLOR_LINE. Una vez hecho esto, podemos indicar más de un color en la propiedad de color de cada una de las líneas. La cantidad de colores es totalmente arbitraria y puede tener un máximo de 64 valores, según la propia documentación de MQL5. De hecho, en una línea declaré tres colores y en la otra dos. No obstante, puedes colocar los colores que desees. Sin embargo, esto no es suficiente. Necesitamos implementar algunas cosas más para que MetaTrader 5 entienda lo que queremos hacer.
Ahora presta atención, mi estimado lector. Cuando utilizamos un sistema de representación gráfica multicolor, necesitamos un buffer extra. Esto se puede observar en la imagen de abajo, que se encuentra en la documentación.
Imagen 04
Como puedes ver, todos estos puntos destacados exigen la presencia de un buffer de color. Sin este buffer, MetaTrader 5 NO SABRÁ QUÉ COLOR UTILIZAR. Por esta razón, el siguiente cambio que debemos realizar es en la declaración de los buffers. Esto puede verse en el fragmento de código que se muestra a continuación.
. . . 09. //+----------------+ 10. #property indicator_buffers 4 11. #property indicator_plots 2 12. //+----------------+ 13. double gl_buff_max[], 14. gl_buff_min[], 15. gl_color_max[], 16. gl_color_min[]; 17. //+------------------------------------------------------------------+ . . .
Código 08
En este fragmento del código 08, en realidad estamos definiendo nuestros buffers. Fíjate en que, en la línea diez, indicamos que necesitamos cuatro buffers. ¿Pero por qué cuatro, si solo vamos a representar dos líneas gráficamente? El motivo es que necesitamos un buffer para los valores que se van a representar y otro para cada color. Piensa en una pequeña estructura de dos valores. Aunque MetaTrader 5 no utiliza una estructura para esto, necesitas pensar de esta manera. Y, como MetaTrader 5 no utiliza estructuras para este modelado, terminamos necesitando dos buffers. Sin embargo, como tenemos dos líneas que representar gráficamente, al final necesitaremos cuatro buffers. Estos se declaran a partir de la línea trece, como se puede ver en el fragmento del código 08.
Genial, ahora solo falta implementar el último paso. Se muestra en el fragmento de abajo.
. . . 17. //+------------------------------------------------------------------+ 18. int OnInit() 19. { 20. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 21. SetIndexBuffer(1, gl_color_max, INDICATOR_COLOR_INDEX); 22. SetIndexBuffer(2, gl_buff_min, INDICATOR_DATA); 23. SetIndexBuffer(3, gl_color_min, INDICATOR_COLOR_INDEX); 24. 25. return INIT_SUCCEEDED; 26. }; 27. //+------------------------------------------------------------------+ 28. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 29. { 30. double mhs = 0, 31. mhi = 0, 32. ml = 0; 33. const double desv = 0.01; 34. 35. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 36. { 37. gl_color_max[c] = (mhi > High[c] ? 0 : (mhs < High[c] ? 1 : 2)); 38. mhs = mhi = gl_buff_max[c] = High[c]; 39. mhs += (mhs * desv); 40. mhi -= (mhi * desv); 41. gl_color_min[c] = (ml < Low[c] ? 0 : 1); 42. ml = gl_buff_min[c] = Low[c]; 43. } 44. 45. return rates_total; 46. }; 47. //+------------------------------------------------------------------+
Código 09
Antes de explicar lo que estamos haciendo en este fragmento del código 09, veremos el resultado de este indicador cuando se aplica al gráfico de un símbolo cualquiera. Puede verse en la imagen siguiente.
Imagen 05
Lo que estás viendo, querido lector, es solo con fines demostrativos, ya que no hay ningún objetivo en la creación de este indicador, solo fines didácticos. No obstante, puedes observar que el código de la etapa de inicialización del indicador casi no ha cambiado, solo ha sido necesario añadir las líneas 21 y 23. Sin embargo, es muy importante que entiendas lo que hace cada una de estas nuevas líneas. Para empezar, observa que cada buffer tiene un identificador diferente. Da igual el tipo de cosa que vayamos a colocar en ellos; cada uno necesita tener un identificador diferente. De lo contrario, MetaTrader 5 se confundirá al utilizarlos.
Luego, es muy importante declarar las cosas en un cierto orden. Es decir, ANTES de declarar el próximo buffer de datos, debemos declarar todos los que se van a utilizar en esa línea de representación gráfica. En este caso, se trata de un buffer de color. Si declaras los buffers de datos o de color fuera de un orden lógico, NO OBTENDRÁS el resultado deseado. Por este motivo, presta atención al momento de declarar los elementos aquí. El orden de las cosas influye en el resultado final. Una vez hayamos inicializado esto, podremos centrarnos en la rutina que tratará el evento Calculate, que será activado por MetaTrader 5.
Observa que, en este caso, estamos realizando algunos cálculos y verificaciones. Esto es porque necesitamos decirle a MetaTrader 5 cuál de los colores que definimos en el código 07 debe utilizar en el momento de dibujar la línea en la pantalla. Pero espera un momento, no entiendo cómo se está haciendo esto. Aquí solo tenemos números y en el código 07 teníamos valores de color. ¿Cómo sabe MetaTrader 5 qué color debe utilizar?
Correcto, mi querido lector, en este momento es importante que hayas comprendido algo que se explicó en otro artículo: qué son los arrays. Lo que tenemos en el código 07 son arrays de colores. Cada uno de ellos estaría en un índice del array. Por esta razón, en las líneas 21 y 23 estamos utilizando la enumeración INDICATOR_COLOR_INDEX. NO ESTAMOS DICIENDO QUÉ COLOR USAR, sino cuál es el índice del color dentro de un determinado array. ¿Pero qué array? Si tenemos dos en el código 07, ¿cómo sabe MetaTrader 5 cuál utilizar?
Y ahí es donde entra en juego la otra cuestión de la que hablé hace poco. Es decir, el orden de las cosas influye en el resultado final. Como normalmente utilizaremos este tipo de representación gráfica de manera singular (es decir, un indicador, una línea), MetaTrader 5 utilizará el esquema de color relacionado directamente con el identificador del tipo que se va a representar. Sé que puede parecer confuso, pero observa que en las líneas cuatro y cinco tenemos un valor de identificador, en este caso, el número uno. En las líneas siete y ocho tenemos otro identificador, en este caso el dos. Así, cuando asociemos un valor al indicador que se representará gráficamente, el compilador utilizará ese identificador para saber qué esquema de color debe utilizarse.
Para mostrar esto, definí cantidades diferentes de color en cada una de las declaraciones vistas en el código 07, para que pudieras entenderlo cuando vinieras a experimentar y practicar con el código real.
Aunque esta parte es algo confusa, precisamente porque estamos utilizando todo de forma estática y colocando más de una línea de representación gráfica al mismo tiempo, en la práctica verás que es bastante sencillo entender cómo declarar y utilizar este tipo de cosas.
En cualquier caso, cuando el usuario desee cambiar el esquema de colores, tendrá acceso a una interfaz como la que se muestra a continuación.
Imagen 06
Observa que, debido a las declaraciones realizadas en las líneas cinco y ocho del código 07, el usuario podrá ajustar más de un color. Por eso, es deseable que la interfaz sea lo más clara y sencilla posible. De lo contrario, aunque tu código podría ser bastante útil para un determinado tipo de operación, el usuario tendrá una mala experiencia al utilizarlo.
Como los códigos estarán en el anexo, podrás estudiar cómo lidiar con este tipo de situaciones. Pero antes de terminar este artículo, quiero hablar de otro indicador que, en cierto modo, se encuentra entre un término y otro, dependiendo de cómo lo implementes, y que puede ser un indicador de bandas o incluso un indicador de cruce de medias. Pero, para no mezclar las explicaciones, veremos esto en un nuevo tema.
Indicador del tipo DRAW_FILLING
Este indicador es bastante curioso, ya que, según cómo se implemente, puede dar lugar a un indicador de cruce de medias o incluso a un indicador de bandas. Sin embargo, suele generar cierta duda entre los programadores principiantes precisamente debido a la forma en que debe declararse. Para que comprendas lo sencillo que es declarar y utilizar este tipo de indicador, vamos a tomar como base el código 06, visto al principio de este artículo. Partiendo de ese punto, será mucho más fácil entender lo que estamos intentando hacer con el indicador DRAW_FILLING.
Una vez que tengamos el código 06 como punto de partida, lo modificaremos para entender el indicador DRAW_FILLING. Básicamente, el código 06 quedará como se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_type1 DRAW_FILLING 05. #property indicator_color1 clrRed, clrGreen 06. //+----------------+ 07. #property indicator_buffers 2 08. #property indicator_plots 1 09. //+----------------+ 10. double gl_buff_max[], 11. gl_buff_min[]; 12. //+------------------------------------------------------------------+ 13. int OnInit() 14. { 15. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 16. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 17. 18. return INIT_SUCCEEDED; 19. }; 20. //+------------------------------------------------------------------+ 21. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 22. { 23. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 24. { 25. gl_buff_max[c] = Open[c]; 26. gl_buff_min[c] = Close[c]; 27. } 28. 29. return rates_total; 30. }; 31. //+------------------------------------------------------------------+
Código 10
Hum, interesante. Hasta donde yo sé, el código 06 ha sufrido muy pocas modificaciones. Sin embargo, tengo algunas dudas respecto a ciertos aspectos, como por ejemplo: ¿por qué en la rutina que trata el evento Calculate estamos usando el precio de apertura y cierre? El motivo es precisamente provocar una torsión o cruce de los valores de máxima y mínima, como se denominan aquí en el código 10. Observa lo siguiente, querido lector: de vez en cuando tenemos una barra de venta y, de vez en cuando, una de compra.
Ahora, imagina que este indicador DRAW_FILLING es una tela, con un estampado en un lado y otro estampado en el opuesto. Cuando los valores dentro de los buffers definidos en las líneas 15 y 16 se cruzan, se produce una torsión que hace que MetaTrader 5 nos muestre un lado u otro de la tela. La información que se va a mostrar, o estampar en la tela, se declara en la línea cinco. Por esta razón, podemos pintar una región de un color u otro. Si no hubiera cruce o torsión, solo veríamos uno de los estampados o colores definidos en la línea cinco.
Sin embargo, hay un pequeño detalle: a pesar de la extrema simplicidad del código 10, cuando lo aplicamos a un gráfico, este queda como se muestra en la imagen de abajo.
Imagen 07
Vale, no parece muy atractivo y, de hecho, puede resultar bastante confuso en función del tipo de información que se esté calculando y representando gráficamente. No obstante, en la línea cinco, el usuario tendrá la posibilidad de ajustar algunos datos, como se puede ver en la imagen a continuación.
Imagen 08
Es decir, dependiendo del tipo de cosa que se vaya a planificar, este indicador del tipo DRAW_FILLING puede resultar bastante interesante. Pero, precisamente debido a lo que se puede ver en la imagen 07, lo más habitual no es representar este indicador directamente en el gráfico principal, sino en una ventana aparte. Entonces, uno empieza a pensar: «Amigo, esto se está volviendo muy confuso y complicado. Apenas aprendí a crear un indicador de color, ¿y ahora vienes a hablarme de ponerlo en otra ventana? Me estás saturando con tanta información que tendré que aprender».
Tranquilo, no es para tanto. En realidad, MQL5, pensado para programar en MetaTrader 5, nos proporciona recursos interesantes y prácticos.
Entre estos recursos se encuentra precisamente el de colocar un indicador en otra ventana. Sin embargo, esta ventana se mantendrá vinculada a la principal. Una de las formas más simples y fáciles de hacerlo es indicarle al compilador que genere un código de indicador de manera que, cuando MetaTrader 5 lo aplique al gráfico, perciba que debe abrir una nueva ventana o subventana. Esto se consigue añadiendo una única línea al código del indicador. Así, el código 10 visto anteriormente quedará como se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #property indicator_separate_window 05. //+----------------+ 06. #property indicator_type1 DRAW_FILLING 07. #property indicator_color1 clrRed, clrGreen 08. //+----------------+ 09. #property indicator_buffers 2 10. #property indicator_plots 1 11. //+----------------+ 12. double gl_buff_max[], 13. gl_buff_min[]; 14. //+------------------------------------------------------------------+ 15. int OnInit() 16. { 17. SetIndexBuffer(0, gl_buff_max, INDICATOR_DATA); 18. SetIndexBuffer(1, gl_buff_min, INDICATOR_DATA); 19. 20. return INIT_SUCCEEDED; 21. }; 22. //+------------------------------------------------------------------+ 23. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[]) 24. { 25. for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++) 26. { 27. gl_buff_max[c] = Open[c]; 28. gl_buff_min[c] = Close[c]; 29. } 30. 31. return rates_total; 32. }; 33. //+------------------------------------------------------------------+
Código 11
Observa que la única diferencia entre los códigos 10 y 11 es precisamente la línea cuatro, que no existe en el código 10, pero sí en el 11. Después de compilar este código, podrás pedirle a MetaTrader 5 que lo añada al gráfico. Al hacerlo, la imagen 07, que antes podía resultar bastante confusa, pasará a verse como se muestra a continuación.
Imagen 09
Esta imagen 09 es, sin duda, mucho más fácil de entender, aunque al principio pueda resultar algo confusa para algunos usuarios a la hora de interpretar este gráfico.
Consideraciones finales
En este artículo se muestra cómo trabajar con dos tipos de indicadores diferentes que se pueden adaptar de diversas formas. El objetivo es crear algún tipo de aplicación para tus propios objetivos. A pesar de la aparente simplicidad de lo mostrado aquí, creo que, si tienes creatividad y curiosidad, te darás cuenta de que este contenido se puede extender a los demás tipos de indicadores: DRAW_SECTION, DRAW_HISTOGRAM, DRAW_ARROW, DRAW_ZIGZAG, DRAW_BARS y DRAW_CANDLES. Todos funcionan de la misma manera que los vistos en este artículo, aunque solo hemos tratado dos, tres si contamos el hecho de que usamos el tipo DRAW_COLOR_LINE. Pero eso es un mero detalle.
Lo que realmente importa es que practiques y entiendas que todo lo que se representa gráficamente en el gráfico, por muy complicado que pueda parecer, es bastante sencillo de construir. Básicamente, solo necesitas decirle al compilador cómo debe crearse el indicador, utilizando una implementación totalmente estática. Aunque crear indicadores estáticos sea simple, fácil, práctico y divertido, la verdadera diversión está en los indicadores dinámicos. Pero eso lo veremos en breve. Por ahora, estudia y practica lo visto en este artículo, pues pronto haremos que este tipo de implementación sea mucho más divertida e interesante.
Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/15828





- 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