程序库: OnTickMulti - 页 3

 
Stanislav Korotky #:

不会预先查看未来,因为如果时间点 X 存在多个符号的 tick,那么当某个工具上发生第一个事件时,其余符号(其事件仍处于队列中)将显示前一个 tick,而不是下一个 tick (如示例中所示,00:04发生在00:05之前,而不是之后)。

要实现同步,需要在代码中通过算法来保证,例如,在 OnTick 处理程序中,在发起交易之前,先查询所有涉及符号的 tick 时间。 但原则上讲,如果套利操作基于 tick(而非 K 线或分钟),那么很难实现可靠的同步,因为某些交易品种的 tick 实际上可能会缺失几秒钟。

一切都是相对的,对于一种交易品种可能会出现滞后,而对于另一种则可能出现超前。

实际情况是变幻莫测的,而在调试器中一切都同步,即使OnTick函数几乎为空也是如此。

为了测试,不得不将K线拆解为Tick数据,以便正常模拟佣金和点差。

为了让自定义测试器的计算结果与MT一致,不得不将这一操作在OnTick中实现。

   int size=ArraySize(T);
   if(size==0) return;
   datetime dt1=(datetime)SymbolInfoInteger(name1,SYMBOL_TIME);
   datetime dt2=(datetime)SymbolInfoInteger(name2,SYMBOL_TIME);
   while(sh1<size && T[sh1]<dt1) sh1++;
   while(sh2<size && T[sh2]<dt2) sh2++;
   while(sh1<size && T[sh1]==dt1)
     {if(D1[sh1]>0)  Buy(name1);
      if(D1[sh1]<0) Sell(name1);
      if(D1[sh1]==0) Close(name1);
      sh1++;
     }
   while(sh2<size && T[sh2]==dt2)
     {if(D2[sh2]>0)  Buy(name2,D2[sh2]);
      if(D2[sh2]<0) Sell(name2,fabs(D2[sh2]));
      if(D2[sh2]==0) Close(name2);
      sh2++;
     }
 
Stanislav Korotky #:

要实现同步,需要在代码中通过算法来确保这一点,例如,在 OnTick 处理程序中,在发起交易之前,需对所有涉及的符号查询其 tick 时间。

恐怕这样无法让 OnTick 处理程序识别出当前时间的 tick 队列已经结束。最有可能的是,只有毫秒级的 OnTimer 才能解决这个问题。

 
Rorschach #:

一切都是相对的,对一种工具来说是落后,对另一种工具来说则是领先。

只有当存在(测试器的)当前时间时,才可相对于该时间使用“预见未来”这一术语。 如果当前时间为X,且对于两种工具分别存在对应于时刻X-1和X-2的 tick——那么这些就是已知的最新有效 tick,算法需要基于它们进行计算。 倘若在时刻X-2时,有人试图计算X-1和X时刻的 tick 数据,那便属于“预见未来”。但从技术上讲,测试器不允许这样做。
 
fxsaber #:

恐怕这样会让 OnTick 无法识别出当前时间段的 tick 队列已经结束。很可能只有毫秒级的 OnTimer 才能解决这个问题。

这取决于在 if 语句中如何编写时间条件——需要使用严格的 > 而不是 >=,并且不要将触发该条件的那个 tick 计入在内。使用定时器时也是同样的道理。
 
Stanislav Korotky #:
这取决于在if语句中如何编写时间条件——需要使用严格的“>”而非“>=”,并且不要计算导致条件触发的那个时钟 tick。
没明白。
 
Stanislav Korotky #:
用计时器也是同样的道理。
那样更简单。
 
fxsaber #:
没明白。

粗略来说,以毫秒为单位的时间识别(秒级也是同样的原理):

// TODO: ArrayResize(lookback, <符号数>)
MqlTick lookback[];

void OnTickMulti(const string &symbol, const uint &index)
{
   static MqlTick t[1];
   static long timeCurrentMsc;
   
   SymbolInfoTick(symbol, t[0]);
   
   if(t[0].time_msc > timeCurrentMsc)
   {
      if(!timeCurrentMsc) // 并非完全从头开始,因此这是一个新的毫秒值
      {
         // TODO:使用 lookback[] ticks 进行分析和交易
         // 它们目前还不包含当前时标,因为该时标来自下一毫秒
         // ...
      }
      timeCurrentMsc = t[0].time_msc;
   }

   // 仅在分析完成后,才将新时间戳写入注册表
   lookback[index] = t[0];
}

但我还要再强调一次(给Rorschach看),这种基于极小时间间隔的同步是虚幻的。某些工具的 tick 数据可能在数秒内缺失,因此对其而言的实时价格实际上可能会“过时”。 如果有人特别在意所有价格都必须来自同一个[毫]秒,那么在给出的代码片段中(被注释掉的分析代码块内),需要额外验证时钟 tick 时间是否相等,并且只有在满足这一条件时才进行交易。

 
Stanislav Korotky #:

粗略估算一下,时间识别精度为毫秒级(秒级同样如此):

这种方法根本无法保证所有字符的计时点都是最新的。只有通过毫秒级的 OnTimer 才能实现。
 
fxsaber #:
这种方法根本无法保证所有符号的 tick 数据都是最新的。只有通过毫秒级的 OnTimer 才能实现。
这里所说的“及时性”具体指什么(该方法返回所有交易品种的最新已知 tick 数据,如果指的是这个,可以使用 CopyTicks)?OnTimer 又将如何产生不同的结果?
 

Stanislav Korotky #:
Что подразумевается под актуальностью (этот метод отдает последние известные тики по всем инструментам)?

将不再显示基于最后已知时间的计时点。

那么 OnTimer 又会产生怎样的不同结果呢?

以毫秒为单位的 OnTimer 可确保在此定时器事件发生之前,所有时间点都已过去。也就是说,对于所有符号而言,时间点都是最新的。