Biblioteca de classes genéricas - bugs, descrição, perguntas, recursos de uso e sugestões - página 11

 

O último exemplo para hoje e aparentemente para esta semana: a correspondência entre o número de comércio e o número de ordem que o iniciou:

//+------------------------------------------------------------------+
//|                                                     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 o meu caso em que existem mais de 10.000 transacções na conta, o resultado é o seguinte:

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

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Biblioteca de classes genéricas - bugs, descrição, perguntas, peculiaridades de uso e sugestões

Vasiliy Sokolov, 2017.12.08 13:30

Se N é muito pequeno, simplesmente normalizamos o número obtido pela função hash, para que esteja sempre no limite de N:

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

Até agora, li até aqui. Vasily, obrigado, está tudo claro, excepto o destacado. Na minha opinião, tomar o resíduo como uma normalização é errado. Parece mais lógico

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

O problema é esse: o tamanho do dicionário é muitas vezes desconhecido. Um exemplo simples, digamos que temos um consultor a negociar. Rastreia os negócios realizados. Quando uma troca aparece na história, precisamos de ligar esta troca com o Medjack do Expert Advisor. Para isso, é lógico usar o dicionário. Onde o número da negociação é usado como chave (identificador único), e o número mágico do Expert Advisor é usado como um valor. O problema é que no início da EA não podemos determinar antecipadamente se teremos 100 negociações, 1000 ou nenhuma negociação. Independentemente da quantidade de memória que você alocar de antemão, ela ainda será muito pequena ou muito grande.

É óbvio que ainda não me arrebentei. Podes explicar o que está a ser atribuído? Eu não entendo nada disso.

 

Parece um escárnio.

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


HashFunction.mqh sem um inlude. Isto não está certo.


Qual é a utilidade desta função?

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));
     }
  }
Afinal de contas, não vai compilar apenas para estruturação e união.
 
fxsaber:

Acho que ainda não parti completamente o meu cérebro. Poderia esclarecer o destacado? Eu não entendo nada disso.

Pessoalmente, entendi que quando as trocas são feitas, a EA deve escrever o número de um magik no dicionário (array) pelo número da troca, que neste caso é um índice de células.

O número de futuras negociações não é conhecido antecipadamente, e já devemos ter um array declarado para escrever as majors. A tarefa é alocar com antecedência a quantidade de memória necessária para a matriz.

É impossível alocar com antecedência a quantidade exata de memória. Assim, poderíamos escrever um cordel com cordas, obter o número de substratos, inicializar a matriz e escrever todos os substratos (favos de mel) ali.

Então cada medjack será acessado pelo número do comércio.

É mais ou menos assim que eu vejo as coisas.

 
Vasiliy Sokolov:

O último exemplo para hoje e aparentemente para esta semana: a correspondência entre o número de comércio e o número de ordem que o iniciou:

Para o meu caso onde existem mais de 10.000 transacções na conta, o resultado é o seguinte:

Quanto é que a versão clássica retorna no seu 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 é o tempo de execução do printf.
 
fxsaber:

Qual é a utilidade desta função?

Não se limitará a compilar para estruturação e união.

Acrescentou outra sobrecarga

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


Encontrei-me.

//+------------------------------------------------------------------+
//| 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);
  }
Retorna números negativos, que logicamente decorrem de tal código. Está tudo bem?
 
fxsaber:

Acrescentou outra sobrecarga

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

Parece-me que se um objeto não implementar alguma interface ou método, é melhor gerar explicitamente uma exceção do que mantê-lo em silêncio e depois procurar a fonte do problema em termos inequívocos.


Ele retorna números negativos, o que logicamente se segue a esse código. Está tudo bem?

Absolutamente normal.
Hash não lhe garante nada, é apenas um número que caracteriza este ou aquele objecto até certo ponto.
Se precisar de um número inteiro, use uint.

 
Sergey Dzyublik:

Quanto a mim, se um objeto não implementa alguma interface ou método, é melhor gerar explicitamente uma exceção do que ficar em silêncio e depois procurar a fonte do problema por um tempo desconhecido.

MqlTick?

 
fxsaber:

MqlTick?


Você entende o que o código faz se não houver uma implementação explícita da especialização da função do modeloGetHashCode para o tipo T?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
Resposta: é patético, porque encobre a falta de implementação. Todos os objetos da mesma classe retornarão o mesmo valor de hash.
Razão: