测试 "CopyTicks"。 - 页 42

 
1702 - 发现的CopyTicks故障已被修复!
 

在成功调用CopyTicks离线后,GetLastError 返回4403。

 
想通过这种方式获得所有的自定义符号 刻度,导致内存不足
CopyTicks(Symb, Ticks, COPY_TICKS_ALL, 0, UINT_MAX); // out of memory


我将通过CopyTicksRange来做,但CopyTicks的行为似乎适合改变。

 
有时CopyTicksRange会导致BAR从大胡子的年份上传:2003.hcc,等等。
 
自定义字符 的CopyTicksRange返回0。CopyTicks是可以的。
 

CopyTicks (build 1881)如果不要求新的刻度,则返回比要求的更早的数据。也就是说,它返回的数据比参数中的数据更早。错误是浮动的--它出现在不同的时间,所以我写了一些小代码来重现它。我在测试器中运行了欧元兑美元H1,2017.08.01 - 2018.08.01。

void OnTick()
{
   static datetime lastActivityTime = D'2017.08.01';   
   static MqlTick ticks[2000];
   static const uint requestedCount = 2000;
   datetime dt[1];
   CopyTime(NULL, PERIOD_CURRENT, 0, 1, dt);
   if (lastActivityTime >= dt[0]) {
      return;
   }
   lastActivityTime = TimeCurrent();
   
   int zero = 0;
   int idx = 0;
   do {
      ++idx;
      CopyTime(NULL, PERIOD_CURRENT, idx, 1, dt);
      if (dt[0] <= D'2017.08.01') break;
      Print("dt[0]=", dt[0]);
      ulong from = 1000 * dt[0];
      int cnt = CopyTicks(Symbol(), ticks, COPY_TICKS_INFO, from, requestedCount);
      if (cnt < 1) {
         Print("Error in CopyTicks");
         return;
      }
      Print("cnt=", cnt);
      for (int i = 0; i < cnt; ++i) {
         if (ticks[i].time_msc < from) {
            Print("ERROR: i=", i, ", ticks[i].time_msc=", ticks[i].time_msc, " (", ticks[i].time, ")");
            i = i / zero;
         }
      }
      Print("done");
   } while(true);
}

下面是输出结果。

2018.10.17 21:31:26.221 2017.08.01 12:00:00 dt[0]=2017.08.01 03:00:00

2018.10.17 21:31:26.221 2017.08.01 12:00:00 cnt=2000

2018.10.17 21:31:26.221 2017.08.01 12:00:00 ERROR: i=0, ticks[i].time_msc=1501552175606 (2017.08.01 01:49:35)。

也就是说,我们从03:00申请,从01:49收到。在现实条件下,差异超过一个月。

 
给有经验的人一个问题。这种获取新鲜蜱虫的方法有哪些潜在的隐患?
input datetime inFrom = __DATETIME__;

// Свежие тики с последнего вызова
int GetFreshTicks( MqlTick &Ticks[] )
{
  static long LastTime = 0;
  static int LastAmount = 0;
  
  ArrayFree(Ticks);

  int Size = CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, LastTime ? LastTime : (long)inFrom * 1000);
  
  if (Size > LastAmount)
  {
    LastTime = Ticks[Size - 1].time_msc;
    int NewLastAmount = 1;
    
    for (int i = Size - 2; (i >= LastAmount) && (Ticks[i].time_msc == LastTime); i--)
      NewLastAmount++;
      
    if (ArrayRemove(Ticks, 0, LastAmount))
      Size -= LastAmount;
      
    LastAmount = NewLastAmount;
  }
  else
    Size = ArrayResize(Ticks, 0);
  
  return(Size);
}

void OnTick()
{
  MqlTick Ticks[];
  
  if (GetFreshTicks(Ticks))
    ArrayPrint(Ticks);
}
 
fxsaber:
这里有一个问题要问专家。这种获取新鲜蜱虫的方法会有哪些潜在的错误?

看来,具有相同时间的蜱虫的顺序是不能保证的。

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

实时的刻度线

Andrey Khatimlianskii, 2020.01.31 14:40

顺便说一下,瓦西里-索科洛夫有一篇 关于正确收集蜱虫的优秀文章。那里详细介绍了它的模拟同步过程(我没有这个过程,因为它有时会打印出相同的刻度)。

但CopyTiks函数不允许请求N个最后刻度。相反,它提供了所有刻度,这些刻度来自指定的时间点。这使任务变得复杂。我们应该执行一个查询,得到一个ticks数组,并将其与之前更新时收到的ticks数组进行比较。同时,我们会发现哪些新来的蜱虫不属于 "以前的供应",即它们是新的。但是不可能直接比较它们之间的虱子,原因很简单,因为它们之间可能根本没有明显的差别。例如,让我们看一下下面的交易表。

图5.所有交易的表格,包括一个相同交易的例子。

我们立即看到两组绝对相同的虱子。它们被标记为红色框架,它们具有相同的时间、数量、方向和价格。因此,我们看到,不可能将单个蜱虫相互比较。

但有可能对一组 蜱虫进行比较。如果两组刻度线彼此相等,我们可以得出结论,这些刻度线和后面的刻度线在上一次价格更新期间已经被分析过。


Пишем скальперский стакан цен на основе графической библиотеки CGraphic
Пишем скальперский стакан цен на основе графической библиотеки CGraphic
  • www.mql5.com
Именно с этой, улучшенной и дополненной версией мы и начнем работать, чтобы постепенно превратить ее в скальперский стакан цен. Краткий обзор графической библиотеки CPanel Созданию пользовательских интерфейсов в MQL5 посвящено много статей. Среди них особенно выделяется серия Анатолия Кажарского "Графические интерфейсы", после которой сложно...
 
Andrey Khatimlianskii:

看来,具有相同时间的蜱虫的顺序是不能保证的。

如果你说的是蜱虫群,在代码中似乎没有什么问题。

 
勾选缓存不被重置。
#define  TOSTRING(A) " " + #A + " = " + (string)(A)

MqlTick Ticks[];

void OnInit()
{
  Print(__FUNCTION__ + TOSTRING(TerminalInfoInteger(TERMINAL_MEMORY_USED)) + TOSTRING(MQLInfoInteger(MQL_MEMORY_USED))); // Распечатываем начальное состояние памяти.
  
  CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, D'2020.01.01' * 1000); // Получили историю тиков для инициализации по ней советника.
}

void OnTick()
{
  const int Size = ArraySize(Ticks);
  
  if (Size)
  {
    const long BeginTime = Ticks[Size - 1].time_msc;
    
    ArrayFree(Ticks);
    
    CopyTicksRange(_Symbol, Ticks, COPY_TICKS_INFO, BeginTime); // Получаем свежие тики без пропусков, чтобы гнать по ним советник.
  }
  
  Print(__FUNCTION__ + TOSTRING(TerminalInfoInteger(TERMINAL_MEMORY_USED)) + TOSTRING(MQLInfoInteger(MQL_MEMORY_USED))); // Распечатываем текущее состояние памяти.
}


结果(冷运行--终端机启动后立即运行)。

OnInit TerminalInfoInteger(TERMINAL_MEMORY_USED) = 395 MQLInfoInteger(MQL_MEMORY_USED) = 1
OnTick TerminalInfoInteger(TERMINAL_MEMORY_USED) = 446 MQLInfoInteger(MQL_MEMORY_USED) = 1
OnTick TerminalInfoInteger(TERMINAL_MEMORY_USED) = 446 MQLInfoInteger(MQL_MEMORY_USED) = 1
OnTick TerminalInfoInteger(TERMINAL_MEMORY_USED) = 446 MQLInfoInteger(MQL_MEMORY_USED) = 1


可以关闭专家顾问,但在终端的消耗方面不会有任何变化。