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

 
Renat Fatkhullin:

No se puede comparar HistorySelect(pone rango de acceso en el probador) e HistoryDealSelect(ticket), que realmente busca un ticket específico y lo almacena en caché.

Por entender esto, se creó inmediatamente la variante Clear. Para poder comparar Clear vs Full al mismo tiempo.

 
fxsaber:
De este modo, el historial (especialmente en el probador) sólo se complementa, los registros antiguos no se modifican. Me refiero a la variante Clear.


En la realidad, parece que aunque una orden se ejecute parcialmente y genere varias operaciones, no entra en el historial hasta que se ejecuta completamente o se cancela. Es decir, se conserva la regla de la historia congelada.

Si escribiéramos software sin controles, todo se habría desmoronado hace tiempo.

El software financiero no le permite escribir en modo de "recorte". Si cortas en un sitio, luego en otro, los desarrolladores se creerán con derecho a saltarse las duras comprobaciones y el fracaso será inevitable.

En el probador, todavía puede disminuir la comprobación, pero en el EA real hay muchos procesos asíncronos que trabajan en los cambios constantes de todo el entorno del mercado simultáneamente con el trabajo de su EA. Ni siquiera se puede pensar en que se guarde algo entre las llamadas de MQL5.

 
Renat Fatkhullin:

Si escribiéramos software sin controles, todo se habría desmoronado hace tiempo.

El software financiero no le permite escribir en modo de "recorte". Si cortas en un sitio, luego en otro, los desarrolladores se creerán con derecho a saltarse las duras comprobaciones y el fracaso será inevitable.

Todavía puede aflojar los controles en el probador, pero en el mundo real hay un montón de procesos asíncronos trabajando en el cambio constante de todo el entorno del mercado en paralelo con su Asesor Experto. Da miedo pensar que se guardará algo entre las llamadas de MQL5.

Gracias por la aclaración. Es de esperar que el probador lo apriete un poco.

 
fxsaber:

Gracias a este entendimiento, se creó inmediatamente la variante Clear. Así que podrías comparar Clear vs Full al mismo tiempo.

No entiendes lo que estás probando. Esto no es de ninguna manera una variante clara y no hay ninguna relación con la referencia originalmente establecida a HistorySelect.

Su variante completa significa esencialmente una doble llamada (búsqueda de entradas), la primera de las cuales selecciona la operación en la caché y la segunda accede al resultado almacenado en la caché. En una tarea concreta, en la que se sabe que existe una operación, la primera llamada de selección es redundante. Los métodos Get almacenan implícitamente en caché el registro afectado.



A título informativo, tenemos que exponer internamente los códigos detallados del último error (bajo la llamada GetLastError()), para que los desarrolladores puedan obtener las razones subyacentes del fallo. Por lo general, hay varias comprobaciones de este tipo por llamada en el fondo de la plataforma.
 
Renat Fatkhullin:

No entiendes lo que estás probando. No se trata en absoluto de una opción de Borrar y no hay ninguna relación con la referencia originalmente indicada a HistorySelect.

Parece que no te has dado cuenta.

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

Biblioteca de clases genéricas - errores, descripción, problemas, casos de uso y sugerencias

fxsaber, 2017.12.08 22:46

  BENCH(HistorySelect(0, INT_MAX));
  BENCH(Print(SumProfit(Deals, GetDealProfitClear))); // Реализация с предварительно загруженной историей
O tal vez estemos hablando de cosas diferentes.
 
fxsaber:

Parece que no te has dado cuenta.

O tal vez estemos hablando de cosas diferentes.

Lo he notado.

¿Qué historia precargada? He señalado que HistorySelect en el probador es falso y no hace una transferencia real a la caché de toda la historia especificada en la consulta, pero sólo marca posiciones de & a en la base de datos existente de ofertas. Por lo tanto, el coste es cero.

En GetDealProfitClear, se hace exactamente una petición al mismo lugar utilizando HistoryDealGetDouble(Deal, DEAL_PROFIT), como en su método GetDealProfitFull, incorrectamente entendido, donde hay dos métodos que son exactamente iguales en su esencia física

return(HistoryDealSelect(Deal) ? HistoryDealGetDouble(Deal, DEAL_PROFIT) : 0)

Es decir, el acceso al historial en el probador está muy optimizado y se centra realmente en el hecho de que nadie puede cambiar el historial de operaciones excepto su Asesor Experto (y las comprobaciones siguen ahí).

En el terminal real todo es diferente y HistorySelect es caro.

 
Renat Fatkhullin:

Entiendo lo que quieres decir. Gracias por los detalles. Me pregunto cuál será el resultado.

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

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

Renat Fatkhullin, 2017.12.08 23:19

He mirado nuestro código: es posible optimizar las llamadas a la base comercial. Intentaremos implementarlo para el lanzamiento de la próxima semana.

Sin embargo, el tema genérico es muy útil. Lo seguiré con interés.
 

He comprobado la implementación deCHashMap
Me ha gustado, sinceramente.

//+------------------------------------------------------------------+
//| Class CHashMap<TKey, TValue>.                                    |
//| Usage: Represents a collection of keys and values.               |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
  {
protected:
   int               m_buckets[];                        
   Entry<TKey,TValue>m_entries[];
   int               m_count;
   int               m_free_list;
   int               m_free_count;
   IEqualityComparer<TKey>*m_comparer;
   bool              m_delete_comparer;

public:
                     CHashMap(void);
                     CHashMap(const int capacity);
                     CHashMap(IEqualityComparer<TKey>*comparer);
                     CHashMap(const int capacity,IEqualityComparer<TKey>*comparer);
                     CHashMap(IMap<TKey,TValue>*map);
                     CHashMap(IMap<TKey,TValue>*map,IEqualityComparer<TKey>*comparer);
                    ~CHashMap(void);
   //--- methods of filling data 
   bool              Add(CKeyValuePair<TKey,TValue>*pair);
   bool              Add(TKey key,TValue value);
   //--- methods of access to protected data
   int               Count(void)                                       { return(m_count-m_free_count); }
   IEqualityComparer<TKey>*Comparer(void)                        const { return(m_comparer);           }
   bool              Contains(CKeyValuePair<TKey,TValue>*item);
   bool              Contains(TKey key,TValue value);
   bool              ContainsKey(TKey key);
   bool              ContainsValue(TValue value);
   //--- methods of copy data from collection   
   int               CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0);
   int               CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
   //--- methods of cleaning and deleting
   void              Clear(void);
   bool              Remove(CKeyValuePair<TKey,TValue>*item);
   bool              Remove(TKey key);
   //--- method of access to the data
   bool              TryGetValue(TKey key,TValue &value);
   bool              TrySetValue(TKey key,TValue value);

private:
   void              Initialize(const int capacity);
   void              Resize(int new_size,bool new_hash_codes);
   int               FindEntry(TKey key);
   bool              Insert(TKey key,TValue value,const bool add);
  };


Hay algunas sugerencias de posibles mejoras:

1) En mi humilde opinión, la implementación contiene una elección no del todo correcta de la capacidad - tanto del tamaño inicial 3 como de los subsiguientes al reconstruir la tabla hash.
Sí, es correcto que se elija un número primo para la uniformidad de la distribución.
Sin embargo, la implementación de CPrimeGenerator no cumple las expectativas y contiene omisiones de números primos.
El objetivo de este "generador" es claro: proporcionar un factor de incremento del orden de 1,2 con la generación automática de números primos.
Sin embargo, ¿no es un coeficiente demasiado pequeño? En C++, para los vectores, el coeficiente suele ser de 1,5-2,0, dependiendo de la biblioteca (ya que afecta mucho a la complejidad media de la operación).
La salida podría ser un coeficiente constante seguido del redondeo del número a primo mediante una búsqueda binaria de una lista de números primos.
Y un tamaño inicial de 3 es demasiado pequeño, no vivimos en el siglo pasado.

2) Actualmente la reconstrucción de la tabla hash (Resize) se ejecuta sólo cuando se llena el 100% de la capacidad (todas las m_entradas[] están llenas).
Debido a esto, puede haber muchas colisiones para las claves que no están distribuidas de manera muy uniforme.
Como opción, considere la posibilidad de introducir un factor de llenado que reduzca el 100% del límite requerido para realizar una reconstrucción de la tabla hash.

 
fxsaber:

Y la versión clásica de ¿cuánto devuelve 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 микросекунд

Es el tiempo de ejecución de printf.

De alguna manera has entendido mi ejemplo de forma extraña. No tengo el objetivo de comparar nada con la funcionalidad del MetaTrader estándar. Sólo se trata de cómo organizar algoritmos eficientes de asociaciones y muestreo de cualquier cosa con cualquier cosa a su nivel de usuario. El ejemplo de asociación de un número de trato con un número de pedido debe considerarse sólo como un ejemplo con poco valor práctico, ya que existe un sistemaHistoryDealGetInteger(Deal, DEAL_ORDER).

 
fxsaber:

Pues bien, he aquí una comparación de las dos métricas destacadas. Resulta que el acceso al HashMap es 4 veces más rápido que el de los desarrolladores. Pero los desarrolladores ya lo tienen incluyendo la historia...

Por la misma razón la comparación es incorrecta. ¿Cómo se puede comparar el CHashMap personalizado y el trabajo con las funciones del sistema para conseguir un entorno comercial?