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

 
Ihor Herasko:

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

好了,我们已经整理好了。但我们必须清楚地添加文档,否则快速计时器会给开发人员带来很多问题。

 
Ihor Herasko:

一般来说,解决什么样的问题,终端连接的存在 是如此关键?我对该指标的理解是,它是一个可视化数据的工具。现有的数据。当新的数据到达时,它将更新可视化。不应要求检查数据是否是最新的。这就是终端的任务。

任务是尽快获得高级TF的数据。Vitaly Gorbunov 提醒了我关于IsConnected()。

 
Alexey Kozitsyn:

哦,伙计...我们已经过了那个点。见自己的日志。

顺序。首先,我们检查连接情况。一旦建立了连接,我们就能得到时间。请向我解释一下,为什么先返回错误4066,然后又不返回!?自上次调用以来,20ms内有什么变化?

错误4066说没有数据,更新请求已发送。

一旦发送了请求,就不再发送另一个请求,所以4066错误不会生效。这一点已经讨论过很多次了。

为什么要在指示器中启动一个定时器?它是如此之小。你必须明白,在MT4中,指标在一个界面线程中运行。接口线程是所有风控信息的去处

 
Slava:

错误4066表示没有数据,已经发送了更新请求。

一旦发送了一个请求,就不再发送另一个请求,所以不会出现错误4066。这一点已经讨论过很多次了。

为什么要在一个指标中启动一个计时器?它是如此之小。你必须明白,在MT4中,指标在界面线程中工作。所有的风向信息都要通过接口线程

很高兴你加入讨论。

这不是我第一天上论坛+几个人在这里评论,他们也不是第一天上论坛。没有人说过什么。

一旦发送了一个请求,就不再发送另一个请求,所以4066错误不会被触发。这一点已经讨论过很多次了。

谢谢你,我们会知道的。我真的希望在帮助中看到这一点。那么,肯定只有在OnTick()/OnCalculate()事件发生时才会 "引发 "错误?

为什么要在指示器中启动定时器?它是如此之小。

你需要从几个字符中获取数据。尽可能的快。不幸的是,MT4和MT5都没有实现接收任何符号的报价到达事件(不可能订阅这样的更新),因此唯一的出路(据我所知)是在定时器中询问所需的符号。

你应该明白,在MT4中,指标在界面线程中工作。所有的风向信息都要通过接口线程

好吧,他们来了,但然后呢?你能详细说明这有什么坏/好/如何影响定时器的运行吗?
 

这已经讨论过很多次了。每次请求12页,"错误4066"。

你被建议在OnInit中发送请求,在OnCalculate中分析它是正确的。

你需要一个毫秒 级的计时器做什么?你正在阻止客户终端的正常启动。不是风的信息干扰了你的定时器,而是你的定时器干扰了所有人。再次强调:客户的MT4终端中的指示器是以界面潜力来工作的。

 
Slava:

这已经讨论过很多次了。12页关于 "错误4066"。

读了它,谢谢。只有在OnCalculate()或OnTick()中的工作没有问题,问题出在OnTimer()中。在请求 "错误4066计时器 "时,我只得到了这个分支的结果:(

而你被正确地建议向OnInit发送一个请求,并在OnCalculate中分析它。

我听从了建议,但这并没有改变文档中没有提到的定时器处理的特殊性。

为什么你需要一个毫秒级的计时器?你的行为使客户终端无法正常上升。不是风的信息干扰了你的定时器,而是你的定时器干扰了其他人的。再次强调:客户的MT4终端中的指示器在接口箱中工作。

再一次,毫秒级的计时器是为了尽可能快地从多个符号中获取信息!即,算法如下:指标被加载,尽快获得高TFs的数据,然后它在毫秒计时器中监测所需符号的位。除了使用定时器,还有没有其他方法来解决监控问题?

让我们总结一下这里所写的一切,如果我错了就纠正我。

1.任务:通过一个计时器获得几个符号的报价。

实施:当使用高频定时器时,你必须在加载终端时等待OnCalculate()中与服务器建立IsConnected(),只有这样你才能访问定时器。

2.目标:在指标启动后尽快获得较高TF的数据(指标使用快速计时器)。

实施:首先我们在OnInit()中请求必要的数据,然后我们在OnCalculate()中等待连接IsConnected(),然后我们在OnCalculate()中也获得更高一级的TFs的数据。

3.启动高频定时器是否会减慢接口线程的速度,进而减慢计算机的速度,是否根本就不应该启动它?那么如何解决任务1呢?

4.目标:从较早的TFs中加载实际数据。

实施:不要使用高频定时器来做,因为数据检索功能不是为在这样的定时器中工作而设计的?我们只使用OnCalculate()?

5.如果收到4066错误并随后被重置,是否在OnCalculate()中的每一次打勾都被打勾?

6.MT5的OnTimer()在接口线程中不工作吗?

@Slava,请你也逐一回答。

 

1.通常情况下,你会在第二次调用OnCalculate 时获得IsConnected状态。启动终端后立即进行第一次呼叫,历史数据到达时进行第二次呼叫

2.不要使用快速定时器。首先评估什么时间是你可以接受的。它可能是100毫秒或500毫秒。这不是偶然的,我们最初引入了秒级计时器,SetMillisecondsTimer是在5(!)年后才引入的。但在五个方面的架构是不同的。

3.1 获得一台能够处理即时信息队列的强大计算机。

3.2 不要立即启动毫秒计时器,但至少要在第一次OnCalculate之后。或者说:在第一个OnCalculate中启动第二个定时器(在没有连接或休息日的情况下),这样你就可以分析环境了。然后,当你确定所有的数据都被加载,有一个连接,一切正常时,杀死第二个定时器,并启动毫秒定时器。 然后你将安全地通过狭窄的前门。在最好的情况下(将有99%的情况),你将在开始时损失2至5秒。

4.计时器是可能的。但不是立即就能做到的(见3.2)。而我认为50毫秒已经足够了。你不是在提供HFT,对吗?

5.4066只出现在对别人的周期性字符数据的第一次请求上。在下一次对同一字符周期的请求中,4066不会再得到任何更多的

6.在MT5中,指标是在一个单独的符号处理线程中计算的。因此,如果你在该符号上有多个图表(或在该符号上有其他指标),你可以让它们慢下来。但它仍然不是一个接口线程

 
Slava:

1.通常情况下,你会在第二次调用OnCalculate 时获得IsConnected状态。终端启动后立即进行第一次调用,历史数据到达时进行第二次调用

2.不要使用快速定时器。首先评估什么时间是你可以接受的。它可能是100毫秒或500毫秒。这不是偶然的,我们最初引入了秒级计时器,SetMillisecondsTimer是在5(!)年后才引入的。但在五个方面的架构是不同的。

3.1 获得一台能够处理即时信息队列的强大计算机。

3.2 不要立即启动毫秒计时器,但至少要在第一次OnCalculate之后。或者说:在第一个OnCalculate中启动第二个定时器(如果没有连接或休息日怎么办),这样你就可以分析环境了。然后,当你确定所有的数据都被加载,有一个连接,一切正常时,杀死第二个定时器,并启动毫秒定时器。 然后你将安全地通过狭窄的前门。在最好的情况下(将有99%的情况),你将在开始时损失2至5秒。

4.计时器是可能的。但不是立即就能做到的(见3.2)。而我认为50毫秒已经足够了。你不是在提供HFT,对吗?

5.4066只出现在对别人的周期性字符数据的第一次请求上。在下一次对同一时期字符的请求中,你将不会再得到4066。

6.在MT5中,指标是在一个单独的符号处理线程中计算的。因此,如果你在这个符号上有一个以上的图表(或在这个符号上有其他指标),你可以把它们放慢。但它仍然不是一个接口线程

1.这正是它的工作方式。

2.这就是问题所在。越快越好。并且已经进行了评估。该指标是为套利而写的(或者说是对套利的研究),也就是说,每一毫秒都很重要,收到的报价越快越好。

3.1.而现在的系统相当强大:8600k CPU,SSD终端,16gb DDR4内存。

3.2.wow...好的,注意到了。

4.仲裁任务有可能是指HFT。

5.起初,这正是让我感到压力的地方。如果我继续得到这个错误,并且知道数据还没有准备好,这个话题就不会发生。

6.我明白了。

谢谢你的详细答复。

 
Igor Makanu:

如果这不难,这里是主题的主题--从较早的TF正确加载历史,这里是指标:"我需要从较早的TF的条形图上画出MA",我在5分钟内做到了,它将为98%正确工作,在这个代码中的2%"陷阱 "将导致bug?

是的,只是关于这个主题的问题。而这一切都在这里得到了整理。

首先, 在对其他TFs/符号的时间序列进行任何引用之前,一定要检查数据是否可用(见上文IsTFDataReady()函数)。在上面的代码中,你只被CopyClose的结果所引导。但它对历史负荷一无所知。因此,首先--要确保数据是可用的,然后才是请求。

其次, 调用一个函数作为另一个函数的参数并不总是合理的。而在上述情况下,这在原则上是不可接受的。毕竟,调用iBars的结果也应该被检查。因此,首先调用iBars,对结果进行缓存和检查,然后只将收到的值传输给CopyClose()。

第三,调用CopyClose 之后,没有检查得到所有要求的数据。毕竟,该函数可以返回1或2条,而它被要求,例如,10条。我认为这样的结果是一个错误。

第四, 这种方法的想法本身就有一个错误。循环假设它是在另一个TF的柱子上操作的,但它与 rates_total 变量的计算相混淆,该变量的值是指当前TF。这里有两种可能的方法,我在这种或那种情况下使用。

  1. 循环浏览当前TF的条形图,并在数据请求前将当前TF的条形图索引转换为另一个TF的条形图索引(以下代码中使用了这种方法)。
  2. 循环通过另一个TF的小节。但是,我们需要为当前TF小于另一个TF的情况增加一个循环。因为旧TF的一个柱子将对应于当前TF的几个柱子。

我对MT4的正确代码感兴趣

根据这四点,它应该是这样的(我没有检查,我是用手做的,但意义应该很清楚)。

   if (!IsTFDataReady(TimeFrame))
      return 0;

   int i,limit;

   static int nOldBars = 0;
   int nBars = iBars(_Symbol, TimeFrame);
   if (nBars == 0)
      return 0;
      
   if (nOldBars == 0 || nBars - nOldBars > 1)
   {
      if(nBars < MAPeriod)
      {
         Comment("Большой период МА!!!, в истории доступно ", nBars," баров");
         return 0;
      }
      
      limit = nBars - fmin(MAPeriod, nBars);
   }
   else
      limit = nBars - nOldBars;  // здесь всегда будет 0 или 1
   
   nOldBars = nBars;
   datetime dtTime = iTime(NULL, TimeFrame, limit);
   if (dtTime == 0)
      return 0;

   limit = iBarShift(NULL, PERIOD_CURRENT, dtTime);

// основной цикл расчета индикатора
   for(i = limit; i >= 0 && !IsStopped(); i--)
   {
      int nOtherTFBarIndex = iBarShift(NULL, TimeFrame, time[i]);
      if (nOtherTFBarIndex < 0 || nOtherTFBarIndex >= nBars)
         continue;
      
      BufMA[i] = iMA(_Symbol,TimeFrame,MAPeriod,0,MODE_SMA,PRICE_CLOSE,nOtherTFBarIndex);
   }
//---
   return rates_total;

顺便说一下,我检查了一下。


 
Ihor Herasko:

是的,这就是这个话题的主题。而这一切都已经在这里整理好了。

首先, 在对其他TF/符号时间序列进行任何引用之前,确保数据是可用的(见上文IsTFDataReady()函数)。在上面的代码中,你只被CopyClose的结果所引导。但它对历史负荷一无所知。因此,首先--确保数据是可用的,然后才要求提供。

其次, 调用一个函数作为另一个函数的参数并不总是合理的。而在上述情况下,这在原则上是不可接受的。毕竟,调用iBars的结果也必须被检查。因此,首先调用iBars,对结果进行缓存和检查,然后只将收到的值传输给CopyClose()。

第三,调用CopyClose 之后,没有检查得到所有要求的数据。毕竟,该函数可以返回1或2条,而它被要求,例如,10条。我认为这样的结果是一个错误。

第四, 这种方法的想法本身就有一个错误。循环假设它是在另一个TF的柱子上操作的,但它与 rates_total 变量的计算相混淆,该变量的值是指当前TF。这里有两种可能的方法,我在这种或那种情况下使用。

  1. 循环浏览当前TF的条形图,并在请求数据前将当前TF的条形图索引转换为另一个TF的条形图索引(以下代码中使用了这种方法)。
  2. 循环通过另一个TF的小节。但是,我们需要为当前TF小于另一个TF的情况增加一个循环。毕竟,旧TF的一个柱子将对应于当前TF的几个柱子。

根据这四点,应该是这样的(我没有检查,我是用手做的,但意义应该很清楚)。

顺便说一下,我检查了一下。


1.考虑到了这一点!谢谢你!"。

2.金句!我以前也这么写,但随着时间的推移,看了别人的代码,这些代码都是追求紧凑性的......我更注意 "简洁是人才的姐妹"....,并把时间花在搜索我遇到的错误上。

4."简洁是人才的姐妹"......你是对的!

3.有趣的分析点,什么返回CopyClose(),我自己检查了一下,如果没有请求的TF的.hst文件,CopyClose()从来没有返回超过2048- 即这是可以下载的最大值?