Trabajando con los precios en la biblioteca DoEasy (Parte 59): Objeto para almacenar los datos de un tick

2 febrero 2021, 17:12
Artyom Trishkin
0
223

Contenido


Concepto

En este artículo, empezaremos a desarrollar la funcionalidad de la biblioteca para trabajar con los datos de ticks.

El concepto del almacenamiento y el uso de los datos de ticks será muy parecido al concepto del almacenamiento de los datos de series temporales, donde la unidad mínima de los datos es una barra. Los objetos de barras se almacenan en las listas que pertenecen a los marcos temporales correspondientes, que a su vez se guardan en las listas pertenecientes a los símbolos.

En el concepto del almacenamiento de los datos de ticks, la unidad mínima del volumen será representada por los valores de la estructura del precio en un tick. Estos valores se describen a través de la estructura para el guardado de las últimas cotizaciones del símbolo MqlTick. El objeto para almacenar estos valores va a contener unas propiedades adicionales: spread (diferencia entre los precios Ask y Bid) y símbolo cuyos datos de un tick se describen por el objeto.

Para cada uno de los símbolos van a crearse sus propias listas de objetos con los datos de ticks (para una estructurización más conveniente de las listas). Naturalmente, cada una de las listas de objetos de los datos de ticks va a actualizarse automáticamente. La lista va a recibir los datos nuevos de los ticks que llegan, y el tamaño de las listas va a mantenerse según el volumen definido por el usuario.

El concepto del almacenamiento de los datos en la biblioteca implica la búsqueda y ordenación según cualquiera de las propiedades de los objetos almacenados en las listas. Eso permite obtener los datos requeridos para su posterior uso o ejecución de estudios analíticos. Y esto significa que los datos de ticks también tendrán esta posibilidad. Eso permite al usuario analizar rápidamente los flujos de ticks de los datos para su seguimiento, por ejemplo, si se trata de algunos cambios en el carácter de su llegada, o para la búsqueda de patrones establecidos, etc.


Preparando los datos

Igual como para cualquier objeto de la biblioteca, tenemos que añadir los mensajes de texto para visualizar la descripción de sus parámetros y crear enumeraciones de las propiedades del objeto, según las cuales podremos buscarlos en las listas u ordenar objetos según estas propiedades.

Añadimos los índices de nuevos mensajes al archivo \MQL5\Include\DoEasy\Data.mqh:

//--- CSeriesDataInd
   MSG_LIB_TEXT_METHOD_NOT_FOR_INDICATORS,            // The method is not intended to handle indicator programs
   MSG_LIB_TEXT_IND_DATA_FAILED_GET_SERIES_DATA,      // Failed to get indicator data timeseries
   MSG_LIB_TEXT_IND_DATA_FAILED_GET_CURRENT_DATA,     // Failed to get current data of indicator buffer
   MSG_LIB_SYS_FAILED_CREATE_IND_DATA_OBJ,            // Failed to create indicator data object
   MSG_LIB_TEXT_IND_DATA_FAILED_ADD_TO_LIST,          // Failed to add indicator data object to list
   
//--- CTick
   MSG_TICK_TEXT_TICK,                                // Tick
   MSG_TICK_TIME_MSC,                                 // Time of the last update of prices in milliseconds
   MSG_TICK_TIME,                                     // Time of the last update of prices
   MSG_TICK_VOLUME,                                   // Volume for the current Last price
   MSG_TICK_FLAGS,                                    // Flags
   MSG_TICK_VOLUME_REAL,                              // Volume for the current Last price with greater accuracy
   MSG_TICK_SPREAD,                                   // Spread
   MSG_LIB_TEXT_TICK_CHANGED_DATA,                    // Changed data on tick:
   MSG_LIB_TEXT_TICK_FLAG_BID,                        // Bid price change
   MSG_LIB_TEXT_TICK_FLAG_ASK,                        // Ask price change
   MSG_LIB_TEXT_TICK_FLAG_LAST,                       // Last deal price change
   MSG_LIB_TEXT_TICK_FLAG_VOLUME,                     // Volume change

  };
//+------------------------------------------------------------------+

así como, añadimos los textos de los mensajes correspondientes a los índices nuevamente añadidos:

//--- CSeriesDataInd
   {"Метод не предназначен для работы с программами-индикаторами","The method is not intended for working with indicator programs"},
   {"Не удалось получить таймсерию индикаторных данных","Failed to get indicator data timeseries"},
   {"Не удалось получить текущие данные буфера индикатора","Failed to get the current data of the indicator buffer"},
   {"Не удалось создать объект индикаторных данных","Failed to create indicator data object"},
   {"Не удалось добавить объект индикаторных данных в список","Failed to add indicator data object to the list"},
   
//--- CTick
   {"Тик","Tick"},
   {"Время последнего обновления цен в миллисекундах","Last price update time in milliseconds"},
   {"Время последнего обновления цен","Last price update time"},
   {"Объем для текущей цены Last","Volume for the current Last price"},
   {"Флаги","Flags"},
   {"Объем для текущей цены Last c повышенной точностью","Volume for the current \"Last\" price with increased accuracy"},
   {"Спред","Spread"},
   {"Изменённые данные на тике:","Changed data on a tick:"},
   {"Изменение цены Bid","Bid price change"},
   {"Изменение цены Ask","Ask price change"},
   {"Изменение цены последней сделки","Last price change"},
   {"Изменение объема","Volume change"},
   
  };
//+---------------------------------------------------------------------+


Añadimos al archivo \MQL5\Include\DoEasy\Defines.mqh las enumeraciones para especificar las propiedades de tipo entero, real y string del objeto de los datos de ticks:

//+------------------------------------------------------------------+
//| Data for working with tick data                                  |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Integer tick properties                                          |
//+------------------------------------------------------------------+
enum ENUM_TICK_PROP_INTEGER
  {
   TICK_PROP_TIME_MSC = 0,                                  // Time of the last price update in milliseconds
   TICK_PROP_TIME,                                          // Time of the last update
   TICK_PROP_VOLUME,                                        // Volume for the current Last price
   TICK_PROP_FLAGS,                                         // Tick flags
  }; 
#define TICK_PROP_INTEGER_TOTAL (4)                         // Total number of tick integer properties
#define TICK_PROP_INTEGER_SKIP  (0)                         // Number of tick properties not used in sorting
//+------------------------------------------------------------------+
//| Real tick properties                                             |
//+------------------------------------------------------------------+
enum ENUM_TICK_PROP_DOUBLE
  {
   TICK_PROP_BID = TICK_PROP_INTEGER_TOTAL,                 // Tick Bid price
   TICK_PROP_ASK,                                           // Tick Ask price
   TICK_PROP_LAST,                                          // Current price of the last trade (Last)
   TICK_PROP_VOLUME_REAL,                                   // Volume for the current Last price with greater accuracy
   TICK_PROP_SPREAD,                                        // Tick spread (Ask - Bid)
  }; 
#define TICK_PROP_DOUBLE_TOTAL  (5)                         // Total number of real tick properties
#define TICK_PROP_DOUBLE_SKIP   (0)                         // Number of tick properties not used in sorting
//+------------------------------------------------------------------+
//| String tick properties                                           |
//+------------------------------------------------------------------+
enum ENUM_TICK_PROP_STRING
  {
   TICK_PROP_SYMBOL = (TICK_PROP_INTEGER_TOTAL+TICK_PROP_DOUBLE_TOTAL), // Tick symbol
  };
#define TICK_PROP_STRING_TOTAL  (1)                         // Total number of string tick properties
//+------------------------------------------------------------------+

Indicamos para cada una de las enumeraciones el número total de las propiedades utilizadas y no utilizadas en la ordenación.

Para tener la posibilidad de buscar y ordenar según las propiedades especificadas, vamos a añadir una enumeración más, en la que se indicarán unos posibles criterios de la ordenación de los datos de ticks:

//+------------------------------------------------------------------+
//| Possible tick sorting criteria                                   |
//+------------------------------------------------------------------+
#define FIRST_TICK_DBL_PROP          (TICK_PROP_INTEGER_TOTAL-TICK_PROP_INTEGER_SKIP)
#define FIRST_TICK_STR_PROP          (TICK_PROP_INTEGER_TOTAL-TICK_PROP_INTEGER_SKIP+TICK_PROP_DOUBLE_TOTAL-TICK_PROP_DOUBLE_SKIP)
enum ENUM_SORT_TICK_MODE
  {
//--- Sort by integer properties
   SORT_BY_TICK_TIME_MSC = 0,                               // Sort by the time of the last price update in milliseconds
   SORT_BY_TICK_TIM,                                        // Sort by the time of the last price update
   SORT_BY_TICK_VOLUME,                                     // Sort by volume for the current Last price
   SORT_BY_TICK_FLAGS,                                      // Sort by tick flags
//--- Sort by real properties
   SORT_BY_TICK_BID = FIRST_TICK_DBL_PROP,                  // Sort by tick Bid price
   SORT_BY_TICK_ASK,                                        // Sort by tick Ask price
   SORT_BY_TICK_LAST,                                       // Sort by current price of the last trade (Last)
   SORT_BY_TICK_VOLUME_REAL,                                // Sort by volume for the current Last price with greater accuracy
   SORT_BY_TICK_SPREAD,                                     // Sort by tick spread
//--- Sort by string properties
   SORT_BY_TICK_SYMBOL = FIRST_TICK_STR_PROP,               // Sort by tick symbol
  };
//+------------------------------------------------------------------+


Antes, ya creamos el objeto «Nuevo tick» en el artículo 38 que permitía monitorear la llegada de un tick nuevo para el símbolo especificado.
El objeto se ubica en la carpeta \MQL5\Include\DoEasy\Objects\Ticks\ del directorio de la biblioteca, en el archivo NewTickObj.mqh.
Vamos a mejorar la clase del objeto de tal manera que haya posibilidad de transmitir al método de definición del símbolo el valor NULL (o una cadena vacía) para indicar el símbolo actual para el objeto:

//--- Set a symbol
   void              SetSymbol(const string symbol)   { this.m_symbol=(symbol==NULL || symbol=="" ? ::Symbol() : symbol);  }

En la lista de inicialización del constructor de la clase, vamos a establecer el valor false para la variable m_new_tick que almacena la bandera del tick nuevo:

//+------------------------------------------------------------------+
//| Parametric constructor CNewTickObj                               |
//+------------------------------------------------------------------+
CNewTickObj::CNewTickObj(const string symbol) : m_symbol(symbol),m_new_tick(false)
  {
//--- Reset the structures of the new and previous ticks
   ::ZeroMemory(this.m_tick);
   ::ZeroMemory(this.m_tick_prev);
//--- If managed to get the current prices to the tick structure,
//--- copy data of the obtained tick to the previous tick data and reset the first launch flag
  if(::SymbolInfoTick(this.m_symbol,this.m_tick))
     { 
      this.m_tick_prev=this.m_tick;
      this.m_first_start=false;
     }
  }
//+------------------------------------------------------------------+

Antes, esta variable no se inicializaba con el valor inicial en ninguna parte, lo cual no es correcto.


Clase del objeto de datos del tick

En la carpeta donde se ubica la clase del objeto «Nuevo tick» \MQL5\Include\DoEasy\Objects\Ticks\ vamos a crear el nuevo archivo de la clase del objeto de los datos de tick DataTick.mqh.

El objeto no va a representar nada nuevo para las clases de la biblioteca: todo será del tipo estándar. Vamos a analizar el cuerpo de la clase:

//+------------------------------------------------------------------+
//|                                                     DataTick.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/es/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/es/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\BaseObj.mqh"
#include "..\..\Services\DELib.mqh"
//+------------------------------------------------------------------+
//| "Tick" class                                                     |
//+------------------------------------------------------------------+
class CDataTick : public CBaseObj
  {
private:
   MqlTick           m_tick;                                      // Structure for obtaining current prices
   int               m_digits;                                    // Symbol's digits value
   long              m_long_prop[TICK_PROP_INTEGER_TOTAL];        // Integer properties
   double            m_double_prop[TICK_PROP_DOUBLE_TOTAL];       // Real properties
   string            m_string_prop[TICK_PROP_STRING_TOTAL];       // String properties

//--- Return the index of the array the tick’s (1) double and (2) string properties are actually located at
   int               IndexProp(ENUM_TICK_PROP_DOUBLE property)       const { return(int)property-TICK_PROP_INTEGER_TOTAL;                       }
   int               IndexProp(ENUM_TICK_PROP_STRING property)       const { return(int)property-TICK_PROP_INTEGER_TOTAL-TICK_PROP_DOUBLE_TOTAL;}

public:
//--- Set tick’s (1) integer, (2) real and (3) string property
   void              SetProperty(ENUM_TICK_PROP_INTEGER property,long value)  { this.m_long_prop[property]=value;                               }
   void              SetProperty(ENUM_TICK_PROP_DOUBLE property,double value) { this.m_double_prop[this.IndexProp(property)]=value;             }
   void              SetProperty(ENUM_TICK_PROP_STRING property,string value) { this.m_string_prop[this.IndexProp(property)]=value;             }
//--- Return tick’s (1) integer, (2) real and (3) string property from the properties array
   long              GetProperty(ENUM_TICK_PROP_INTEGER property)    const { return this.m_long_prop[property];                                 }
   double            GetProperty(ENUM_TICK_PROP_DOUBLE property)     const { return this.m_double_prop[this.IndexProp(property)];               }
   string            GetProperty(ENUM_TICK_PROP_STRING property)     const { return this.m_string_prop[this.IndexProp(property)];               }

//--- Return the flag of the tick supporting this property
   virtual bool      SupportProperty(ENUM_TICK_PROP_INTEGER property)      { return true; }
   virtual bool      SupportProperty(ENUM_TICK_PROP_DOUBLE property)       { return true; }
   virtual bool      SupportProperty(ENUM_TICK_PROP_STRING property)       { return true; }
//--- Return itself
   CDataTick        *GetObject(void)                                       { return &this;}

//--- Compare CDataTick objects with each other by the specified property (for sorting the lists by a specified object property)
   virtual int       Compare(const CObject *node,const int mode=0) const;
//--- Compare CDataTick objects with each other by all properties (to search equal objects)
   bool              IsEqual(CDataTick* compared_obj) const;
//--- Constructors
                     CDataTick(){;}
                     CDataTick(const string symbol,const MqlTick &tick);
        
//+------------------------------------------------------------------+
//| Descriptions of object tick data properties                      |
//+------------------------------------------------------------------+
//--- Return description of tick's (1) integer, (2) real and (3) string property
   string            GetPropertyDescription(ENUM_TICK_PROP_INTEGER property);
   string            GetPropertyDescription(ENUM_TICK_PROP_DOUBLE property);
   string            GetPropertyDescription(ENUM_TICK_PROP_STRING property);

//--- Display the description of tick properties in the journal (full_prop=true - all properties, false - supported ones only)
   void              Print(const bool full_prop=false);
//--- Display a short description of the tick in the journal
   virtual void      PrintShort(void);
//---  Return the (1) short name and (2) description of tick data object flags
   virtual string    Header(void);
   string            FlagsDescription(void);
   
//+------------------------------------------------------------------+ 
//| Methods of simplified access to tick data object properties      |
//+------------------------------------------------------------------+
//--- Return tick’s (1) Time, (2) time in milliseconds, (3) volume, (4) flags
   datetime          Time(void)                                         const { return (datetime)this.GetProperty(TICK_PROP_TIME);           }
   long              TimeMSC(void)                                      const { return this.GetProperty(TICK_PROP_TIME_MSC);                 }
   long              Volume(void)                                       const { return this.GetProperty(TICK_PROP_VOLUME);                   }
   uint              Flags(void)                                        const { return (uint)this.GetProperty(TICK_PROP_FLAGS);              }
   
//--- Return tick’s (1) Bid, (2) Ask, (3) Last price, (4) volume with greater accuracy, (5) spread of the tick
//--- size of the (9) candle upper, (10) lower wick
   double            Bid(void)                                          const { return this.GetProperty(TICK_PROP_BID);                      }
   double            Ask(void)                                          const { return this.GetProperty(TICK_PROP_ASK);                      }
   double            Last(void)                                         const { return this.GetProperty(TICK_PROP_LAST);                     }
   double            VolumeReal(void)                                   const { return this.GetProperty(TICK_PROP_VOLUME_REAL);              }
   double            Spread(void)                                       const { return this.GetProperty(TICK_PROP_SPREAD);                   }
   
//--- Return tick symbol
   string            Symbol(void)                                       const { return this.GetProperty(TICK_PROP_SYMBOL);                   }

//--- Return bar (1) time, (2) index on the specified timeframe the tick time falls into
   datetime          TimeBar(const ENUM_TIMEFRAMES timeframe)const
                       { return ::iTime(this.Symbol(),timeframe,this.Index(timeframe));                                                      }
   int               Index(const ENUM_TIMEFRAMES timeframe)  const
                       { return ::iBarShift(this.Symbol(),(timeframe==PERIOD_CURRENT ? ::Period() : timeframe),this.Time());                 }  

//--- Return the flag of (1) Bid, (2) Ask, (3) Last price, (4) volume change; (5) buy and (6) sell trades
   bool              IsChangeBid()                                      const { return((this.Flags() & TICK_FLAG_BID)==TICK_FLAG_BID);       }
   bool              IsChangeAsk()                                      const { return((this.Flags() & TICK_FLAG_ASK)==TICK_FLAG_ASK);       }
   bool              IsChangeLast()                                     const { return((this.Flags() & TICK_FLAG_LAST)==TICK_FLAG_LAST);     }
   bool              IsChangeVolume()                                   const { return((this.Flags() & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME); }
   bool              IsChangeBuy()                                      const { return((this.Flags() & TICK_FLAG_BUY)==TICK_FLAG_BUY);       }
   bool              IsChangeSell()                                     const { return((this.Flags( )& TICK_FLAG_SELL)==TICK_FLAG_SELL);     }
//---
  };
//+------------------------------------------------------------------+

En el primer artículo, ya hablamos en detalle de la estructura y de la creación de los objetos de la biblioteca. Ahora, sólo vamos a repasar rápidamente las variables y los métodos principales, y luego, analizaremos su implementación en la clase.

En la sección privada de la clase, se encuentran las variables auxiliares, las matrices para almacenar los valores de las propiedades de tipo entero, real y string del objeto, así como los métodos que devuelven los índices reales de las propiedades de acuerdo de los cuales ellas se ubican físicamente en las matrices.

En la sección pública de la clase, se encuentran los métodos para establecer y devolver valores de las propiedades indicadas en las matrices correspondientes de las propiedades del objeto, los métodos que devuelven las banderas del soporte de una u otra propiedad por el objeto, los métodos para buscar, comparar y ordenar objetos, así como los constructores de la clase.

Ahí mismo, se encuentran los métodos para visualizar las descripciones de las propiedades del objeto y los métodos para un acceso simplificado a las propiedades del objeto.

Ahora, vamos a analizar la implementación de los métodos de la clase.

Al constructor paramétrico de la clase se le transmite el símbolo y la estructura rellenada con datos del tick actual:

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CDataTick::CDataTick(const string symbol,const MqlTick &tick)
  {
//--- Save symbol’s Digits
   this.m_digits=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- Save integer tick properties
   this.SetProperty(TICK_PROP_TIME,tick.time);
   this.SetProperty(TICK_PROP_TIME_MSC,tick.time_msc);
   this.SetProperty(TICK_PROP_VOLUME,tick.volume);
   this.SetProperty(TICK_PROP_FLAGS,tick.flags);
//--- Save real tick properties
   this.SetProperty(TICK_PROP_BID,tick.bid);
   this.SetProperty(TICK_PROP_ASK,tick.ask);
   this.SetProperty(TICK_PROP_LAST,tick.last);
   this.SetProperty(TICK_PROP_VOLUME_REAL,tick.volume_real);
//--- Save additional tick properties
   this.SetProperty(TICK_PROP_SPREAD,tick.ask-tick.bid);
   this.SetProperty(TICK_PROP_SYMBOL,(symbol==NULL || symbol=="" ? ::Symbol() : symbol));
  }
//+------------------------------------------------------------------+

Dentro del constructor de la clase, simplemente rellenamos las propiedades del objeto con valores correspondientes desde la estructura del tick y el símbolo del que se reciben los datos del tick.

Método de comparación de dos parámetros de objetos según la propiedad indicada:

//+--------------------------------------------------------------------+
//| Compare CDataTick objects with each other by the specified property|
//+--------------------------------------------------------------------+
int CDataTick::Compare(const CObject *node,const int mode=0) const
  {
   const CDataTick *obj_compared=node;
//--- compare integer properties of two objects
   if(mode<TICK_PROP_INTEGER_TOTAL)
     {
      long value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_INTEGER)mode);
      long value_current=this.GetProperty((ENUM_TICK_PROP_INTEGER)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare real properties of two objects
   else if(mode<TICK_PROP_DOUBLE_TOTAL+TICK_PROP_INTEGER_TOTAL)
     {
      double value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_DOUBLE)mode);
      double value_current=this.GetProperty((ENUM_TICK_PROP_DOUBLE)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
//--- compare string properties of two objects
   else if(mode<TICK_PROP_DOUBLE_TOTAL+TICK_PROP_INTEGER_TOTAL+TICK_PROP_STRING_TOTAL)
     {
      string value_compared=obj_compared.GetProperty((ENUM_TICK_PROP_STRING)mode);
      string value_current=this.GetProperty((ENUM_TICK_PROP_STRING)mode);
      return(value_current>value_compared ? 1 : value_current<value_compared ? -1 : 0);
     }
   return 0;
  }
//+------------------------------------------------------------------+

Al método se le transmite el puntero al objeto con el que es necesario comparar el objeto actual, y el tipo de la propiedad según la cual van a compararse estos dos objetos.

Dependiendo del modo transmitido de la comparación de objetos, comparamos estas propiedades de dos objetos y devolvemos 1/-1/0 si el valor de la propiedad del objeto actual es mayor/menor o igual al valor de la propiedad del objeto comparado, respectivamente.

El método que compara si dos objetos son iguales:

//+------------------------------------------------------------------+
//| Compare CDataTick objects with each other by all properties      |
//+------------------------------------------------------------------+
bool CDataTick::IsEqual(CDataTick *compared_obj) const
  {
   int beg=0, end=TICK_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_INTEGER prop=(ENUM_TICK_PROP_INTEGER)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=TICK_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_DOUBLE prop=(ENUM_TICK_PROP_DOUBLE)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   beg=end; end+=TICK_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_STRING prop=(ENUM_TICK_PROP_STRING)i;
      if(this.GetProperty(prop)!=compared_obj.GetProperty(prop)) return false; 
     }
   return true;
  }
//+------------------------------------------------------------------+

Aquí: al método se le transmite el puntero al objeto para la comparación. Luego, en cada grupo de propiedades, comparamos en tres ciclos cada siguiente propiedad de dos objetos. Si aunque sea una sola de las propiedades no es igual a la misma del objeto comparado, devolvemos false. Una vez finalizados los tres ciclos, devolvemos true, lo que significa que todas las propiedades de ambos objetos son iguales, entonces, los objetos son idénticos.

Método para mostrar en el diario todas las propiedades del objeto:

//+------------------------------------------------------------------+
//| Display tick properties in the journal                           |
//+------------------------------------------------------------------+
void CDataTick::Print(const bool full_prop=false)
  {
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_BEG)," (",this.Header(),") =============");
   int beg=0, end=TICK_PROP_INTEGER_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_INTEGER prop=(ENUM_TICK_PROP_INTEGER)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=TICK_PROP_DOUBLE_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_DOUBLE prop=(ENUM_TICK_PROP_DOUBLE)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("------");
   beg=end; end+=TICK_PROP_STRING_TOTAL;
   for(int i=beg; i<end; i++)
     {
      ENUM_TICK_PROP_STRING prop=(ENUM_TICK_PROP_STRING)i;
      if(!full_prop && !this.SupportProperty(prop)) continue;
      ::Print(this.GetPropertyDescription(prop));
     }
   ::Print("============= ",CMessage::Text(MSG_LIB_PARAMS_LIST_END)," (",this.Header(),") =============\n");
  }
//+------------------------------------------------------------------+

Aquí: recorriendo en tres ciclos cada uno de los grupos de las propiedades del objeto, mostramos la descripción de cada propiedad siguiente a través del método correspondiente GetPropertyDescription(). Si en los parámetros del método, se transmite el valor false en la variable full_prop, se visualizan sólo las propiedades soportadas por el objeto. Para una propiedad que no se soporta, en el registro se muestra que esta propiedad no se soporta. Aunque en este objeto, se soportan todas las propiedades, pero se puede modificar eso en los objetos herederos de la clase.

Los métodos que retornan la descripción de la propiedad especificada de tipo entero, real y string del objeto:

//+------------------------------------------------------------------+
//| Return description of tick's integer property                    |
//+------------------------------------------------------------------+
string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_INTEGER property)
  {
   return
     (
      property==TICK_PROP_TIME_MSC           ?  CMessage::Text(MSG_TICK_TIME_MSC)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+TimeMSCtoString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==TICK_PROP_TIME               ?  CMessage::Text(MSG_TICK_TIME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::TimeToString(this.GetProperty(property),TIME_DATE|TIME_MINUTES|TIME_SECONDS)
         )  :
      property==TICK_PROP_VOLUME             ?  CMessage::Text(MSG_TICK_VOLUME)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)
         )  :
      property==TICK_PROP_FLAGS              ?  CMessage::Text(MSG_TICK_FLAGS)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+(string)this.GetProperty(property)+"\n"+CMessage::Text(MSG_LIB_TEXT_TICK_CHANGED_DATA)+this.FlagsDescription()
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of tick's real property                       |
//+------------------------------------------------------------------+
string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_DOUBLE property)
  {
   int dg=(this.m_digits>0 ? this.m_digits : 1);
   return
     (
      property==TICK_PROP_BID                ?  CMessage::Text(MSG_LIB_PROP_BID)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      property==TICK_PROP_ASK                ?  CMessage::Text(MSG_LIB_PROP_ASK)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      property==TICK_PROP_LAST               ?  CMessage::Text(MSG_LIB_PROP_LAST)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      property==TICK_PROP_VOLUME_REAL        ?  CMessage::Text(MSG_TICK_VOLUME_REAL)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),2)
         )  :
      property==TICK_PROP_SPREAD             ?  CMessage::Text(MSG_TICK_SPREAD)+
         (!this.SupportProperty(property)    ?  ": "+CMessage::Text(MSG_LIB_PROP_NOT_SUPPORTED) :
          ": "+::DoubleToString(this.GetProperty(property),dg)
         )  :
      ""
     );
  }
//+------------------------------------------------------------------+
//| Return description of tick's string property                     |
//+------------------------------------------------------------------+
string CDataTick::GetPropertyDescription(ENUM_TICK_PROP_STRING property)
  {
   return(property==TICK_PROP_SYMBOL ? CMessage::Text(MSG_LIB_PROP_SYMBOL)+": \""+this.GetProperty(property)+"\"" : "");
  }
//+------------------------------------------------------------------+

Aquí: dependiendo de la propiedad transmitida al método, retornamos su descripción de tipo string.

Método que devuelve la cadena con la descripción de todas las banderas del tick:

//+------------------------------------------------------------------+
//| Display the description of flags                                 |
//+------------------------------------------------------------------+
string CDataTick::FlagsDescription(void)
  {
   string flags=
     (
      (this.IsChangeAsk()     ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_ASK)     : "")+
      (this.IsChangeBid()     ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_BID)     : "")+
      (this.IsChangeLast()    ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_LAST)    : "")+
      (this.IsChangeVolume()  ? "\n - "+CMessage::Text(MSG_LIB_TEXT_TICK_FLAG_VOLUME)  : "")+
      (this.IsChangeBuy()     ? "\n - "+CMessage::Text(MSG_DEAL_TO_BUY)                : "")+
      (this.IsChangeSell()    ? "\n - "+CMessage::Text(MSG_DEAL_TO_SELL)               : "")
     );
  return flags; 
  }
//+------------------------------------------------------------------+

En las propiedades de cada tick hay una variable que almacena un conjunto de banderas. Estas banderas describen los eventos que provocan este tick.

Información sobre MqlTick en el manual de referencia

Para saber qué datos han sido alterados con la llegada del tick actual, analizamos sus banderas:

  • TICK_FLAG_BID — el tick ha cambiado el precio bid
  • TICK_FLAG_ASK — el tick ha cambiado el precio ask
  • TICK_FLAG_LAST — el tick ha cambiado el precio de la última transacción
  • TICK_FLAG_VOLUME — el tick ha cambiado el volumen
  • TICK_FLAG_BUY — el tick ha aparecido como resultado de una transacción de compra
  • TICK_FLAG_SELL — el tick ha aparecido como resultado de una transacción de venta

Tenemos seis métodos (según el número de banderas) que devuelven la bandera de la presencia de cada una de las banderas en la variable:

//--- Return the flag of (1) Bid, (2) Ask, (3) Last price, (4) volume change; (5) buy and (6) sell trades
   bool IsChangeBid()    const { return((this.Flags() & TICK_FLAG_BID)==TICK_FLAG_BID);       }
   bool IsChangeAsk()    const { return((this.Flags() & TICK_FLAG_ASK)==TICK_FLAG_ASK);       }
   bool IsChangeLast()   const { return((this.Flags() & TICK_FLAG_LAST)==TICK_FLAG_LAST);     }
   bool IsChangeVolume() const { return((this.Flags() & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME); }
   bool IsChangeBuy()    const { return((this.Flags() & TICK_FLAG_BUY)==TICK_FLAG_BUY);       }
   bool IsChangeSell()   const { return((this.Flags() & TICK_FLAG_SELL)==TICK_FLAG_SELL);     }

En el método descrito, primero, se verifica la bandera de la presencia de la bandera en la estructura de la variable. Dependiendo de que si este cambio ha tenido lugar o no, en la cadena resultante se escribe el avance de línea + la descripción de la bandera, o bien, una cadena vacía. Después de verificar todas las banderas, como resultado, tenemos una cadena completada que contiene las descripciones de las banderas que se encuentran en la variable. Si tenemos varias banderas, la descripción de cada una de ellas va a comenzar a partir de una línea nueva en el registro.

Método que muestra en el registro la descripción breve del objeto de los datos de tick:

//+------------------------------------------------------------------+
//| Display a short description of the tick in the journal           |
//+------------------------------------------------------------------+
void CDataTick::PrintShort(void)
  {
   ::Print(this.Header());
  }
//+------------------------------------------------------------------+

El método simplemente muestra en el registro su nombre breve que se devuelve por el siguiente método:

//+------------------------------------------------------------------+
//| Return a short name of tick data object                          |
//+------------------------------------------------------------------+
string CDataTick::Header(void)
  {
   return
     (
      CMessage::Text(MSG_TICK_TEXT_TICK)+" \""+this.Symbol()+"\" "+TimeMSCtoString(TimeMSC())
     );
  }
//+------------------------------------------------------------------+

Con esto, damos por finalizada la creación del objeto de los datos de ticks.


Probando el objeto de datos del tick

Para la simulación, vamos a tomar el asesor del artículo anterior
y guardarlo en la nueva carpeta \MQL5\Experts\TestDoEasy\Part59\ con el nombre nuevo TestDoEasyPart59.mq5
.

En este asesor, ya no necesitamos los indicadores y sus datos con sus series temporales. Aquí, simplemente vamos a crear el objeto de los datos de ticks, mostrar su descripción completa en el registro y su descripción breve en el comentario en el gráfico. Con la llegada de cada tick nuevo, su descripción en el gráfico va a cambiar, mientras que en el registro se visualizará el primer tick que llegue tras la ejecución de asesor.

Dado que todavía no hay ninguna vinculación del asesor con este objeto nuevo de la biblioteca, simplemente vamos a incluir el archivo de su clase en el asesor:

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart59.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                             https://mql5.com/es/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://mql5.com/es/users/artmedia70"
#property version   "1.00"
//--- includes
#include <DoEasy\Engine.mqh>
#include <DoEasy\Objects\Ticks\DataTick.mqh>

En el área de variables globales del asesor, en vez de las matrices de los parámetros de indicadores personalizados,

//--- Arrays of custom indicator parameters
MqlParam       param_ma1[];
MqlParam       param_ma2[];
//+------------------------------------------------------------------+

declaramos el objeto de la clase «Nuevo tick». Lo necesitamos para simular el trabajo dentro de las futuras clases de colección de los datos de ticks de la biblioteca:

//--- global variables
CEngine        engine;
SDataButt      butt_data[TOTAL_BUTT];
string         prefix;
double         lot;
double         withdrawal=(InpWithdrawal<0.1 ? 0.1 : InpWithdrawal);
ushort         magic_number;
uint           stoploss;
uint           takeprofit;
uint           distance_pending;
uint           distance_stoplimit;
uint           distance_pending_request;
uint           bars_delay_pending_request;
uint           slippage;
bool           trailing_on;
bool           pressed_pending_buy;
bool           pressed_pending_buy_limit;
bool           pressed_pending_buy_stop;
bool           pressed_pending_buy_stoplimit;
bool           pressed_pending_close_buy;
bool           pressed_pending_close_buy2;
bool           pressed_pending_close_buy_by_sell;
bool           pressed_pending_sell;
bool           pressed_pending_sell_limit;
bool           pressed_pending_sell_stop;
bool           pressed_pending_sell_stoplimit;
bool           pressed_pending_close_sell;
bool           pressed_pending_close_sell2;
bool           pressed_pending_close_sell_by_buy;
bool           pressed_pending_delete_all;
bool           pressed_pending_close_all;
bool           pressed_pending_sl;
bool           pressed_pending_tp;
double         trailing_stop;
double         trailing_step;
uint           trailing_start;
uint           stoploss_to_modify;
uint           takeprofit_to_modify;
int            used_symbols_mode;
string         array_used_symbols[];
string         array_used_periods[];
bool           testing;
uchar          group1;
uchar          group2;
double         g_point;
int            g_digits;

//--- "New tick" object
CNewTickObj    check_tick;
//+------------------------------------------------------------------+

En el manejador OnInit() eliminamos el bloque de la creación de indicadores:

//--- Create indicators
   ArrayResize(param_ma1,4);
   //--- Name of indicator 1
   param_ma1[0].type=TYPE_STRING;
   param_ma1[0].string_value="Examples\\Custom Moving Average.ex5";
   //--- Calculation period
   param_ma1[1].type=TYPE_INT;
   param_ma1[1].integer_value=13;
   //--- Horizontal shift
   param_ma1[2].type=TYPE_INT;
   param_ma1[2].integer_value=0;
   //--- Smoothing method
   param_ma1[3].type=TYPE_INT;
   param_ma1[3].integer_value=MODE_SMA;
   //--- Create indicator 1
   engine.GetIndicatorsCollection().CreateCustom(NULL,PERIOD_CURRENT,MA1,1,INDICATOR_GROUP_TREND,param_ma1);
   
   ArrayResize(param_ma2,5);
   //--- Name of indicator 2
   param_ma2[0].type=TYPE_STRING;
   param_ma2[0].string_value="Examples\\Custom Moving Average.ex5";
   //--- Calculation period
   param_ma2[1].type=TYPE_INT;
   param_ma2[1].integer_value=13;
   //--- Horizontal shift
   param_ma2[2].type=TYPE_INT;
   param_ma2[2].integer_value=0;
   //--- Smoothing method
   param_ma2[3].type=TYPE_INT;
   param_ma2[3].integer_value=MODE_SMA;
   //--- Calculation price
   param_ma2[4].type=TYPE_INT;
   param_ma2[4].integer_value=PRICE_OPEN;
   //--- Create indicator 2
   engine.GetIndicatorsCollection().CreateCustom(NULL,PERIOD_CURRENT,MA2,1,INDICATOR_GROUP_TREND,param_ma2);
   
   //--- Create indicator 3
   engine.GetIndicatorsCollection().CreateAMA(NULL,PERIOD_CURRENT,AMA1);
   //--- Create indicator 4
   engine.GetIndicatorsCollection().CreateAMA(NULL,PERIOD_CURRENT,AMA2,14);
   
   //--- Display descriptions of created indicators
   engine.GetIndicatorsCollection().Print();
   engine.GetIndicatorsCollection().PrintShort();

Al final de OnInit() establecemos el símbolo actual para el objeto «Nuevo tick» como símbolo de trabajo:

//--- Set the current symbol for "New tick" object
   check_tick.SetSymbol(Symbol());
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

Añadimos al manejador OnTick() del asesor el bloque del código para determinar un tick nuevo (como simulación del trabajo dentro de la futura clase de colección de los ticks) y para crear un nuevo objeto de los datos de ticks con la visualización de su descripción en el gráfico y en el registro:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Handle the NewTick event in the library
   engine.OnTick(rates_data);

//--- If working in the tester
   if(MQLInfoInteger(MQL_TESTER))
     {
      engine.OnTimer(rates_data);   // Working in the timer
      PressButtonsControl();        // Button pressing control
      engine.EventsHandling();      // Working with events
     }

//--- Create a temporary list for storing “Tick data” objects,
//--- a variable for obtaining tick data and
//--- a variable for calculating incoming ticks
   static int tick_count=0;
   CArrayObj list;
   MqlTick tick_struct;
//--- Check a new tick on the current symbol
   if(check_tick.IsNewTick())
     {
      //--- If failed to get the price - exit
      if(!SymbolInfoTick(Symbol(),tick_struct))
         return;
      //--- Create a new tick data object
      CDataTick *tick_obj=new CDataTick(Symbol(),tick_struct);
      if(tick_obj==NULL)
         return;
      //--- Increase tick counter (simply to display on the screen, no other purpose is provided)
      tick_count++;
      //--- Limit the number of ticks in the counting as one hundred thousand (again, no purpose is provided)
      if(tick_count>100000) tick_count=1;
      //--- In the comment on the chart display the tick number and its short description
      Comment("--- №",IntegerToString(tick_count,5,'0'),": ",tick_obj.Header());
      //--- If this is the first tick (which follows the first launch of EA) display its full description in the journal
      if(tick_count==1)
         tick_obj.Print();
      //--- Remove if failed to put the created tick data object in the list
      if(!list.Add(tick_obj))
         delete tick_obj;
     }
   
//--- If the trailing flag is set
   if(trailing_on)
     {
      TrailingPositions();          // Trailing positions
      TrailingOrders();             // Trailing pending orders
     }
  }
//+------------------------------------------------------------------+

La lógica se describe detalladamente en los comentarios del listado. Creo que todo está bien claro y es fácil.

Compilamos el EA y lo iniciamos en el gráfico, estableciendo previamente en los ajustes el uso del símbolo y marco temporal actuales. Después de ejecutarlo y recibir un tick nuevo, la descripción del objeto de los datos de ticks (tick recibido) se visualizará en el registro:

Account 8550475: Artyom Trishkin (MetaQuotes Software Corp.) 10426.13 USD, 1:100, Hedge, MetaTrader 5 demo
--- Initializing "DoEasy" library ---
Working with the current symbol only: "EURUSD"
Working with the current timeframe only: H1
EURUSD symbol timeseries: 
- Timeseries "EURUSD" H1: Requested: 1000, Actual: 1000, Created: 1000, On the server: 5153
Library initialization time: 00:00:00.000
============= Beginning of parameter list (Tick "EURUSD" 2020.12.16 13:22:32.822) =============
Last price update time in milliseconds: 2020.12.16 13:22:32.822
Last price update time: 2020.12.16 13:22:32
Volume for the current Last price: 0
Flags: 6
Changed data on the tick:
 - Ask price change
 - Bid price change
------
Bid price: 1.21927
Ask price: 1.21929
Last price: 0.00000
Volume for the current Last price with greater accuracy: 0.00
Spread: 0.00002
------
Symbol: "EURUSD"
============= End of parameter list (Tick "EURUSD" 2020.12.16 13:22:32.822) =============

Con la llegada de cada tick nuevo, el comentario con su descripción breve se mostrará en el gráfico:



¿Qué es lo próximo?

En el siguiente artículo, comenzaremos a crear la colección de los datos de ticks para un símbolo.

Más abajo se adjuntan todos los archivos de la versión actual de la biblioteca y el archivo del asesor de prueba para MQL5. Puede descargarlo todo y ponerlo a prueba por sí mismo.
Si tiene preguntas, observaciones o sugerencias, podrá concretarlas en los comentarios al artículo.

Volver al contenido

Artículos de esta serie:

Trabajando con las series temporales en la biblioteca DoEasy (Parte 35): El objeto "Barra" y la lista de serie temporal del símbolo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 36): El objeto de series temporales de todos los periodos utilizados del símbolo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 37): Colección de series temporales - Base de datos de series temporales según el símbolo y el periodo
Trabajando con las series temporales en la biblioteca DoEasy (Parte 38): Colección de series temporales - Actualización en tiempo real y acceso a los datos desde el programa
Trabajando con las series temporales en la biblioteca DoEasy (Parte 39): Indicadores basados en la biblioteca - Preparación de datos y eventos de la series temporales
Trabajando con las series temporales en la biblioteca DoEasy (Parte 40): Indicadores basados en la biblioteca - actualización de datos en tiempo real
Trabajando con las series temporales en la biblioteca DoEasy (Parte 41): Ejemplo de indicador de símbolo y periodo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 42): La clase del objeto de búfer de indicador abstracto
Trabajando con las series temporales en la biblioteca DoEasy (Parte 43): Las clases de los objetos de búferes de indicador
Trabajando con las series temporales en la biblioteca DoEasy (Parte 44): Las clases de colección de los objetos de búferes de indicador
Trabajando con las series temporales en la biblioteca DoEasy (Parte 45): Búferes de indicador de periodo múltiple
Trabajando con las series temporales en la biblioteca DoEasy (Parte 46): Búferes de indicador de periodo y símbolos múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 47): Indicadores estándar de periodo y símbolo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 48): Indicadores de periodo y símbolo múltiples en un búfer en una subventana
Trabajando con las series temporales en la biblioteca DoEasy (Parte 49): Indicadores estándar de periodo, símbolo y búfer múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 50): Indicadores estándar de periodo y símbolo múltiples con desplazamiento
Trabajando con las series temporales en la biblioteca DoEasy (Parte 51): Indicadores estándar compuestos de período y símbolo múltiples
Trabajando con las series temporales en la biblioteca DoEasy (Parte 52): Concepto multiplataforma de indicadores estándar de periodo y símbolo múltiples de búfer único
Trabajando con las series temporales en la biblioteca DoEasy (Parte 53): Clase del indicador abstracto básico
Trabajando con las series temporales en la biblioteca DoEasy (Parte 54): Clases herederas del indicador abstracto básico
Trabajando con las series temporales en la biblioteca DoEasy (Parte 55): Clase de colección de indicadores
Trabajando con las series temporales en la biblioteca DoEasy (Parte 56): Objeto del indicador personalizado, obtención de datos de parte de los objetos de indicador en la colección
Trabajando con las series temporales en la biblioteca DoEasy (Parte 57): Objeto de datos del búfer de indicador
Trabajando con las series temporales en la biblioteca DoEasy (Parte 58): Series temporales de los datos de búferes de indicadores


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

Archivos adjuntos |
MQL5.zip (3868.71 KB)
Trabajando con las series temporales en la biblioteca DoEasy (Parte 58): Series temporales de los datos de búferes de indicadores Trabajando con las series temporales en la biblioteca DoEasy (Parte 58): Series temporales de los datos de búferes de indicadores

En conclusión del tema de trabajo con series temporales, vamos a organizar el almacenamiento, la búsqueda y la ordenación de los datos que se guardan en los búferes de indicadores. En el futuro, eso nos permitirá realizar el análisis a base de los valores de los indicadores que se crean a base de la biblioteca en nuestros programas. El concepto general de todas las clases de colección de la biblioteca permite encontrar fácilmente los datos necesarios en la colección correspondiente, y por tanto, lo mismo también será posible en la clase que vamos a crear hoy.

Aproximación por fuerza bruta a la búsqueda de patrones Aproximación por fuerza bruta a la búsqueda de patrones

En este artículo buscaremos patrones en el mercado, crearemos asesores expertos usando estos como base y verificaremos cuánto tiempo dichos patrones siguen funcionando y, en general, si se mantienen.

Cuadrícula y martingale: ¿qué son y cómo usarlos? Cuadrícula y martingale: ¿qué son y cómo usarlos?

En este artículo trataremos de explicar con detalle qué son la cuadrícula y el martingale, y qué tienen en común. También intentaremos analizar cómo de viables son en realidad estas estrategias. En el artículo habrá una parte matemática y otra práctica.

Redes neuronales: así de sencillo (Parte 6): Experimentos con la tasa de aprendizaje de la red neuronal Redes neuronales: así de sencillo (Parte 6): Experimentos con la tasa de aprendizaje de la red neuronal

Ya hemos hablado sobre algunos tipos de redes neuronales y su implementación. En todos los casos, hemos usado el método de descenso de gradiente para entrenar las redes neuronales, lo cual implica la elección de una tasa de aprendizaje. En este artículo, queremos mostrar con ejemplos lo importante que resulta elegir correctamente la tasa de aprendizaje, y también su impacto en el entrenamiento de una red neuronal.