English Русский 中文 Deutsch 日本語 Português
preview
Desarrollo de un sistema de repetición (Parte 42): Proyecto Chart Trade (I)

Desarrollo de un sistema de repetición (Parte 42): Proyecto Chart Trade (I)

MetaTrader 5Ejemplos | 2 julio 2024, 09:51
306 0
Daniel Jose
Daniel Jose

Introducción

En el artículo anterior Desarrollo de un sistema de repetición (Parte 41): Iniciando la segunda fase (II), mostré cómo crear un indicador para usar como mouse. Puede que hayas pensado que eso es una tontería y que no tendrá utilidad a largo plazo. Si piensas así, es porque no lograste entender lo que está ocurriendo.

Cada vez que necesitas crear ciertas cosas, tendrás que hacer una serie de pruebas y crear condiciones para que un programa o proceso pueda convivir con otros. Lograr esto demuestra si estás preparado para afirmarte como profesional.

Es común que los principiantes tengan problemas cuando un programa o proceso interfiere con otro. Cuando esto ocurre, suceden cosas extrañas. Un principiante no logrará resolver estos problemas, pero un profesional debe poder lidiar con esta situación.

Lo que quiero decir es lo siguiente: De nada sirve programar un EA capaz de realizar mil y una operaciones; o tener una serie de indicadores y elementos gráficos; o muchos programas o procesos que te ayudan a operar en el mercado. Si al intentar poner dos de estos programas juntos en el mismo gráfico, empiezan a estorbarse mutuamente.

O peor, si creas un programa extremadamente seguro y robusto y luego debes crear otro que use parte de la funcionalidad del primero, y al hacer esto, el nuevo programa empieza a tener una serie de errores y fallas, aún más cuando se coloca junto con otros procesos. Definitivamente perderás tiempo intentando resolver esas fallas. Algunas serán simples, pero otras muy complicadas.

¿Por qué digo esto? El motivo es que ya tenemos un indicador de mouse creado. La plataforma MetaTrader 5 cuenta con diversas herramientas para ayudarnos. Algunas son más simples, necesitando una mejora para realmente atender las necesidades personales de cada uno. Puedes hacer esto creando diversos programas para construir el rifle ideal, el arma perfecta para usar en el mercado. Pero me gustaría que pienses en lo siguiente: ¿Qué tal si en lugar de intentar crear el arma perfecta, creamos diversos componentes y piezas para usarlos y combinarlos, con el objetivo de tener un arma adecuada para lo que enfrentaremos?

Parece una buena solución, ¿no es cierto? Hicimos esto al crear el indicador de mouse. Con base en ese indicador, comenzaremos a crear una serie de piezas y componentes que nos ayudarán inmensamente.

Desde el inicio de esta secuencia sobre cómo desarrollar un sistema de repetición/simulación, he dicho que la idea es usar la plataforma MetaTrader 5 de manera idéntica, tanto en el sistema que estamos desarrollando como en el mercado real. Es importante que esto se haga de manera adecuada. No querrás entrenar y aprender a luchar usando determinadas herramientas y en el momento de la pelea tener que usar otras. Créeme, usar el sistema de repetición/simulador es hacer el entrenamiento. Operar en la cuenta REAL es de hecho partir para la lucha. Si vas a luchar, debes usar lo que aprendiste y a lo que te acostumbraste en el entrenamiento.

Existen dos herramientas, después del indicador de mouse, que son más urgentes de crear. Una es simple y la otra bastante complicada, debido a lo que tendremos que hacer en términos de modelado de datos. Entonces comenzaremos por la más simple. Así te vas acostumbrando y cuando veas la otra, que es mucho más complicada, ya tendrás una buena noción de cómo funcionarán las cosas.

La herramienta simple es el Chart Trade. Este fue presentado en su última versión en el artículo: Desarrollo de un EA de trading desde cero (Parte 30): ¿CHART TRADE ahora como indicador?. Lo que haremos ahora hará que ese indicador parezca un juego de niños. Esto debido a lo simple que era y lo poco versátil. Vamos a crear un nuevo Chart Trade que consiga convivir en armonía con el indicador ya creado. El indicador del que hablo es el indicador de mouse.


Un nuevo Chart Trade

Ese Chart Trade visto en el artículo mencionado nos servirá como base. Sin embargo, no usaremos el código ni la plantilla. Crearemos otro, mucho más maduro y adecuado a nuestras necesidades.

En este nuevo código que presentaré, notarás que es considerablemente más simple y compacto. Como consecuencia, es más fácil corregir y modificar las cosas en él. La idea es usar el indicador de mouse para mover, hacer clic e interactuar con cualquier cosa en el gráfico. Para hacer esto, necesitaremos montar un código bastante peculiar. Entonces, para que puedan seguir lo que se hará, mostraré las cosas con calma. Esto porque es algo muy, muy diferente de lo que muchos están acostumbrados a ver y usar en MetaTrader 5. Hablando de programación, muchos tal vez no entenderán nada al principio.

Para empezar, nuestro Chart Trade usa un concepto que presenté hace tiempo: Programación RAD. Esta palabra RAD viene de Rapid Application Development, o traducido: Desarrollo Rápido de Aplicaciones. Me presentaron este concepto años atrás cuando comenzaba a programar para sistemas Windows. Ayuda bastante en la creación eficiente de aplicaciones. En lugar de preocuparse con la apariencia del programa, usas este sistema de programación y pasarás más tiempo ocupándote del código en sí. En el artículo Múltiples indicadores en un gráfico (Parte 06): Convirtamos el MetaTrader 5 en un sistema RAD (II), mostré cómo usar algo similar en MetaTrader 5.

Ese mismo concepto se usará aquí nuevamente. Sin embargo, lo mejoraremos. Si deseas empezar con el pie derecho, lee el artículo mencionado, así como el anterior, que también es importante para comprender lo que haremos aquí. El artículo se puede leer en:  Múltiples indicadores en un gráfico (Parte 05): Convirtamos el MetaTrader 5 en un sistema RAD (I). Es importante comprender lo que se explica allí. Aquí el tema será más denso y complicado, a pesar de que este indicador sea la parte fácil comparado con lo que vendrá después.

Nuestro nuevo template tendrá la apariencia mostrada en la figura 01 a continuación:

Figura 01

Figura 01 - Template RAD

Exacto. En la figura 01 tenemos la apariencia real que tendrá el Chart Trade. Lo que ves es el template del Chart Trade, y no el Chart Trade en sí, puede ser visto en el vídeo 01, justo debajo, donde demuestro la interacción entre él y el indicador de mouse. Vean el vídeo y noten cómo funciona. El vídeo representa exactamente lo que se verá en este artículo. Es importante ver el vídeo para entender mejor lo que se explicará.


Vídeo 01 - Vídeo de demostración.

Considerando que ya viste el vídeo 01, comencemos a ver el código del indicador Chart Trade. Pero antes, necesitamos añadir algo pequeño al código de la clase C_Terminal. Lo que se añadirá se ve en el siguiente fragmento.

Fragmento de la clase C_Terminal

156. //+------------------------------------------------------------------+
157.            bool IndicatorCheckPass(const string szShortName)
158.                    {
159.                            string szTmp = szShortName + "_TMP";
160.                            
161.                            if (_LastError != ERR_SUCCESS) return false;
162.                            IndicatorSetString(INDICATOR_SHORTNAME, szTmp);
163.                            if (ChartWindowFind(m_Infos.ID, szShortName) != -1)
164.                            {
165.                                    ChartIndicatorDelete(m_Infos.ID, 0, szTmp);
166.                                    Print("Only one instance is allowed...");
167.            
168.                                    return false;
169.                            }
170.                            IndicatorSetString(INDICATOR_SHORTNAME, szShortName);
171.                            ResetLastError();
172.    
173.                            return true;
174.                    }
175. //+------------------------------------------------------------------+


Este código puede no parecer extraño, y de hecho no lo es. Se ha visto antes, pero ahora forma parte de la clase C_Terminal, de modo que todas las clases o indicadores que usen esta clase se beneficiarán de este código. Él hace exactamente lo que queremos. Evita que el indicador se coloque más de una vez en el gráfico. Existe una forma de burlar esto, y la usaremos en el futuro, pero por ahora, no te preocupes por este detalle. Ten en cuenta que este código evitará que tengamos dos indicadores idénticos en el gráfico al mismo tiempo.

Pero antes de entrar en la clase inicial que dará soporte a nuestro Chart Trade, veamos primero el código del indicador. Estoy cambiando el orden de presentación para que la explicación de la clase sea más adecuada. El código íntegro del indicador puede verse a continuación.

Código fuente del Indicador Chart Trade

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Base version for Chart Trade (DEMO version)"
04. #property version   "1.42"
05. #property link "https://www.mql5.com/pt/articles/11652"
06. #property indicator_chart_window
07. #property indicator_plots 0
08. //+------------------------------------------------------------------+
09. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
10. //+------------------------------------------------------------------+
11. C_ChartFloatingRAD *chart = NULL;
12. //+------------------------------------------------------------------+
13. int OnInit()
14. {
15.     chart = new C_ChartFloatingRAD("Indicator Chart Trade", new C_Mouse("Indicator Mouse Study"));
16.     if (_LastError != ERR_SUCCESS)
17.     {
18.             Print("Error number:", _LastError);
19.             return INIT_FAILED;
20.     }
21.     
22.     return INIT_SUCCEEDED;
23. }
24. //+------------------------------------------------------------------+
25. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
26. {
27.     return rates_total;
28. }
29. //+------------------------------------------------------------------+
30. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
31. {
32.     (*chart).DispatchMessage(id, lparam, dparam, sparam);
33.     
34.     ChartRedraw();
35. }
36. //+------------------------------------------------------------------+
37. void OnDeinit(const int reason)
38. {
39.     delete chart;
40.     
41.     ChartRedraw();
42. }
43. //+------------------------------------------------------------------+


Este código del indicador es bastante simple como puedes ver arriba. Es cierto que añadiremos más información para hacer una descripción adecuada. Pero por ahora es suficiente para lo que necesitamos.

Observa que lo único que hacemos es indicar que no se trazará ningún dato, en la línea 07. Y después, el resto del trabajo consiste en inicializar el puntero para usar la clase que dará soporte al chart trade, y destruir este mismo puntero. Aún así, tendremos el comportamiento visto en el vídeo 01.

Creo que no tendrás dificultades en comprender ninguna línea del código del indicador. Tal vez la única que dé un poco más de trabajo sea la línea 15. Pero incluso esta sigue siendo bastante simple. Estamos usando dos operadores new para inicializar ambas las clases.

El único detalle al que debes prestar atención es a la información pasada como strings. La primera string se refiere al nombre que será reconocido por MetaTrader 5 cuando el indicador esté en el gráfico. La segunda string se refiere al nombre que tiene el indicador de mouse. Esto se define en el código del indicador de mouse. Para más detalles, ve el artículo: Desarrollo de un sistema de repetición (Parte 41): Inicio de la segunda fase (II).

Ahora que ya viste lo simple que es el código del indicador Chart Trade, veamos el código de la clase. Recuerda que el código que verás será el inicial. Aún se le añadirán más elementos para que el indicador sea realmente funcional.


La clase C_ChartFloatingRAD

A pesar del nombre, esta clase estará destinada básicamente a trabajar con el indicador Chart Trade. En el estado actual de desarrollo, ya contiene toda la lógica necesaria para que tengamos un comportamiento idéntico al visto en el vídeo 01. Es decir, si estamos realizando un estudio, no podremos mover la ventana, incluso cuando hacemos clic en ella y arrastramos el mouse. Durante un estudio, no será posible mover la ventana.

Puede que pienses que fue necesario crear un esquema complejo para lograr esto, así como crear la imagen vista en el vídeo, donde ya tenemos la apariencia final del indicador. Bueno, veamos si esto es cierto. Para ello, basta con mirar el código de la clase. Este puede observarse íntegramente a continuación.

Código fuente de la clase C_ChartFloatingRAD

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #include "../Auxiliar/C_Terminal.mqh"
05. #include "../Auxiliar/C_Mouse.mqh"
06. //+------------------------------------------------------------------+
07. class C_ChartFloatingRAD : private C_Terminal
08. {
09.     private :
10.             struct st00
11.             {
12.                     int     x, y, cx, cy;
13.                     string  szObj_Chart;
14.                     long    WinHandle;
15.             }m_Info;
16. //+------------------------------------------------------------------+
17.             C_Mouse *m_Mouse;
18. //+------------------------------------------------------------------+
19.             void CreateWindowRAD(int x, int y, int w, int h)
20.                     {
21.                             m_Info.szObj_Chart = (string)ObjectsTotal(GetInfoTerminal().ID);
22.                             ObjectCreate(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJ_CHART, 0, 0, 0);
23.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = x);
24.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = y);
25.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XSIZE, w);
26.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, h);
27.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_DATE_SCALE, false);
28.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_PRICE_SCALE, false);
29.                             m_Info.WinHandle = ObjectGetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_CHART_ID);
30.                             m_Info.cx = w;
31.                             m_Info.cy = 26;
32.                     };
33. //+------------------------------------------------------------------+
34. inline void UpdateChartTemplate(void)
35.                     {
36.                             ChartApplyTemplate(m_Info.WinHandle, "IDE_RAD.tpl");
37.                             ChartRedraw(m_Info.WinHandle);
38.                     }
39. //+------------------------------------------------------------------+
40.     public  :
41. //+------------------------------------------------------------------+
42.             C_ChartFloatingRAD(string szShortName, C_Mouse *MousePtr)
43.                     :C_Terminal()
44.                     {
45.                             if (!IndicatorCheckPass(szShortName)) SetUserError(C_Terminal::ERR_Unknown);
46.                             m_Mouse = MousePtr;
47.                             CreateWindowRAD(0, 0, 170, 240);
48.                             UpdateChartTemplate();
49.                     }
50. //+------------------------------------------------------------------+
51.             ~C_ChartFloatingRAD()
52.                     {
53.                             ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Chart);
54.                             delete m_Mouse;
55.                     }
56. //+------------------------------------------------------------------+
57.             void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
58.                     {
59.                             static int sx = -1, sy = -1;
60.                             int x, y, mx, my;
61.     
62.                             switch (id)
63.                             {
64.                                     case CHARTEVENT_MOUSE_MOVE:
65.                                             if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft))
66.                                             {
67.                                                     x = (int)lparam;
68.                                                     y = (int)dparam;
69.                                                     if ((x > m_Info.x) && (x < (m_Info.x + m_Info.cx)) && (y > m_Info.y) && (y < (m_Info.y + m_Info.cy)))
70.                                                     {
71.                                                             if (sx < 0)
72.                                                             {
73.                                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
74.                                                                     sx = x - m_Info.x;
75.                                                                     sy = y - m_Info.y;
76.                                                             }
77.                                                             if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = mx);
78.                                                             if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = my);
79.                                                     }
80.                                             }else if (sx > 0)
81.                                             {
82.                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                                                
83.                                                     sx = sy = -1;
84.                                             }
85.                                             break;
86.                             }
87.                     }
88. //+------------------------------------------------------------------+
89. };
90. //+------------------------------------------------------------------+
91. 


¿Pero es solo esto? ¿Dónde están los códigos de creación de objetos? ¿La manipulación del mouse?

No puedo creer que estos dos simples códigos vistos hasta ahora sean capaces de hacer lo que veo en el vídeo 01. Estás bromeando con todos nosotros. Confiesa. No, no estoy bromeando. De hecho, solo estas pocas líneas son capaces de hacer que esa ventana vista en la figura 01 tenga el comportamiento visto en el vídeo 01.

Puedes realizar estudios usando el mouse. Puedes hacer clic y arrastrar la ventana del Chart Trade. Todo esto usando solo y únicamente este código. Aún hay algunas cosas que se añadirán a este código de la clase para hacer que la ventana sea funcional, para que el activo pueda mostrarse. Los botones se volverán funcionales y podremos editar los valores que aún no están presentes. De hecho, todavía faltan algunas cosas por hacer. Pero no esperen ver la creación de esos objetos aquí. Usaré una forma diferente de hacer funcional esta ventana. Y esto se verá en el próximo artículo.

Mas, esperen, todavía no hemos terminado. Para que entiendas realmente lo que está sucediendo, veamos la explicación del código de la clase y por qué tiene este código específico.

Comencemos con la línea 07. Observa que la clase C_ChartFloatingRAD está heredando de la clase C_Terminal. Como siempre debemos dar el mínimo privilegio a las herencias, hacemos la herencia privada. Así, ningún otro código tendrá acceso a la clase C_Terminal, al menos no a través de la clase C_ChartFloatingRAD. Esto no es un problema, ya que el código del indicador no hace ninguna mención a cualquier código de la clase C_Terminal.

Una vez entendido este punto, podemos pasar al constructor. Así, el flujo de ejecución será más fácil de comprender.

El constructor comienza en la línea 42. Observa que recibirá una string y un objeto, en realidad un puntero, para referenciar el indicador de mouse. En la línea 43, hacemos la inicialización requerida de la clase C_Terminal. Al entrar en el código del constructor a partir de la línea 45, hacemos una llamada al código de chequeo para garantizar que el indicador Chart Trade no esté presente en el gráfico. Si esta comprobación falla, lo indicamos en la constante _LastError. Para hacerlo, usamos la llamada SetUserError.

Presta mucha atención a lo siguiente. Si no entiendes lo que explicaré, te perderás completamente en el resto de esta secuencia de artículos. Así que presta mucha atención a lo que diré.

En la línea 46, almacenamos el puntero que se pasó mediante la llamada al operador new. Esto está en el código del indicador Chart Trade. Puedes ver esta llamada en la línea 15 del código del indicador. NO IMPORTA si el indicador de mouse está o no presente en el gráfico en el momento en que se ejecute la línea 46. Repetiré porque es importante: NO IMPORTA si el indicador está o no presente en el gráfico en el momento de la llamada.

Lo que realmente importa, y esto es lo que muchos pueden no entender, es el nombre que se está pasando en la llamada vista en la línea 15 del código del indicador Chart Trade. Esa string que se pasa al constructor de la clase C_Mouse. Eso sí importa. El hecho de que el indicador esté o no en el gráfico importa poco.

Puede que pienses que esto no tiene sentido. Pero sí lo tiene. Para entenderlo, es necesario volver al artículo anterior Desarrollo de un sistema de repetición (Parte 41): Inicio de la segunda fase (II), y observar la línea 169 en el código de la clase C_Mouse. Esa línea, y solo esa línea, hará que el código visto en la clase C_ChartFloatingRAD funcione adecuadamente. Por eso, es necesario informar correctamente el nombre del indicador de mouse. Para que la plataforma MetaTrader 5 pueda encontrarlo cuando sea necesario ejecutar la línea 169 en la clase C_Mouse.

Puede que esto aún esté confuso. Sigamos con la explicación sobre cómo funciona el código. Regresaremos a este punto más adelante para aclarar las cosas.

En la línea 47, hacemos una llamada a la función que se encuentra en la línea 19. Esta función en la línea 19 es simplemente un procedimiento que creará un objeto OBJ_CHART en el gráfico. Solo eso. Sin embargo, en la línea 29, almacenamos la ID de este objeto. Esto para poder usarlo de una manera muy específica más adelante. Creo que nadie tendrá dificultades para entender las demás líneas de este procedimiento.

Volviendo al código del constructor, en la línea 48, hay otra llamada. Esta ejecutará el procedimiento presente en la línea 34. Dentro de este procedimiento, por ahora, tenemos dos líneas. La línea 36 buscará el template que estamos indicando. Este template es exactamente el que se ve en la figura 01. Y en la línea 37, forzamos a MetaTrader 5 a actualizar el objeto OBJ_CHART para que se muestre el template.

De esta manera presentamos nuestro Chart Trade. Es cierto que no está funcional aún. Sin embargo, ya podemos hacer algún tipo de "manipulación" para entender la interacción entre el indicador de mouse y el indicador Chart Trade.

El código del destructor es bastante simple, no necesita ninguna explicación especial. Pero tenemos que observar bien el código de tratamiento de mensajes: El procedimiento DispatchMessage comienza en la línea 57. Aquí es donde tendremos la interacción entre los dos indicadores.

Básicamente, en este momento, lo único que estaremos tratando es el evento de movimiento del mouse. Esto comienza en la línea 64. Pero atención, no trataremos el evento del mouse de la manera convencional. Lo trataremos de una forma totalmente y completamente diferente. Para aquellos que están acostumbrados a programar las cosas de cierta manera, lo que verán aquí es algo muy loco. O como algunos dicen: "Very crazy"😂.  

Para entender todo, y por eso no estoy mostrando otras cosas en este artículo, necesitas recurrir al artículo anterior, Desarrollo de un sistema de repetición (Parte 41): Inicio de la segunda fase (II). Estamos tratando no con uno, sino con dos indicadores al mismo tiempo. Ellos se están comunicando para que puedan convivir en armonía y el usuario pueda hacer las cosas como se muestra en el vídeo 01.

En este código de tratamiento de mensajes del indicador Chart Trade, solo mencionaremos una única vez al indicador de mouse. Esta mención se hace en la línea 65. Presta mucha atención para entender lo que está ocurriendo. Si entiendes esto, el resto será pan comido.

Existen dos situaciones aquí. La primera es cuando el indicador de mouse está en el gráfico. La segunda es cuando el indicador no está en el gráfico. Recordando que el indicador debe tener el nombre que indicamos en el constructor de la clase C_ChartFloatingRAD. Si el nombre es diferente, MetaTrader 5 no nos ayudará y tendremos la situación donde el indicador no está en el gráfico. Atención a este detalle.

Una vez que esto esté claro y estés consciente de estas dos situaciones, podemos comenzar la explicación.

Cuando esto ocurre, la llamada de la línea 65 ejecutará la llamada de la línea 158 de la clase C_Mouse (Artículo anterior). En la línea 15 del código del indicador Chart Trade, indicamos al constructor de la clase C_Mouse que usaremos la clase C_Mouse como traductora. La línea 158 de la clase C_Mouse llamará a la línea 163 para verificar si ocurrió un clic con el botón indicado en la línea 65 de la clase C_ChartFloatingRAD.

En el momento en que se ejecute la línea 165 en la clase C_Mouse, el código se dará cuenta de que estamos usando el traductor. Entonces, ejecutaremos la línea 169 para capturar el handle del indicador de mouse. En este momento, pediremos ayuda a MetaTrader 5, por lo que los nombres indicados deben ser los mismos. Si MetaTrader 5 encuentra el indicador al que nos referimos, el handle tendrá el índice para acceder al buffer del indicador. Si el buffer puede ser leído, la línea 172 capturará los datos del indicador de mouse. Si el buffer no puede ser leído, la función fallará, haciendo que la función en la línea 158 también falle. Esto resultará en la falla de la prueba presente en la línea 65 de la clase C_ChartFloatingRAD. Así, tendremos la indicación de que el clic no ocurrió.

Toda esta lógica funcionará en dos situaciones:

  • cuando el indicador de mouse no esté presente en el gráfico. Recordando que debe tener el mismo nombre indicado para que MetaTrader 5 lo encuentre.
  • Cuando estemos realizando un estudio en el gráfico usando el indicador de mouse.

En cualquiera de estas dos situaciones, la línea 65 de la clase C_ChartFloatingRAD indicará fallo en el clic del mouse.

¿Te parece confusa esta parte? Tranquilo, la cosa se pone aún más interesante.

Ahora analicemos la situación donde MetaTrader 5 encuentra el indicador de mouse y queremos arrastrar el indicador Chart Trade por el gráfico, tal como se ve en el video 01. Para entender cómo ocurrirá esto, es necesario que hayas comprendido los siguientes artículos:

Cada uno de estos artículos te prepara para lo que está por venir. Si no los has leído o no comprendiste su contenido, te sugiero que vuelvas a ellos y entiendas cómo se da la comunicación. Aunque pueda parecer simple, estos conceptos se vuelven bastante complejos de entender cuando se ponen en práctica, especialmente para quienes no usan estas prácticas.

Lo que estoy mostrando aquí es la parte más simple de todas. Lo que viene después hará que esto parezca educación infantil. Por eso, es bien importante que entiendas cómo funciona este código.

De cualquier manera, en algún momento, la llamada presente en la línea 65 de la clase C_ChartFloatingRAD encontrará la llamada presente en la línea 181 de la clase C_Mouse. Cuando esto suceda, la línea 160 en la clase C_Mouse probará el código del botón pasado a ella. Si el código coincide con el pasado, la función devolverá un valor verdadero. En este momento, y durante todo el tiempo que el botón del mouse esté presionado, ejecutaremos el código presente entre las líneas 67 a 79.

Hay una pequeña falla en este código, pero dado que es solo para demostración, podemos dejarla pasar por ahora.

Ahora surge una pregunta. ¿Por qué en las líneas 67 y 68 uso los valores proporcionados por MetaTrader 5 y no por el indicador de mouse? Esto tiene un motivo. No lo hago porque parezca más bonito o más fácil. Hay una razón para usar los valores proporcionados por MetaTrader 5 y no los del indicador. Para entender esto, debes mirar el código en la clase C_Mouse entre las líneas 203 y 206. En esas líneas, hacemos una conversión, transformación y ajuste en los puntos de coordenadas del mouse. Al hacer esto, las coordenadas del mouse dejan de ser del tipo pantalla (x e y) y pasan a ser del tipo activo (precio y tiempo).

Esto es muy útil para trabajar con ciertos tipos de cosas, pero es problemático cuando necesitamos trabajar de otra manera. Si usas en las líneas 67 y 68 de la clase C_ChartFloatingRAD un código como el mostrado a continuación:

x = (*m_Mouse).GetInfoMouse().Position.X;
y = (*m_Mouse).GetInfoMouse().Position.Y;

Obtendrás un movimiento del objeto OBJ_CHART como si estuviera anclado en las coordenadas del activo (precio y tiempo). Pero en realidad, tal objeto usa coordenadas de pantalla (x, y). Por eso, el movimiento sería bastante extraño y no tendría la misma suavidad vista en el video 01. Para algunos tipos de cosas, es de hecho deseable usar las coordenadas proporcionadas por el indicador de mouse.


Conclusión

En este artículo, mostré cómo producir la primera etapa del indicador Chart Trade. Mostré cómo puedes usar el indicador de mouse en perfecta armonía con el indicador Chart Trade que estamos creando. Es cierto que el indicador Chart Trade aún no tiene ninguna funcionalidad, aparte de poder ser arrastrado en el gráfico.

En el próximo artículo, comenzaremos a dar funcionalidad a este indicador Chart Trade.


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

Archivos adjuntos |
Anexo.zip (420.65 KB)
GIT: ¿Pero qué es esto? GIT: ¿Pero qué es esto?
En este artículo presentaré una herramienta de suma importancia para quienes desarrollan programas. Si no conoces GIT, consulta este artículo para tener una noción de lo que se trata esta herramienta y cómo usarla junto al MQL5.
Redes neuronales: así de sencillo (Parte 69): Restricción de la política de comportamiento basada en la densidad de datos offline (SPOT) Redes neuronales: así de sencillo (Parte 69): Restricción de la política de comportamiento basada en la densidad de datos offline (SPOT)
En el aprendizaje offline, utilizamos un conjunto de datos fijo, lo que limita la cobertura de la diversidad del entorno. Durante el proceso de aprendizaje, nuestro Agente puede generar acciones fuera de dicho conjunto. Si no hay retroalimentación del entorno, la corrección de las evaluaciones de tales acciones será cuestionable. Mantener la política del Agente dentro de la muestra de entrenamiento se convierte así en un aspecto importante para garantizar la solidez del entrenamiento. De eso hablaremos en este artículo.
Redes neuronales: así de sencillo (Parte 70): Mejoramos las políticas usando operadores de forma cerrada (CFPI) Redes neuronales: así de sencillo (Parte 70): Mejoramos las políticas usando operadores de forma cerrada (CFPI)
En este trabajo, proponemos introducir un algoritmo que use operadores de mejora de políticas de forma cerrada para optimizar las acciones offline del Agente.
Patrones de diseño en MQL5 (Parte 4): Patrones conductuales 2 Patrones de diseño en MQL5 (Parte 4): Patrones conductuales 2
Este artículo concluye la serie sobre patrones de diseño en ingeniería de software. Ya hemos mencionado que existen tres tipos de patrones de diseño: de creación, estructurales y conductuales. Hoy perfeccionaremos los patrones conductuales restantes, que nos ayudarán a especificar la forma en que interactúan los objetos de manera que nuestro código sea limpio.