[SERVICE DESK]在获取计时器中的高级TF的时间时出错! - 页 6

 
我非常想听听开发者对此的看法。
 
 ResetLastError();
      if(iBarShift(Symbol(),PERIOD_M15,TimeCurrent(),true)==-1)
        {
         Print(__FILE__+": Данные истории по последнему часу отсутствуют! Ошибка #",GetLastError());
         return( false );
        }
      //---
      if(GetLastError()==ERR_NO_ERROR)
        {
         ResetLastError();
         //--- Запоминаем время открытия бара
         _m15OpenTime=iTime(NULL,PERIOD_M15,0);
         //---
         Print(__FILE__,": Актуальное время открытия бара М15 = "+TimeToString(_m15OpenTime)+". Ошибка #",GetLastError());
         //--- Возвращаем истину
         return( true );
        }
 
Alexey Kozitsyn:

看来,最可靠的解决方案是等待OnCalculate()的调用,并强制检查与交易服务器的连接。如果我们不检查连接(IsConnected()),那么即使在OnCalculate()中我们也会在终端加载时得到它。

然而,它并没有消除所有问题。

1.为什么IsConnected()的文档中没有写明必须在OnCalculate()中从高级TF接收数据(至少是)之前调用?

2.为什么OnTimer()中的IsConnected()实际上不起作用?与贸易服务器建立连接的事实不是应该告诉我们可以获得数据吗?

3.一旦我们与交易服务器建立了连接,并试图在OnTimer()中接收数据,如果函数iTime()、iBarShift()、SeriesInfoInteger()以及与之类似的函数从该特定交易服务器获取的数据尚未同步,难道不应该返回错误?否则就会出现一些胡言乱语,比如我们向你返回一次错误4066,然后你就可以使用你的数据。

我已经和开发商以及我在那里的一个朋友谈过了,我告诉他们如下:1 我应该怎么做?

1 胡说八道,你可以随时随地打电话给它。

2 IsConnected可以从代码中的任何地方调用,而且可以工作,但它是一个不在错误堆栈中写任何东西的函数,它返回真/假,仅此而已。考虑到连接过程相当长(至少1秒),而且IsConnected是在登录时触发的,因此有必要在启动终端时检查连接状态并等待报价流的开始。

3 这些函数并不向错误堆栈写任何东西,它们自己返回结果。

为什么我们会得到4066? 那个错误是由TimeCurrent函数引起的。终端登录和从服务器请求时间取决于连接质量,它也需要一些时间,所以我们有一个快速计时器。然后我们在TimeCurrent的请求中得到了4066。然后我们得到了时间,我们的函数开始正常工作,它们自己也因为绕过错误堆栈的工作而返回了一个错误。

作为在这种情况下的建议,快速定时器和终端启动,一定要检查我们是否开始从服务器获取数据。我的版本有点拐弯抹角,从OnCalculate得到一个信号开始接收数据才是正确的。

 
比这更简单。
 
Alexey Kozitsyn:

你有什么建议来解决这个问题(在你看来是有的)?等到OnCalculate()被调用 1-2次?

是的,没错。在OnInit()中只需调用所需的TFs,而不用检查结果(你不能在那里依赖它),在OnCalculate中调用函数IsTFDataReady()。一旦所有请求的TFs都返回true,你就可以开始执行指标的算法。

 
Alexey Kozitsyn:

1.为什么IsConnected()的文档没有说它必须总是在OnCalculate()中从高级TF接收数据(至少是)之前被调用?

IsConnected()是一个相当棘手的函数。它只返回与服务器的一个连接的状态。但终端使用的连接不止一个。本身就有8条交易线。因此,即使IsConnected()返回真,也不太清楚它的含义。至少,我们不能指望时间序列会被请求和建立。但如果IsConnected()返回false,那么我们就可以确定终端仍然处于离线状态。

是什么任务让终端连接的存在 如此关键?据我所知,指标是一个可视化数据的工具。现有的数据。当新的数据到达时,它将更新可视化。不应要求检查数据是否是最新的。这就是终端的任务。

 
Igor Makanu:

我想我们谈论的是MQL5,OHLC的准备与MT4不一样。

我说的是MT4。大约2-3年前,我正在抓一个关于Time[0]的错误。开发者似乎已经修复了它,但随着时间的推移,它又出现了。问题是,不可能明确地重现这个错误。

 
Ihor Herasko:

IsConnected()是一个相当棘手的函数。它只返回与服务器的其中一个连接的状态。但终端使用的连接不止一个。仅仅有8个贸易主题。因此,即使IsConnected()返回真,也不太清楚它的含义。至少,我们不能指望时间序列会被请求和建立。但如果IsConnected()返回false,那么我们就可以确定终端仍然处于离线状态。

是什么任务让终端连接的存在 如此关键?据我所知,指标是一个可视化数据的工具。现有的数据。当新的数据到达时,它将更新可视化。不应要求检查数据是否是最新的。这就是终端的任务。

对于指标,我不记得有必要检查与服务器的连接,我们在历史中的内容是绘制的,当历史被加载时,意味着所有的指标缓冲区被重新计算。

我已经在我的EA中开发并使用了以下功能,总体来说是令人满意的,它能正确检查与服务器的连接。

bool ServerDisable(int count=10){
   if(IsTesting()||IsOptimization())return(false);
   for(int i=0;i<count;i++){
      if(IsConnected())
         if(IsTradeAllowed())
            if(!IsTradeContextBusy()){RefreshRates(); return(false);}
      Sleep(157);
   }
   Print(__FUNCTION__," Торговый сервер не отвечает");
return(true);}

我特别使用Sleep()将控制权传送到终端,然后检查与服务器的连接和交易的可能性。

 
Ihor Herasko:

我说的是MT4。大约2-3年前,我正在抓一个关于Time[0]的错误。开发人员似乎已经解决了这个问题,但随着时间的推移,它又出现了。问题是,不可能明确地重现这个错误。

如果不是太麻烦的话,这里是话题的主题--从主要TF中正确下载历史数据,这里是指标:"我需要在次要TF的条形图上从主要TF中画出MA",我在5分钟内做出了它,它将98%正确工作,在这段代码中哪里有2%的 "陷阱 "会导致bug?

我对MT4的正确代码感兴趣

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot line1
#property indicator_label1  "line1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input ENUM_TIMEFRAMES   TimeFrame   =  PERIOD_H4;
input int               MAPeriod    =  25;
//--- indicator buffers
double         BufMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   double cl[];
//--- indicator buffers mapping
   SetIndexBuffer(0,BufMA);
   IndicatorDigits(Digits);
// запускаем подгрузку истории и выходим, даже не проверяя подгружена она или нет, история тут еще не нужна
   CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),cl);
//---
   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 i,limit,resultcopy;
   double closetf[];
   if(prev_calculated==0)
     {
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-1;
        }else{
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-prev_calculated+1;
     }
   limit = fmin(rates_total-1,limit);
// основной цикл расчета индикатора
   for(i=limit; i>=0 && !IsStopped(); i--)
     {
      BufMA[i]=iMA(_Symbol,TimeFrame,MAPeriod,0,MODE_SMA,PRICE_CLOSE,i);
     }
//---
   return(resultcopy);

  }
 
Vitaly Gorbunov:

我和开发商以及我在那里认识的一个朋友聊过,我每次都会告诉你一件事。

1 胡说八道,你可以在任何时候、任何地方打电话。

2 IsConnected可以从代码中的任何地方调用,而且可以工作,但它是一个不在错误堆栈中放任何东西的函数,它返回真/假,仅此而已。考虑到连接过程相当长(至少1秒),而且IsConnected是在登录时触发的,因此有必要在启动终端时检查连接状态并等待报价流的开始。

3 这些函数并不向错误堆栈写任何东西,它们自己返回结果。

为什么我们会得到4066? 那个错误是由TimeCurrent函数引起的。终端登录和从服务器请求的时间,取决于连接的质量,也需要一些时间,所以不要忘记我们的快速计时器。然后我们在TimeCurrent的请求中得到了4066。然后我们得到了时间,我们的函数开始正常工作,它们自己也因为绕过错误堆栈的工作而返回了一个错误。

作为在这种情况下的建议,快速定时器和终端启动,一定要检查我们是否开始从服务器获取数据。我的变体有点拐弯抹角,从OnCalculate得到一个信号开始接收数据是正确的。

1.仔细阅读我写的东西。这不是我第一次这样告诉你了!我没有说过不给某个地方打电话的事!"。

你是说所有函数iBarShift()、iTime()、SeriesInfo...()都要求使用TimeCurrent()?