Test des "CopyTicks". - page 42

 
1702 - les défauts de CopyTicks trouvés ont été corrigés !
 

Après un appel réussi à CopyTicks hors ligne, GetLastError renvoie 4403.

 
Vouloir obtenir tous les ticks de symboles personnalisés de cette façon provoque un manque de mémoire.
CopyTicks(Symb, Ticks, COPY_TICKS_ALL, 0, UINT_MAX); // out of memory


Je vais le faire via CopyTicksRange, mais le comportement de CopyTicks semble correct à modifier.

 
Parfois, CopyTicksRange provoque le téléchargement des BARs de l'année barbe : 2003.hcc, etc.
 
CopyTicksRange sur un caractère personnalisé renvoie zéro. CopyTicks est normal.
 

CopyTicks (build 1881) retourne des données plus anciennes que celles demandées, si des ticks frais ne sont pas demandés. C'est-à-dire qu'il renvoie des données plus anciennes que celles du paramètre. Le bug est flottant - il apparaît à différents moments, j'ai donc écrit un petit code qui le reproduit. Je l'ai exécuté dans le testeur sur 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);
}

Voici le résultat :

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)

C'est-à-dire que nous avons demandé à partir de 03:00 et reçu à partir de 01:49. En conditions réelles, la différence était de plus d'un mois.

 
Une question pour les personnes expérimentées. Quels sont les pièges potentiels de cette méthode d'obtention de tiques fraîches ?
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:
Voici une question pour les experts. Quelles erreurs potentielles cette méthode d'obtention de tiques fraîches peut-elle entraîner ?

L'ordre des ticks ayant la même heure n'est pas garanti, semble-t-il.

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Tics en temps réel

Andrey Khatimlianskii, 2020.01.31 14:40

À propos, il existe unexcellent article de Vasily Sokolov sur la collecte correcte des tiques. Il y détaille son processus de synchronisation analogique (que je n'ai pas, ce qui fait que parfois les mêmes ticks sont imprimés) :

Mais la fonction CopyTiks ne permet pas de demander les N derniers ticks. Au lieu de cela, il fournit tous les ticks, qui proviennent du moment spécifié du temps. Cela complique la tâche. Nous devons effectuer une requête, obtenir un tableau de ticks et le comparer avec un tableau de ticks, reçu lors de la mise à jour précédente. En même temps, nous découvrirons quelles tiques nouvellement arrivées ne font pas partie de la "réserve précédente", c'est-à-dire qu'elles sont nouvelles. Mais il est impossible de comparer directement les tics entre eux, tout simplement parce qu'il peut n'y avoir aucune différence visible entre eux. Par exemple, examinons le tableau des transactions ci-dessous :

Figure 5. Tableau de toutes les transactions avec un exemple de transactions identiques.

On voit immédiatement deux groupes de tiques absolument identiques. Ils sont marqués par des cadres rouges, ils ont le même temps, volume, direction et prix. Nous constatons donc qu'il est impossible de comparer les tics individuels entre eux.

Mais il est possible de comparerun groupe de tiques. Si deux groupes de ticks sont égaux l'un à l'autre, nous pouvons en conclure que ces ticks et les suivants ont déjà été analysés lors de la précédente mise à jour des prix.


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

L'ordre des ticks ayant la même heure n'est pas garanti, semble-t-il.

Si vous parlez de groupes de ticks, il ne semble pas y avoir de problème à ce niveau dans le code.

 
La mémoire cache n'est pas remise à zéro.
#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))); // Распечатываем текущее состояние памяти.
}


Résultat (à froid - immédiatement après le démarrage du terminal).

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


Il est possible de désactiver l'Expert Advisor, rien ne changera en termes de consommation par le Terminal.

Raison: