Testing 'CopyTicks' - page 42

 
1702 - the found CopyTicks faults have been fixed!
 

After a successful call to CopyTicks offline, GetLastError returns 4403.

 
Wanting to get all custom symbol ticks this way causes Out of memory
CopyTicks(Symb, Ticks, COPY_TICKS_ALL, 0, UINT_MAX); // out of memory


I'll do it via CopyTicksRange, but the CopyTicks behaviour seems right to change.

 
Sometimes CopyTicksRange causes BARs to be uploaded from the bearded year: 2003.hcc, etc.
 
CopyTicksRange on custom character returns zero. CopyTicks is ok.
 

CopyTicks (build 1881) returns older data than requested, if not fresh ticks are requested. I.e. it returns data older than from parameter. Bug is floating - it appears at different times, so I wrote some small code that reproduces it. I ran it in tester on EURUSD 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);
}

Here's the output:

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)

I.e. we requested from 03:00 and received from 01:49. In real conditions, the difference was more than a month.

 
A question for the experienced. What are the potential pitfalls of this method of obtaining fresh ticks?
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:
Here is a question for the experts. What potential errors can there be with this method of obtaining fresh ticks?

The order of ticks with the same time is not guaranteed, it seems.

Forum on trading, automated trading systems and trading strategy testing

Real time ticks

Andrey Khatimlianskii, 2020.01.31 14:40

By the way, there isan excellent article by Vasily Sokolov on correct collection of ticks. There in details it's analogue synchronisation process (which I don't have, because of which sometimes same ticks are printed):

But CopyTiks function doesn't allow requesting N last ticks. Instead it provides all ticks, which came from the specified moment of time. This complicates the task. We should perform a query, get an array of ticks and compare it with an array of ticks, received on the previous update. At the same time, we'll find out which newly arrived ticks are not part of the "previous supply", i.e. they are new. But it's impossible to compare ticks between them directly, simply because there may be no visible differences between them at all. For example, let's look at the table of deals below:

Figure 5. Table of all deals with an example of identical deals.

We immediately see two groups of absolutely identical ticks. They are marked with red frames, they have the same time, volume, direction and price. Thus, we see that it is impossible to compare individual ticks with each other.

But it is possible to comparea group of ticks. If two groups of ticks are equal to each other, we can conclude that these and following ticks were already analysed during the previous price update.


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

The order of ticks with the same time is not guaranteed, it seems.

If you're talking about groups of ticks, there seems to be nothing wrong with that in the code.

 
Tick cache is not reset.
#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))); // Распечатываем текущее состояние памяти.
}


Result (run cold - immediately after the Terminal starts).

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


It is possible to switch off the Expert Advisor, nothing will change in terms of consumption by the Terminal.