Generic Class Library - bugs, description, questions, usage and suggestions - page 11

 

The last example for today and apparently for this week: the correspondence between the trade number and the number of the order that triggered it:

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

For my case where there are more than 10,000 trades in my account, the result is as follows:

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 on trading, automated trading systems and trading strategies testing

Generic classes library - errors, description, questions, peculiarities of use and suggestions

Vasiliy Sokolov, 2017.12.08 13:30

If N is very small, we simply normalize the number obtained by the hash function, so that it would always be in the N limit:

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

I've read it up to this point so far. Vasily, Thanks, everything is clear, except for the highlighted one. In my opinion, taking the remainder as a normalization is wrong. This seems more logical.

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

That's the thing: the size of the dictionary is often unknown. A simple example, let's say we have an Expert Advisor that trades. It tracks performed trades. When a trade appears in the history, we need to associate this trade with the EA's "Medjic". For this it is logical to use the dictionary. Where the deal number is used as a key (unique identifier), and the magic number of the Expert Advisor is used as a value. The problem is that at the start of the EA we cannot determine in advance if we will have 100 trades, 1000 or none. No matter how much memory you allocate in advance, it will still be either too little or too much.

I guess I haven't racked my brains yet. Could you please explain what you just said? I don't understand it at all.

 

It looks like a mockery.

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


HashFunction.mqh without the hook. This is not right.


What's the use of this function?

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));
     }
  }
After all, it won't just compile for struct and union.
 
fxsaber:

I guess I haven't completely cracked my brain. Could you clarify the highlighted? I don't understand it at all.

Personally, I understood it as follows: when making trades, the Expert Advisor should write the number of a magik in the dictionary (array) according to the number of the trade, which in this case is the index of the cell.

The number of future trades is not known in advance, and we should already have an array declared for writing the majors. The task is to allocate the necessary amount of memory for the array in advance.

It's impossible to allocate the exact amount of memory in advance. So, we could write a string of hashes, get number of substring, initialize the array and write all its substring (hashes).

Then each medjack will be accessed by trade number.

That's roughly how I see it.

 
Vasiliy Sokolov:

The last example for today and apparently for this week: the correspondence between the trade number and the number of the order that triggered it:

For my case where there are more than 10,000 trades in my account, the result is as follows:

How much does the classical variant return in your case?

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 микросекунд
This is the execution time of printf.
 
fxsaber:

What's the use of this function?

Will not just compile for struct and union.

Added another overload

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


Ran into.

//+------------------------------------------------------------------+
//| 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);
  }
Returns negative numbers, which logically follows from such code. Is this normal?
 
fxsaber:

I added one more overload.

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

To me, if an object doesn't implement some interface or method, it's better to explicitly generate an exception than to keep it quiet and then look for the source of the problem.


It returns negative numbers, which logically follows from this code. Is it normal?

Absolutely normal.
Hash doesn't guarantee you anything, it's just a number that characterizes this or that object to some extent.
If you need an integer, you can use uint.

 
Sergey Dzyublik:

As for me, if an object does not implement some interface or method, it is better to explicitly generate an exception than to keep silent and then search for the source of the problem.

MqlTick?

 
fxsaber:

MqlTick?


Do you understand what the code does if there is no explicit implementation of theGetHashCode template function specialization for type T?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
Answer: it's pathetic because it glosses over the problem of lack of implementation. All objects of the same class will return the same hash value.