通用类库 - 错误、说明、问题、使用功能和建议 - 页 13

 
雷纳特-法特库林

你不能比较HistorySelect(把访问范围放在测试器中)和HistoryDealSelect(ticket),后者实际上是搜索一个特定的票据并缓存它。

因为了解这一点,所以立即创建了Clear-variant。为了能够同时比较清晰与完整。

 
fxsaber:
这样一来,历史(尤其是在测试器中)只是得到了补充,旧的记录没有被改变。我指的是透明变体。


在现实中,似乎即使一个订单被部分执行并产生了几个交易,它也不会进入历史,直到它被完全填补或取消。也就是说,冻结的历史规则被保留下来。

如果我们写的软件没有检查,那么一切早就崩溃了。

财务软件不允许你在 "偷工减料 "模式下写作。你在一个地方切,然后在另一个地方切,然后开发商会相信有权跳过硬性检查,失败是不可避免的。

在测试器中,你仍然可以减少检查,但在真正的EA中,有许多异步进程在整个市场环境的不断变化中与你的EA的工作同时进行。你甚至不能考虑在MQL5调用之间保存的东西。

 
雷纳特-法特库林

如果我们写的软件没有检查,那么一切早就崩溃了。

财务软件不允许你在 "偷工减料 "模式下写作。你在一个地方切,然后在另一个地方切,然后开发商会相信有权跳过硬性检查,失败是不可避免的。

你仍然可以在测试器中放松检查,但在现实世界中,有很多异步进程在不断改变整个市场环境,与你的专家顾问并行工作。想想看,在MQL5调用之间会有一些东西被保存,这是很可怕的。

谢谢你的澄清!希望测试员能把它弄得更紧一些。

 
fxsaber:

由于这种理解,"透明 "变体立即被创建。因此,你可以同时比较清晰与完整。

你误解了你的测试内容。这绝不是Clear variant,与最初所说的HistorySelect 的参考没有关系。

你的Full variant本质上是指一个双倍的调用(ticket lookup),其中第一个选择交易进入缓存,第二个访问缓存的结果。在一个特定的任务中,如果已知存在交易,第一次选择调用是多余的。获取方法隐含地缓存了受影响的记录。



为了获得信息,我们在内部必须公开详细的最后错误代码(在GetLastError()调用下),这样开发者就可以获得失败的根本原因。通常情况下,每次调用都有几个这样的检查,深入到平台。
 
雷纳特-法特库林

你误解了你的测试内容。这绝不是一个清除选项,而且与最初所说的HistorySelect的参考没有任何联系。

看来你没有注意到这一点。

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

通用类库 - 错误、描述、问题、用例和建议

fxsaber, 2017.12.08 22:46

  BENCH(HistorySelect(0, INT_MAX));
  BENCH(Print(SumProfit(Deals, GetDealProfitClear))); // Реализация с предварительно загруженной историей
或者,也许我们在谈论不同的事情。
 
fxsaber:

你似乎没有注意到。

或者,也许我们在谈论不同的事情。

注意到了。

什么预装历史?我指出,测试器中的 HistorySelect是假的,并没有把查询中指定的所有历史记录真正转移到缓存中,而只是在现有的交易数据库中标记了从和到的位置。因此,成本为零。

在GetDealProfitClear中,你正好使用HistoryDealGetDouble(Deal,DEAL_PROFIT)向同一个地方提出请求,就像你被误解的GetDealProfitFull方法一样,它使用的两个方法在物理本质上完全相同

return(HistoryDealSelect(Deal) ? HistoryDealGetDouble(Deal, DEAL_PROFIT) : 0)

也就是说,在测试器中对历史的访问是非常优化的,真正的重点是除了你的专家顾问,没有人可以改变交易历史(而且检查还在那里)。

在真正的终端中,一切都不同,HistorySelect很昂贵。

 
雷纳特-法特库林

我明白你的意思。谢谢你提供的细节!我想知道结果会是什么。

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

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

Renat Fatkhullin, 2017.12.08 23:19

我看了我们的代码--有可能优化对贸易 基础的调用。我们将尝试在下周的发布中实施。

而通用的主题是非常有用的,虽然!我将饶有兴趣地关注它。
 

检查了CHashMap 的实现
,说实话,我很喜欢它。

//+------------------------------------------------------------------+
//| Class CHashMap<TKey, TValue>.                                    |
//| Usage: Represents a collection of keys and values.               |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
  {
protected:
   int               m_buckets[];                        
   Entry<TKey,TValue>m_entries[];
   int               m_count;
   int               m_free_list;
   int               m_free_count;
   IEqualityComparer<TKey>*m_comparer;
   bool              m_delete_comparer;

public:
                     CHashMap(void);
                     CHashMap(const int capacity);
                     CHashMap(IEqualityComparer<TKey>*comparer);
                     CHashMap(const int capacity,IEqualityComparer<TKey>*comparer);
                     CHashMap(IMap<TKey,TValue>*map);
                     CHashMap(IMap<TKey,TValue>*map,IEqualityComparer<TKey>*comparer);
                    ~CHashMap(void);
   //--- methods of filling data 
   bool              Add(CKeyValuePair<TKey,TValue>*pair);
   bool              Add(TKey key,TValue value);
   //--- methods of access to protected data
   int               Count(void)                                       { return(m_count-m_free_count); }
   IEqualityComparer<TKey>*Comparer(void)                        const { return(m_comparer);           }
   bool              Contains(CKeyValuePair<TKey,TValue>*item);
   bool              Contains(TKey key,TValue value);
   bool              ContainsKey(TKey key);
   bool              ContainsValue(TValue value);
   //--- methods of copy data from collection   
   int               CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0);
   int               CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
   //--- methods of cleaning and deleting
   void              Clear(void);
   bool              Remove(CKeyValuePair<TKey,TValue>*item);
   bool              Remove(TKey key);
   //--- method of access to the data
   bool              TryGetValue(TKey key,TValue &value);
   bool              TrySetValue(TKey key,TValue value);

private:
   void              Initialize(const int capacity);
   void              Resize(int new_size,bool new_hash_codes);
   int               FindEntry(TKey key);
   bool              Insert(TKey key,TValue value,const bool add);
  };


有几条可能的改进建议。

1)在我看来,实现中对容量的选择不太正确--包括初始大小3和重建哈希表时的后续容量。
是的,应该选择一个素数来实现分布的均匀性,这是正确的。
然而,CPrimeGenerator的实现并不符合预期,包含了质数的遗漏。
这样一个 "生成器 "的目的很明确--提供一个增量系数为1.2的自动生成素数。
然而,这个系数不是太小了吗?在C++中,对于向量来说,系数通常是1.5-2.0,这取决于库(因为它强烈地影响着操作的平均复杂性)。
出路可能是一个常数系数,然后通过对素数列表的二进制搜索,将数字四舍五入 到素数。
而3的初始规模太小了,我们不是生活在上个世纪。

2) 目前哈希表重建(Resize)只在100%的容量被填满时执行(所有的m_entries[]被填满)。
正因为如此,对于分布不是很均匀的钥匙,可能会有很多碰撞。
作为一种选择,考虑引入一个填充因子,通过所需的限制来减少100%,以执行哈希表重建。

 
fxsaber:

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

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的执行时间。

你对我的例子不知怎么理解的,很奇怪。我的目标不是要与标准MetaTrader的功能作任何比较。这只是关于如何在你的用户层面上安排高效的关联算法和对任何事物的采样。交易号码与订单号码关联的例子应该只被视为一个实际价值不高的例子,因为有一个系统HistoryDealGetInteger(Deal, DEAL_ORDER)

 
fxsaber:

好吧,这里是两个突出的数字的比较。事实证明,HashMap的访问速度是开发者的4倍。但是开发商已经有了它,包括历史...

出于同样的原因,这种比较是不正确的。如何比较自定义CHashMap和使用系统功能获得交易环境?