Biblioteca de clases genéricas - errores, descripción, preguntas, características de uso y sugerencias - página 11

 

El último ejemplo de hoy y aparentemente de esta semana: la correspondencia entre el número de operación y el número de orden que la inició:

//+------------------------------------------------------------------+
//|                                                     OrdersID.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#include <Generic\HashMap.mqh>
input ulong FindTicketOrder = 82479995;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   ulong tiks = GetMicrosecondCount();
   HistorySelect(0, TimeCurrent());
   CHashMap<ulong, ulong> deals_orders;
   int total = HistoryDealsTotal();
   ulong deal_id = 0;
   for(int i = 0; i < total; i++)
   {
      deal_id = HistoryDealGetTicket(i);
      ulong order_id = HistoryDealGetInteger(deal_id, DEAL_ORDER);
      deals_orders.Add(deal_id, order_id);
   }
   ulong t2 = GetMicrosecondCount()-tiks;
   printf("Время заполнения коллекции: " + (string)t2 + " микросекунд");
   tiks = GetMicrosecondCount();
   ulong find_order = 0;
   if(deals_orders.TryGetValue(deal_id, find_order))
      printf("Сделке с номером " + (string)deal_id + " Соответствует ордер с номером " + (string)find_order);
   ulong delay = GetMicrosecondCount() - tiks;
   printf("Время выполнения запроса: " + (string)delay + " микросекунд");
}

Para mi caso, en el que hay más de 10.000 operaciones en la cuenta, el resultado es el siguiente:

2017.12.08 17:56:05.184 OrdersID (SBRF Splice,M1)       Время заполнения коллекции: 145865 микросекунд
2017.12.08 17:56:05.184 OrdersID (SBRF Splice,M1)       Сделке с номером 44455231 Соответствует ордер с номером 83473421
2017.12.08 17:56:05.184 OrdersID (SBRF Splice,M1)       Время выполнения запроса: 9 микросекунд
 

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Biblioteca de clases genéricas - errores, descripción, preguntas, peculiaridades de uso y sugerencias

Vasiliy Sokolov, 2017.12.08 13:30

Si N es muy pequeño, simplemente normalizamos el número obtenido por la función hash, de forma que siempre esté en el límite de N:

int index = GetHashCode(word)%ArraySize(m_array);

que he leído hasta ahora. Vasily, gracias, todo está claro, excepto el resaltado. En mi opinión, tomar el residuo como una normalización es un error. Parece más lógico

int index = GetHashCode(word) * ArraySize(m_array) / HashSize; // Надо бы и округлять, а не отбрасывать нецелочисленную часть, но не стал усложнять
 
Vasiliy Sokolov:

Esa es la cuestión: a menudo se desconoce el tamaño del diccionario. Un ejemplo sencillo, digamos que tenemos un asesor que comercia. Hace un seguimiento de las operaciones realizadas. Cuando aparece una operación en el historial, tenemos que conectar esta operación con el Medjack del Asesor Experto. Para ello es lógico utilizar el diccionario. Donde el número de operación se utiliza como clave (identificador único), y el número mágico del Asesor Experto se utiliza como valor. El problema es que al inicio del EA no podemos determinar de antemano si tendremos 100 operaciones, 1000 o ninguna. Independientemente de la cantidad de memoria que se asigne de antemano, seguirá siendo poca o demasiada.

Obviamente no me he devanado los sesos todavía. ¿Podría explicar qué es lo que se asigna? No lo entiendo en absoluto.

 

Parece una burla.

//+------------------------------------------------------------------+
//| Returns a hashcode for boolean.                                  |
//+------------------------------------------------------------------+
int GetHashCode(const bool value)
  {
   return((value)?true:false);
  }


HashFunction.mqh sin un inlude. Esto no está bien.


¿Para qué sirve esta función?

template<typename T>
int GetHashCode(T value)
  {
//--- try to convert to equality comparable object  
   IEqualityComparable<T>*equtable=dynamic_cast<IEqualityComparable<T>*>(value);
   if(equtable)
     {
      //--- calculate hash by specied method   
      return equtable.HashCode();
     }
   else
     {
      //--- calculate hash from name of object
      return GetHashCode(typename(value));
     }
  }
Al fin y al cabo, no sólo compilará para struct y union.
 
fxsaber:

Creo que no me he roto del todo el cerebro. ¿Podría aclarar lo resaltado? No lo entiendo en absoluto.

Personalmente, he entendido que cuando se hacen operaciones, el EA debe escribir el número de un magik en el diccionario (array) por el número de la operación, que en este caso es un índice de celda.

El número de operaciones futuras no se conoce de antemano, y ya deberíamos tener un array declarado para escribir las mayores. La tarea consiste en asignar por adelantado la cantidad de memoria necesaria para el array.

Es imposible asignar la cantidad exacta de memoria por adelantado. Por lo tanto, podríamos escribir una cadena con cadenas, obtener el número de subcadenas, inicializar la matriz y escribir todas las subcadenas (panales) allí.

Entonces se accederá a cada medjack por número de oficio.

A grandes rasgos, así es como yo lo veo.

 
Vasiliy Sokolov:

El último ejemplo de hoy y aparentemente de esta semana: la correspondencia entre el número de operación y el número de orden que la inició:

Para mi caso, en el que hay más de 10.000 operaciones en mi cuenta, el resultado es el siguiente:

¿Cuánto devuelve la versión clásica en su caso?

ulong GetDealOrder( const ulong Deal )
{
  return(HistoryDealSelect(Deal) ? HistoryDealGetInteger(Deal, DEAL_ORDER) : 0);
}


2017.12.08 17:56:05.184 OrdersID (SBRF Splice,M1)       Время выполнения запроса: 9 микросекунд
Este es el tiempo de ejecución de printf.
 
fxsaber:

¿Para qué sirve esta función?

No sólo compilará para struct y union.

Se ha añadido otra sobrecarga

template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }


Se ha tropezado con él.

//+------------------------------------------------------------------+
//| Returns a hashcode for string.                                   |
//+------------------------------------------------------------------+
int GetHashCode(const string value)
  {
   int len=StringLen(value);
   int hash=0;
//--- check length of string
   if(len>0)
     {
      //--- calculate a hash as a fucntion of each char
      for(int i=0; i<len; i++)
         hash=31*hash+value[i];
     }
   return(hash);
  }
Devuelve números negativos, lo que se deduce lógicamente de dicho código. ¿Está bien?
 
fxsaber:

Se ha añadido otra sobrecarga

template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }

A mí me parece que si un objeto no implementa alguna interfaz o método, es mejor generar explícitamente una excepción que callarse y luego buscar el origen del problema sin más.


Devuelve números negativos, lo que se deduce lógicamente de dicho código. ¿Está bien?

Absolutamente normal.
El hash no te garantiza nada, sólo es un número que caracteriza en cierta medida a tal o cual objeto.
Si necesitas un entero, utiliza uint.

 
Sergey Dzyublik:

Para mí, si un objeto no implementa alguna interfaz o método, es mejor generar explícitamente una excepción que guardar silencio y luego buscar el origen del problema durante un tiempo desconocido.

¿MqlTick?

 
fxsaber:

¿MqlTick?


¿Entiendes qué hace el código si no hay una implementación explícita de la especialización de la función de plantillaGetHashCode para el tipo T?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
Respuesta: es patético porque glosa la falta de aplicación. Todos los objetos de la misma clase devolverán el mismo valor hash.