CustomTicksAdd

Añade a la historia de precios del instrumento personalizado los datos de la matriz del tipo MqlTick. El símbolo personalizado debe ser elegido en la ventana de MarketWatch (Observación del mercado).

int  CustomTicksAdd(
   const string     symbol,             // nombre del símbolo
   const MqlTick&   ticks[],            // matriz con los datos de ticks que necesitamos aplicar al instrumento personalizado
   uint             count=WHOLE_ARRAY   // número de elementos que se usarán de la matriz ticks[]
   );

Parámetros

symbol

[in]  Nombre del instrumento personalizado.

ticks[]

[in]   Matriz con los datos de ticks del tipo MqlTick, organizados en orden temporal ascendente, es decir, es necesario que ticks[k].time_msc <= ticks[n].time_msc, si k<n.

count=WHOLE_ARRAY

[in]  Número de elementos de la matriz ticks[] que se usarán para la adición. El valor WHOLE_ARRAY indica que se debe usar todos los elementos de la matriz ticks[].

Valor devuelto

Número de ticks añadidos o bien -1 en caso de error.

Nota

La función CustomTicksAdd solo funciona para los símbolos personalizados abiertos en la ventana MarketWatch (Observación del mercado). Si el símbolo no se ha elegido en MarketWatch, para insertar ticks será necesario usar CustomTicksReplace.

La función CustomTicksAdd permite transmitir los ticks como si llegaran desde el servidor del bróker. La información no se guarda directamente en el banco de datos de ticks, sino que es enviada a la ventana "Observación de mercado". Y ya desde ella, el terminal almacena los ticks en su base. Cuando la cantidad de información transferida por la llamada tiene un gran volumen, la función cambia su comportamiento para ahorrar recursos. Si se transfieren más de 256 ticks, los datos se dividen en dos partes. La primera de ellas (la grande) se carga de inmediato en la base de ticks (como hace CustomTicksReplace). La segunda, que consta de los últimos 128 ticks, se transfiere a la ventana "Observación de mercado" y, después de ello, es guardada por el terminal en la base de ticks.

La estructura MqlTick tiene dos campos con el valor de hora - time (hora del tick en segundos) y  time_msc (hora del tick en milisegundos) que llevan la cuenta desde el 01 de enero del año 1970. El procesamiento de estos campos en los ticks añadidos se realiza según las normas siguientes en el orden indicado:

  1. si el valor ticks[k].time_msc!=0, lo usaremos para rellenar el campo ticks[k].time, es decir, para el tick se muestra la hora ticks[k].time=ticks[k].time_msc/1000 (división en números enteros)
  2. si ticks[k].time_msc==0 y ticks[k].time!=0, la hora en milisigundos resultará multiplicada por 1000, es decir,  ticks[k].time_msc=ticks[k].time*1000
  3. si ticks[k].time_msc==0 y ticks[k].time==0, en estos campos se registra la hora actual del servidor comercial con una precisión de milisegundos en el momento de la llamada de la función CustomTicksAdd.

Si el valor de los campos ticks[k].bid, ticks[k].ask, ticks[k].last o ticks[k].volume es superior a cero, en el campo ticks[k].flags se escribirá una combinación de las banderas correspondientes:

  • TICK_FLAG_BID — el tick ha cambiado el precio bid
  • TICK_FLAG_ASK  — el tick ha cambiado el precio ask
  • TICK_FLAG_LAST — el tick ha cambiado el precio de la última transacción
  • TICK_FLAG_VOLUME — el tick ha cambiado el volumen

Si el valor de algún campo es menor o igual a cero, la bandera que le corresponda no se anotará en el campo ticks[k].flags.

 

Las banderas TICK_FLAG_BUY y TICK_FLAG_SELL no se añaden a la historia del instrumento personalizado.

 

Ejemplo:

//+------------------------------------------------------------------+
//|                                               CustomTicksAdd.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
 
#define   CUSTOM_SYMBOL_NAME     Symbol()+".C"     // nombre del símbolo personalizado
#define   CUSTOM_SYMBOL_PATH     "Forex"           // nombre del grupo en el que se creará el símbolo
#define   CUSTOM_SYMBOL_ORIGIN   Symbol()          // nombre del símbolo a partir del cual se creará el símbolo personalizado
 
#define   DATATICKS_TO_COPY      UINT_MAX          // cantidad de ticks copiados
#define   DATATICKS_TO_PRINT     20                // cantidad de ticks a mostrar en el registro
 
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- obtenemos el código de error al crear un símbolo personalizado
   int create=CreateCustomSymbol(CUSTOM_SYMBOL_NAMECUSTOM_SYMBOL_PATHCUSTOM_SYMBOL_ORIGIN);
   
//--- si el código de error no es 0 (el símbolo se ha creado con éxito) y no es 5304 (símbolo ya creado), salimos.
   if(create!=0 && create!=5304)
      return;
 
//--- obtenemos en la matriz MqlTick los datos de los ticks del símbolo estándar
   MqlTick array[]={};
   if(!GetTicksToArray(CUSTOM_SYMBOL_ORIGINDATATICKS_TO_COPYarray))
      return;
   
//--- imprimimos la hora del primer y el último tick obtenidos del símbolo estándar
   int total=(int)array.Size();
   PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
               TimeToString(array[0].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
               TimeToString(array[total-1].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
               
//--- imprimimos en el registro DATATATICKS_TO_PRINT los últimos ticks del símbolo estándar
   PrintFormat("\nThe last %d ticks for the standard symbol '%s':"DATATICKS_TO_PRINTCUSTOM_SYMBOL_ORIGIN);
   for(int i=total-DATATICKS_TO_PRINTi<totali++)
     {
      if(i<0)
         continue;
      PrintFormat("  %dth Tick: %s"iGetTickDescription(array[i]));
     }
   
//--- añadimos el símbolo personalizado a la ventana MarketWatch (observación de mercado)
   ResetLastError();
   if(!SymbolSelect(CUSTOM_SYMBOL_NAMEtrue))
     {
      Print("SymbolSelect() failed. Error "GetLastError());
      return;
     }
     
//--- añadimos a la historia de precios del símbolo personalizado los datos de la matriz de ticks
   Print("...");
   uint start=GetTickCount();
   PrintFormat("Start of adding %u ticks to the history of the custom symbol '%s'"array.Size(), CUSTOM_SYMBOL_NAME);
   int added=CustomTicksAdd(CUSTOM_SYMBOL_NAMEarray);
   PrintFormat("Added %u ticks to the history of the custom symbol '%s' in %u ms"addedCUSTOM_SYMBOL_NAMEGetTickCount()-start);
   
//--- obtenemos en la matriz MqlTick los datos de los ticks del símbolo personalizado
   Print("...");
   if(!GetTicksToArray(CUSTOM_SYMBOL_NAMEarray.Size(), array))
      return;
   
//--- imprimimos la hora del primer y el último tick obtenidos del símbolo personalizado
   total=(int)array.Size();
   PrintFormat("First tick time: %s.%03u, Last tick time: %s.%03u",
               TimeToString(array[0].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
               TimeToString(array[total-1].timeTIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
               
//--- imprimimos en el registro DATATATICKS_TO_PRINT los últimos ticks del símbolo personalizado
   PrintFormat("\nThe last %d ticks for the custom symbol '%s':"DATATICKS_TO_PRINTCUSTOM_SYMBOL_NAME);
   for(int i=total-DATATICKS_TO_PRINTi<totali++)
     {
      if(i<0)
         continue;
      PrintFormat("  %dth Tick: %s"iGetTickDescription(array[i]));
     }
 
//--- mostramos en el gráfico en el comentario la pista sobre las teclas de finalización del script
   Comment(StringFormat("Press 'Esc' to exit or 'Del' to delete the '%s' symbol and exit"CUSTOM_SYMBOL_NAME));
//--- en un ciclo infinito esperamos que Esc o Del para la salida
   while(!IsStopped() && TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)==0)
     {
      Sleep(16);
      //--- al presionar Supr, eliminamos el símbolo personalizado creado y sus datos
      if(TerminalInfoInteger(TERMINAL_KEYSTATE_DELETE)<0)
        {
         //--- eliminamos los datos de las barras
         int deleted=CustomRatesDelete(CUSTOM_SYMBOL_NAME0LONG_MAX);
         if(deleted>0)
            PrintFormat("%d history bars of the custom symbol '%s' were successfully deleted"deletedCUSTOM_SYMBOL_NAME);
         
         //--- eliminamos los datos de ticks
         deleted=CustomTicksDelete(CUSTOM_SYMBOL_NAME0LONG_MAX);
         if(deleted>0)
            PrintFormat("%d history ticks of the custom symbol '%s' were successfully deleted"deletedCUSTOM_SYMBOL_NAME);
         
         //--- eliminamos el símbolo
         if(DeleteCustomSymbol(CUSTOM_SYMBOL_NAME))
            PrintFormat("Custom symbol '%s' deleted successfully"CUSTOM_SYMBOL_NAME);
         break;
        }
     }
//--- antes de la salida, limpiamos el gráfico
   Comment("");
   /*
   resultado:
   Requested 4294967295 ticks to download tick history for the symbol 'EURUSD'
   The tick history for the 'EURUSDsymbol is received in the amount of 351183943 ticks in 56454 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.20 21:18:12.010
   
   The last 20 ticks for the standard symbol 'EURUSD':
     351183923th Tick2024.06.20 21:17:46.380 Bid=1.07124 (Info tick)
     351183924th Tick2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
     351183925th Tick2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
     351183926th Tick2024.06.20 21:17:49.481 Ask=1.07125 (Info tick)
     351183927th Tick2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
     351183928th Tick2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
     351183929th Tick2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
     351183930th Tick2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
     351183931th Tick2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
     351183932th Tick2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
     351183933th Tick2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
     351183934th Tick2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
     351183935th Tick2024.06.20 21:18:00.102 Bid=1.07126 (Info tick)
     351183936th Tick2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
     351183937th Tick2024.06.20 21:18:03.699 Bid=1.07129 (Info tick)
     351183938th Tick2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
     351183939th Tick2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
     351183940th Tick2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
     351183941th Tick2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
     351183942th Tick2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (Info tick)
   ...
   Start of adding 351183943 ticks to the history of the custom symbol 'EURUSD.C'
   Added 351183943 ticks to the history of the custom symbol 'EURUSD.Cin 269890 ms
   ...
   Requested 351183943 ticks to download tick history for the symbol 'EURUSD.C'
   The tick history for the 'EURUSD.Csymbol is received in the amount of 351183943 ticks in 116407 ms
   First tick time2011.12.19 00:00:08.000Last tick time2024.06.20 21:18:12.010
   
   The last 20 ticks for the custom symbol 'EURUSD.C':
     351183923th Tick2024.06.20 21:17:46.380 Ask=1.07124 Bid=1.07124 (Info tick)
     351183924th Tick2024.06.20 21:17:47.779 Ask=1.07125 Bid=1.07125 (Info tick)
     351183925th Tick2024.06.20 21:17:48.584 Ask=1.07124 Bid=1.07124 (Info tick)
     351183926th Tick2024.06.20 21:17:49.481 Ask=1.07125 Bid=1.07125 (Info tick)
     351183927th Tick2024.06.20 21:17:49.985 Ask=1.07122 Bid=1.07122 (Info tick)
     351183928th Tick2024.06.20 21:17:50.482 Ask=1.07124 Bid=1.07124 (Info tick)
     351183929th Tick2024.06.20 21:17:51.584 Ask=1.07123 Bid=1.07123 (Info tick)
     351183930th Tick2024.06.20 21:17:52.786 Ask=1.07124 Bid=1.07124 (Info tick)
     351183931th Tick2024.06.20 21:17:53.487 Ask=1.07125 Bid=1.07125 (Info tick)
     351183932th Tick2024.06.20 21:17:53.989 Ask=1.07126 Bid=1.07126 (Info tick)
     351183933th Tick2024.06.20 21:17:55.789 Ask=1.07125 Bid=1.07125 (Info tick)
     351183934th Tick2024.06.20 21:17:58.495 Ask=1.07126 Bid=1.07126 (Info tick)
     351183935th Tick2024.06.20 21:18:00.102 Ask=1.07126 Bid=1.07126 (Info tick)
     351183936th Tick2024.06.20 21:18:00.698 Ask=1.07129 Bid=1.07129 (Info tick)
     351183937th Tick2024.06.20 21:18:03.699 Ask=1.07129 Bid=1.07129 (Info tick)
     351183938th Tick2024.06.20 21:18:04.699 Ask=1.07128 Bid=1.07128 (Info tick)
     351183939th Tick2024.06.20 21:18:05.901 Ask=1.07129 Bid=1.07129 (Info tick)
     351183940th Tick2024.06.20 21:18:07.606 Ask=1.07128 Bid=1.07128 (Info tick)
     351183941th Tick2024.06.20 21:18:11.512 Ask=1.07127 Bid=1.07127 (Info tick)
     351183942th Tick2024.06.20 21:18:12.010 Ask=1.07126 Bid=1.07126 (Info tick)
   */
  }
//+------------------------------------------------------------------+
//| Crea un símbolo personalizado, devuelve el código de error       |
//+------------------------------------------------------------------+
int CreateCustomSymbol(const string symbol_nameconst string symbol_pathconst string symbol_origin=NULL)
  {
//--- determinamos el nombre del símbolo a partir del cual se creará uno personalizado
   string origin=(symbol_origin==NULL ? Symbol() : symbol_origin);
   
//--- si no hemos podido crear el símbolo personalizado, y no se trata de un error 5304, informaremos sobre ello en el registro
   ResetLastError();
   int error=0;
   if(!CustomSymbolCreate(symbol_namesymbol_pathorigin))
     {
      error=GetLastError();
      if(error!=5304)
         PrintFormat("CustomSymbolCreate(%s, %s, %s) failed. Error %d"symbol_namesymbol_pathoriginerror);
     }
//--- con éxito
   return(error);
  }
//+------------------------------------------------------------------+
//| Elimina el símbolo personalizado                                |
//+------------------------------------------------------------------+
bool DeleteCustomSymbol(const string symbol_name)
  {
//--- ocultamos el símbolo de la ventana de Observación de mercado
   ResetLastError();
   if(!SymbolSelect(symbol_namefalse))
     {
      PrintFormat("SymbolSelect(%s, false) failed. Error %d"GetLastError());
      return(false);
     }
      
//--- si no se ha podido eliminar el símbolo personalizado, informaremos de ello en el registro y retornaremos false
   ResetLastError();
   if(!CustomSymbolDelete(symbol_name))
     {
      PrintFormat("CustomSymbolDelete(%s) failed. Error %d"symbol_nameGetLastError());
      return(false);
     }
//--- con éxito
   return(true);
  }
//+------------------------------------------------------------------+
//| Obtiene el número indicado de ticks en la matriz                  |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbolconst uint countMqlTick &array[])
  {
//--- notificamos sobre el inicio de la carga de datos históricos
   PrintFormat("Requested %u ticks to get tick history for the symbol '%s'"countsymbol);
   
//--- haceremos tres intentos para obtener los ticks
   int attempts=0;
   while(attempts<3)
     {
      //--- medimos la hora de inicio antes de obtener los ticks
      uint start=GetTickCount();
      
      //--- solicitamos la historia de ticks desde el momento 1970.01.01 00:00.001 (parámetro from=1 ms)
      int received=CopyTicks(symbolarrayCOPY_TICKS_ALL1count);
      if(received!=-1)
        {
         //--- mostramos la información sobre el número de ticks y el tiempo invertido
         PrintFormat("The tick history for the '%s' symbol is received in the amount of %u ticks in %d ms"symbolreceivedGetTickCount()-start);
         
         //--- si la historia de ticks está sincronizada, el código de error será igual a cero, retornaremos true
         if(GetLastError()==0)
            return(true);
 
         PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d"
                     symbolreceivedGetTickCount()-startGetLastError());
        }
      //--- calculamos los intentos 
      attempts++; 
      //--- pausa de 1 segundo a la espera de que finalice la sincronización de la base de ticks 
      Sleep(1000);
     }
//--- no ha sido posible copiar los ticks en 3 intentos
   return(false);
  }
//+------------------------------------------------------------------+ 
//| retorna la descripción de tipo string del tick                   |
//+------------------------------------------------------------------+ 
string GetTickDescription(MqlTick &tick
  { 
   string desc=StringFormat("%s.%03u "TimeToString(tick.timeTIME_DATE|TIME_MINUTES|TIME_SECONDS),tick.time_msc%1000);
   
//--- comprobamos las banderas de tick
   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); 
   
//--- comprobamos primero si hay banderas comerciales en el tick (para CustomTicksAdd() no las hay)
   if(buy_tick || sell_tick
     { 
      //--- formamos la salida para el tick comercial 
      desc += (buy_tick ? StringFormat("Buy Tick: Last=%G Volume=%d "tick.lasttick.volume)  : ""); 
      desc += (sell_tickStringFormat("Sell Tick: Last=%G Volume=%d ",tick.lasttick.volume) : ""); 
      desc += (ask_tick ? StringFormat("Ask=%G "tick.ask) : ""); 
      desc += (bid_tick ? StringFormat("Bid=%G "tick.ask) : ""); 
      desc += "(Trade tick)"
     } 
   else 
     { 
      //--- para la información del tick, formamos la salida un poco diferente 
      desc += (ask_tick   ? StringFormat("Ask=%G ",  tick.ask)    : ""); 
      desc += (bid_tick   ? StringFormat("Bid=%G ",  tick.ask)    : ""); 
      desc += (last_tick  ? StringFormat("Last=%G "tick.last)   : ""); 
      desc += (volume_tickStringFormat("Volume=%d ",tick.volume): ""); 
      desc += "(Info tick)"
     } 
//--- retornamos la descripción del tick
   return(desc); 
  } 

 

Vea también

CustomRatesDelete, CustomRatesUpdate, CustomTicksReplace, CopyTicks, CopyTicksRange