English Русский 中文 Deutsch 日本語 Português
Mejorando el trabajo con Paneles: cómo añadir transparencia, cambiar el color del fondo y heredar a partir de CAppDialog/CWndClient

Mejorando el trabajo con Paneles: cómo añadir transparencia, cambiar el color del fondo y heredar a partir de CAppDialog/CWndClient

MetaTrader 5Ejemplos | 25 junio 2018, 16:13
1 479 0
Vladimir Karputov
Vladimir Karputov

Contenido

Introducción

Los paneles basados en la clase CAppDialog no tienen métodos suficientes de acceso directo a las propiedades de los elementos de control de los que consta el panel, tales como el "Color de fondo" y el "Color del marco". Por lo tanto, todos los paneles se crean igualmente grises. 

Al no tener forma de cambiar el color de los controles, no podemos implementar las ideas del diseño. Por supuesto que podemos resolver este problema mediante la herencia y la adición de sus métodos. Pero para ello será necesario hacer bastantes correcciones al código generado. ¿Existe alguna forma más simple y rápida de acceder a las propiedades "Color de fondo" y "Color del marco" para los elementos de control del panel?


Transparencia del panel durante el desplazamiento

Vamos a mostrar en primer lugar qué podemos hacer para el panel basado en la clase CAppDialog (se trata de un ejemplo de funcionamiento del código "Live panel.mq5").

Live panel

Esta animación se muestra que, al desplazar el panel, solo queda el marco exterior del mismo. Durante el desplazamiento, el marco externo también cambiará su color en un orden arbitrario. Cuando se completa el desplazamiento, la forma vuelve a ser normal: aparecen las áreas de trabajo.

Cómo se hace

Todo el trabajo se hará alrededor de la clase CDialog. Esta se ubica en el archivo [data folder]\MQL5\Include\Controls\Dialog.mqh

Recordemos de qué objetos consta el panel (estos objetos están declarados en la clase CDialog, en la sección privada) y cómo se incorporan visualmente estos a los elementos gráficos:

//+------------------------------------------------------------------+
//| Class CDialog                                                    |
//| Usage: base class to create dialog boxes                         |
//|             and indicator panels                                 |
//+------------------------------------------------------------------+
class CDialog : public CWndContainer
  {
private:
   //--- dependent controls
   CPanel            m_white_border;        // the "white border" object
   CPanel            m_background;          // the background object
   CEdit             m_caption;             // the window title object
   CBmpButton        m_button_close;        // the "Close" button object
   CWndClient        m_client_area;         // the client area object

protected:

CDialog objects

Para dar transparencia al panel durante al arrastre, debemos tener en cuenta cuatro momentos clave.

1. A nosotros nos interesan los elementos "Border" y "Back" (creados por los objetos m_white_borderm_background de la clase CPanel) y el elemento "Client" (creado por el objeto m_client_area de la clase CWndClient). Podemos ver cómo se crean y qué color se les asigna en las funciones CDialog::CreateWhiteBorder, CDialog::CreateBackground y CDialog::CreateClientArea, respectivamente.

2. Durante su creación, el panel recibe un nombre único, es decir, un prefijo digital que se coloca antes de los nombres de todos los objetos gráficos (en la figura siguiente, el prefijo es 03082):

Objects

3. En la clase CDialog hay tres procesadores de arrastre:

 Procesamiento del arrastre
 OnDialogDragStart  Procesador virtual del evento "DialogDragStart" del elemento de control
 OnDialogDragProcess  Procesador virtual del evento "DialogDragProcess" del elemento de control
 OnDialogDragEnd  Procesador virtual del evento "DialogDragEnd" del elemento de control

4. El truco del artículo "Cómo crear un panel gráfico de cualquier nivel de complejidad" consiste en la iteración de los objetos del panel (aquí ExtDialog es un objeto de clase del panel):

   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
...

¿Por qué al iterar el ciclo, el puntero al objeto obj se declara con el tipo CWnd?

Porque CWnd es una clase básica, de la cual proceden todas las clases descendientes:

Ahora podemos proceder a la implementación

Para trabajar con el color, necesitamos dos macros, y para captar el desplazamiento del panel, tenemos que redefinir tres funciones de la clase CDialog:

//+------------------------------------------------------------------+
//|                                                   Live panel.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.000"
#property description "El panel cambia su transparencia al desplazarse"
#include <Controls\Dialog.mqh>
#define XRGB(r,g,b)    (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define GETRGB(clr)    ((clr)&0xFFFFFF)
//+------------------------------------------------------------------+
//| Class CLivePanel                                                 |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CLivePanel : public CAppDialog
  {
public:
                     CLivePanel(void);
                    ~CLivePanel(void);
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
   //--- handlers of drag
   virtual bool      OnDialogDragStart(void);
   virtual bool      OnDialogDragProcess(void);
   virtual bool      OnDialogDragEnd(void);

  };

Vamos a omitir la parte estándar del trabajo con el panel (creación, eliminación y transmisión de eventos), deteniéndonos en los controles de desplazamiento con más detalle.

El controlador "OnDialogDragStart": comienzo del desplazamiento del panel

Obtenemos el prefijo, después, en el ciclo iteramos todos los objetos del panel y buscamos el nombre "Border", "Back" o "Client" con el prefijo:

//+------------------------------------------------------------------+
//| Start dragging the dialog box                                    |
//+------------------------------------------------------------------+
bool CLivePanel::OnDialogDragStart(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Border")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrNONE);
         ChartRedraw();
        }
      if(name==prefix+"Back")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrNONE);
         ChartRedraw();
        }
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(clrNONE);
         wndclient.ColorBorder(clrNONE);
         ChartRedraw();
        }
     }
   return(CDialog::OnDialogDragStart());
  }

Cuando los objetos han sido localizados, eliminamos el color del fondo (método "ColorBackground") y los marcos (método "ColorBorder"), adoptando el color clrNONE. De esta forma, se implementa la transparencia de la forma.

El controlador "OnDialogDragProcess": continuamos desplazando el panel

Solo buscamos un objeto — "Back", y cambiamos dinámicamente su color (con la ayuda de dos macros, XRGB y GETRGB):

//+------------------------------------------------------------------+
//| Continue dragging the dialog box                                 |
//+------------------------------------------------------------------+
bool CLivePanel::OnDialogDragProcess(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      if(name==prefix+"Back")
        {
         CPanel *panel=(CPanel*) obj;
         color clr=(color)GETRGB(XRGB(rand()%255,rand()%255,rand()%255));
         panel.ColorBorder(clr);
         ChartRedraw();
        }
     }
   return(CDialog::OnDialogDragProcess());
  }

El controlador "OnDialogDragEnd": finalizamos el desplazamiento del panel

Restablecemos el color del fondo y los marcos con los objetos "Border", "Back" o "Client":

//+------------------------------------------------------------------+
//| End dragging the dialog box                                      |
//+------------------------------------------------------------------+
bool CLivePanel::OnDialogDragEnd(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Border")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(CONTROLS_DIALOG_COLOR_BG);
         panel.ColorBorder(CONTROLS_DIALOG_COLOR_BORDER_LIGHT);
         ChartRedraw();
        }
      if(name==prefix+"Back")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(CONTROLS_DIALOG_COLOR_BG);
         color border=(m_panel_flag) ? CONTROLS_DIALOG_COLOR_BG : CONTROLS_DIALOG_COLOR_BORDER_DARK;
         panel.ColorBorder(border);
         ChartRedraw();
        }
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG);
         wndclient.ColorBorder(CONTROLS_DIALOG_COLOR_CLIENT_BORDER);
         ChartRedraw();
        }
     }
   return(CDialog::OnDialogDragEnd());
  }

Agregamos un botón al panel y hacemos que el botón sea transparente al mover el panel

Este ejemplo se contiene en el código "Live panel and Button.mq5"

Para trabajar con el botón, primero es necesario incluir en nuestro asesor la clase del botón y agregar las macros responsables de su posicionamiento y tamaño:

#property description "El panel cambia su transparencia al desplazarse,"
#property description " pero en este caso, además, el botón añadido sigue con su color"
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#define XRGB(r,g,b)    (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define GETRGB(clr)    ((clr)&0xFFFFFF)
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT                         (11)      // indent from left (with allowance for border width)
#define INDENT_TOP                          (11)      // indent from top (with allowance for border width)
#define CONTROLS_GAP_X                      (5)       // gap by X coordinate
//--- for buttons
#define BUTTON_WIDTH                        (100)     // size by X coordinate
#define BUTTON_HEIGHT                       (20)      // size by Y coordinate
//+------------------------------------------------------------------+
//| Class CLivePanelAndButton                                        |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CLivePanelAndButton : public CAppDialog

Asimismo, para tener la posibilidad de trabajar con el botón, debemos declarar el objeto de la clase CButton:

//+------------------------------------------------------------------+
//| Class CLivePanelAndButton                                        |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CLivePanelAndButton : public CAppDialog
  {
private:
   CButton           m_button1;                       // the button object

public:
                     CLivePanelAndButton(void);

y el procedimiento de creación del botón:

   virtual bool      OnDialogDragEnd(void);

protected:
   //--- create dependent controls
   bool              CreateButton1(void);

  };

En cuanto al código "CreateButton1", después de crear el botón, no debemos olvidarnos de añadir el botón al panel creado:

//+------------------------------------------------------------------+
//| Create the "Button1" button                                      |
//+------------------------------------------------------------------+
bool CLivePanelAndButton::CreateButton1(void)
  {
//--- coordinates
   int x1=INDENT_LEFT;        // x1            = 11  pixels
   int y1=INDENT_TOP;         // y1            = 11  pixels
   int x2=x1+BUTTON_WIDTH;    // x2 = 11 + 100 = 111 pixels
   int y2=y1+BUTTON_HEIGHT;   // y2 = 11 + 20  = 32  pixels
//--- create
   if(!m_button1.Create(0,"Button1",0,x1,y1,x2,y2))
      return(false);
   if(!m_button1.Text("Button1"))
      return(false);
   if(!Add(m_button1))
      return(false);
//--- succeed
   return(true);
  }

Aquí tenemos el resultado, si añadimos el botón al panel del ejemplo de arriba:

Live panel and Button

Como podemos ver, al moverse, el panel se vuelve transparente, pero el control agregado (es decir, el botón), permanece opaco. Aquí hay varias opciones para escribir el código según su gusto: hay quien solo necesitará que el panel del fondo sea transparente cuando se mueva, y hay quien querrá eso y que además el botón se vuelva transparente al mismo tiempo. Trabajaremos con la segunda opción: hagamos que el botón sea transparente cuando mueva el panel.

Cómo hacer que el botón también sea transparente al desplazar el panel

Vamos a implementarlo con la ayuda del código "Live panel and transparent Button.mq5".

Cuando se añade al panel un elemento de control simple o compuesto, el objeto que lo crea se añade al objeto m_client_area (recordemos que el objeto m_client_area se declara en la clase CDialog). Por consiguiente, al detectar el desplazamiento del panel, debemos organizar la iteración en el ciclo por todos los objetos añadidos a m_client_area. Es cómodo hacer esto en el primer procesador "OnDialogDragStart" (comienzo del desplazamiento del panel):

//+------------------------------------------------------------------+
//| Start dragging the dialog box                                    |
//+------------------------------------------------------------------+
bool CLivePaneTransparentButton::OnDialogDragStart(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Border")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrNONE);
         ChartRedraw();
        }
      if(name==prefix+"Back")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(clrNONE);
         ChartRedraw();
        }
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(clrNONE);
         wndclient.ColorBorder(clrNONE);
         //---
         int client_total=wndclient.ControlsTotal();
         for(int j=0;j<client_total;j++)
           {
            CWnd*client_obj=wndclient.Control(j);
            string client_name=client_obj.Name();
            if(client_name=="Button1")
              {
               CButton *button=(CButton*) client_obj;
               button.ColorBackground(clrNONE);
               ChartRedraw();
              }
           }
         ChartRedraw();
        }
     }
   return(CDialog::OnDialogDragStart());
  }

Al detectar por primera vez el desplazamiento, tanto el panel como el botón se vuelven transparentes.

Nuestro segundo procesador "OnDialogDragProcess" (continuación del desplazamiento del panel) no lo vamos a cambiar. Y el tercero, "OnDialogDragEnd" (finalización del desplazamiento del panel), lo vamos a modificar, ya que debemos retornar el color para el botón:

//+------------------------------------------------------------------+
//| End dragging the dialog box                                      |
//+------------------------------------------------------------------+
bool CLivePaneTransparentButton::OnDialogDragEnd(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Border")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(CONTROLS_DIALOG_COLOR_BG);
         panel.ColorBorder(CONTROLS_DIALOG_COLOR_BORDER_LIGHT);
         ChartRedraw();
        }
      if(name==prefix+"Back")
        {
         CPanel *panel=(CPanel*) obj;
         panel.ColorBackground(CONTROLS_DIALOG_COLOR_BG);
         color border=(m_panel_flag) ? CONTROLS_DIALOG_COLOR_BG : CONTROLS_DIALOG_COLOR_BORDER_DARK;
         panel.ColorBorder(border);
         ChartRedraw();
        }
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG);
         wndclient.ColorBorder(CONTROLS_DIALOG_COLOR_CLIENT_BORDER);
         //---
         int client_total=wndclient.ControlsTotal();
         for(int j=0;j<client_total;j++)
           {
            CWnd*client_obj=wndclient.Control(j);
            string client_name=client_obj.Name();
            if(client_name=="Button1")
              {
               CButton *button=(CButton*) client_obj;
               button.ColorBackground(CONTROLS_BUTTON_COLOR_BG);
               ChartRedraw();
              }
           }
         ChartRedraw();
        }
     }
   return(CDialog::OnDialogDragEnd());
  }

Ahora, en el código "Live panel and transparent Button.mq5" se ha implementado por completo el cambio de color del panel y el botón al desplazar el panel:

Live panel and transparent Button


Añadimos dos botones al panel: controlamos el color de fondo del panel y el color del encabezado

Este ejemplo se contine en el código "Live panel and button Clicks.mq5", y ha sido creado usando como base el código anterior "Live panel and transparent Button.mq5". Solo que ahora, en lugar de los eventos de movimiento del panel, "capturaremos" los eventos de clic en los botones. Igualmente, en el panel habrá dos botones: un botón será responsable de cambiar el color del fondo del panel, y el segundo se encargará de cambiar el color de su encabezado.

Para detectar los eventos asociados a los controles agregados al panel, debemos declarar el procesador de eventosescribir el propio controlador:

//+------------------------------------------------------------------+
//| Class CLivePaneButtonClicks                                      |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CLivePaneButtonClicks : public CAppDialog
  {
private:
   CButton           m_button1;                       // the button object
   CButton           m_button2;                       // the button object

public:
                     CLivePaneButtonClicks(void);
                    ~CLivePaneButtonClicks(void);
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

protected:
   //--- create dependent controls
   bool              CreateButton1(void);
   bool              CreateButton2(void);
   //--- handlers of the dependent controls events
   void              OnClickButton1(void);
   void              OnClickButton2(void);

  };
//+------------------------------------------------------------------+
//| Event Handling                                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CLivePaneButtonClicks)
ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
ON_EVENT(ON_CLICK,m_button2,OnClickButton2)
EVENT_MAP_END(CAppDialog)
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+

El procesador no es otra cosa que el método OnEvent, anotado con las macros del bloque "Events" y del bloque "Macro of event handling map" del archivo "Defines.mqh" (leer más información en el artículo Cómo crear un panel gráfico de cualquier nivel de complejidad).

El procesador se lee así:

  • el evento OnEvent para la clase CLivePaneButtonClicks:
    • si hay un clic en el elemento de control "m_button1", llamamos al procesador "OnClickButton1"
    • si hay un clic en el elemento de control "m_button2", llamamos al procesador "OnClickButton2"
  • retorno del evento OnEvent para la clase padre CAppDialog

Los controladores "OnClickButton1" y "OnClickButton2"

En ambos procesadores de eventos se ha organizado la iteración por todos los objetos de los que consta el panel (estos se enumeran en el punto Cómo se hace) en este caso, por todos los objetos del panel objeto "ExtDialog". Como resultado, se llama el método CWndContainer::ControlsTotal()

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CLivePaneButtonClicks::OnClickButton1(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         color clr=(color)GETRGB(XRGB(rand()%255,rand()%255,rand()%255));
         wndclient.ColorBackground(clr);
         ChartRedraw();
         return;
        }
     }
  }
//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CLivePaneButtonClicks::OnClickButton2(void)
  {
   string prefix=Name();
   int total=ExtDialog.ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=ExtDialog.Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Caption")
        {
         CEdit *edit=(CEdit*) obj;
         color clr=(color)GETRGB(XRGB(rand()%255,rand()%255,rand()%255));
         edit.ColorBackground(clr);
         ChartRedraw();
         return;
        }
     }
  }

En el procesador "OnClickButton1" buscamos el objeto-área de cliente con el nombre prefix+"Client" (se tratará de un objeto de la clase CWndClient), mientras que en el procesador "OnClickButton2" será el objeto-encabezado con el nombre prefix+"Caption" (se tratará de un objeto de la clase CEdit). En ambos casos, seleccionamos aleatoriamente el color de fondo para los objetos encontrados. Así se ve el resultado:

Live panel and button Clicks


Heredamos de CAppDialog

El esquema de implementación se distingue del aplicado en los ejemplos de la biblioteca estándar (\MQL5\Experts\Examples\Controls\ y \MQL5\Indicators\Examples\Panels\SimplePanel\), y precisamente en lo siguiente: en el archivo de inclusión "MyAppDialog.mqh" se crea la clase "CMyAppDialog", heredada de CAppDialog. En la clase se implementan solo los tres métodos de control del color de la forma y el encabezado. En ella no hay métodos para crear elementos de control añadidos, el procesador OnEvent y los procesadores de clic para los botones (controles agregados). 

Los objetos de la clase CButton (se han añadido elementos de control, dos botones) se crean en el archivo de inicio "MyAppWindow.mq5". Asimismo, en el archivo "MyAppWindow.mq5", en el procesador OnChartEvent, se depuran los eventos de clic en los botones y se llaman con los métodos de cambio de color.

MyAppDialog.mqh

En nuestra clase, agregamos tres métodos: 

  • CMyAppDialog::ColorBackground — establecer el color del fondo,
  • void CMyAppDialog::ColorCaption — establecer el color del encabezado,
  • color CMyAppDialog::ColorCaption — obtener el color del encabezado.

El algoritmo para acceder a las propiedades de los objetos es análogo a los códigos anteriores: en el ciclo, se itera por todos los objetos que componen el panel y se comparan los nombres del objeto. Falta un método más: obtener el color de fondo. Pero esto no puede hacerse con medios simples.

//+------------------------------------------------------------------+
//|                                                  MyAppDialog.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property description "Clase CMyAppDialog, heredada de CAppDialog"
#property description "Añadidos los métodos para establecer el color del fondo y el encabezado"
#include <Controls\Dialog.mqh>
//+------------------------------------------------------------------+
//| Class CLivePanelTwoButtons                                       |
//| Usage: main dialog of the Controls application                   |
//+------------------------------------------------------------------+
class CMyAppDialog : public CAppDialog
  {
public:
   void              ColorBackground(const color clr);
   color             ColorCaption(void);
   void              ColorCaption(const color clr);
//--- constructor y destructor   
public:
                     CMyAppDialog(void){};
                    ~CMyAppDialog(void){};
  };
//+------------------------------------------------------------------+
//| Establece el color del fondo                                     |
//+------------------------------------------------------------------+
void CMyAppDialog::ColorBackground(const color clr)
  {
   string prefix=Name();
   int total=ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Client")
        {
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(clr);
         ChartRedraw();
         return;
        }
     }
//---     
  } 
//+------------------------------------------------------------------+
//| Establece el color del encabezado                                |
//+------------------------------------------------------------------+
void CMyAppDialog::ColorCaption(const color clr)
  {
   string prefix=Name();
   int total=ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Caption")
        {
         CEdit *edit=(CEdit*) obj;
         edit.ColorBackground(clr);
         ChartRedraw();
         return;
        }
     }
//---     
  }  
//+------------------------------------------------------------------+
//| Obtiene el color del encabezado                                  |
//+------------------------------------------------------------------+
color CMyAppDialog::ColorCaption(void)
  {
   string prefix=Name();
   int total=ControlsTotal();
   color clr=clrNONE;
   for(int i=0;i<total;i++)
     {
      CWnd*obj=Control(i);
      string name=obj.Name();
      //---
      if(name==prefix+"Caption")
        {
         CEdit *edit=(CEdit*) obj;
         clr=edit.ColorBackground(clr);
         return clr;
        }
     }
//--- retornamos el color
   return clr;     
  }  
//+------------------------------------------------------------------+


MyAppWindow.mq5

 "MyAppWindow.mq5" — archivo de inicio. En este archivo se declaran las macros XRGB y GETRGB para generar el color. En OnInit se crea el panel, se añaden los botones y se inicia el funcionamiento del propio panel.

//+------------------------------------------------------------------+
//|                                                  MyAppWindow.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property description "Aplicación MyAppWindow basada en la clase CMyAppDialog"
#property description "Añadidos los botones para establecer el color del fondo y el encabezado"
#include "MyAppDialog.mqh"
#include <Controls\Button.mqh>
//--- macros para trabajar con el color
#define XRGB(r,g,b)    (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b))
#define GETRGB(clr)    ((clr)&0xFFFFFF)
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
//--- indents and gaps
#define INDENT_LEFT                         (11)      // indent from left (with allowance for border width)
#define INDENT_TOP                          (11)      // indent from top (with allowance for border width)
#define CONTROLS_GAP_X                      (5)       // gap by X coordinate
//--- for buttons
#define BUTTON_WIDTH                        (100)     // size by X coordinate
#define BUTTON_HEIGHT                       (20)      // size by Y coordinate
//---
CMyAppDialog         AppWindow;
CButton              m_button1;                       // the button object
CButton              m_button2;                       // the button object
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create application dialog
   if(!AppWindow.Create(0,"CMyAppDialog: change Back and Caption colors",0,40,40,380,344))
      return(INIT_FAILED);
//--- create dependent controls
   if(!CreateBackButton())
      return(false);
   if(!CreateCaptionButton())
      return(false);
//--- run application
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
//--- destroy dialog
   AppWindow.Destroy(reason);
  }
//+------------------------------------------------------------------+
//| Expert chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event ID  
                  const long& lparam,   // event parameter of the long type
                  const double& dparam, // event parameter of the double type
                  const string& sparam) // event parameter of the string type
  {
//--- primero procesamos los eventos de los botones 
   if((StringFind(sparam,"Back")!=-1) && id==(CHARTEVENT_OBJECT_CLICK))
     {
      Print(__FUNCSIG__," sparam=",sparam);
      AppWindow.ColorBackground(GetRandomColor());
     }
   if((StringFind(sparam,"Caption")!=-1) && id==(CHARTEVENT_OBJECT_CLICK))
     {
      Print(__FUNCSIG__," sparam=",sparam);
      AppWindow.ColorCaption(GetRandomColor());
     }
//--- ahora procesamos los demás eventos con el método de clase CMyAppDialog   
   AppWindow.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+
//| Create the "Button1" button                                      |
//+------------------------------------------------------------------+
bool CreateBackButton(void)
  {
//--- coordinates
   int x1=INDENT_LEFT;        // x1            = 11  pixels
   int y1=INDENT_TOP;         // y1            = 11  pixels
   int x2=x1+BUTTON_WIDTH;    // x2 = 11 + 100 = 111 pixels
   int y2=y1+BUTTON_HEIGHT;   // y2 = 11 + 20  = 32  pixels
//--- create
   if(!m_button1.Create(0,"Back",0,x1,y1,x2,y2))
      return(false);
   if(!m_button1.Text("Back"))
      return(false);
   if(!AppWindow.Add(m_button1))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Create the "Button2"                                             |
//+------------------------------------------------------------------+
bool CreateCaptionButton(void)
  {
//--- coordinates
   int x1=INDENT_LEFT+2*(BUTTON_WIDTH+CONTROLS_GAP_X);   // x1 = 11  + 2 * (100 + 5) = 221 pixels
   int y1=INDENT_TOP;                                    // y1                       = 11  pixels
   int x2=x1+BUTTON_WIDTH;                               // x2 = 221 + 100           = 321 pixels
   int y2=y1+BUTTON_HEIGHT;                              // y2 = 11  + 20            = 31  pixels
//--- create
   if(!m_button2.Create(0,"Caption",0,x1,y1,x2,y2))
      return(false);
   if(!m_button2.Text("Caption"))
      return(false);
   if(!AppWindow.Add(m_button2))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Obtiene el color de forma aleatoria                              |
//+------------------------------------------------------------------+
color GetRandomColor()
  {
   color clr=(color)GETRGB(XRGB(rand()%255,rand()%255,rand()%255));
   return clr;
  }
//+------------------------------------------------------------------+

Asimismo, en el archivo principal se encuentra el procesador de eventos OnChartEvent. Este reenvía todos los eventos al panel, pero al detectar el evento de clic de uno de los botones (CHARTEVENT_OBJECT_CLICK) llama los métodos de clase del panel (AppWindow.ColorBackground o AppWindow.ColorCaption).

Así funciona la conexión de los dos archivos: el mq5 principal iniciable y el archivo mqh de inclusión, en el que se encuentra la clase del panel.


Heredamos de CWndClient

En este ejemplo analizaremos la herencia de CWndClient: crearemos un objeto de la clase "CWndClient". Este objeto contendrá dicha funcionalidad:

  • la creación del objeto "CMyWndClient" — área de cliente del panel;
  • la creación del objeto de adición de dos botones al área de cliente;
  • el procesador de clics sobre los botones añadidos (cambio de color del fondo del área de cliente y el color del encabezado del panel);
  • además, para el área de cliente se activará el desplazmaiento horizontal (recuerde que la clase CWndClient supone un elemento combinado de control "Área de cliente" y es una clase básica para crear áreas con franjas de scrolling);
  • por consiguiente, serán también procesadores de clics de desplazamiento horizontal (desplazamiento de los botones añadidos por el área de cliente).

Vamos a detenernos con más detalle en los archivos MyWndClient.mq5 y MyWndClient.mqh.

MyWndClient.mq5

La diferencia respecto a los ejemplos de la biblioteca estándar (\MQL5\Experts\Examples\Controls\ y \MQL5\Indicators\Examples\Panels\SimplePanel\) consiste en que en el archivo de inclusión se encuentra la clase heredada de la clase CWndClient 10, el área de cliente. El ciclo completo de creación de un panel tiene el aspecto siguiente.

  1. Se crea el panel (el objeto AppWindow de la clase CAppDialog llama el método Create).
  2. Se crea nuestra área de cliente (el objeto ClientArea de la clase CMyWndClient, del archivo de inclusión MyWndClient.mqh llama el método Create).
  3. El área de cliente creada se añade al panel (en esencia, se encuentra sobre el área de cliente del panel).
CAppDialog           AppWindow;
CMyWndClient         ClientArea;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create application dialog
   bool result_create=false;
   if(!InpTwoButtonsVisible)
     {
      //--- after creation of the panel, one button will be visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,360,344);
     }
   else
     {
      //--- after creation of the panel, will two buttons are visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,420,344);
     }
   if(!result_create)
      return(INIT_FAILED);
//--- create the panel
   PrintFormat("Application Rect: Height=%d  Width=%d",AppWindow.Rect().Height(),AppWindow.Rect().Width());
   CRect inner_rect=ClientArea.GetClientRect(GetPointer(AppWindow));
   PrintFormat("Client Area: Height=%d  Width=%d",inner_rect.Height(),inner_rect.Width());
   ClientArea.Create(0,"MyWndClient",0,0,0,inner_rect.Width(),inner_rect.Height());
   AppWindow.Add(ClientArea);
//--- establecemos el propietario
   ClientArea.SetOwner(GetPointer(AppWindow));
//--- ocultar lo invisible
   ClientArea.HideInvisble(HideInvisble);
//--- run application
   AppWindow.Run();
//--- succeed
   return(INIT_SUCCEEDED);
  }

En el archivo de inclusión hay dos parámetros de entrada:

  • anchura del panel — crear un panel de anchura normal o un panel ancho;
  • ocultar lo invisible — representar u ocultar los elementos de control ocultos.

Al crear el panel, se tiene en cuenta solo un parámetro de entrada, la "anchura del panel". Así creamos el panel de anchura normal:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create application dialog
   bool result_create=false;
   if(!InpTwoButtonsVisible)
     {
      //--- after creation of the panel, one button will be visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,360,344);
     }
   else
     {
      //--- after creation of the panel, will two buttons are visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,420,344);
     }
   if(!result_create)
      return(INIT_FAILED);
//--- create the panel

MyWndClient normal width panel

aquí tenemos un panel ancho:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create application dialog
   bool result_create=false;
   if(!InpTwoButtonsVisible)
     {
      //--- after creation of the panel, one button will be visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,360,344);
     }
   else
     {
      //--- after creation of the panel, will two buttons are visible
      result_create=AppWindow.Create(0,"CAppDialog with CMyWndClient",0,40,40,420,344);
     }
   if(!result_create)
      return(INIT_FAILED);
//--- create the panel

MyWndClient wide panel

El código de creación se diferencia solo en la anchura indicada (360 y 420); al crear los dos botones, esta anchura no se tiene en cuenta. Compare las dos últimas imágenes. Ahora, colóquelas una sobre otra:

CMyWndClient imposition

Vemos que el botón "Caption" está ligeramente fuera del borde del panel de anchura normal, más allá del borde del área de cliente. Cuando el elemento de control agregado sale más allá de los límites, se oculta del usuario a la fuerza (pero no se elimina ni se destruye). El procedimiento para determinar si se oculta el elemento de control comienza al agregar este al área de cliente, al llamar el método CWndContainer::Add. En nuestro ejemplo, el método Add se llama en AddButton2:

//+------------------------------------------------------------------+
//| Create the "Button2"                                             |
//+------------------------------------------------------------------+
bool CMyWndClient::AddButton2(void)
  {
...
   if(!Add(m_button2))
     {
      Print("Add(m_button2) --> false");
      return(false);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Add control to the group (by reference)                          |
//+------------------------------------------------------------------+
bool CWndContainer::Add(CWnd &control)
  {
//--- add by pointer
   return(Add((CWnd*)GetPointer(control)));
  }

y sucesivamente se llama lo más importante: precisamente aquí se define si ocultar o no el elemento de control

//+------------------------------------------------------------------+
//| Add control to the group (by pointer)                            |
//+------------------------------------------------------------------+
bool CWndContainer::Add(CWnd *control)
  {
//--- check of pointer
   if(control==NULL)
      return(false);
//--- correct the coordinates of added control
   control.Shift(Left(),Top());
 //--- "projecting" the group flag "visibility" to the added element
   if(IS_VISIBLE && control.IsVisible())
     {
      //--- element will be "visible" only if the group is "visible" and the element is completely "within" this group
      control.Visible(Contains(control));
     }
   else
      control.Hide();
//--- "projecting" the group flag "enabled" to the added element
   if(IS_ENABLED)
      control.Enable();
   else
      control.Disable();
//--- adding
   return(m_controls.Add(control));
  }

La configuración de la visibilidad del objeto se crea SOLO EN EL MOMENTO EN QUE SE AGREGA el elemento de control al área de cliente. Este es precisamente el inconveniente que puede aparecer después de minimizar y desplegar el panel.

Ejemplo: ambos parámetros de entrada se establecen como "false", después minimizamos y desplegamos el panel. Como resultado, después de crear el panel, se crea el botón "Caption", pero se oculta visualmente (ya que el botón está fuera del área del cliente, se oculta al agregarse al área del cliente). Pero una vez minimizado y desplegado el panel, la visibilidad de los elementos añadidos ya no se verifica y, por lo tanto, el botón Caption estará visible:

CMyWndClient button caption

En este archivo se encuentra una clase heredada de la clase CWndClient, el área de cliente. En dicho archivo se contiene toda la funcionalidad:

  • para crear nuestra área de cliente, 
  • para crear y añadir elementos de control, 
  • para procesar el evento de despliegue del panel
  • para procesar los eventos de clic en la barra de desplazamiento horizontal
  • para procesar eventos de clic en los botones: cambio del color del fondo del área de cliente y el color del encabezado.

Desplazamiento horizontal y elementos de control ocultos

Puesto que la clase del panel es heredada de la clase CWndClient, y la clase CWndClient constituye el elemento combinado de control "Área de cliente" y es una clase básica para crear áreas con barras de desplazamiento, incluimos en nuestra área de cliente una barra de desplazamiento vertical:

//+------------------------------------------------------------------+
//| Crear el panel                                                   |
//+------------------------------------------------------------------+
bool CMyWndClient::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//---
   if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- enable horizontal scrollbar
   if(!HScrolled(true))
      return(false);
   m_scroll_h.MaxPos(5);
   m_scroll_h.CurrPos(5);
   Print("CurrPos: ",m_scroll_h.CurrPos());
   if(!AddButton1())

Para que se pueda mover la barra de desplazamiento, indicamos su número de gradación: el valor de la posición máxima, y colocamos instantáneamente la barra de posicionamiento en su posición más a la derecha

El desplazamiento horizontal también se usa para depurar el evento de despliegue del panel, para ello, "captamos" el evento ON_SHOW para el objeto m_scroll_h y llamamos el procesador OnShowScrollH:

//+------------------------------------------------------------------+
//| Event Handling                                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CMyWndClient)
ON_EVENT(ON_CLICK,m_button1,OnClickButton1)
ON_EVENT(ON_CLICK,m_button2,OnClickButton2)
ON_EVENT(ON_SHOW,m_scroll_h,OnShowScrollH)
EVENT_MAP_END(CWndClient)

EVENT_MAP_BEGIN no es otra cosa que el método OnEvent, anotado por macros desde el bloque "Events" y desde el bloque "Macro of event handling map" del archivo"Defines.mqh" (leer más información en el artículo Cómo crear un panel gráfico de cualquier nivel de complejidad).

En el procesador OnShowScrollH comprobamos el valor de la bandera interior m_hide_invisble (esta bandera adopta el valor del parámtro de entrada "ocultar lo invisible" del archivo MyWndClient.mq5 a través del método CMyWndClient::HideInvisble), y si no es necesario ocultar los elementos, simplemente salimos del procedimiento:

//+------------------------------------------------------------------+
//| Ha aparecido el desplazamiento ocultamos/representamos           |
//+------------------------------------------------------------------+
void CMyWndClient::OnShowScrollH(void)
  {
   if(!m_hide_invisble)
      return;
   int total=CWndClient::ControlsTotal();
   for(int i=0;i<total;i++)
     {
      CWnd*obj=Control(i);
      string name=obj.Name();
      //---
      if(StringFind(name,"Button")!=-1)
        {
         CButton *button=(CButton*)obj;
         button.Visible(Contains(GetPointer(button)));
         ChartRedraw();
        }
     }
  }

Si desea ocultar los elementos invisibles, buscamos los objetos que contengan en su nombre "Button" en un ciclo por todos los objetos del área del cliente, y comprobamos/asignamos forzosamente la visibilidad.

Clics de desplazamiento horizontal

Para los clics en el desplazamiento horizontal, estableceremos la posibilidad de mover los dos botones añadidos en nuestra área de cliente. Para ello, redefinimos los procesadores OnScrollLineRightOnScrollLineLeft: los procesadores de los clics de los bonotes de desplazamiento horizontal. Si ha habido un clic en el botón derecho de desplazamiento horizontal, movemos los botones (método ShiftButton) en el salto m_scroll_size. Si ha habido un clic en el botón izquierdo, movemos los botones en un salto "-m_scroll_size", es decir, establecemos un desplazamiento negativo:

//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
bool CMyWndClient::OnScrollLineRight(void)
  {
   Print(__FUNCTION__);
   ShiftButton(GetPointer(m_button1),m_scroll_size);
   ShiftButton(GetPointer(m_button2),m_scroll_size);
   return(true);
  }
//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
bool CMyWndClient::OnScrollLineLeft(void)
  {
   Print(__FUNCTION__);
   ShiftButton(GetPointer(m_button1),-m_scroll_size);
   ShiftButton(GetPointer(m_button2),-m_scroll_size);
   return(true);
  }
En el método CMyWndClient::ShiftButton obtenemos el objeto con las coordenadas del botón, establecemos el desplazamiento de las coordenadas, desplazamos el botón y comprobamos/configuramos forzosamente la visibilidad del mismo:

//+-------------------------------------------------------------------------------+
//| Desplazamiento del botón a la izquierda o la derecha (dependiendo de shift)   |
//+-------------------------------------------------------------------------------+
bool CMyWndClient::ShiftButton(CButton *button,const int shift)
  {
   Print(__FUNCTION__);
//--- desplazamos el botón
   CRect rect=button.Rect();
   rect.Move(rect.left+shift,rect.top);
   button.Move(rect.left,rect.top);
   button.Visible(Contains(GetPointer(button)));
   return(true);
  }

Este es el aspecto que tiene (no olvide poner el parámetro "ocultar lo invisible" en el valor true):

CMyWndClient move buttons



Nuevos proyectos. ¿Cómo pueden ayudarnos en el estudio de los paneles?

Para escribir algo, siempre hay que estudiar el código. En el caso de la creación de paneles, estudiar las clases puede consumir mucho tiempo. Esto se debe principalmente al hecho de que no hay una representación visual de la estructura de las clases. Y al mismo tiempo es muy difícil entender qué clases de la biblioteca estándar han estado involucradas en la creación de los paneles. 

Por fortuna, hace poco se presentaron los Nuevos Proyectos en el editor MetaEditor.

Un proyecto es un archivo aparte con la extensión "MQPROJ" que almacena la configuración del programa, los parámetros de compilación y la información sobre todos los archivos utilizados. Para trabajar cómodamente con el proyecto, disponemos de una pestaña aparte en el navegador. En ella se muestran por categorías todos los archivos utilizados: de inclusión, de recursos, de encabezado, etcétera.

Echemos un vistazo a la descripción de la pestaña creada por separado. "En ella se muestran por categorías todos los archivos utilizados: de inclusión, de recursos, encabezado, etcétera."! ¡Y esto es justo lo que necesitamos!

Vamos a tratar de crear un proyecto a partir del último archivo "Live panel and button Clicks.mq5". Para lograrlo, hacemos clic con el botón derecho en el archivo "Live panel and button Clicks.mq5" y en el menú desplegable seleccionamos el punto "Nuevo proyecto del archivo fuente":

New Project from Source

Como resultado, se creará un nuevo proyecto, y en la ventana "Navegador" se abrirá la pestaña "Proyecto", en la que podremos ver todos los archivos utilizados:

New Project

y "Wnd.mqh" (en ella está la clase CWnd), y "Dialog.mqh (en ella están las clases CDialog y CAppDialog), y Button.mhq (clase CButton). Desde esta pestaña, es conveniente ir a la clase requerida. Es mucho más cómodo que navegar a través de las pestañas del editor MetaEditor. Por ejemplo, tengo un pequeño "zoológico" con una amplia variedad de archivos. Ir desde allí, por ejemplo, a Dialog.mqh a través de la búsqueda en las pestañas, es problemático:

Many windows

Conclusión

El artículo muestra una forma bastante inusual de acceder a las propiedades "Color de fondo", "Color del marco" y "Color del encabezado" para los elementos del panel. Nosotros no habíamos encontrado este método antes. El truco radica en saber que todos los elementos del panel se heredan de la clase padre CWnd, por lo que el objeto (y por lo tanto la clase del panel creado), es un contenedor para todos los elementos de control. Esto implica que podemos recorrer todos los controles y obtener/establecer las propiedades necesarias.

Nombre del archivo Comentarios
 Live panel.mq5  Panel sin elementos de control agregados. Al arrastrarlo se vuelve transparente
 Live panel and Button.mq5  Panel del botón añadido. Al arrastrar el panel se vuelve transparente, y el botón permanece con su color
 Live panel and transparent Button.mq5  Panel del botón añadido. Durante el arrastre, tanto el panel como el botón se vuelven transparentes
 Live panel and button Clicks.mq5  Panel con dos botones. Procesamiento de clics en los botones: se genera un color de fondo para el panel y el encabezado
 MyAppWindow.mq5 y MyAppDialog.mqh  Ejemplo de creación del panel mediante herencia desde CAppDialog
 MyWndClient.mq5 y MyWndClient.mqh  Ejemplo de creación de un panel heredando de CWndClient: de la clase del área de cliente

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/4575

Archivos adjuntos |
MQL5.zip (18.86 KB)
Cómo transferir los cálculos de cualquier indicador al código de un asesor experto Cómo transferir los cálculos de cualquier indicador al código de un asesor experto
Las razones para transferir el código de un indicador a un asesor pueden ser muchas. ¿Cómo valorar las ventajas y desventajas de este enfoque? En este artículo ofrecemos una tecnología para transferir el código del indicador a un asesor. Asimismo, se han realizado varios experimentos para evaluar la velocidad de funcionamiento del asesor.
Neuroredes profundas (Parte VI). Conjunto de clasificadores de redes neuronales: bagging Neuroredes profundas (Parte VI). Conjunto de clasificadores de redes neuronales: bagging
Vamos a ver los métodos de construcción y entrenamiento de conjuntos de redes neuronales con la estructura bagging. También vamos a definir las peculiaridades de la optimización de los hiperparámetros de los clasificadores de redes neuronales individuales que componen el conjunto. Asimismo, compararemos la calidad de la red neuronal optimizada obtenida en el artículo anterior de la serie, y el conjunto creado de redes neuronales. Para finalizar, analizaremos las diferentes opciones para mejorar aún más la calidad de clasificación del conjunto.
Cómo analizar las transacciones de la Señal elegida en el gráfico Cómo analizar las transacciones de la Señal elegida en el gráfico
El servicio de señales comerciales se desarrolla a pasos agigantados. A la hora de confiar nuestro dinero a un proveedor de señales, querríamos minimizar el riesgo de pérdida del depósito. Pero, ¿cómo aclararse entre semejante cantidad de señales? ¿Cómo encontrar precisamente aquella que nos reportará beneficios? En este artículo vamos a crear un método para analizar visualmente la historia de transacciones de las señales comrciales en el gráfico del instrumento.
Simulación de patrones de parejas de divisas: Uso y perspectivas para el trading real. Parte IV Simulación de patrones de parejas de divisas: Uso y perspectivas para el trading real. Parte IV
Con este artículo terminamos la serie sobre el trading con las cestas de parejas de divisas. En este artículo, vamos a simular el último patrón y discutir sobre el uso de la metodología completa en el trading real. Han sido consideradas la entrada y la salida del mercado, la búsqueda y el análisis de los patrones, y la aplicación de los indicadores combinados.