Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 11

 

L'ultimo esempio per oggi e apparentemente per questa settimana: la corrispondenza tra il numero del trade e il numero dell'ordine che lo ha avviato:

//+------------------------------------------------------------------+
//|                                                     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 + " микросекунд");
}

Per il mio caso in cui ci sono più di 10.000 compravendite nel conto, il risultato è il seguente:

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 микросекунд
 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Libreria di classi generiche - bug, descrizione, domande, peculiarità d'uso e suggerimenti

Vasiliy Sokolov, 2017.12.08 13:30

Se N è molto piccolo, si normalizza semplicemente il numero ottenuto dalla funzione hash, in modo che sia sempre nel limite N:

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

Ho letto fino a questo punto finora. Vasily, grazie, tutto è chiaro, tranne quello evidenziato. Secondo me, prendere il residuo come normalizzazione è sbagliato. Sembra più logico

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

Questo è il punto: la dimensione del dizionario è spesso sconosciuta. Un semplice esempio, diciamo che abbiamo un consulente che fa trading. Tiene traccia delle transazioni effettuate. Quando un trade appare nella storia, dobbiamo collegare questo trade con il Medjack dell'Expert Advisor. Per questo è logico usare il dizionario. Dove il numero di trade è usato come chiave (identificatore unico), e il numero magico dell'Expert Advisor è usato come valore. Il problema è che all'inizio dell'EA non possiamo determinare in anticipo se avremo 100 trade, 1000 o nessun trade. Indipendentemente da quanta memoria si alloca in anticipo, sarà sempre o troppo poca o troppo grande.

Ovviamente non mi sono ancora scervellato. Può spiegare cosa viene assegnato? Non lo capisco affatto.

 

Sembra una presa in giro.

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


HashFunction.mqh senza un inlude. Questo non è giusto.


A cosa serve questa funzione?

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));
     }
  }
Dopo tutto, non si compila solo per struct e union.
 
fxsaber:

Credo di non essermi rotto completamente il cervello. Potresti chiarire la parte evidenziata? Non lo capisco affatto.

Personalmente, ho capito che quando si fanno dei trade, l'EA dovrebbe scrivere il numero di un magik nel dizionario (array) per il numero del trade, che in questo caso è un indice di cella.

Il numero di scambi futuri non è noto in anticipo, e dovremmo già avere un array dichiarato per scrivere i maggiori. Il compito è quello di allocare in anticipo la quantità di memoria necessaria per l'array.

È impossibile allocare la quantità esatta di memoria in anticipo. Quindi, potremmo scrivere una stringa con delle stringhe, ottenere il numero di sottostringhe, inizializzare l'array e scrivere tutte le sottostringhe (nidi d'ape) lì.

Poi ogni medjack sarà accessibile per numero di mestiere.

Questo è più o meno come lo vedo io.

 
Vasiliy Sokolov:

L'ultimo esempio per oggi e apparentemente per questa settimana: la corrispondenza tra il numero del trade e il numero dell'ordine che lo ha avviato:

Per il mio caso, in cui ci sono più di 10.000 operazioni sul mio conto, il risultato è il seguente:

Quanto rende la versione classica nel suo 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 микросекунд
Questo è il tempo di esecuzione di printf.
 
fxsaber:

A cosa serve questa funzione?

Non si compila solo per struct e union.

Aggiunto un altro sovraccarico

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


Si è imbattuto in.

//+------------------------------------------------------------------+
//| 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);
  }
Restituisce numeri negativi, il che segue logicamente da tale codice. Va bene?
 
fxsaber:

Aggiunto un altro sovraccarico

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

Mi sembra che se un oggetto non implementa qualche interfaccia o metodo, è meglio generare esplicitamente un'eccezione piuttosto che tenerlo nascosto e poi cercare la fonte del problema senza mezzi termini.


Restituisce numeri negativi, cosa che segue logicamente da tale codice. Va bene?

Assolutamente normale.
L'hash non garantisce nulla, è solo un numero che caratterizza in qualche misura questo o quell'oggetto.
Se avete bisogno di un intero, usate uint.

 
Sergey Dzyublik:

Per quanto mi riguarda, se un oggetto non implementa qualche interfaccia o metodo, è meglio generare esplicitamente un'eccezione piuttosto che tacere e poi cercare la fonte del problema per un tempo sconosciuto.

MqlTick?

 
fxsaber:

MqlTick?


Capite cosa fa il codice se non c'è un'implementazione esplicita della specializzazione della funzione templateGetHashCode per il tipo T?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
Risposta: è patetico perché sorvola sulla mancanza di attuazione. Tutti gli oggetti della stessa classe restituiranno lo stesso valore di hash.