Português
preview
Del básico al intermedio: Objetos (I)

Del básico al intermedio: Objetos (I)

MetaTrader 5Ejemplos |
20 0
CODE X
CODE X

Introducción

En el artículo anterior, Del básico al intermedio: Indicador (V), se explicó cómo podríamos, de manera simple, adecuar, aunque sea parcialmente, un indicador al modo de trazado que se esté utilizando en un gráfico de MetaTrader 5. Aunque no se mostró cómo utilizar los tres modelos de trazado, ya que esto requiere un conocimiento que aún no ha sido debidamente explicado por mí aquí.

Podemos, dentro de ciertos límites, utilizar el modo vela o el modo barra en un mismo indicador, y esto sin muchos problemas. Y, si queremos utilizar el modo línea, habrá que crear un indicador aparte y colocarlo manualmente en el gráfico. Sin embargo, a pesar de este pequeño inconveniente, que en el futuro mostraré cómo evitar.

Creo que tú, mi querido lector, has logrado entender cómo podemos lidiar con las limitaciones existentes, durante un tiempo, hasta que hayamos alcanzado un nivel adecuado en estos artículos, de modo que tú, mi querido lector, puedas entender cómo hacer las cosas sin que sea necesario explicar cada mínimo detalle involucrado en la implementación.

Pero, independientemente de esto, hay cosas que ya podemos empezar a abordar, aunque pueden ser más o menos interesantes para este o aquel lector en particular. Digo esto porque muchos de ustedes pueden no llegar a ver un propósito mayor en el tema que empezaremos a tratar en este artículo. Sin embargo, para otros, lo que se mostrará y explicará en este y en los próximos artículos es, sí, algo muy interesante, y puede llegar a tener un objetivo bastante noble.

Entonces, empecemos viendo algo que no se abordará por completo en este artículo, pero que servirá para dar un puntapié inicial a lo que será el tema a tratar.


Cuidados especiales

Hay algunos tipos de cosas que muchos operadores disfrutan tener en el gráfico. Algunas de estas cosas son más o menos útiles, dependiendo de cada momento específico. Una de ellas son los contadores de velas o barras. Para mucha gente, este tipo de cosa es completamente inútil y no tiene ningún propósito, mientras que, para otros, es un medio de comunicarse con otros operadores de manera rápida y eficiente, a fin de intercambiar una idea sobre cómo están viendo el mercado.

Muy bien, lo dicho se refiere a algo que colocamos en el gráfico, desde lo que sería la visión de un usuario. Pero, para nosotros, pensando como programadores, la cosa se desarrolla de una manera ligeramente diferente.

Esto se debe a que tú puedes elaborar formas diferentes y atractivas de mostrar algo en el gráfico. Sin embargo, en este humilde ejemplo mío, no hay formas muy diferentes de hacer tal cosa. ya que el objetivo principal es simplemente poner un texto en el gráfico. Nada más. La verdadera diferencia, de hecho, no estará en el texto en sí, sino en la forma en que lo pondremos en el gráfico y lo actualizaremos de vez en cuando.

Muchas personas que programan por hobby no tienen una visión clara y aguda como la de un programador que realmente se dedica y estudia un tema. Y, por favor, no me interpretes mal. No estoy diciendo aquí que una persona que crea programas ocasionales y con objetivos particulares no sepa lo que está haciendo. El problema es que no siempre estas personas son conscientes de ciertos tipos de problemas que los programas mal optimizados pueden acarrear para la plataforma MetaTrader 5, causando una degradación gradual y progresiva del rendimiento, hasta el punto de volver completamente inviable el uso de la plataforma, con todas esas aplicaciones ejecutándose en el gráfico.

Un simple contador de velas, cuyo objetivo es solo poner un texto en el gráfico, si está mal optimizado, puede terminar consumiendo muchos más recursos de los que, de hecho, serían necesarios. Incluso aquí, donde la idea y la intención siempre serán didácticas, procuro mostrar códigos que no traerán grandes perjuicios al desempeño de MetaTrader 5. Y cuando esto, por casualidad, pueda llegar a ocurrir, menciono el peligro y el cuidado que se debe tener, para evitar dolores de cabeza por parte de quienes estén estudiando y practicando lo que se viene mostrando en los artículos.

Muy bien, pero volvamos a nuestra cuestión: ¿cómo pensarías en un contador de velas, mi querido lector? Posiblemente, pensarías en algún tipo de aplicación que escribiría valores numéricos en las barras. Pero la cuestión aún sigue. ¿Qué tipo de aplicación usarías? Bien, como hasta el momento hemos visto cómo crear scripts e indicadores, muy probablemente te quedarías entre esos dos casos. Sin embargo, debido a algunas limitaciones de los scripts, acabarías migrando a los indicadores.

¿Y qué tipo de limitación sería esa que existe en los scripts? Si has estado experimentando, estudiando y practicando, debes haber notado que, siempre que ponemos un script en un gráfico, se elimina cuando cambiamos el periodo de tiempo del gráfico. Incluso aunque usemos un bucle en el script para impedirlo. Muy bien, esto nos obligaría a tomar medidas para que, con cada cambio de timeframe, volvamos a colocar el script en el gráfico. Hay una forma de evitar los problemas involucrados en la ejecución de scripts. Pero, como esto implica el uso de servicios, y estos, cuando se vinculan a gráficos, son bastante complejos, no sería, en realidad, una elección adecuada.

Si tienes curiosidad e interés en saber lo complicado que es este tipo de vínculo, busca mis artículos sobre la creación de un sistema de repetición/simulador. Pero, como esos artículos están orientados a quien ya tiene una buena base en programación MQL5, lo que no ocurre en este momento, ya que aún estamos comenzando, no entraré en los detalles de cómo manipular un gráfico usando, para ello, servicios.

Quedando así la alternativa de usar indicadores. Cierto, pero, sin embargo, indicadores, la mayor parte de las veces, no son adecuados para ciertos tipos de tareas. Esto se debe a que los indicadores, en MetaTrader 5, se ejecutan en bloque, como si fueran una única aplicación ejecutándose en un gráfico. Esto es para agilizar cálculos que MetaTrader 5 esté realizando para proporcionarnos ciertos valores. Estos valores que estoy mencionando forman parte de un conjunto de entradas que podemos elegir en el momento en que un indicador se coloque en el gráfico. Esto se vio y se mencionó en artículos anteriores.

Sin embargo, teniendo en cuenta que un contador de barras se ejecutará solo en el momento en que aparezca una nueva barra en el gráfico, tú, mi querido lector, terminas sintiéndote tentado a usar un temporizador para sincronizar las cosas. Y aquí es donde las cosas empiezan a dar problemas. Usar un temporizador en un indicador no es algo que, de hecho, se recomiende. Esto se debe a que, si ocurre algún fallo en el código del temporizador, todos los demás indicadores se verán perjudicados, e incluso puede llegar a bloquear MetaTrader 5 por algunos instantes, instantes que pueden ser, de hecho, cruciales.

Pero hay formas de trabajar con un sistema cuyo objetivo es saber si apareció o no una nueva barra en el gráfico. Hacer esto usando un indicador es, de hecho, la manera más simple y práctica de saber cuándo apareció una nueva barra y, de este modo, poder contabilizar las velas, presentando un texto después. Para llegar a este punto, donde ocurrirá el conteo de velas, necesitamos empezar en algún lugar. Y esto comienza con el código que se ve justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.     return INIT_SUCCEEDED;
07. };
08. //+------------------------------------------------------------------+
09. 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[])
10. {
11.     return rates_total;
12. };
13. //+------------------------------------------------------------------+

Código 01

Ahora, presta atención a algo aquí, mi querido lector. Todo indicador recibirá de MetaTrader 5 un evento Calculate cada vez que la cotización del símbolo presente en el gráfico cambie. MetaTrader 5 no dispara el evento Calculate basándose en una actividad en el tiempo. Si estás usando un gráfico en un periodo de 10 minutos, cada vez que aparezca una nueva barra, después de aproximadamente 10 minutos, no tendremos un evento Calculate, a menos que la cotización, de hecho, haya cambiado. Hasta entonces, no ocurrirá ningún evento Calculate.

Teniendo en cuenta que, en símbolos muy volátiles, podemos tener eventos Calculate en periodos de tiempo muy cortos, del orden de milisegundos, necesitamos que este evento Calculate se ejecute lo más rápido posible. Es decir, no quieres quedarte calculando o buscando información de manera innecesaria, ya que eso haría que el tratamiento del evento fuera muy lento.

Perjudicando así a todas las demás aplicaciones vinculadas a ese gráfico en particular. Y recuerda que aún no hemos entrado en la cuestión de los Asesores Expertos. Y sí, tener indicadores mal optimizados trae serios perjuicios a MetaTrader 5. Pero esto se verá mejor pronto.

Por ahora, necesitas entender que la velocidad de ejecución depende de cómo buscas la información. En este código 01, puedes observar que tenemos un array cuyo objetivo es proporcionarnos el valor de tiempo de cada barra. Presta atención: aquí, en el evento Calculate, no sabemos en qué momento la cotización, de hecho, cambió. Solo sabemos cuándo se creó la barra. Y, basándonos en el periodo de tiempo del gráfico, podemos estimar cuánto falta para que se cierre. Esta información es importante para que puedas crear otro tipo de aplicación, que veremos después.

Pero aquí nuestro objetivo es crear un contador de velas o, al menos, saber cuándo tenemos o no la presencia de una nueva barra en el gráfico. Así, siempre que este array Time, que se puede ver en la línea nueve, cambie de valor, significa que hay una nueva barra en el gráfico.

Otra forma que, a mi ver, es mucho más simple de hacer esto es observando el valor prev_calculated y rates_total. Pero ¿por qué? El motivo es que el valor presente en el array Time es de tipo datetime. En cambio, los valores prev_calculated y rates_total son valores que el propio MetaTrader 5 nos proporciona, y son de tipo entero, algo mucho más simple y rápido de comprobar. Y, como solo cambian cuando aparecen nuevas barras en el gráfico, todo resulta mucho más fácil de observar.

Además de otra cuestión que, en breve, veremos. ¿Ves a dónde quiero llegar, mi querido lector? No importa cómo vayas a implementar algo. Lo que importa es que entiendas qué tipo de información tienes en las manos para poder alcanzar tu objetivo. Para probarlo, vamos a cambiar el código 01 por el código 02, que se ve justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.     return INIT_SUCCEEDED;
07. };
08. //+------------------------------------------------------------------+
09. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
10. {    
11.     return rates_total;
12. };
13. //+------------------------------------------------------------------+

Código 02

Ahora sí, tenemos un punto de partida para que puedas comprender que todo depende de entender correctamente las cosas y de saber cómo usar la información que tienes en las manos. No existe una forma más o menos correcta de hacer las cosas, sino una forma más o menos simple de lograr el mismo tipo de objetivo y resultado. Muy bien, pero ¿cómo podemos saber si aparece o no una nueva barra en el gráfico? Esta es la parte fácil, mi querido lector. Para hacerlo, vamos a modificar el código 02 por lo que se ve justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.     return INIT_SUCCEEDED;
07. };
08. //+------------------------------------------------------------------+
09. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
10. {
11.     if ((prev_calculated > 0) && (prev_calculated != rates_total))
12.         Print("New Bar...");
13. 
14.     return rates_total;
15. };
16. //+------------------------------------------------------------------+

Código 03

Este código 03 pone en práctica exactamente lo que quiero mostrar y lo que se dijo hace un momento. Es decir, tenemos aquí una forma muy simple de saber cuándo se cerró la barra actual y cuándo apareció una nueva. Para mostrarlo, mira la animación justo abajo.

Animação 01

Como el código 03 es muy simple, al igual que la propia animación, podemos prescindir de cualquier explicación y, así, iniciar lo que será la parte divertida del artículo. Pero, para ello, abordaremos un nuevo tema.


Objetos y el gráfico

A diferencia de lo que muchos pueden pensar, todo y cualquier cosa presente en un gráfico son objetos. Claro que estos objetos pueden tener objetivos completamente diferentes, dependiendo del tipo de cosa que estemos intentando crear. Pero eso no cambia el hecho de que siguen siendo objetos. Y, detalle: estos objetos a los que me refiero no tienen nada que ver con programación orientada a objetos. Ahora viene la parte complicada. Existen dos tipos de objetos o, mejor dicho, dos formas de posicionar objetos en un gráfico de cotización. Como es el caso de los gráficos creados y mantenidos por MetaTrader 5.

El primer tipo son objetos cuyo sistema son coordenadas de pantalla, y el segundo tipo son objetos con coordenadas de cotización. Hay diferencias entre estos objetos, tanto en la forma de presentarlos en pantalla como en la forma de manipularlos. Sin embargo, existe cierta relación entre algunos tipos. Saber elegir el tipo correcto facilita, y mucho, el trabajo de implementación y, por supuesto, agiliza la ejecución del código.

Entonces, como este es el primer contacto que estamos teniendo con este tipo de cosas, hagamos una pequeña pausa en lo que sería el contador de velas, ya que primero necesitamos entender cómo lidiar con estos objetos.

El punto de partida que debes observar será mirar, en la documentación de MQL5, Tipos de objeto. Allí verás una enumeración con diversos objetos diferentes. Aunque tú, mi querido lector, imagines que quizá no tenemos un número adecuado de objetos ahí, y que faltan algunos, esto no es verdad. MQL5, a mi entender, nos proporciona un número más que suficiente de objetos para usarlos en el gráfico. Para ser sincero, no necesitaríamos todos esos objetos. Pero, si fueron implementados y están a nuestra disposición, no veo ningún problema en hacer buen uso de ellos. Además, muchos pueden usarse de una forma muy interesante, ahorrándonos mucho trabajo.

Para demostrarlo, vamos a crear un pequeño código, como forma de mostrar cómo sería trabajar con objetos en el gráfico. El código en cuestión se puede ver justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_NameChannel    "Demo"
05. //+------------------------------------------------------------------+
06. int OnInit()
07. {
08.    ObjectCreate(0, def_NameChannel, OBJ_REGRESSION, 0, 0, 0);
09. 
10.    return INIT_SUCCEEDED;
11. };
12. //+------------------------------------------------------------------+
13. 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[])
14. {
15.    const int   n = 20,
16.                a = 2;
17. 
18.    if ((prev_calculated > (n + a)) && (prev_calculated != rates_total))
19.    {
20.       ObjectMove(0, def_NameChannel, 0, Time[rates_total - (n + a)], Close[rates_total - (n + a)]);
21.       ObjectMove(0, def_NameChannel, 1, Time[rates_total - a], Close[rates_total - a]);
22.    }
23. 
24.    return rates_total;
25. };
26. //+------------------------------------------------------------------+
27. void OnDeinit(const int reason)
28. {
29.    ObjectDelete(0, def_NameChannel);
30.    ChartRedraw();
31. };
32. //+------------------------------------------------------------------+

Código 04

Este código 04 demuestra lo que sería nuestro primer objeto dentro de un indicador. Puede que estés mirando y pensando: hombre, pero esto no es un indicador, ya que no tiene esas estructuras que vimos en los artículos anteriores. Pero sí, mi querido lector, este código 04 sí es un indicador. Y tú lo sabes al ver la función OnCalculate, que es la responsable de capturar y tratar el evento Calculate, generado por MetaTrader 5.

El hecho es que este indicador, en el código 04, no es un indicador convencional. Tiene un objetivo mucho más específico y orientado a una determinada tarea. Antes de ver cómo funciona este código 04, míralo ejecutándose en un gráfico, como se ve en la animación justo abajo.

Animação 02

Es necesario verlo en animación, ya que una imagen estática no sería suficiente para entender algo que veremos en breve. Pero, antes de empezar a hacer gracia en el código, entendamos cómo funciona este código 04. En la línea cuatro, tenemos una definición para poder darle un nombre al objeto que vamos a crear. Y sí, mi querido lector, cada cosa colocada en el gráfico necesita tener un nombre. De ahora en adelante, empieza a acostumbrarte a esto.

Así, en la línea ocho, solo intentamos crear un objeto. En este caso, se trata de un canal de regresión lineal. Como no sabemos dónde se mostrará este canal, no hacemos nada más. Lo que sucede ahora es lo siguiente: el indicador esperará a que MetaTrader 5 dispare un evento Calculate con una característica específica. La característica esperada se define en la línea 18. Observa que esta línea 18, vista en este código 04, se parece bastante a la línea 11, vista en el código 03, y tiene el mismo objetivo: esperar a que aparezca una nueva barra. Hasta que esto ocurra, el objeto que creamos en la línea ocho no se mostrará en el gráfico.

En cuanto se dispare una nueva barra, usamos las líneas 20 y 21 para crear el canal de regresión lineal. Fíjate en cómo se está haciendo esto. En breve trataremos esto con más detalle. Por ahora, observa que no tiene mucho misterio. La línea 20 dice dónde empieza a trazarse el canal, y la línea 21, dónde termina. Al hacer esto, tenemos un canal que seguirá la cotización, con una regresión de 20 barras, y que ignorará la barra actual.

Ahora, siempre que tú creas un objeto y lo pones en el gráfico mediante una aplicación, es de buen tono y educado que tu aplicación quite el objeto del gráfico. Para hacerlo, usamos la línea 29, dentro de lo que sería el manejador de eventos Deinit.

Pero ahora viene la parte divertida. ¿Y si cambias la forma de analizar cómo debería imprimirse la regresión lineal? ¿Cómo se comportaría el indicador? Para saberlo, vamos a modificar el código 04, como se muestra justo abajo, íntegro.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_NameChannel    "Demo"
05. //+------------------------------------------------------------------+
06. int OnInit()
07. {
08.    ObjectCreate(0, def_NameChannel, OBJ_REGRESSION, 0, 0, 0);
09. 
10.    return INIT_SUCCEEDED;
11. };
12. //+------------------------------------------------------------------+
13. 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[])
14. {
15.    const int   n = 20,
16.                a = 1;
17. 
18.    if (prev_calculated > (n + a))
19.    {
20.       ObjectMove(0, def_NameChannel, 0, Time[rates_total - (n + a)], Close[rates_total - (n + a)]);
21.       ObjectMove(0, def_NameChannel, 1, Time[rates_total - a], Close[rates_total - a]);
22.    }
23. 
24.    return rates_total;
25. };
26. //+------------------------------------------------------------------+
27. void OnDeinit(const int reason)
28. {
29.    ObjectDelete(0, def_NameChannel);
30.    ChartRedraw();
31. };
32. //+------------------------------------------------------------------+

Código 05

Observa que, en este código 05, cambiamos solo el manejador de eventos OnCalculate, respecto a lo que era en el código 04. Pero el resultado es, como mínimo, muy interesante, como puedes ver en la animación justo abajo.

Animação 03

Este tipo de cosa que se ve en la animación 03 es una locura, más aún considerando que la regresión se está creando en tiempo real. Es decir, con cada nueva cotización, el canal de regresión lineal va cambiando. Y, dependiendo de la configuración que estés usando, podrías tener un indicador de tendencia realmente muy sensible, incluso más que una media móvil exponencial. Pero eso se lo dejo a los traders de turno, que siempre quisieron una forma de tener un canal de regresión lineal que pudiera autoajustarse.

Quizá me estés mirando y pensando: hombre, pero ¿cuál sería la utilidad de este tipo de indicador? Mi respuesta a eso sería: no lo sé. Pero que es bastante interesante y divertido, eso no puedes negarlo. Sin embargo, quien tenga una visión más elaborada ya habrá pensado en una forma de usar esto para otros fines, ya que todo lo que necesitarías hacer sería cambiar el tipo de objeto que se va a crear y, justo después, indicar cuáles serían los puntos de anclaje. Y, de vez en cuando, los objetos se ajustarían automáticamente, sin que tengas que acordarte de ajustarlos, pues el simple hecho de estar en el gráfico ya será suficiente para que se cumplan y se sigan las reglas que creaste.

Entonces, veamos otro ejemplo. En este caso, utilizaremos otro tipo de objeto. Recordando que lo que voy a mostrar es solo con fines didácticos. El código se ve justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_NameChannel    "Demo"
05. //+------------------------------------------------------------------+
06. int OnInit()
07. {
08.    ObjectCreate(0, def_NameChannel, OBJ_TREND, 0, 0, 0);
09.    ObjectSetInteger(0, def_NameChannel, OBJPROP_RAY_RIGHT, true);
10. 
11.    return INIT_SUCCEEDED;
12. };
13. //+------------------------------------------------------------------+
14. 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[])
15. {
16.     const int   n = 60;
17.     double      p = DBL_MIN;
18.     int         t = 0;
19. 
20.     for (int c = rates_total - (n + 1); c < rates_total; c++)
21.         p = (High[c] > p ? High[t = c] : p);
22.     ObjectMove(0, def_NameChannel, 0, Time[t], p);
23.     p = DBL_MIN;
24.     for (int c = t + 1; c < rates_total; c++)
25.         p = ((High[c] > p) && (Open[c] < Close[c]) ? High[t = c] : p);
26.     ObjectMove(0, def_NameChannel, 1, Time[t], p);
27. 
28.    return rates_total;
29. };
30. //+------------------------------------------------------------------+
31. void OnDeinit(const int reason)
32. {
33.    ObjectDelete(0, def_NameChannel);
34.    ChartRedraw();
35. };
36. //+------------------------------------------------------------------+

Código 06

Este código 04, cuando se ejecute, generará lo que se puede ver justo abajo.

Animação 04

No te entusiasmes con lo que estás viendo, mi querido lector, porque esto que se está haciendo es solo una demostración. En ningún caso debe tomarse como una aplicación final. Pero lo que podemos ver ocurriendo aquí, en esta animación 04, es la aparición de una línea de tendencia bajista trazada según los criterios programados en el código 04. Pero, ¿cómo es posible? Simple: solo le indiqué al código cómo debía buscar una línea de tendencia bajista, según mis criterios.

Ahora, entendamos qué ocurrió. En la línea ocho, tal como se hacía en el código 03, estamos indicando qué tipo de objeto queremos poner en el gráfico. Ya en la línea nueve, estamos modificando una de las propiedades del objeto. Si esta propiedad no se definiera, como se muestra aquí en el código 04, el resultado sería lo que se puede ver en la imagen justo abajo.

Imagem 01

Observa que ahora, al mirar esta imagen 01, estamos viendo desde dónde hasta dónde se creó la línea de tendencia. En este caso, estamos buscando una línea de tendencia bajista. Las líneas de tendencia alcista siguen otro tipo de criterio. Pero, como el objetivo aquí no es mostrar cómo identificar y crear líneas de tendencia automáticamente, el criterio y la forma en que estamos haciendo esto, de hecho, funcionan. Muy bien, pero entonces, ¿cómo logró el indicador encontrar esos puntos para trazar la línea de tendencia? Parece magia.

No, mi querido lector, esto definitivamente no es magia. Es solo la aplicación de un criterio elemental. Observa el manejador de eventos Calculate. Nota que en él tenemos dos bucles: uno para identificar lo que sería el primer punto para trazar la línea de tendencia y otro bucle para identificar cuál sería el segundo punto, a fin de trazar la línea de tendencia. Cuando se encuentra el primer punto, usamos la línea 22 para indicarle al objeto dónde estaría el primer punto de anclaje. Justo después de encontrar el segundo punto, usamos la línea 26 para indicar dónde está el segundo punto de anclaje. Y el resto lo hace el propio MetaTrader 5.

Sin embargo, aun así, voy a recalcar el hecho de que tú NO DEBES TOMAR este indicador como algo plausible. Fue creado para detectar lo que estás observando en la imagen 01 y en la animación 04. Difícilmente logrará detectar otros puntos tan perfectos como estos que puedes ver justo arriba.

Vale, entendido. Pero ¿acaso no podemos cambiar otras propiedades, a fin de construir objetos más personalizados? Sí, mi querido lector. Y con un detalle: a diferencia de lo que ocurre cuando intentas ajustar las propiedades directamente en el gráfico, algunos de estos objetos tienen propiedades que solo pueden ajustarse vía código.

Pero veamos un ejemplo simple de cambios de propiedades. Este se ve justo abajo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_NameChannel    "Demo"
05. //+------------------------------------------------------------------+
06. int OnInit()
07. {
08.    ObjectCreate(0, def_NameChannel, OBJ_TREND, 0, 0, 0);
09.    ObjectSetInteger(0, def_NameChannel, OBJPROP_COLOR, clrLawnGreen);
10.    ObjectSetInteger(0, def_NameChannel, OBJPROP_WIDTH, 4);
11. 
12.    return INIT_SUCCEEDED;
13. };
14. //+------------------------------------------------------------------+
                   .
                   .
                   .

Código 07

Aquí, en este código 07, tenemos solo el fragmento que fue necesario modificar, respecto a lo que se puede ver en el código 06. Pero observa que, en la línea nueve, estamos indicando qué color queremos que se use en el objeto. Así como también, en la línea diez, qué grosor de línea deberá utilizarse. Como resultado de la ejecución de este código, tenemos lo que se ve en la imagen justo abajo.

Imagem 02

Ahora, presta atención, mi querido lector. Tal como se implementó este código, tú NO PODRÁS cambiar ni el color ni el grosor de la línea, usando un acceso directo a la información del indicador, como puedes ver en la imagen justo abajo.

Imagem 03

Para modificar estas propiedades del objeto, necesitarás usar otra caja de diálogo. Es decir, en este caso, tendrás que usar lo que se muestra en la imagen justo abajo.

Imagem 04

Sé que esto parece algo complicado y confuso. Pero esta sería la forma clásica de usar MetaTrader 5. A pesar de todo, hay maneras de evitar este tipo de cosa, permitiendo que el usuario pueda modificar las propiedades de un objeto basándose en alguna configuración hecha directamente en el indicador. Pero vamos con calma, porque este está siendo solo el primer contacto que estamos teniendo con objetos. Siendo así, creo que ya tendrás bastante cosa para experimentar y probar, a fin de que estés preparado para el próximo artículo.


Consideraciones finales

En este artículo, comenzamos a ver cómo podríamos trabajar con objetos directamente en el gráfico, usando un código construido especialmente para mostrarnos algo. Aunque este primer contacto haya sido algo superficial, ya mostró que, si el objetivo que se quiere alcanzar se piensa con calma y se planifica bien, podemos hacer muchas cosas muy interesantes. Para ello, necesitas, de hecho, practicar y estudiar cómo funciona cada uno de los objetos proporcionados por MQL5 y que pueden utilizarse en MetaTrader 5. Esto se debe a que, sin entender realmente las posibilidades disponibles, no podrás poner en práctica ideas que puedas llegar a tener.

Bueno, como siempre, en esta serie de artículos, en el anexo encontrarás los códigos íntegros. Sin embargo, y especialmente para este artículo, debo advertir que todos los códigos proporcionados tienen como objetivo el estudio y una forma de practicar lo explicado en el artículo. No utilices los códigos vistos aquí como si fueran aplicaciones finalizadas o con un propósito distinto al estudio de conceptos, porque esto puede hacerle mucho daño a tu bolsillo.

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

Archivos adjuntos |
Anexo.zip (2.82 KB)
Algoritmo de optimización caótica — Chaos optimization algorithm (COA): Continuación Algoritmo de optimización caótica — Chaos optimization algorithm (COA): Continuación
Continuamos el estudio del algoritmo de optimización caótica. La segunda parte del artículo está dedicada a los aspectos prácticos de la implementación del algoritmo, sus pruebas y conclusiones.
Simulación de mercado (Parte 21): Iniciando SQL (IV) Simulación de mercado (Parte 21): Iniciando SQL (IV)
Muchos de ustedes, queridos lectores, pueden tener un nivel de experiencia muy superior al mío en lo que respecta a trabajar con bases de datos y, así, por esta razón, tener una visión diferente de la mía. Pero, como era necesario definir y desarrollar alguna forma de explicar el motivo por el cual las bases de datos se crean como se crean, explicar por qué SQL tiene el formato que tiene y, sobre todo, por qué surgieron las claves primarias y las claves foráneas, fue necesario dejar las cosas un poco abstractas.
Superando las limitaciones del aprendizaje automático (Parte 1): Falta de métricas interoperables Superando las limitaciones del aprendizaje automático (Parte 1): Falta de métricas interoperables
Existe una fuerza poderosa y omnipresente que corrompe silenciosamente los esfuerzos colectivos de nuestra comunidad por desarrollar estrategias comerciales fiables que empleen la IA en cualquiera de sus formas. Este artículo establece que parte de los problemas a los que nos enfrentamos tienen su origen en la adhesión ciega a las «mejores prácticas». Al proporcionar al lector pruebas sencillas basadas en el mercado real, le explicaremos por qué debemos abstenernos de tal conducta y adoptar, en su lugar, las mejores prácticas específicas del ámbito si nuestra comunidad quiere tener alguna posibilidad de recuperar el potencial latente de la IA.
Visión por computadora para el trading (Parte 1): Creamos una funcionalidad básica sencilla Visión por computadora para el trading (Parte 1): Creamos una funcionalidad básica sencilla
Sistema de previsión de EURUSD mediante visión por computadora y aprendizaje profundo. Descubra cómo las redes neuronales convolucionales pueden reconocer patrones de precios complejos en el mercado de divisas y predecir la evolución de los tipos con una precisión de hasta el 54%. El artículo revela la metodología de creación de un algoritmo que usa tecnologías de inteligencia artificial para analizar visualmente los gráficos en lugar de los indicadores técnicos tradicionales. El autor muestra el proceso de transformación de los datos de precios en "imágenes", su procesamiento por una red neuronal y una visión única de la "conciencia" de la IA a través de mapas de activación y mapas de calor de la atención. El práctico código Python que utiliza la biblioteca MetaTrader 5 permite a los lectores reproducir el sistema y aplicarlo a sus propias transacciones.