Português
preview
Del básico al intermedio: Indicadores técnicos (I)

Del básico al intermedio: Indicadores técnicos (I)

MetaTrader 5Ejemplos |
17 0
CODE X
CODE X

Introducción

En el artículo anterior Del básico al intermedio: Sobrecarga de operadores (VI), se mostró una forma de trabajar con la sobrecarga de operadores en su nivel más interesante, hasta llegar a un punto en el que necesitábamos programar cada vez menos y, al mismo tiempo, podíamos generar un código cada vez más sencillo de comprender. Al menos así veo yo el resultado final. Tal vez se deba a mi experiencia con C y C++, donde el código tiende a ser bastante simbólico. Algo diferente de lo que normalmente podemos observar en código escrito en MQL5 o en otros lenguajes, como Python, por ejemplo. A diferencia de Python, con el que no podrás utilizar el propio lenguaje para intentar hacer el código más simbólico, en MQL5 sí podemos producir algo como lo que vimos en los artículos anteriores.

Tengo que reconocer una cosa. La idea de los creadores de MQL5 de permitir que los programadores con más experiencia demuestren cómo podrían hacerse las cosas fue realmente genial. A esto se suma, por supuesto, que MQL5 se parece en muchos aspectos a C y C++. Esto facilita mucho el aprendizaje a estos profesionales, aunque C y C++ sean lenguajes mucho más difíciles y complejos de dominar que MQL5. Pero eso no viene al caso.

En este artículo abordaremos un tema un poco más ligero y diferente. Tal vez incluso mucho más interesante para buena parte de ustedes, ya que los últimos artículos han sido bastante densos y contenían material que no resulta fácil de estudiar ni asimilar de un momento para otro. Así que en este artículo veremos un tema mucho más agradable y bastante más sencillo. Además, será algo que podrás empezar a aprovechar casi de inmediato.

Bien, ha llegado el momento de dejar a un lado todo aquello que pueda distraernos y centrarnos en lo que veremos y explicaremos en este artículo. Así que empecemos.


Indicadores técnicos (I)

Tal vez una de las cosas que más tiempo les lleva a quienes empiezan a estudiar MQL5 con la intención de crear algún mecanismo de setup que agilice sus análisis al operar en el mercado sea entender cómo crear o, mejor dicho, programar cualquier indicador. También es necesario saber cómo vincularlo a un Asesor Experto. Pero esto lo veremos con detalle más adelante.

Ya vimos en Del básico al intermedio: Indicador (IV) cómo implementar un indicador sencillo cuyo objetivo era señalar cuándo una barra se encuentra dentro de otra anterior, generando así lo que se conoce como un patrón inside bar. Aunque todo el código que se muestra aquí tiene un propósito didáctico y está orientado al aprendizaje, no puedo negar que, en algunos momentos, podemos crear una aplicación muy sencilla. Aun así, puede no estar debidamente programada y, en ningún caso, debe considerarse 100 % terminada. Este será precisamente el caso que veremos a partir de ahora. Así que ten cuidado al utilizar en una cuenta real lo que implementaremos aquí, ya que, por razones obvias, podrían producirse pérdidas financieras. Lo que vamos a hacer es únicamente una aplicación didáctica.

Si estás empezando a programar en MQL5, seguramente ya habrás buscado cómo crear indicadores para una cosa u otra. Sin embargo, MetaTrader 5 ya nos proporciona de forma predeterminada diversos indicadores cuyos cálculos se realizan internamente en la propia plataforma. Y no, no me refiero a los indicadores que puedes encontrar al consultar el contenido del directorio de indicadores. No son esos.

Los indicadores a los que me refiero pueden consultarse en Funciones de indicadores técnicos. Todos los indicadores que aparecen allí son calculados de forma predeterminada por MetaTrader 5. No necesitas crear todo el código necesario para calcularlos. Lo único que debes hacer es acceder a ellos desde tu código para poder utilizarlos. Esto es válido para cualquier aplicación desarrollada para ejecutarse en MetaTrader 5.

Sé que, para muchos, este enfoque puede parecer algo poco interesante, mientras que para otros puede resultar difícil de implementar. Cuando estás empezando, es natural pensar que necesitas crear todo el código necesario para realizar el cálculo del indicador. En otros casos, también puedes imaginar que, si trazas el indicador en el gráfico sin haberlo creado desde cero, no tendrás un control total sobre su comportamiento.

Bien, esta forma de pensar, hasta cierto punto, forma parte del aprendizaje. Difícilmente aprenderás de verdad algo si te limitas a utilizar soluciones ya preparadas. Eso no constituye realmente un aprendizaje, sino simplemente una forma de ahorrar tiempo mientras intentas reinventar la rueda. Como todo buen profesional, debes procurar establecer metas y objetivos siempre que sea posible. Esto no significa que aprender a trabajar con todos los recursos que ofrece una herramienta sea una simple pérdida de tiempo. No lo es. Por eso estoy mostrando muchos recursos que probablemente nunca necesites utilizar. Una de ellas fue la sobrecarga de operadores. Es algo divertido, aunque quizá nunca llegues a utilizar realmente ese conocimiento.

¿Por qué estoy mencionando esto? La razón, mi querido lector, es que encontrarás una enorme cantidad de personas que te mostrarán cómo hacer una cosa u otra. Sin embargo, pocas te explicarán realmente por qué hacer una cosa u otra. Así podrás elegir el camino más fácil y rápido para alcanzar tu objetivo.

Muy bien, empecemos por el que considero el indicador más sencillo de todos: una media móvil. Para crear algo así utilizando los indicadores técnicos, lo único que necesitamos es escribir un código como el que se muestra a continuación.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_applied_price   PRICE_CLOSE
08. #property indicator_buffers         1
09. #property indicator_plots           1
10. #property indicator_type1           DRAW_LINE
11. #property indicator_color1          clrRed
12. #property indicator_style1          STYLE_SOLID
13. #property indicator_width1          1
14. //+------------------------------------------------------------------+
15. #define  def_nPeriods               9
16. //+------------------------------------------------------------------+
17. double   Buff_iMA[];
18. int      Handle;
19. //+------------------------------------------------------------------+
20. int OnInit(void)
21. {
22.    SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
23.    if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, MODE_EMA, _AppliedTo)) == INVALID_HANDLE)
24.    {
25.       Print("Could not start the indicator...");
26.       return INIT_FAILED;
27.    };
28. 
29.    return INIT_SUCCEEDED;
30. };
31. //+------------------------------------------------------------------+
32. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
33. {
34.    CopyBuffer(Handle, 0, 0, Bars(NULL, NULL), Buff_iMA);
35. 
36.    return rates_total;
37. };
38. //+------------------------------------------------------------------+
39. void OnDeinit(const int reason)
40. {
41.    if (Handle != INVALID_HANDLE) 
42.       IndicatorRelease(Handle);
43. };
44. //+------------------------------------------------------------------+

Código 01

Este código 01 contiene todo lo que necesitamos para crear una media móvil y trazarla en el gráfico. Es cierto que no podemos cambiar el tipo de media ni el período o, dicho de otro modo, la cantidad de barras utilizadas en el cálculo. Sin embargo, sí podemos modificar varios aspectos, como el color, el grosor, el estilo de la línea y el tipo de precio que se utilizará. Y todo ello con este código, que resulta casi ridículamente sencillo.

Espera un momento. Me estás diciendo que aquí podemos cambiar varias cosas, pero no veo ninguna línea que indique cómo hacerlo. Desde mi punto de vista, si queremos modificar algo, tendremos que recompilar el código. Así que tenemos un incrédulo (RISAS). Perfecto, me gusta que la gente dude de las cosas en un primer momento. Veamos entonces cómo se comporta este código para comprobar si lo que estoy diciendo sobre él es cierto o no.

Para empezar, necesitamos un código que sepamos que nos proporcionará datos correctos antes de utilizar nuestro código 01 en el gráfico. Por suerte, MetaTrader 5 cuenta con uno perfectamente adecuado. Así que añadiremos primero este indicador para utilizarlo como referencia. Esto se muestra en la siguiente animación.

Animación 01

Ahora tenemos una forma de comprobar si el código 01 funciona correctamente. Bien, vamos a añadirlo al gráfico. Al hacerlo, obtendremos el resultado que se muestra en la siguiente animación.

Animación 02

Observa que se superpuso perfectamente a la media que ya estaba en el gráfico. Ahora, para modificar los parámetros, hacemos lo que se muestra en la siguiente animación.

Animación 03

Fíjate en que, aunque a primera vista parecía que no podíamos ajustar nada, conseguimos realizar todos los cambios que mencioné anteriormente. Esto demuestra que el código funciona tal como se había indicado. Sin embargo, no estamos limitados a esto. Podemos ir un poco más allá. Pero vayamos con calma. Primero quiero explicar por qué este código 01 funciona de la forma que vimos en las animaciones. Buena parte de lo que necesitas saber ya se explicó en otro artículo.

Consulta los artículos Del básico al intermedio: Indicador (I) hasta Del básico al intermedio: Indicador (IV) para comprender la base de este código 01.

Quizá también necesites consultar el artículo Del básico al intermedio: Eventos (I), donde se explicó la base de la programación basada en eventos. Esto te ayudará a entender cómo y por qué funciona el código 01.

Suponiendo que ya tienes los conocimientos necesarios para entender lo que se explicará, podemos continuar. Observa que, en la línea 15, estoy definiendo un valor. Este será el valor que se utilizará para calcular la media móvil. Ahora viene la parte creativa del código. Decir que es la parte creativa puede parecer extraño, pero enseguida entenderás por qué. Como ocurre con cualquier indicador que vaya a trazar algo en el gráfico, necesitamos definir al menos un buffer. Esto se hace en la línea 22. En la línea 23 intentamos definir la variable que almacenará el identificador del indicador técnico. Ahora presta atención a esto, mi querido lector. Cada indicador técnico debe configurarse para que MetaTrader 5 sepa qué hacer con él.

No basta con decir «quiero un indicador» y esperar que MetaTrader 5 lo cree exactamente como deseas. Para que esto ocurra, necesitamos indicarle cómo debe calcularse el indicador. Para saber qué información debes proporcionar a MetaTrader 5, consulta la documentación correspondiente a los indicadores técnicos. Sin embargo, en la mayoría de los casos puedes utilizar los dos primeros argumentos tal como se muestra en el código 01. Esto hará que el indicador se adapte al símbolo y al período gráfico actuales. Si aquí defines un período gráfico o incluso un símbolo concreto, MetaTrader 5 buscará y utilizará los datos correspondientes a lo que hayas especificado.

Esto nos permite, por ejemplo, tener un gráfico de 10 minutos mientras los cálculos se realizan a partir de los datos de un gráfico de 60 minutos o incluso del gráfico diario. Lo mismo se aplica al símbolo. Puedes indicar un símbolo y utilizar el indicador en el gráfico de otro distinto.

Amigo, esto es una pasada. No sabía que podíamos hacer algo así. Sí, mi querido lector, podemos hacer esto y mucho más. La cuestión es: ¿por qué harías algo así en la práctica?

Bien, como puedes ver, en el caso de iMA debemos indicar cuántas barras se utilizarán en el cálculo mediante el tercer argumento. A continuación, especificamos el desplazamiento aplicado a la media. Normalmente aquí se utiliza el valor cero, aunque en algunos casos puede ser necesario emplear otro valor, por ejemplo, si estás implementando una media para visualizar la formación de una reversión de tendencia. En el quinto parámetro indicamos, en el caso de iMA, qué tipo de media debe calcularse. Por último, especificamos qué tipo de precio se utilizará en el cálculo.

Si la creación del identificador tiene éxito, el siguiente paso tendrá lugar en el manejador del evento OnCalculate. Si se produce algún error, se indicará mediante el mensaje de la línea 25. En cualquier caso, tanto si aquí se produce un error como si todo funciona correctamente, en algún momento se ejecutará el evento OnDeinit. Cuando esto ocurra, liberaremos el identificador en la línea 42. Esta es una buena práctica de programación, ya que, en teoría, si no liberamos el identificador, MetaTrader seguirá realizando cálculos que ya no son necesarios y consumir recursos valiosos.

Ahora veamos la parte creativa del código. Se encuentra en el evento OnCalculate. Pero espera un momento, ¿dónde están los cálculos para crear la media móvil? Bien, esta es la parte interesante, mi querido lector. No necesitas programar los cálculos ni siquiera preocuparte por ellos, ya que MetaTrader 5 se encarga de realizarlos. Por esta razón, lo único que debemos hacer es pedirle a MetaTrader 5 que transfiera los valores calculados al buffer del indicador. Esto se hace en la línea 34.

Hmm. Lo estoy viendo, pero no lo entiendo. Incluso después de haber visto los resultados en las animaciones, sigo sin comprender bien qué hace esta línea 34 y por qué la necesitamos. Bien, vamos a entenderlo. Como MetaTrader 5 realiza los cálculos por nosotros, los resultados quedan almacenados en un buffer interno de la plataforma. Para acceder a esos datos, debemos indicarle a MetaTrader 5 qué datos queremos que nos proporcione.

Para hacerlo, necesitamos conocer el identificador asociado a esos cálculos. Sin él, no tenemos forma de recuperar los datos. Pero espera un momento. ¿Me estás diciendo que, si sé dónde están los datos, puedo leerlos en cualquier momento? Sí, mi querido lector, siempre que estén disponibles, podrás acceder a ellos en cualquier momento si sabes qué identificador utilizar. Interesante. En efecto, esto es bastante interesante y, más adelante, te mostraré cómo puedes aprovecharlo. Pero sigamos viendo qué hace este código 01.

El segundo argumento de la línea 34 puede variar dependiendo de determinadas circunstancias. Normalmente será igual a cero. Sin embargo, esto no es una regla. En cuanto al tercer parámetro, en casi todos los casos también será igual a cero, salvo que quieras realizar algún análisis para intentar detectar una reversión de tendencia o estudiar un movimiento específico. Pero, en general, este tercer parámetro será cero.

En cuanto al cuarto parámetro, aquí tenemos algo interesante. Dependiendo de cómo configures los parámetros, podremos tener más o menos datos trazados. Además, según cómo utilices este parámetro, puedes obtener una media móvil que, a primera vista, resultará bastante curiosa. El último parámetro, por su parte, estará relacionado con el segundo, precisamente porque ambos están vinculados al buffer donde se almacenarán los datos que se van a trazar.

Ahora vamos a experimentar un poco con esto. Esto tiene todo que ver precisamente con el cuarto parámetro de la línea 34. Para entender lo que acabo de comentar sobre ese comportamiento curioso e interesante, vamos a modificar el código del evento OnCalculate por el fragmento que se muestra a continuación.

                   .
                   .
                   .
31. //+------------------------------------------------------------------+
32. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
33. {
34.     CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA);
35.     PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Bars(NULL, NULL) - def_nPeriods);
36. 
37.    return rates_total;
38. };
39. //+------------------------------------------------------------------+
                   .
                   .
                   .

fragmento 01

Ahora presta atención, mi querido lector. Normalmente verás las medias móviles trazadas desde barras muy antiguas hasta la barra más reciente del gráfico. Sin embargo, como programadores, podemos hacer las cosas de una forma completamente distinta y evitar así que el gráfico quede demasiado saturado o muestre datos innecesarios.

Lo que hace este fragmento 01 es crear una media móvil tipo gusano que, a medida que aparecen nuevas barras, va avanzando y mantiene una longitud equivalente a la cantidad de períodos utilizados en los cálculos. En la siguiente animación puedes ver este comportamiento.

Animación 04

Observa que hay una media móvil amarilla dentro de la media roja. La media roja es la que vimos al principio del artículo. La media amarilla corresponde al código 01, pero utilizando el fragmento 01. En cuanto aparece una nueva barra, la media se desplaza para que su longitud se mantenga en nueve barras, o en el valor definido en la línea 15 del código 01. Muy interesante, ¿no? Y fíjate en lo sencillo que ha sido crear algo así. Este es el tipo de implementación que puedes conseguir cuando aprendes a programar. Los usuarios habituales no saben que podemos hacer esto en MetaTrader 5.

Genial. Pero ¿no podríamos hacer las cosas un poco más interesantes? Lo digo porque me gustaría saber cómo podría cambiar la cantidad de barras utilizadas en el cálculo o, quizá, el tipo de media que se utilizará, sin tener que compilar el código varias veces. Sí, mi querido lector, podemos hacerlo de una forma muy sencilla, fácil y rápida.

Partiendo del código 01, lo modificamos utilizando el fragmento que se muestra a continuación.

                   .
                   .
                   .
14. //+------------------------------------------------------------------+
15. input uint              def_nPeriods = 9;
16. input ENUM_MA_METHOD    def_MA_Method  = MODE_EMA;
17. //+------------------------------------------------------------------+
18. double   Buff_iMA[];
19. int      Handle;
20. //+------------------------------------------------------------------+
21. int OnInit(void)
22. {
23.    SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
24.    if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE)
25.    {
26.       Print("Could not start the indicator...");
27.       return INIT_FAILED;
28.    };
29. 
30.    return INIT_SUCCEEDED;
31. };
32. //+------------------------------------------------------------------+
                   .
                   .
                   .

Fragmento 02

Ahora, al volver a compilar el código, tendrás acceso a lo que se muestra en la siguiente imagen.

Imagen 01

Aunque funciona, la información resaltada en la imagen 01 no resulta muy descriptiva para el usuario. Lo adecuado sería modificar el propio fragmento 02 por lo que se muestra a continuación. De esta forma, obtendremos el resultado que aparece en la siguiente imagen.

                   .
                   .
                   .
14. //+------------------------------------------------------------------+
15. input uint              def_nPeriods = 9;             //Period:
16. input ENUM_MA_METHOD    def_MA_Method  = MODE_EMA;    //Method:
17. //+------------------------------------------------------------------+
                   .
                   .
                   .

Fragmento 03

Imagen 02

Ahora el usuario sabrá cómo influye cada valor en el cálculo, aunque no tenga la menor idea de cómo funciona realmente el código ni de cómo se traza la media móvil. Es cierto que este indicador funciona. Sin embargo, dependiendo de cómo implementes tu indicador, puede que aparezca algo relativamente extraño en el gráfico cuando añadas el indicador. El problema puede verse en la siguiente imagen.

Imagen 03

El problema está resaltado dentro del círculo verde. Pero ¿por qué mi indicador mostró este tipo de resultado? La razón, mi querido lector, son los datos almacenados dentro del indicador. En el caso del indicador que estamos viendo en este artículo, si el código estuviera escrito como se muestra a continuación, ocurriría exactamente el mismo problema.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_applied_price   PRICE_CLOSE
08. #property indicator_buffers         1
09. #property indicator_plots           1
10. #property indicator_type1           DRAW_LINE
11. #property indicator_color1          clrRed
12. #property indicator_style1          STYLE_SOLID
13. #property indicator_width1          1
14. //+------------------------------------------------------------------+
15. input uint              def_nPeriods = 9;             //Period:
16. input ENUM_MA_METHOD    def_MA_Method  = MODE_EMA;    //Method:
17. //+------------------------------------------------------------------+
18. double   Buff_iMA[];
19. int      Handle;
20. //+------------------------------------------------------------------+
21. int OnInit(void)
22. {
23.    SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
24.    if ((Handle = iMA(NULL, NULL, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE)
25.    {
26.       Print("Could not start the indicator...");
27.       return INIT_FAILED;
28.    };
29. 
30.    return INIT_SUCCEEDED;
31. };
32. //+------------------------------------------------------------------+
33. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
34. {
35.    CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA);
36. 
37.    return rates_total;
38. };
39. //+------------------------------------------------------------------+
40. void OnDeinit(const int reason)
41. {
42.    if (Handle != INVALID_HANDLE) 
43.       IndicatorRelease(Handle);
44. };
45. //+------------------------------------------------------------------+

Código 02

Pero espera un momento. Este código 02 es casi igual al código 01. Sin embargo, no vi que apareciera este problema allí. Aun así, el problema también está presente, mi querido lector. El detalle es que, como tenemos muchas barras en el gráfico, queda parcialmente oculto. Pero sigue estando ahí. En este código 02, el problema se hace más evidente precisamente porque, en la línea 35, donde copiamos los valores al buffer del indicador que se va a trazar, la distancia entre el inicio y el final de los datos es menor. Lo que quiero mostrar con esto es que, aunque no detectes un fallo en tu código, eso no significa que no exista; puede estar simplemente en un lugar donde no puedes verlo.

Bien, para corregir este tipo de problema tenemos básicamente dos alternativas. La primera ya apareció en el fragmento 01, donde la línea 35 corrige precisamente esta cuestión. Otra forma de resolver el mismo problema consiste en inicializar el buffer que contiene los datos que se van a trazar. El lugar exacto donde inicialices el buffer de datos del indicador influirá en el tipo de resultado que podremos obtener.

Para que esto quede un poco más claro y puedas entenderlo mejor, vamos a hacer dos pruebas. La primera consistirá en inicializar el buffer directamente en el procedimiento OnInit, como se muestra a continuación.

                   .
                   .
                   .
20. //+------------------------------------------------------------------+
21. int OnInit(void)
22. {
23.    SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
24.     ArrayInitialize(Buff_iMA, EMPTY_VALUE);
25.    if ((Handle = iMA(NULL, 0, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE)
26.    {
27.       Print("Could not start the indicator...");
28.       return INIT_FAILED;
29.    };
30. 
31.    return INIT_SUCCEEDED;
32. };
33. //+------------------------------------------------------------------+
34. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
35. {
36.    CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA);
37. 
38.    return rates_total;
39. };
40. //+------------------------------------------------------------------+
                   .
                   .
                   .

Fragmento 04

El problema es que este enfoque puede hacer que el indicador se comporte de forma un poco extraña, como puedes observar en la siguiente imagen.

Imagen 04

¿Ves cómo el trazado de la media en esta imagen 04 queda completamente descontrolado? Esto suele ocurrir cuando fuerzas la actualización del indicador entre dos llamadas que MetaTrader 5 haga a la función OnCalculate. Recuerda que los datos que se van a trazar proceden de MetaTrader 5. No los estamos calculando localmente. Simplemente utilizamos los datos calculados previamente por MetaTrader 5. Incluso después de que MetaTrader 5 dispare un evento OnCalculate, el evento NO HARÁ que el trazado se corrija. Esto se debe a que, al copiar el buffer, estaremos recuperando únicamente una parte de los valores calculados previamente. Puedes verlo en la línea 36.

Ahora bien, si cargas todos los datos calculados por MetaTrader 5, el problema que aparece en la imagen 04 no se producirá. Por eso debes tener cuidado al programar este tipo de lógica, especialmente si tu objetivo es comercializar o utilizar estos cálculos y aplicaciones para automatizar tus operaciones en el mercado financiero.

Muy bien, volvamos a nuestra cuestión principal. ¿Recuerdas que dije que había básicamente dos formas de inicializar el buffer? Pues bien, la segunda se muestra a continuación.

                   .
                   .
                   .
20. //+------------------------------------------------------------------+
21. int OnInit(void)
22. {
23.    SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
24.    if ((Handle = iMA(NULL, 0, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE)
25.    {
26.       Print("Could not start the indicator...");
27.       return INIT_FAILED;
28.    };
29. 
30.    return INIT_SUCCEEDED;
31. };
32. //+------------------------------------------------------------------+
33. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
34. {
35.    ArrayInitialize(Buff_iMA, EMPTY_VALUE);
36.    CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA);
37. 
38.    return rates_total;
39. };
40. //+------------------------------------------------------------------+
                   .
                   .
                   .

Fragmento 05

La ventaja de este segundo método es que el indicador no correrá el riesgo de comportarse de forma extraña. El resultado será muy similar a lo que vimos en la animación 04, donde el indicador irá acompañando cómo evoluciona todo. Sin embargo, quizá la animación 04 no haya dejado esto suficientemente claro. Si es así, observa la siguiente animación.

Animación 05

Como ya comenté, este tipo de cosas resulta muy interesante. Y, como último punto que quiero mostrar en este artículo, voy a explicar cómo modificar uno de los elementos que se muestran cuando el usuario configura el indicador. Esto puede verse en la imagen 05.

Imagen 05

Este tipo de información no resulta nada descriptivo para el usuario. Sin embargo, podrías decir que modificar esto no tiene demasiado sentido. Y, en muchos casos, realmente no lo tiene. Aun así, quiero recordarte, por si no lo has visto, que un mismo indicador puede mostrar simultáneamente varias líneas o conjuntos de datos.

En el artículo Del básico al intermedio: Indicador (III), mostré cómo podía hacerse. Sin embargo, allí olvidé explicar cómo modificar la información resaltada en la imagen 05. Hacerlo es bastante sencillo y directo. Lo único que necesitamos es añadir al código lo que aparece en la línea 14 del fragmento que se muestra a continuación.

                   .
                   .
                   .
12. #property indicator_style1          STYLE_SOLID
13. #property indicator_width1          1
14. #property indicator_label1          "EMA"
15. //+------------------------------------------------------------------+
16. input uint              def_nPeriods   = 9;           //Period:
17. input ENUM_MA_METHOD    def_MA_Method  = MODE_EMA;    //Method:
                   .
                   .
                   .

Fragmento 06

Con esto obtendremos lo que puede verse en la siguiente imagen.

Imagen 06

Aunque esto funciona relativamente bien y hace que la configuración resulte más clara e interesante y facilita al usuario el ajuste de los parámetros, tenemos un pequeño inconveniente. La información resaltada en la imagen 06 es estática. Es decir, si el usuario cambia el tipo de media móvil, la información de la imagen 06 no reflejará ese cambio. Y, si estás definiendo varias medias móviles dentro de un mismo indicador, esto acabará perjudicando por completo la experiencia del usuario.

Resolver esta cuestión es bastante sencillo. Sin embargo, no voy a abordarla en este momento, ya que antes quiero mostrar algunas otras cosas relacionadas con la posibilidad de hacer que distintos elementos de información se gestionen de una forma algo más dinámica. Pero esto lo veremos en el próximo artículo.


Consideraciones finales

En este artículo vimos cómo utilizar los indicadores técnicos incluidos y mantenidos por MetaTrader 5. Conocer y comprender este tipo de indicadores puede hacer que la implementación de una solución sea una tarea mucho más sencilla, rápida y eficiente, ya que no necesitas preocuparte por los cálculos que deben realizarse. La propia plataforma se encarga de realizarlos por nosotros.

Sin embargo, saber utilizar los indicadores técnicos es solo una parte de un conjunto mucho más amplio. En el próximo artículo veremos cómo sacar mucho más partido de este tipo de implementación para poder implementar de una forma mucho más sencilla determinados modelos operativos. Así que hasta pronto.

Archivo MQ5Descripción
Code 01Demostración básica
Code 02Demostración básica

Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/17025

Archivos adjuntos |
Anexo.zip (1.64 KB)
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Red neuronal en la práctica: El caso de la puerta XOR Red neuronal en la práctica: El caso de la puerta XOR
En este artículo intentaré mostrarte, mi querido lector, que no todo es como parece. Muchas veces tendemos a pensar que las cosas son de una determinada manera cuando, en realidad, podemos acabar creyendo algo que no necesariamente es cierto. Las redes neuronales son, con diferencia, uno de los temas más interesantes en términos generales. Tanto desde el punto de vista matemático como electrónico o incluso del software. A diferencia de lo que muchos creen o afirman, las redes neuronales no son, ni mucho menos, el problema ni la solución definitiva. Son solo una rama de investigación en la que debemos seguir estudiando e informándonos sobre lo que ocurre entre bastidores.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Del básico al intermedio: Sobrecarga de operadores (VI) Del básico al intermedio: Sobrecarga de operadores (VI)
Aquí implementaremos la eliminación mediante sobrecarga de operadores. Sin duda, este será un artículo que muchos necesitarán estudiar durante bastante tiempo para poder asimilar todo lo que se mostrará aquí. Quiero recordarte que lo que veremos será solo una pequeña e insignificante parte de todo aquello que llamamos programación.