文章 "交易员生存技巧: 由指标制作的快餐" - 页 2

 
Renat Fatkhullin:

...

此外,从指标中提取 1 个值的效率不高。

...

所有这些都是理论上的。但实际上,99% 的指标都是在先进先出环形缓冲区中计算的:删除最后一个元素,添加一个新元素,重新计算指标。也就是说,在实践中,计算缓冲区的添加也是由一个元素完成的,而指标中 99% 的计算 都是添加一个元素。因此,"CopyBuffer"、"CopyRates"、"CopyXXX "的想法很好,但与主题领域不符

 
Renat Fatkhullin:

...

难以想象的是,指标句柄的泄漏(为什么要关闭指标句柄?)和惊人的开销(试图重新创建指标,落入指标管理器内部)。足够多的人会在不看不理解的情况下复制它。

...

不清楚您的意思。据我所知,在任何地方都不会关闭句柄(不会调用 IndicatorRelease)。我们会不断调用 Hendle 创建的标准函数,如 iMACD:

//+------------------------------------------------------------------+
//| 以 MQL4 符号表示的 iMACD 函数|
//| 缓冲区编号如下:|||......
//| mql4 0 - mode_main, 1 - mode_signal|
//| mql5 0 - main_line,1 - signal_line|
//+------------------------------------------------------------------+
double   iMACD(
               string                     symbol,              // 符号名称 
               ENUM_TIMEFRAMES            timeframe,           // 时限 
               int                        fast_ema_period,     // 快速平均计算期 
               int                        slow_ema_period,     // 用于计算慢速平均值的时间段 
               int                        signal_period,       // 差值平均的周期 
               ENUM_APPLIED_PRICE         applied_price,       // 价格或句柄类型 
               int                        buffer,              // 缓冲区 
               int                        shift                // 移位
               )
  {
   
   double result=NaN;
//---
   int handle=iMACD(symbol,timeframe,fast_ema_period,slow_ema_period,signal_period,applied_price);
   if(handle==INVALID_HANDLE)
     {
      Print(__FUNCTION__,": INVALID_HANDLE error=",GetLastError());
      return(result);
     }
   double val[1];
   int copied=CopyBuffer(handle,buffer,shift,1,val);
   if(copied>0)
      result=val[0];
   else
      Print(__FUNCTION__,": CopyBuffer error=",GetLastError());
   return(result);
  }

显然,整个游戏的基础是 iMACD 和类似函数将先前返回的句柄缓存在自己内部,因此不应该重新创建指标。

 
Vasiliy Sokolov:

所有这些都是理论上的。但实际上,99% 的指标都是在先进先出环形缓冲区中进行计算:删除最后一个元素,添加一个新元素,重新计算指标。也就是说,在实践中,计算缓冲区的添加也是由一个元素完成的,而指标中 99% 的计算 都是添加一个元素。因此,"CopyBuffer"、"CopyRates"、"CopyXXX "的想法很美,但与主题领域并不相符

如果您编写的是最简单、最原始的最后查看处理程序,情况就会如此。但是,只要你往旁边迈出一步,开始检查 2 个或更多点,你就会立即看到区别和效果。

当然,一般来说,听到 CopyXXX 函数据说不在主题范围内是很奇怪的。

对于进入市场环境的基本功能,您应该尽量少说这样的话。


还有--给指标 100%的全部历史记录进行计算不是没有道理的:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
这是为了证明不存在 "环形缓冲区中的 99%"。我们非常需要的是对历史的大规模访问,而不是单一的最后值。
 
Vasiliy Sokolov:

不清楚您所说的是什么意思。据我所知,hendle 并没有在任何地方关闭 没有调用 IndicatorRelease)。会不断调用 hendle 创建的标准函数,如 iMACD:

显然,整个游戏的基础是 iMACD 和类似函数将先前返回的句柄缓存在自己内部,因此不应该重新创建指标。

整个游戏建立在黑客攻击和完全无视句柄控制的基础上。

另一个交易者使用这些代码,不注意句柄的分配,开始调用不同的参数,乘用指标,丢失所有句柄,然后被刹车和内存消耗吓了一跳。

谁的责任可想而知。

 
fxsaber:

这篇文章是另一篇 文章的一小部分节选。

我没有看到任何类比。

fxsaber:

没有采取任何措施使其高效运行。没有对指标和时间序列进行缓存。

这里确实有优化的空间。引入缓存将是一个非常好的主意。

fxsaber:

缺少 High[i]、Low[i] 等。

它们应该出现吗?我认为文章的标题(或者更确切地说是其描述)明确指出只涉及指标?

fxsaber:

没有 iCustom。

不幸的是,MQL 不支持带有任意数量参数的函数,因此 iCustom 无法 "像在 MT4 中一样 "实现。

fxsaber:

本以为会看到完全不同的东西。此外,EA 中的快餐有什么意义呢?

我认为不可能在一篇文章中写出一个完全模拟 MT4 风格的完整引擎。主题很明确:以 MQL4 风格使用指标(可惜文章标题没有反映主题,令人困惑)。

 
Renat Fatkhullin:

...

这是为了证明 "环形缓冲区中没有 99%"。我们非常需要的是对历史记录的大量访问,而不是单一的最后值。

有,而且比经常使用更频繁一些。只是没有特殊手段,开发人员不得不创建嵌套循环。打开任何带有双嵌套 for 的指标:恭喜你,环形缓冲区已经找到了。下面是您超高效计算 MFI指标的 示例:

//+------------------------------------------------------------------+
//| 根据参数 | 按体积计算 MFI
//+------------------------------------------------------------------+
void CalculateMFI(const int nPosition,
                  const int nRatesCount,
                  const double &HiBuffer[],
                  const double &LoBuffer[],
                  const double &ClBuffer[],
                  const long &VolBuffer[],
                  const datetime &time[])
  {
   for(int i=nPosition;i<nRatesCount && !IsStopped();i++)
     {
      double dPositiveMF=0.0;
      double dNegativeMF=0.0;
      double dCurrentTP=TypicalPrice(HiBuffer[i],LoBuffer[i],ClBuffer[i]);
      if(time[i] == D'2016.05.23')
         int dbg = 4;
      for(int j=1;j<=ExtMFIPeriod;j++)
        {
         int    index=i-j;
         double dPreviousTP=TypicalPrice(HiBuffer[index],LoBuffer[index],ClBuffer[index]);
         if(dCurrentTP>dPreviousTP)
            dPositiveMF+=VolBuffer[index+1]*dCurrentTP;
         if(dCurrentTP<dPreviousTP)
            dNegativeMF+=VolBuffer[index+1]*dCurrentTP;
         dCurrentTP = dPreviousTP;
        }
      if(dNegativeMF!=0.0) ExtMFIBuffer[i]=100.0-100.0/(1+dPositiveMF/dNegativeMF);
      else                 ExtMFIBuffer[i]=100.0;
     }
  }

很明显,该指标的计算速度取决于平均周期,而事实并非如此。这样的例子有很多,有些还是 MQ 自己写的,你却说没有环形缓冲区。

 
Vasiliy Sokolov:

确实有,而且使用的频率比一直以来都要高一些。只是没有专门的工具,开发人员不得不创建嵌套循环。打开任何带有双嵌套 for 的指标:恭喜你,环形缓冲区已经找到了。下面是您超高效计算 MFI指标的 示例:

很明显,该指标的计算速度取决于平均周期,而事实并非如此。有很多这样的例子,其中一些是 MQ 自己写的,你说没有环形缓冲区。

99% 的情况下都没有环形缓冲器。90% 的情况下没有环形缓冲区,50% 的情况下没有环形缓冲区。但在 OnCalculate 参数中,有 100% 的初始数据量(整个历史深度)。

这甚至不是计算指标的问题,而是使用指标结果和访问源数据的问题。需要的是大规模访问,而不是单一访问。

您试图以 "整个分析市场由最后一个指标值来代表 "和 "CopyXXXX 与主题领域不符 "的方式来说明情况。

你在极力勾勒。

 
Renat Fatkhullin:

...

这甚至不是计算指标的问题,而是利用指标结果和获取原始数据的问题。需要的是大规模的获取,而不是单一的获取。

...

请注意 #1923700。频繁访问大量数据存在一些问题。

已经很久没有评论和问题了,请提供更多意见,帮助找出造成这一结果的原因。

 
Renat Fatkhullin:

另一个交易者使用这段代码,不注意分配句柄,开始调用不同参数,乘以指标,丢失所有句柄,然后对刹车和内存消耗感到惊讶。

同样,其他交易者也可以开始调用带有不同参数的标准 iHandles。如果参数不同,无论您是直接使用句柄还是使用 MQL4-Style,都会创建不同的指标。

 
Renat Fatkhullin:

你很努力地在画素描。

这是一种耻辱。

而且,这根本不是计算指标的问题,而是把指标作为结果的问题。

是的。

雷纳特-法特胡林

...

总之,我不想争论,因为这毫无意义。如果能对复制****功能的使用情况进行统计,那将会非常有趣。用户平均复制了多少条目,这将说明很多问题。