错误、漏洞、问题 - 页 3027

 
Сергей Таболин:

指标是我最薄弱的地方 ))))

但是!

要么我根本不懂,要么你有点错。

据我所知,prev_calculated是一个未计算数据的计数器。而一旦传入的数据被计数,该计数器就会被重置......。就像,就这样,伙计,没有更多的新数据可以计算....。)))

而在这种情况下,指标应该完全 重新计算的原因是什么--我不知道!

---------------

说了一个小谎 ))))

不是指标被重新计算,而是 "指数 "被重新计算,以使它们在历史上 "看起来不错";)

计数器由于程序员无法控制的原因而被重置,就像指示器第一次启动一样!

我不希望我的信息在难以理解的解释中丢失,但它终于到达了开发商那里。



我们需要注意OnCalculate()返回的值和第二个输入参数prev_calculated之间的联系。在调用函数时,prev_calculated参数包含了前一次调用时OnCalculate()返回的值。这允许在计算自定义指标 时采用经济的算法,以避免对那些自上次调用此函数以来没有变化的条形图进行重复计算。

-一个不能正常工作的计算打破了整个经济计算的概念。
 
Andrey Dik:
计数器因程序员无法控制的原因而被重置,就像指示灯第一次运行一样!

我不想让我的信息在难以理解的掌声中消失,但它确实传到了尊敬的开发者那里。

每一个新酒吧都是这样的吗?他们被安抚了,不是吗?

如果不是每一个柱子,有不同的原因来重设pre_calc。

 

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

虫子、虫子、问题

Andrey Dik, 2021.05.27 13:53

也就是说,一旦新的 时间框架 出现,预先计算的计数器就会被清零。这意味着指标会被重新计算,就像它第一次启动时一样

这样的结构你熟悉吗?

if (rates_total == prev_calculated) return rates_total;
  
int startInd = rates_total - prev_calculated;

for (int i = startInd; i >= 0; i--)
{
  //тут считаем индикатор, который обращается к другому индикатору на старшем ТФ
}

问题不在于EA的逻辑(重画、不重画、少画或其他什么),而在于prev_calculated被重置,而没有人要求它这样做!这就是问题所在。

我认为问题在于。

if (rates_total == prev_calculated) return rates_total;

你不要让另一个TF上的被调用的指标计算每一个tick,然后你调用它,历史是同步的,从该指标的零开始计算。


我创建了一个测试,被调用的指标计算了所有内容,但没有重置为prev_calculated == 0。

我在指标中画了收盘,并以一个新的条形图和prev_calculated == 0来解开事件。

// tst.mq5

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[])
{
   int start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }
   
   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}

调用这个指标(获得缓冲区的最后两个值),同时在你的TF上画出收盘价。

input ENUM_TIMEFRAMES TF = PERIOD_M5;
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   ind_handle = iCustom(NULL, TF, "NewFolder\\tst");
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
{
   int start;
   static datetime t = 0;
   if(t != time[rates_total-1])
   {
      t = time[rates_total-1];
      Print(MQLInfoString(MQL_PROGRAM_NAME), " New bar ", t);
   }

   if(prev_calculated == 0)
   {
      start = 0;
      ArrayInitialize(Buffer, EMPTY_VALUE);
      Print(MQLInfoString(MQL_PROGRAM_NAME), " prev_calculated == 0");
   }
   else start = prev_calculated - 1;


   for(int i = start; i < rates_total; i++)
   {
      Buffer[i] = close[i];
   }
   double buf[];
   if(CopyBuffer(ind_handle, 0, 0, 2, buf) < 0) Print("Error CopyBuffer # ",GetLastError());
//--- return value of prev_calculated for next call
   return(rates_total);
}


运行M1的最后一个指标,对数。

2021.05.27 21:48:34.196 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:48:00

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) tst_tf prev_calculated == 0

2021.05.27 21:48:34.197 tst_tf (EURUSD,M1) Error CopyBuffer # 4806

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst 新栏 2021.05.27 21:45:00

2021.05.27 21:48:34.197 tst (EURUSD,M5) tst prev_calculated == 0

2021.05.27 21:49:01.636 tst_tf (EURUSD,M1) tst_tf new bar 2021.05.27 21:49:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:50:00

2021.05.27 21:50:00.149 tst_tf (EURUSD,M5) tst 新栏 2021.05.27 21:50:00

2021.05.27 21:51:01.789 tst_tf (EURUSD,M1) tst_tf 新条 2021.05.27 21:51:00

2021.05.27 21:52:02.832 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:52:00

2021.05.27 21:53:00.920 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:53:00

2021.05.27 21:54:02.778 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:54:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:55:00

2021.05.27 21:55:00.308 tst_tf (EURUSD,M5) tst 新栏 2021.05.27 21:55:00

2021.05.27 21:56:00.118 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:56:00

2021.05.27 21:57:00.419 tst_tf (EURUSD,M1) tst_tf 新栏 2021.05.27 21:57:00

 
Andrey Khatimlianskii:

每家新酒吧都是这样的吗?他们是过度保险还是什么......。

如果不是在每个柱子上,有不同的原因来重置pre_calc。

确切地说,是在每一个主要TF的新条上。

例如,如果指标在M1上工作,在M5上访问指标,那么每5分钟,指标将被完全重新计算。

 
Igor Makanu:

我认为问题在于。

你不能让另一个TF上的被调用指标每隔一段时间就计算一次,然后你调用它,历史记录就会同步,并从该指标的零开始计算。


我创建了一个测试,被调用的指标计算了所有内容,但没有重置为prev_calculated == 0。

我在指标中画了收盘,然后用一个新的条形图解开事件,并且prev_calculated == 0 。

调用该指标(获得缓冲区的最后两个值),同时在你的TF上画出收盘价。

我检查所要求的更高的TF(M5)上的数据同步 和指标的准备情况,如果它没有准备好,则退出。

因此,该指标只在M1栏开盘时工作一次,而不是在每个tick上工作。


//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

//проверка на наличие нового бара
if (rates_total == prev_calculated) return rates_total;

我希望开发商能听从我的请求。

 
Andrey Dik:

我检查所要求的更高的TF(M5)上的数据同步 和其上指标的准备情况,如果没有准备好,则退出。

因此,该指标只在M1栏开盘时工作一次,而不是在每个tick上工作。


我希望开发商能听从我的请求。

这不应该在指标中正确工作。

if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))

如果我没有弄错的话,在帮助中,有一个关于所有TFs的分页数据的脚本明细,应该有一个警告,即不能从指标中请求历史数据,因为该指标是异步工作的。

建议在你绑定句柄后使用BarsCalculated()一次。


UPD: 历史分页的脚本和解释为什么它在指标中不起作用:https://www.mql5.com/ru/docs/series/timeseries_access

 
Andrey Dik:

我检查所要求的更高的TF(M5)上的数据同步 和其上指标的准备情况,如果它没有准备好,则退出。

因此,该指标只在M1栏开盘时工作一次,而不是在每个tick上工作。


我真的必须使用我的自定义预计算吗? 我希望开发者能听从我的请求。

这样的检查是为了什么?

//проверка готовности данных и индикатора на другом TF
if (SeriesInfoInteger (Symbol (), tf, SERIES_SYNCHRONIZED))
{
  if (iBars (Symbol (), tf) != BarsCalculated (handleFr)) return 0;
}
else return 0;

如果写成return 0;没有条件,那就简单多了。

在每个新的条形图上,条件将被满足,所有条形图将被重新计算,而不考虑同步性。你写了一个考虑不周的代码,并假装它是一个终端错误...

 
一个编译错误。
union X1 { //(1) нормально
        char x11[INT_MAX/2+1];
};
union X2 { //(2) Error: 'X2' - struct is too large
        char x21[INT_MAX/2+1];
        char x22[INT_MAX/2+1];
};
1)和(2)之间的根本区别是什么?
 
与单一领域的联合是一件奇怪的事情。
 
Alexey Viktorov:

这样的检查有什么意义?

如果不加条件,写成return 0;就更容易了,就是这样。

该条件将在每一个新的条形图上得到满足,所有条形图将被重新计算,而不考虑同步性。你写了一个草率的代码,并把它当作一个终端错误来处理...

再想想吧。

原因: