//+------------------------------------------------------------------+
//| CustomTicksReplace.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_NAME, CUSTOM_SYMBOL_PATH, CUSTOM_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_ORIGIN, DATATICKS_TO_COPY, array))
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].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
TimeToString(array[total-1].time, TIME_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_PRINT, CUSTOM_SYMBOL_ORIGIN);
for(int i=total-DATATICKS_TO_PRINT; i<total; i++)
{
if(i<0)
continue;
PrintFormat(" %dth Tick: %s", i, GetTickDescription(array[i]));
}
//--- añadimos el símbolo personalizado a la ventana MarketWatch (observación de mercado)
ResetLastError();
if(!SymbolSelect(CUSTOM_SYMBOL_NAME, true))
{
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_NAME, array);
PrintFormat("Added %u ticks to the history of the custom symbol '%s' in %u ms", added, CUSTOM_SYMBOL_NAME, GetTickCount()-start);
//--- obtenemos en la matriz MqlTick los datos de los ticks del símbolo personalizado recién obtenidos
Print("...");
if(!GetTicksToArray(CUSTOM_SYMBOL_NAME, array.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].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
TimeToString(array[total-1].time, TIME_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_PRINT, CUSTOM_SYMBOL_NAME);
for(int i=total-DATATICKS_TO_PRINT; i<total; i++)
{
if(i<0)
continue;
PrintFormat(" %dth Tick: %s", i, GetTickDescription(array[i]));
}
//--- ahara cambiamos los valores Ask y Bid de los ticks en la matriz según la fórmula Ask(Symbol) = 1.0 / Ask(Symbol), Bid(Symbol) = 1.0 / Bid(Symbol)
for(int i=0; i<total; i++)
{
array[i].ask = (array[i].ask !=0 ? 1.0 / array[i].ask : array[i].ask);
array[i].bid = (array[i].bid !=0 ? 1.0 / array[i].bid : array[i].bid);
}
Print("\nNow the ticks are changed");
//--- sustituimos la historia de ticks del símbolo personalizado por los datos de la matriz de ticks modificada
Print("...");
start=GetTickCount();
PrintFormat("Start replacing %u changed ticks in the history of the custom symbol '%s'", array.Size(), CUSTOM_SYMBOL_NAME);
int replaced=CustomTicksReplace(CUSTOM_SYMBOL_NAME, array[0].time_msc, array[total-1].time_msc, array);
PrintFormat("Replaced %u ticks in the history of the custom symbol '%s' in %u ms", replaced, CUSTOM_SYMBOL_NAME, GetTickCount()-start);
//--- obtenemos en la matriz MqlTick los datos de los ticks del símbolo personalizado recién sustituidos
Print("...");
if(!GetTicksToArray(CUSTOM_SYMBOL_NAME, array.Size(), array))
return;
//--- imprimimos la hora del primer y el último tick modificados del símbolo personalizado
total=(int)array.Size();
PrintFormat("First changed tick time: %s.%03u, Last changed tick time: %s.%03u",
TimeToString(array[0].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[0].time_msc%1000,
TimeToString(array[total-1].time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), array[total-1].time_msc%1000);
//--- imprimimos en el registro DATATATICKS_TO_PRINT los últimos ticks modificados del símbolo personalizado
PrintFormat("\nThe last %d changed ticks for the custom symbol '%s':", DATATICKS_TO_PRINT, CUSTOM_SYMBOL_NAME);
for(int i=total-DATATICKS_TO_PRINT; i<total; i++)
{
if(i<0)
continue;
PrintFormat(" %dth Changed tick: %s", i, GetTickDescription(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_NAME, 0, LONG_MAX);
if(deleted>0)
PrintFormat("%d history bars of the custom symbol '%s' were successfully deleted", deleted, CUSTOM_SYMBOL_NAME);
//--- eliminamos los datos de ticks
deleted=CustomTicksDelete(CUSTOM_SYMBOL_NAME, 0, LONG_MAX);
if(deleted>0)
PrintFormat("%d history ticks of the custom symbol '%s' were successfully deleted", deleted, CUSTOM_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 get tick history for the symbol 'EURUSD'
The tick history for the 'EURUSD' symbol is received in the amount of 351195822 ticks in 55735 ms
First tick time: 2011.12.19 00:00:08.000, Last tick time: 2024.06.21 08:39:03.113
The last 20 ticks for the standard symbol 'EURUSD':
351195802th Tick: 2024.06.21 08:38:10.076 Ask=1.07194 (Info tick)
351195803th Tick: 2024.06.21 08:38:13.162 Ask=1.07195 (Info tick)
351195804th Tick: 2024.06.21 08:38:13.872 Bid=1.07195 (Info tick)
351195805th Tick: 2024.06.21 08:38:14.866 Ask=1.07194 Bid=1.07194 (Info tick)
351195806th Tick: 2024.06.21 08:38:17.374 Bid=1.07194 (Info tick)
351195807th Tick: 2024.06.21 08:38:18.883 Bid=1.07194 (Info tick)
351195808th Tick: 2024.06.21 08:38:19.771 Bid=1.07194 (Info tick)
351195809th Tick: 2024.06.21 08:38:20.873 Ask=1.07195 Bid=1.07195 (Info tick)
351195810th Tick: 2024.06.21 08:38:22.278 Ask=1.07196 Bid=1.07196 (Info tick)
351195811th Tick: 2024.06.21 08:38:22.775 Bid=1.07196 (Info tick)
351195812th Tick: 2024.06.21 08:38:23.477 Bid=1.07196 (Info tick)
351195813th Tick: 2024.06.21 08:38:38.194 Ask=1.07197 (Info tick)
351195814th Tick: 2024.06.21 08:38:38.789 Ask=1.07196 (Info tick)
351195815th Tick: 2024.06.21 08:38:39.290 Ask=1.07197 (Info tick)
351195816th Tick: 2024.06.21 08:38:43.695 Ask=1.07196 (Info tick)
351195817th Tick: 2024.06.21 08:38:52.203 Ask=1.07195 Bid=1.07195 (Info tick)
351195818th Tick: 2024.06.21 08:38:55.105 Ask=1.07196 Bid=1.07196 (Info tick)
351195819th Tick: 2024.06.21 08:38:57.607 Ask=1.07195 Bid=1.07195 (Info tick)
351195820th Tick: 2024.06.21 08:39:00.512 Ask=1.07196 Bid=1.07196 (Info tick)
351195821th Tick: 2024.06.21 08:39:03.113 Ask=1.07195 Bid=1.07195 (Info tick)
...
Start of adding 351195822 ticks to the history of the custom symbol 'EURUSD.C'
Added 351195822 ticks to the history of the custom symbol 'EURUSD.C' in 349407 ms
...
Requested 351195822 ticks to get tick history for the symbol 'EURUSD.C'
The tick history for the 'EURUSD.C' symbol is received in the amount of 351195822 ticks in 190203 ms
First tick time: 2011.12.19 00:00:08.000, Last tick time: 2024.06.21 08:39:03.113
The last 20 ticks for the custom symbol 'EURUSD.C':
351195802th Tick: 2024.06.21 08:38:10.076 Ask=1.07194 Bid=1.07194 (Info tick)
351195803th Tick: 2024.06.21 08:38:13.162 Ask=1.07195 Bid=1.07195 (Info tick)
351195804th Tick: 2024.06.21 08:38:13.872 Ask=1.07195 Bid=1.07195 (Info tick)
351195805th Tick: 2024.06.21 08:38:14.866 Ask=1.07194 Bid=1.07194 (Info tick)
351195806th Tick: 2024.06.21 08:38:17.374 Ask=1.07194 Bid=1.07194 (Info tick)
351195807th Tick: 2024.06.21 08:38:18.883 Ask=1.07194 Bid=1.07194 (Info tick)
351195808th Tick: 2024.06.21 08:38:19.771 Ask=1.07194 Bid=1.07194 (Info tick)
351195809th Tick: 2024.06.21 08:38:20.873 Ask=1.07195 Bid=1.07195 (Info tick)
351195810th Tick: 2024.06.21 08:38:22.278 Ask=1.07196 Bid=1.07196 (Info tick)
351195811th Tick: 2024.06.21 08:38:22.775 Ask=1.07196 Bid=1.07196 (Info tick)
351195812th Tick: 2024.06.21 08:38:23.477 Ask=1.07196 Bid=1.07196 (Info tick)
351195813th Tick: 2024.06.21 08:38:38.194 Ask=1.07197 Bid=1.07197 (Info tick)
351195814th Tick: 2024.06.21 08:38:38.789 Ask=1.07196 Bid=1.07196 (Info tick)
351195815th Tick: 2024.06.21 08:38:39.290 Ask=1.07197 Bid=1.07197 (Info tick)
351195816th Tick: 2024.06.21 08:38:43.695 Ask=1.07196 Bid=1.07196 (Info tick)
351195817th Tick: 2024.06.21 08:38:52.203 Ask=1.07195 Bid=1.07195 (Info tick)
351195818th Tick: 2024.06.21 08:38:55.105 Ask=1.07196 Bid=1.07196 (Info tick)
351195819th Tick: 2024.06.21 08:38:57.607 Ask=1.07195 Bid=1.07195 (Info tick)
351195820th Tick: 2024.06.21 08:39:00.512 Ask=1.07196 Bid=1.07196 (Info tick)
351195821th Tick: 2024.06.21 08:39:03.113 Ask=1.07195 Bid=1.07195 (Info tick)
Now the ticks are changed
...
Start replacing 351195822 changed ticks in the history of the custom symbol 'EURUSD.C'
Replaced 351195822 ticks in the history of the custom symbol 'EURUSD.C' in 452266 ms
...
Requested 351195822 ticks to get tick history for the symbol 'EURUSD.C'
The tick history for the 'EURUSD.C' symbol is received in the amount of 351195822 ticks in 199812 ms
First changed tick time: 2011.12.19 00:00:08.000, Last changed tick time: 2024.06.21 08:39:03.113
The last 20 changed ticks for the custom symbol 'EURUSD.C':
351195802th Changed tick: 2024.06.21 08:38:10.076 Ask=0.93289 Bid=0.93289 (Info tick)
351195803th Changed tick: 2024.06.21 08:38:13.162 Ask=0.93288 Bid=0.93288 (Info tick)
351195804th Changed tick: 2024.06.21 08:38:13.872 Ask=0.93288 Bid=0.93288 (Info tick)
351195805th Changed tick: 2024.06.21 08:38:14.866 Ask=0.93289 Bid=0.93289 (Info tick)
351195806th Changed tick: 2024.06.21 08:38:17.374 Ask=0.93289 Bid=0.93289 (Info tick)
351195807th Changed tick: 2024.06.21 08:38:18.883 Ask=0.93289 Bid=0.93289 (Info tick)
351195808th Changed tick: 2024.06.21 08:38:19.771 Ask=0.93289 Bid=0.93289 (Info tick)
351195809th Changed tick: 2024.06.21 08:38:20.873 Ask=0.93288 Bid=0.93288 (Info tick)
351195810th Changed tick: 2024.06.21 08:38:22.278 Ask=0.93287 Bid=0.93287 (Info tick)
351195811th Changed tick: 2024.06.21 08:38:22.775 Ask=0.93287 Bid=0.93287 (Info tick)
351195812th Changed tick: 2024.06.21 08:38:23.477 Ask=0.93287 Bid=0.93287 (Info tick)
351195813th Changed tick: 2024.06.21 08:38:38.194 Ask=0.93286 Bid=0.93286 (Info tick)
351195814th Changed tick: 2024.06.21 08:38:38.789 Ask=0.93287 Bid=0.93287 (Info tick)
351195815th Changed tick: 2024.06.21 08:38:39.290 Ask=0.93286 Bid=0.93286 (Info tick)
351195816th Changed tick: 2024.06.21 08:38:43.695 Ask=0.93287 Bid=0.93287 (Info tick)
351195817th Changed tick: 2024.06.21 08:38:52.203 Ask=0.93288 Bid=0.93288 (Info tick)
351195818th Changed tick: 2024.06.21 08:38:55.105 Ask=0.93287 Bid=0.93287 (Info tick)
351195819th Changed tick: 2024.06.21 08:38:57.607 Ask=0.93288 Bid=0.93288 (Info tick)
351195820th Changed tick: 2024.06.21 08:39:00.512 Ask=0.93287 Bid=0.93287 (Info tick)
351195821th Changed tick: 2024.06.21 08:39:03.113 Ask=0.93288 Bid=0.93288 (Info tick)
*/
}
//+------------------------------------------------------------------+
//| Crea un símbolo personalizado, devuelve el código de error |
//+------------------------------------------------------------------+
int CreateCustomSymbol(const string symbol_name, const string symbol_path, const 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_name, symbol_path, origin))
{
error=GetLastError();
if(error!=5304)
PrintFormat("CustomSymbolCreate(%s, %s, %s) failed. Error %d", symbol_name, symbol_path, origin, error);
}
//--- 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_name, false))
{
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_name, GetLastError());
return(false);
}
//--- con éxito
return(true);
}
//+------------------------------------------------------------------+
//| Obtiene el número indicado de ticks en la matriz |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbol, const uint count, MqlTick &array[])
{
//--- notificamos sobre el inicio de la carga de datos históricos
PrintFormat("Requested %u ticks to get tick history for the symbol '%s'", count, symbol);
//--- 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(symbol, array, COPY_TICKS_ALL, 1, count);
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", symbol, received, GetTickCount()-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",
symbol, received, GetTickCount()-start, GetLastError());
}
//--- 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.time, TIME_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.last, tick.volume) : "");
desc += (sell_tick? StringFormat("Sell Tick: Last=%G Volume=%d ",tick.last, tick.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_tick? StringFormat("Volume=%d ",tick.volume): "");
desc += "(Info tick)";
}
//--- retornamos la descripción del tick
return(desc);
}
|