Probando 'CopyTicks' - página 42

 
1702 - ¡Los fallos de CopyTicks encontrados han sido corregidos!
 

Después de una llamada exitosa a CopyTicks offline, GetLastError devuelve 4403.

 
Querer obtener todos los ticks de símbolos personalizados de esta manera provoca Out of memory
CopyTicks(Symb, Ticks, COPY_TICKS_ALL, 0, UINT_MAX); // out of memory


Lo haré a través de CopyTicksRange, pero el comportamiento de CopyTicks parece correcto para cambiar.

 
A veces CopyTicksRange hace que las barras se carguen desde el año de la barba: 2003.hcc etc.
 
CopyTicksRange en carácter personalizado devuelve cero. CopyTicks es normal.
 

CopyTicks (build 1881) devuelve datos más antiguos que los solicitados, si no se solicitan ticks frescos. Es decir, devuelve datos más antiguos que de parámetro. El error es flotante - aparece en diferentes momentos, así que escribí un pequeño código que lo reproduce. Lo ejecuté en tester en 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);
}

Este es el resultado:

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)

Es decir, solicitamos a partir de las 03:00 y recibimos a partir de las 01:49. En condiciones reales, la diferencia era de más de un mes.

 
Una pregunta para los experimentados. ¿Cuáles son los posibles inconvenientes de este método de obtención de garrapatas frescas?
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:
Esta es una pregunta para los expertos. ¿Qué errores potenciales puede haber con este método de obtención de garrapatas frescas?

El orden de las garrapatas con el mismo tiempo no está garantizado, parece.

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Ticks en tiempo real

Andrey Khatimlianskii, 2020.01.31 14:40

Por cierto, hayun excelente artículo de Vasily Sokolov sobre la correcta recogida de garrapatas. Allí se detalla el proceso de sincronización analógica (que no tengo, por lo que a veces se imprimen los mismos ticks):

Pero la función CopyTiks no permite solicitar N últimos ticks. En su lugar, proporciona todos los ticks, que provienen del momento de tiempo especificado. Esto complica la tarea. Debemos realizar una consulta, obtener un array de ticks y compararlo con un array de ticks, recibido en la actualización anterior. Al mismo tiempo, descubriremos cuáles de las garrapatas recién recibidas no forman parte del "suministro anterior", es decir, son nuevas. Pero es imposible comparar las garrapatas entre ellas directamente, simplemente porque puede que no haya ninguna diferencia visible entre ellas. Por ejemplo, veamos la siguiente tabla de ofertas:

Figura 5. Tabla de todos los tratos con un ejemplo de tratos idénticos.

Inmediatamente vemos dos grupos de garrapatas absolutamente idénticas. Están marcados con marcos rojos, tienen la misma hora, volumen, dirección y precio. Así, vemos que es imposible comparar las garrapatas individuales entre sí.

Pero es posible compararun grupo de garrapatas. Si dos grupos de ticks son iguales entre sí, podemos concluir que estos ticks y los siguientes ya fueron analizados durante la anterior actualización del precio.


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

El orden de las garrapatas con el mismo tiempo no está garantizado, parece.

Si te refieres a grupos de garrapatas, parece que no hay nada malo en el código.

 
La memoria caché de la garrapata no se restablece.
#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))); // Распечатываем текущее состояние памяти.
}


Resultado (ejecutado en frío - inmediatamente después del arranque del 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


Es posible desconectar el Asesor Experto, nada cambiará en cuanto al consumo del Terminal.