Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения - страница 11

 

Последний пример на сегодня и по всей видимости на этой неделе: соответствие между номером сделки и номером ордера, который ее инициировал:

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

Для моего случая где сделок на счете больше 10000 результат следующий:

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

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения

Vasiliy Sokolov, 2017.12.08 13:30

Если N очень мало, то мы просто нормируем число полученное хеш-функцией, таким образом, что бы оно всегда находилось в пределе N:

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

Дочитал пока до этого места. Василий, Спасибо, все ясно, кроме выделенного. По-моему, взятие по остатку в качестве нормировки ошибочно. Так видится логичней

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

В том то и дело, что размер словаря часто не известен. Простой пример, допустим, у нас торгует советник. Он отслеживает совершенные сделки. После появления сделки в истории, требуется связать эту сделку допустим с меджиком эксперта. Для этого логично использовать словарь. Где в качестве ключа (уникального идентификатора) используется номер сделки, а в качестве значения - магический номер эксперта. Проблема в том, что при запуске советника ни как нельзя определить заранее будут ли у нас 100 сделок, 1000 или вообще ни одной. Сколько памяти за ранее не выделяй, ее все равно будет либо мало, либо слишком много.

Я, видимо, мозг не до конца сломал. Могли бы Вы пояснить выделенное? Совсем не понимаю.

 

Выглядит, как издевка

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


HashFunction.mqh без инклуда. Неправильно это.


Какой толк в этой функции?

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));
     }
  }
Ведь для struct и union не будет просто компилироваться.
 
fxsaber:

Я, видимо, мозг не до конца сломал. Могли бы Вы пояснить выделенное? Совсем не понимаю.

Лично я это понял так, что при совершении сделок советник должен записывать номер мэджика в словарь (массив) по номеру сделки, который в данном случае является индексом ячейки.

Количество будущих сделок заранее неизвестно, а для записи меджиков у нас уже должен быть объявлен массив. Задача в том, чтобы выделить под массив нужный объем памяти заранее.

Заранее выделить точный объем памяти невозможно. Значит, можно записывать меджики в строку, в конце получить количество подстрок, инициализировать массив и записать туда все подстроки (меджики).

Далее доступ к каждому меджику будет осуществлятся по номеру сделки.

Примерно так себе это представляю.

 
Vasiliy Sokolov:

Последний пример на сегодня и по всей видимости на этой неделе: соответствие между номером сделки и номером ордера, который ее инициировал:

Для моего случая где сделок на счете больше 10000 результат следующий:

А классический вариант сколько возвращает в Вашем случае?

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 микросекунд
Это время выполнения printf.
 
fxsaber:

Какой толк в этой функции?

Ведь для struct и union не будет просто компилироваться.

Добавил еще одну перегрузку

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


Столкнулся, что

//+------------------------------------------------------------------+
//| 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);
  }
Возвращает отрицательные числа, что логично вытекает из такого кода. Это нормально?
 
fxsaber:

Добавил еще одну перегрузку

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

Как по мне, если объект не реализует некий интерфейс или метод, то лучше явно генерировать исключение, чем втихую замалчивать, а потом непонятно сколько искать источник проблем.


Возвращает отрицательные числа, что логично вытекает из такого кода. Это нормально?

Абсолютно нормально.
Хеш ни что вам не гарантирует, это просто число которое в определенной мере характиризирует тот или иной объект.
Если нужно целое - смело берите uint.

 
Sergey Dzyublik:

Как по мне, если объект не реализует некий интерфейс или метод, то лучше явно генерировать исключение, чем втихую замалчивать, а потом непонятно сколько искать источник проблем.

MqlTick?

 
fxsaber:

MqlTick?


Вы понимаете что делает код, если отсутствует явная реализация специализация шаблонной функции GetHashCode для типа T?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
Ответ: пакость, поскольку замалчивается проблема отсутствия реализации. Все объекты одного и того же класса будут возвращать одинаковое значение хеша.
Причина обращения: