CopyTicks

La función recibe en la matriz ticks_array los ticks en formato MqlTick, además, la indexación se tiene lugar del pasado al presente, es decir, el tick con el índice 0 es el más antiguo en la matriz. Para analizar un tick es necesario comprobar el campo flags, que nos informa sobre lo que se ha cambiado precisamente en este tick.

int  CopyTicks(
   string           symbol_name,           // nombre del símbolo
   MqlTick&         ticks_array[],         // matriz para recibir ticks
   uint             flags=COPY_TICKS_ALL,  // bandera que define el tipo de ticks recibidos
   ulong            from=0,                // fecha a partir de la cual se solicitan los ticks
   uint             count=0                // número de ticks que se deben recibir
   );

Parámetros

symbol_name

[in]  Símbolo.

ticks_array

[out]  Matriz del tipo MqlTick para recibir los ticks.

flags

[in]  bandera que define el tipo de los ticks solicitados. COPY_TICKS_INFO — ticks llamados por los cambios de Bid y/o Ask, COPY_TICKS_TRADE — ticks con los cambios de Last y Volume, COPY_TICKS_ALL — todos los ticks. Al realizarse cualquier tipo de solicitud, en los campos restantes de la estructura MqlTick se acaban de escribir los valores del tick anterior.

from

[in]  Fecha a partir de la cual se solicitan los ticks. Se indica en milisegundos desde el 01.01.1970. Si el parámetro from=0, entonces se dan los últimos count ticks.

count

[in]  Número de ticks solicitados. Si los parámetros from y count no se indican, entonces en la matriz ticks_array[] se grabarán todos los últimos ticks disponibles, pero no más de 2000.

Valor devuelto

Número de ticks copiados, o bien -1 en caso de error.

Observación

La función CopyTicks() permite solicitar y analizar todos los ticks entrantes. La primera llamada de CopyTicks() inicia la sincronización de la base de ticks que se guarda en el disco duro de este símbolo. Si los ticks en la base local son insuficientes, entonces los ticks que faltan se cargarán de forma automática desde el servidor comercial. En este caso, los ticks serán sincronizados desde la fecha from, indicada en CopyTicks(), hasta el momento actual. Después de ello, todos los ticks entrantes de dicho símbolo llegarán a la base de ticks y la mantendrán en su actual estado sincronizado.

Si los parámetros from y count no han sido indicados, entonces en la matriz ticks_array[] se grabarán todos los ticks disponibles, pero no más de 2000. El parámetro flags permite definir el tipo de los ticks necesarios.

COPY_TICKS_INFO — se dan los ticks en los que hay cambios del precio Bid y/o Ask. Pero además, también se rellenarán los datos del resto de los campos, por ejemplo, si solo ha cambiado el precio Bid, en los campos ask y volume se grabarán los últimos valores conocidos. Para saber exactamente qué ha sido lo que ha cambiado, es necesario analizar el campo flags, que tendrá el valor TICK_FLAG_BID y/o TICK_FLAG_ASK. Si el tick tiene valores cero de los precios Bid y Ask, y las banderas muestran que los precios han cambiado (flags=TICK_FLAG_BID|TICK_FLAG_ASK), entonces esto nos indica que se ha vaciado la profundidad de mercado. En otras palabras, en este momento no hay solicitudes de compra o venta.

COPY_TICKS_TRADE — se dan los ticks en los que hay cambios del último precio de la operación y del volumen. Pero además, también se rellenarán los datos del resto de los campos, es decir, en los campos Bid y Ask se grabarán los últimos resultados conocidos. Para saber exactamente qué ha sido lo que ha cambiado, es necesario analizar el campo flags, que tendrá el valor TICK_FLAG_LAST y TICK_FLAG_VOLUME.

COPY_TICKS_ALL — se dan todos los ticks en los que hay aunque sea un cambio. Además, los campos no modificados también se rellenan con los últimos valores conocidos.

La llamada de CopyTicks() con la bandera COPY_TICKS_ALL proporciona de golpe todos los ticks del diapasón solicitado, al tiempo que la llamada en otros modos exige de cierto tiempo para el pre-procesado y la selección de los ticks, y por eso no da una ventaja sustancial en cuanto a velocidad de ejecución.

Al solicitar los ticks (no importa si se trata de COPY_TICKS_INFO o de COPY_TICKS_TRADE), en cada tick se contiene información de precio completa en el momento del tick (bid, ask, last y volume). Esto se ha hecho para que sea más cómodo analizar las circunstancias comerciales en el momento de cada tick, y que no resulte necesario solicitar cada vez la historia profunda de ticks y buscar en ella los valores de otros campos.

En los indicadores, la función CopyTicks() retorna el resultado de inmediato: Al llamar CopyTick() desde el indicador se retornarán de inmediato los ticks disponibles del símbolo, y se iniciará la sincronización de la base de ticks, si los datos han sido insuficientes. Todos los indicadores en un símbolo funcionan en un flujo común, por eso el indicador no tiene derecho a esperar la finalización de la sincronización. Después de finalizar la sincronización, con la siguiente llamada, CopyTicks() retornará todos los ticks solicitados. La función OnCalculate() en los indicadores se llama después de que llegue cada tick.

En los expertos y scripts, la función CopyTicks() puede esperar el resultado hasta 45 segundos: A diferencia del indicador, cada experto y script funciona en su propio flujo, y por eso puede esperar la finalización de la sincronización hasta 45 segundos. Si durante este tiempo los ticks aún no se han sincronizando en el número necesario, entonces CopyTicks() retornará por timeout solo los ticks disponibles, y la sincronización continuará. La función OnTick() en los expertos no se constituye como procesador de cada tick, sino que notifica al experto sobre los cambios en el mercado. Los cambios pueden darse en paquetes: al terminal pueden llegar varios ticks al mismo tiempo, pero la función OnTick() será llamada solo una vez para notificar al experto sobre el último estado del mercado.

Velocidad de entrega: el terminal guarda de cada símbolo los 4096 últimos ticks en el caché para el acceso rápido (para los símbolos con la profundidad de mercado iniciada, serán 65536 ticks), las solicitudes de estos datos son las que más rápidamente se ejecutan. Al solicitar los ticks de la sesión comercial actual más allá de los límites del caché, CopyTicks() recurre ya a los ticks que se guardan en la memoria del terminal, estas solicitudes necesitan más tiempo para ejecutarse. Las más lentas son las solicitudes de los ticks de otros días, ya que, en este caso, los datos se leen ya desde el disco.

Ejemplo:

#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property script_show_inputs
//--- Requesting 100 million ticks to be sure we receive the entire tick history
input int      getticks=100000000; // The number of required ticks
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---  
   int     attempts=0;     // Count of attempts
   bool    success=false;  // The flag of a successful copying of ticks
   MqlTick tick_array[];   // Tick receiving array
   MqlTick lasttick;       // To receive last tick data
   SymbolInfoTick(_Symbol,lasttick);
//--- Make 3 attempts to receive ticks
   while(attempts<3)
     {
      //--- Measuring start time before receiving the ticks
      uint start=GetTickCount();
//--- Requesting the tick history since 1970.01.01 00:00.001 (parameter from=1 ms)
      int received=CopyTicks(_Symbol,tick_array,COPY_TICKS_ALL,1,getticks);
      if(received!=-1)
        {
         //--- Showing information about the number of ticks and spent time
         PrintFormat("%s: received %d ticks in %d ms",_Symbol,received,GetTickCount()-start);
         //--- If the tick history is synchronized, the error code is equal to zero
         if(GetLastError()==0)
           {
            success=true;
            break;
           }
         else
            PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d",
            _Symbol,received,GetTickCount()-start,_LastError);
        }
      //--- Counting attempts
      attempts++;
      //--- A one-second pause to wait for the end of synchronization of the tick database
      Sleep(1000);
     }
//--- Receiving the requested ticks from the beginning of the tick history failed in three attempts
   if(!success)
     {
      PrintFormat("Error! Failed to receive %d ticks of %s in three attempts",getticks,_Symbol);
      return;
     }
   int ticks=ArraySize(tick_array);
//--- Showing the time of the first tick in the array
   datetime firstticktime=tick_array[ticks-1].time;
   PrintFormat("Last tick time = %s.%03I64u",
               TimeToString(firstticktime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick_array[ticks-1].time_msc%1000);
//--- выведем время последнего тика в массиве
   datetime lastticktime=tick_array[0].time;
   PrintFormat("First tick time = %s.%03I64u",
               TimeToString(lastticktime,TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick_array[0].time_msc%1000);
 
//---                                                           
   MqlDateTime today;
   datetime current_time=TimeCurrent();                         
   TimeToStruct(current_time,today);                            
   PrintFormat("current_time=%s",TimeToString(current_time));   
   today.hour=0;
   today.min=0;
   today.sec=0;
   datetime startday=StructToTime(today);
   datetime endday=startday+24*60*60;
   if((ticks=CopyTicksRange(_Symbol,tick_array,COPY_TICKS_ALL,startday*1000,endday*1000))==-1) 
     {
      PrintFormat("CopyTicksRange(%s,tick_array,COPY_TICKS_ALL,%s,%s) failed, error %d",       
                  _Symbol,TimeToString(startday),TimeToString(endday),GetLastError());          
      return;                                                                                  
     }
   ticks=MathMax(100,ticks);
//--- Showing the first 100 ticks of the last day
   int counter=0;
   for(int i=0;i<ticks;i++)
     {
      datetime time=tick_array[i].time;
      if((time>=startday) && (time<endday) && counter<100)
        {
         counter++;
         PrintFormat("%d. %s",counter,GetTickDescription(tick_array[i]));
        }
     }
//--- Showing the first 100 deals of the last day
   counter=0;
   for(int i=0;i<ticks;i++)
     {
      datetime time=tick_array[i].time;
      if((time>=startday) && (time<endday) && counter<100)
        {
         if(((tick_array[i].flags&TICK_FLAG_BUY)==TICK_FLAG_BUY) || ((tick_array[i].flags&TICK_FLAG_SELL)==TICK_FLAG_SELL))
           {
            counter++;
            PrintFormat("%d. %s",counter,GetTickDescription(tick_array[i]));
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Returns the string description of a tick                         |
//+------------------------------------------------------------------+
string GetTickDescription(MqlTick &tick)
  {
   string desc=StringFormat("%s.%03d ",
                            TimeToString(tick.time),tick.time_msc%1000);
//--- Checking flags
   bool buy_tick=((tick.flags&TICK_FLAG_BUY)==TICK_FLAG_BUY);
   bool sell_tick=((tick.flags&TICK_FLAG_SELL)==TICK_FLAG_SELL);
   bool ask_tick=((tick.flags&TICK_FLAG_ASK)==TICK_FLAG_ASK);
   bool bid_tick=((tick.flags&TICK_FLAG_BID)==TICK_FLAG_BID);
   bool last_tick=((tick.flags&TICK_FLAG_LAST)==TICK_FLAG_LAST);
   bool volume_tick=((tick.flags&TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME);
//--- Checking trading flags in a tick first
   if(buy_tick || sell_tick)
     {
      //--- Forming an output for the trading tick
      desc=desc+(buy_tick?StringFormat("Buy Tick: Last=%G Volume=%d ",tick.last,tick.volume):"");
      desc=desc+(sell_tick?StringFormat("Sell Tick: Last=%G Volume=%d ",tick.last,tick.volume):"");
      desc=desc+(ask_tick?StringFormat("Ask=%G ",tick.ask):"");
      desc=desc+(bid_tick?StringFormat("Bid=%G ",tick.ask):"");
      desc=desc+"(Trade tick)";
     }
   else
     {
      //--- Form a different output for an info tick
      desc=desc+(ask_tick?StringFormat("Ask=%G ",tick.ask):"");
      desc=desc+(bid_tick?StringFormat("Bid=%G ",tick.ask):"");
      desc=desc+(last_tick?StringFormat("Last=%G ",tick.last):"");
      desc=desc+(volume_tick?StringFormat("Volume=%d ",tick.volume):"");
      desc=desc+"(Info tick)";
     }
//--- Returning tick description
   return desc;
  }
//+------------------------------------------------------------------+
/* Example of the output
Si-12.16: received 11048387 ticks in 4937 ms
Last tick time = 2016.09.26 18:32:59.775 
First tick time = 2015.06.18 09:45:01.000 
1.  2016.09.26 09:45.249 Ask=65370 Bid=65370 (Info tick)
2.  2016.09.26 09:47.420 Ask=65370 Bid=65370 (Info tick)
3.  2016.09.26 09:50.893 Ask=65370 Bid=65370 (Info tick)
4.  2016.09.26 09:51.827 Ask=65370 Bid=65370 (Info tick)
5.  2016.09.26 09:53.810 Ask=65370 Bid=65370 (Info tick)
6.  2016.09.26 09:54.491 Ask=65370 Bid=65370 (Info tick)
7.  2016.09.26 09:55.913 Ask=65370 Bid=65370 (Info tick)
8.  2016.09.26 09:59.350 Ask=65370 Bid=65370 (Info tick)
9.  2016.09.26 09:59.678 Bid=65370 (Info tick)
10. 2016.09.26 10:00.000 Sell Tick: Last=65367 Volume=3 (Trade tick)
11. 2016.09.26 10:00.000 Sell Tick: Last=65335 Volume=45 (Trade tick)
12. 2016.09.26 10:00.000 Sell Tick: Last=65334 Volume=95 (Trade tick)
13. 2016.09.26 10:00.191 Sell Tick: Last=65319 Volume=1 (Trade tick)
14. 2016.09.26 10:00.191 Sell Tick: Last=65317 Volume=1 (Trade tick)
15. 2016.09.26 10:00.191 Sell Tick: Last=65316 Volume=1 (Trade tick)
16. 2016.09.26 10:00.191 Sell Tick: Last=65316 Volume=10 (Trade tick)
17. 2016.09.26 10:00.191 Sell Tick: Last=65315 Volume=5 (Trade tick)
18. 2016.09.26 10:00.191 Sell Tick: Last=65313 Volume=3 (Trade tick)
19. 2016.09.26 10:00.191 Sell Tick: Last=65307 Volume=25 (Trade tick)
20. 2016.09.26 10:00.191 Sell Tick: Last=65304 Volume=1 (Trade tick)
21. 2016.09.26 10:00.191 Sell Tick: Last=65301 Volume=1 (Trade tick)
22. 2016.09.26 10:00.191 Sell Tick: Last=65301 Volume=10 (Trade tick)
23. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=5 (Trade tick)
24. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=1 (Trade tick)
25. 2016.09.26 10:00.191 Sell Tick: Last=65300 Volume=6 (Trade tick)
26. 2016.09.26 10:00.191 Sell Tick: Last=65299 Volume=1 (Trade tick)
27. 2016.09.26 10:00.191 Bid=65370 (Info tick)
28. 2016.09.26 10:00.232 Ask=65297 (Info tick)
29. 2016.09.26 10:00.276 Sell Tick: Last=65291 Volume=31 (Trade tick)
30. 2016.09.26 10:00.276 Sell Tick: Last=65290 Volume=1 (Trade tick)
*/

Véase también

SymbolInfoTick, Estructura para obtener los precios actuales, OnTick()