Probando 'CopyTicks' - página 18

 
fxsaber:
Si uno necesita SOLO la cinta (COPY_TICKS_TRADE - time_msc, last, volume and flags), esta solución es completamente adecuada - no se han detectado errores.
No se ha encontrado ningún fallo. Otro error revelado

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

Misterioso indicador de valores

fxsaber, 2016.09.27 18:32

Todos los frenos parecen estar activados cuando la entrada de CopyTicks no es cero.

Parece que la implementación de CopyTicks en este modo es muy torcida, incluso si se solicitan los ticks desde la última llamada. Parece que debería volar, pero no lo hace.

 
Espera a la beta de esta semana, en la que hemos realizado una serie de mejoras en las actualizaciones de ticks y tumblr.
 
Renat Fatkhullin:
Esperad a la beta de esta semana, en la que hemos introducido una serie de mejoras en las actualizaciones de ticks y tumblr.
1432 - muchos errores resueltos. Gracias.
 
fxsaber:
1432 - Muchos errores resueltos. Gracias.

Pero no todos.

Si se compara el historial añadido con el real, hay discrepancias en el modo COPY_TICKS_ALL (TRADE e INFO - no hay problema). 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");
  }
}

Resultado

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:

Pero no todos.

Si se compara el historial añadido con el real, hay discrepancias en el modo COPY_TICKS_ALL (TRADE e INFO - no hay problema). EA

Resultado

He registrado el código anterior y he descubierto las razones. Si CopyTicks (desde > 0) recibe los ticks hasta el más reciente, puede perder algunos.

Ejemplo.

Ticks solicitados con from = 2016.09.29 11:05:55.564. Obtuve tres ticks en respuesta

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

Algún tiempo después he solicitado el historial de gar rapatas desde lejos y he obtenido una garrapata, que CopyTicks pasó por alto antes

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 

¡Qué bicho!

Parece que hay algún tipo de conflicto al escribir y leer de la base de datos de ticks en paralelo.

 
Otro error, ahora en todos los modos COPY_TICKS_*

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

Misterioso indicador de valores

fxsaber, 2016.09.30 15:09

He podido localizar uno de los errores que causan divergencias en el indicador. Se trata de nuevo de CopyTicks.

Resulta que si recogemos la historia de las garrapatas por partes, puede no coincidir con la historia real. El Asesor Experto lo muestra

#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");
  }    
}

El resultado

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

Este EA también muestra un error débil. He descubierto que a la historia recopilada por partes le pueden faltar algunas partes que duran varios minutos. Sólo que no se ha inventado una reproducción concisa y clara en forma de código. Y no tiene sentido publicar los complejos, porque nadie va a mirar.

En general, no hay manera de vencer los errores en CopyTicks. Y tenga en cuenta que el Asesor Experto trabaja en modo cinta (COPY_TICKS_TRADE). Por lo tanto, no puede funcionar ni siquiera con cinta.


 
fxsaber:
Otro error, ahora en todos los modos COPY_TICKS_*

¿Has probado a obtener ticks tanto a partir de un punto como de un número determinado, por ejemplo, fijo?

Por el código, parece un número determinado (100000) desde el último momento. Y qué pasa si sólo tienes N garrapatas. ¿También habrá saltos?

Permítame decirle de inmediato que yo mismo no he experimentado mucho con las garrapatas...

 
Alexey Kozitsyn:

¿Has probado a obtener ticks tanto a partir de un punto como de un número determinado, por ejemplo, fijo?

Por el código, parece un número determinado (100000) desde el último momento. Y qué pasa si sólo tienes N garrapatas. ¿Habrá también saltos?

Permítame decirle de inmediato que yo mismo no he experimentado mucho con las garrapatas...

Lo he probado.

Hoy prometen una nueva construcción para la demo. Así que tenemos que esperar.

 
fxsaber:

Lo he probado.

Hoy prometen una nueva construcción para la demostración. Por eso tengo que esperar.

Espero que se corrija CopyTicks().

Por cierto, desde que apareció CopyTicks() pedí a los desarrolladores que añadieran la función de sobrecarga como en otras funciones Copy...(). Me dijeron que lo harían. И... el silencio...

 
Alexey Kozitsyn:

Por cierto, desde que apareció CopyTicks(), pedí a los desarrolladores que añadieran la función de sobrecarga, como para otras funciones Copy...(). Me dijeron que lo harían. И... el silencio...

Puede añadir sus propias sobrecargas.