Test des "CopyTicks". - page 18

 
fxsaber:
Si l'on n'a besoin QUE du ruban (COPY_TICKS_TRADE - time_msc, last, volume et flags), cette solution convient parfaitement - aucun bug détecté.
Aucun bogue trouvé ! Un autre bug révélé

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

Indicateur boursier mystérieux

fxsaber, 2016.09.27 18:32

Tous les freins semblent être activés lorsque l'entrée de CopyTicks est différente de zéro.

Il semble que l'implémentation de CopyTicks soit très mal faite dans ce mode, même si les ticks depuis le dernier appel sont demandés. On dirait que ça devrait voler, mais ce n'est pas le cas.

 
Attendez la version bêta de cette semaine, où nous avons apporté un certain nombre d'améliorations aux tics et aux mises à jour de tumblr.
 
Renat Fatkhullin:
Attendez la version bêta de cette semaine, où nous avons apporté un certain nombre d'améliorations aux mises à jour des tics et des tumblr.
1432 - beaucoup de bogues résolus. Merci !
 
fxsaber:
1432 - De nombreux bugs résolus. Merci !

Mais pas tous.

Si l'on compare l'historique ajouté à l'historique réel, on constate des divergences en mode COPY_TICKS_ALL (TRADE et INFO - pas de problème). EA

#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

string GetTickFlag( uint tickflag )
{
  string flag = "";

#define  TICKFLAG_MACRO(A) flag += ((bool)(tickflag & TICK_FLAG_##A)) ? " TICK_FLAG_" + #A : "";
  TICKFLAG_MACRO(BID)
  TICKFLAG_MACRO(ASK)
  TICKFLAG_MACRO(LAST)
  TICKFLAG_MACRO(VOLUME)
  TICKFLAG_MACRO(BUY)
  TICKFLAG_MACRO(SELL)
#undef  TICKFLAG_MACRO

  if (flag == "")
    flag = " FLAG_UNKNOWN (" + (string)tickflag + ")";
     
  return(flag);
}

#define  TOSTRING(A) " " + #A + " = " + (string)Tick.A

string TickToString( const MqlTick &Tick )
{
  return(TOSTRING(time) + "." + (string)IntegerToString(Tick.time_msc %1000, 3, '0') +
         TOSTRING(bid) + TOSTRING(ask) + TOSTRING(last)+ TOSTRING(volume) + GetTickFlag(Tick.flags));
}

// Дописывает свежие тики после предыдущего запуска
int AddFreshTicks( MqlTick &Ticks[], const string Symb = NULL, const uint flags = COPY_TICKS_ALL )
{
  int Res = 0;
  const int Amount = ArraySize(Ticks);
  
  MqlTick NewTicks[];  
  const int NewAmount = (Amount == 0) ? CopyTicks((Symb == NULL)? Symbol() : Symb, NewTicks, flags, (ulong)(TimeCurrent() - 100) * 1000) :
                                        CopyTicks((Symb == NULL)? Symbol() : Symb, NewTicks, flags, Ticks[Amount - 1].time_msc);
  
  if (NewAmount > 0)
  {
    if (Amount > 0)
    {
      // Взяли крайнее время из предыдущей истории
      const long LastTime = Ticks[Amount - 1].time_msc;
      
      int Count = 1;
      
      // Находим (Count) в предыдушей истории количество тиков со временем LastTime
      for (int i = Amount - 2; i >= 0; i--)
      {
        if (Ticks[i].time_msc < LastTime)
          break;
          
        Count++;
      }

      if ((Count < Amount) && (Count < NewAmount))      
        Res = ArrayCopy(Ticks, NewTicks, Amount, Count);
    }
    else
      Res = ArrayCopy(Ticks, NewTicks);
  }
  
  return(Res);
}

#define  TOSTRING2(A) #A + " = " + (string)(A) + " "

template <typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
  const int Amount = MathMin(ArraySize(Array1), ArraySize(Array2));
  bool Res = (Amount > 0);

  if (Res)
    for (int i = 0; i < Amount; i++)
      if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
      {
        Print(TOSTRING2(i) + TOSTRING2(ArraySize(Array1)) +TOSTRING2(ArraySize(Array2)));
        Print(TOSTRING2(TickToString(Array1[i])) + "\n" + TOSTRING2(TickToString(Array2[i])) + "\n");
        
        Res = false;

        break;
      }

  return(Res);
}

void OnTick( void )
{
 static MqlTick PrevTicks[];
  
  // Дописываем свежие тики после предыдущего вызова
  AddFreshTicks(PrevTicks, _Symbol, COPY_TICKS_ALL);
  
  MqlTick Ticks[];
  
  if (ArraySize(PrevTicks) > 0)
  {
    // Взяли историю тиков
    Print(CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, PrevTicks[0].time_msc, 100000));
    
    // Проверка на совпадение собираемой истории с самой историей
    Print(ArrayEqual(Ticks, PrevTicks) ? "Equal" : "Not Equal");
  }
}

Résultat

2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    Not Equal
2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    
2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    TickToString(Array2[i]) =  time = 2016.09.29 10:36:20.547 bid = 64353.0 ask = 64354.0 last = 64353.0 volume = 4 TICK_FLAG_BID 
2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    TickToString(Array1[i]) =  time = 2016.09.29 10:36:20.546 bid = 64353.0 ask = 64354.0 last = 64353.0 volume = 1 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL 
2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    i = 57 ArraySize(Array1) = 59 ArraySize(Array2) = 58 
2016.09.29 10:36:23.722 Test10 (Si-12.16,M1)    59
 
fxsaber:

Mais pas tous.

Si l'on compare l'historique ajouté à l'historique réel, on constate des divergences en mode COPY_TICKS_ALL (TRADE et INFO - pas de problème). EA

Résultat

J'ai enregistré le code ci-dessus et j'ai trouvé les raisons. Si CopyTicks (de > 0) reçoit des ticks jusqu'au plus récent, il peut en manquer.

Exemple.

Ticks demandés avec de = 2016.09.29 11:05:55.564. J'ai reçu trois ticks en réponse

2016.09.29 11:05:58.724 Test10 (Si-12.16,M1)    2:  time = 2016.09.29 11:05:55.580 bid = 64380.0 ask = 64382.0 last = 64381.0 volume = 4 TICK_FLAG_BID TICK_FLAG_ASK
2016.09.29 11:05:58.724 Test10 (Si-12.16,M1)    1:  time = 2016.09.29 11:05:55.576 bid = 64379.0 ask = 64381.0 last = 64381.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY
2016.09.29 11:05:58.724 Test10 (Si-12.16,M1)    0:  time = 2016.09.29 11:05:55.564 bid = 64379.0 ask = 64381.0 last = 64380.0 volume = 1 TICK_FLAG_BID TICK_FLAG_ASK

Quelque temps plus tard, j'ai demandé l'historique des ticks à distance et j'ai obtenu un tick, que CopyTicks avait manqué auparavant.

2016.09.29 11:05:58.732 Test10 (Si-12.16,M1)    time = 2016.09.29 11:05:55.579 bid = 64380.0 ask = 64382.0 last = 64381.0 volume = 16 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 

Quel insecte !

Il semble qu'il y ait une sorte de conflit entre l'écriture et la lecture de la base de données tick en parallèle.

 
Un autre bug, maintenant dans tous les modes COPY_TICKS_*

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

Indicateur boursier mystérieux

fxsaber, 2016.09.30 15:09

J'ai pu localiser l'un des bugs provoquant une divergence dans l'indicateur. C'est encore à propos de CopyTicks.

Il s'avère que si l'on recueille l'histoire des tiques par parties, elle peut ne pas coïncider avec l'histoire réelle. Le conseiller expert le montre

#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

long LastTime = 0; // time_msc-время последнего тика (самого свежего), полученного из истории
int Count = 0;     // Количество тиков в последенем запросе, у которых time_msc == LastTime

// Возвращает следующие тики (после предыдущего вызова)
int GetFreshTicks( MqlTick &Ticks[], const uint flags = COPY_TICKS_TRADE, const uint count = 100000 )
{
  int Res = 0;

  MqlTick NewTicks[];
  const int NewAmount = CopyTicks(Symbol(), NewTicks, flags, LastTime, count);

  if ((NewAmount > 0) && (Count < NewAmount))
  {
    Res = ArrayCopy(Ticks, NewTicks, 0, Count);

    // Взяли крайнее время из текущей истории
    LastTime = Ticks[Res - 1].time_msc;
    Count = 1;

    // Находим (Count) в текущей истории количество тиков со временем LastTime
    for (int i = Res - 2; i >= 0; i--)
    {
      if (Ticks[i].time_msc < LastTime)
        break;

      Count++;
    }
  }
  
  return(ArrayResize(Ticks, Res));
}

// Сравнение двух массивов
template <typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
  const int Amount = MathMin(ArraySize(Array1), ArraySize(Array2));
  bool Res = (Amount > 0);

  if (Res)
    for (int i = 0; i < Amount; i++)
      if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
      {
        Res = false;
        
        ExpertRemove();

        break;
      }

  return(Res);
}

void OnTick()
{
  // возьмем тики с начала утренней сессии
  Count = 0;
  LastTime = (TimeCurrent() - (TimeCurrent() % (24 * 3600))) * 1000;
  
  MqlTick Ticks[];    // История, собранная по частям
  MqlTick NewTicks[]; // массив для следующей части тиков
  
  // Собираем историю по частям  
  while (GetFreshTicks(NewTicks, COPY_TICKS_TRADE, 100000) > 0)
    ArrayCopy(Ticks, NewTicks, ArraySize(Ticks));
    
  if (ArraySize(Ticks) > 0)    
  {
    // Взяли ВСЮ историю тиков
    Print(CopyTicks(_Symbol, NewTicks, COPY_TICKS_TRADE, Ticks[0].time_msc, 10000000)); // 10000000 - большое число, чтобы все выкачать.
    
    // Проверка на совпадение собранной по частям истории с самой историей
    Print(ArrayEqual(NewTicks, Ticks) ? "Equal" : "Not Equal");
  }    
}

Le résultat

2016.09.30 16:02:54.661 Test (Si-12.16,M1)      Not Equal
2016.09.30 16:02:54.661 Test (Si-12.16,M1)      ExpertRemove() function called
2016.09.30 16:02:54.621 Test (Si-12.16,M1)      333740
2016.09.30 16:02:54.121 Test (Si-12.16,M1)      Equal
2016.09.30 16:02:54.071 Test (Si-12.16,M1)      333736
2016.09.30 16:02:53.791 Test (Si-12.16,M1)      Equal
2016.09.30 16:02:53.741 Test (Si-12.16,M1)      333723

Cette EA montre également un bug faible. J'ai découvert que l'histoire collectée en plusieurs parties peut manquer certaines parties qui durent plusieurs minutes. Seule une reproduction concise et claire sous forme de code n'a pas été inventée. Et il est inutile d'en poster des complexes, car personne ne regardera.

En général, il n'y a aucun moyen de vaincre les bogues dans CopyTicks. Et notez que l'Expert Advisor fonctionne en mode ruban (COPY_TICKS_TRADE). Il ne peut donc même pas fonctionner avec un ruban.


 
fxsaber:
Un autre bug, maintenant dans tous les modes COPY_TICKS_*

Avez-vous essayé d'obtenir des ticks à partir d'un certain point et d'un certain nombre, par exemple fixe ?

D'après le code, il semble qu'un certain nombre (100000) du dernier moment. Et si vous obtenez seulement N ticks. Y aura-t-il aussi des sauts de puce ?

Laissez-moi vous dire tout de suite que je n'ai pas encore beaucoup expérimenté les tiques moi-même...

 
Alexey Kozitsyn:

Avez-vous essayé d'obtenir des ticks à partir d'un certain point et d'un certain nombre, par exemple fixe ?

D'après le code, il semble qu'un certain nombre (100000) du dernier moment. Et si vous obtenez seulement N ticks. Y aura-t-il aussi des sauts de puce ?

Laissez-moi vous dire tout de suite que je n'ai pas encore beaucoup expérimenté les tiques moi-même...

Je l'ai essayé.

Aujourd'hui, ils promettent une nouvelle construction pour la démo. Nous devons donc attendre.

 
fxsaber:

Je l'ai essayé.

Aujourd'hui, ils promettent une nouvelle construction pour la démo. C'est pourquoi je dois attendre.

J'espère que CopyTicks() sera corrigé.

A propos, depuis l'apparition de CopyTicks(), j'ai demandé aux développeurs d'ajouter une fonction de surcharge comme dans les autres fonctions Copy...(). Ils m'ont dit qu'ils le feraient. И... le silence...

 
Alexey Kozitsyn:

D'ailleurs, depuis l'apparition de CopyTicks(), j'ai demandé aux développeurs d'ajouter une fonction de surcharge, comme pour les autres fonctions Copy...(). Ils m'ont dit qu'ils le feraient. И... le silence...

Vous pouvez ajouter vos propres surcharges.