通用类库 - 错误、说明、问题、使用功能和建议 - 页 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 + " микросекунд");
}

对于我的情况,即账户里有超过10,000个交易,结果如下。

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

关于交易、自动交易系统和交易策略测试的论坛

通用类库 - 错误、描述、问题、使用的特殊性和建议

Vasiliy Sokolov, 2017.12.08 13:30

如果N非常小,我们只需将哈希函数得到的数字归一化,这样它就会一直处于N的极限。

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

到目前为止,我已经读到了这一点。瓦西里,谢谢,一切都很清楚了,除了强调的那一点。在我看来,把残余物作为归一化是错误的。这似乎更符合逻辑

int index = GetHashCode(word) * ArraySize(m_array) / HashSize; // Надо бы и округлять, а не отбрасывать нецелочисленную часть, но не стал усложнять
 
瓦西里-索科洛夫

这就是问题所在:字典的大小往往是未知的。一个简单的例子,假设我们有一个顾问交易。它跟踪已执行的交易。当一个交易出现在历史上时,我们需要将这个交易与专家顾问的Medjack联系起来。为此,使用字典是合乎逻辑的。其 中,交易号码被用作键(唯一的标识符),而专家顾问的神奇号码被用作值。问题是,在EA开始时,我们无法事先确定我们是否会有100个交易、1000个交易或没有交易。不管你事先分配了多少内存,它还是会太少或太多。

我显然还没有绞尽脑汁。你能解释一下正在分配的是什么吗?我一点也不明白。

 

它看起来像一个嘲弄。

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


HashFunction.mqh没有一个inlude。这是不对的。


这个功能有什么用?

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));
     }
  }
毕竟,它不会只为结构体和联合体进行编译。
 
fxsaber:

我想我还没有完全破解我的大脑。你能说明一下突出的问题吗?我一点也不明白。

我个人的理解是,当交易进行时,EA应该按交易的编号将magik的编号写进字典(数组),在这种情况下是一个单元格索引。

未来的交易数量是事先不知道的,我们应该已经声明了一个数组,用于编写主修课程。任务是提前为阵列分配必要的内存量。

不可能提前分配准确的内存量。所以,我们可以用字符串写一个字符串,得到子串的数量,初始化数组,并将所有子串(蜂巢)写在那里。

然后,每个medjack将按交易号码访问。

我大致上是这样看的。

 
Vasiliy Sokolov:

今天的最后一个例子,显然也是本周的最后一个例子:交易号码和启动交易的订单号码之间的对应关系。

对于我的情况,我的账户中有超过10,000个交易,结果如下。

在你的情况下,经典版本的回报是多少?

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:

这个功能有什么用?

不会只对结构和联盟进行编译。

增加了另一个重载

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。

 
谢尔盖-迪尤布利 克。

对我来说,如果一个对象没有实现某些接口或方法,与其保持沉默,然后在未知的时间内寻找问题的来源,不如明确地产生一个异常。

MqlTick?

 
fxsaber:

MqlTick?


如果没有对T类型的GetHashCode 模板函数的明确实现,你明白代码的作用吗?
template<typename T>
int GetHashCode(T &value)
  {
    return GetHashCode(typename(value));
  }
答案是:这很可悲,因为它掩盖了实施的不足。同类的所有对象将返回相同的哈希值。