//+------------------------------------------------------------------+
//| 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" // nome do símbolo personalizado
#define CUSTOM_SYMBOL_PATH "Forex" // nome do grupo onde o símbolo será criado
#define CUSTOM_SYMBOL_ORIGIN Symbol() // nome do símbolo usado como base para a criação do símbolo personalizado
#define DATATICKS_TO_COPY UINT_MAX // quantidade de ticks copiados
#define DATATICKS_TO_PRINT 20 // quantidade de ticks exibidos no log
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- obtemos o código de erro ao criar o símbolo personalizado
int create=CreateCustomSymbol(CUSTOM_SYMBOL_NAME, CUSTOM_SYMBOL_PATH, CUSTOM_SYMBOL_ORIGIN);
//--- se o código de erro não for 0 (criação bem-sucedida do símbolo) e não for 5304 (símbolo já criado), saímos.
if(create!=0 && create!=5304)
return;
//--- obtemos no array MqlTick os dados de ticks do símbolo padrão
MqlTick array[]={};
if(!GetTicksToArray(CUSTOM_SYMBOL_ORIGIN, DATATICKS_TO_COPY, array))
return;
//--- imprimimos o horário do primeiro e último tick obtido do símbolo padrão
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 no log os últimos DATATICKS_TO_PRINT ticks do símbolo padrão
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]));
}
//--- adicionamos o símbolo personalizado na janela MarketWatch (observação do mercado)
ResetLastError();
if(!SymbolSelect(CUSTOM_SYMBOL_NAME, true))
{
Print("SymbolSelect() failed. Error ", GetLastError());
return;
}
//--- adicionamos à história de preços do símbolo personalizado os dados do array 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);
//--- obtemos no array MqlTick os dados de ticks recém-adicionados do símbolo personalizado
Print("...");
if(!GetTicksToArray(CUSTOM_SYMBOL_NAME, array.Size(), array))
return;
//--- imprimimos o horário do primeiro e último tick obtido do 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 no log os últimos DATATICKS_TO_PRINT ticks do 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]));
}
//--- agora, alteramos os valores Ask e Bid dos ticks no array usando a 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");
//--- substituímos a história de ticks do símbolo personalizado com os dados do array de ticks alterado
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);
//--- obtemos no array MqlTick os dados de ticks recém-substituídos do símbolo personalizado
Print("...");
if(!GetTicksToArray(CUSTOM_SYMBOL_NAME, array.Size(), array))
return;
//--- imprimimos o horário do primeiro e último tick alterado do 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 no log os últimos DATATICKS_TO_PRINT ticks alterados do 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]));
}
//--- no comentário do gráfico exibimos a dica sobre as chaves de encerramento do script
Comment(StringFormat("Press 'Esc' to exit or 'Del' to delete the '%s' symbol and exit", CUSTOM_SYMBOL_NAME));
//--- em um loop infinito, esperamos as teclas Esc ou Del para sair
while(!IsStopped() && TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)==0)
{
Sleep(16);
//--- ao pressionar Del, excluímos o símbolo personalizado criado e seus dados
if(TerminalInfoInteger(TERMINAL_KEYSTATE_DELETE)<0)
{
//--- excluímos os dados das 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);
//--- excluímos os dados 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);
//--- excluímos o símbolo
if(DeleteCustomSymbol(CUSTOM_SYMBOL_NAME))
PrintFormat("Custom symbol '%s' deleted successfully", CUSTOM_SYMBOL_NAME);
break;
}
}
//--- antes de sair, limpamos o 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)
*/
}
//+------------------------------------------------------------------+
//| Cria um símbolo personalizado, retorna o código de erro |
//+------------------------------------------------------------------+
int CreateCustomSymbol(const string symbol_name, const string symbol_path, const string symbol_origin=NULL)
{
//--- definimos o nome do símbolo usado como base para criar o símbolo personalizado
string origin=(symbol_origin==NULL ? Symbol() : symbol_origin);
//--- se não for possível criar o símbolo personalizado, e isso não for um erro 5304, informamos no log
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);
}
//--- sucesso
return(error);
}
//+------------------------------------------------------------------+
//| Exclui o símbolo personalizado |
//+------------------------------------------------------------------+
bool DeleteCustomSymbol(const string symbol_name)
{
//--- ocultamos o símbolo da janela Observação do Mercado
ResetLastError();
if(!SymbolSelect(symbol_name, false))
{
PrintFormat("SymbolSelect(%s, false) failed. Error %d", GetLastError());
return(false);
}
//--- se não for possível excluir o símbolo personalizado, informamos no log e retornamos false
ResetLastError();
if(!CustomSymbolDelete(symbol_name))
{
PrintFormat("CustomSymbolDelete(%s) failed. Error %d", symbol_name, GetLastError());
return(false);
}
//--- sucesso
return(true);
}
//+------------------------------------------------------------------+
//| Obtém a quantidade especificada de ticks no array |
//+------------------------------------------------------------------+
bool GetTicksToArray(const string symbol, const uint count, MqlTick &array[])
{
//--- informamos sobre o início do carregamento dos dados históricos
PrintFormat("Requested %u ticks to get tick history for the symbol '%s'", count, symbol);
//--- fazemos 3 tentativas de obter ticks
int attempts=0;
while(attempts<3)
{
//--- medimos o tempo de início antes de obter ticks
uint start=GetTickCount();
//--- solicitamos a história de ticks desde 1970.01.01 00:00.001 (parâmetro from=1 ms)
int received=CopyTicks(symbol, array, COPY_TICKS_ALL, 1, count);
if(received!=-1)
{
//--- informamos sobre a quantidade de ticks e o tempo gasto
PrintFormat("The tick history for the '%s' symbol is received in the amount of %u ticks in %d ms", symbol, received, GetTickCount()-start);
//--- se a história de ticks estiver sincronizada, o código de erro é zero - retornamos 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());
}
//--- contamos as tentativas
attempts++;
//--- pausa de 1 segundo aguardando a conclusão da sincronização da base de ticks
Sleep(1000);
}
//--- não foi possível copiar ticks em 3 tentativas
return(false);
}
//+------------------------------------------------------------------+
//| retorna a descrição do tick em formato string |
//+------------------------------------------------------------------+
string GetTickDescription(MqlTick &tick)
{
string desc=StringFormat("%s.%03u ", TimeToString(tick.time, TIME_DATE|TIME_MINUTES|TIME_SECONDS),tick.time_msc%1000);
//--- verificamos os flags do 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);
//--- verificamos primeiro os flags de negociação do tick (para CustomTicksAdd() não há)
if(buy_tick || sell_tick)
{
//--- formatamos a saída para um tick de negociação
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 um tick de informação, formatamos a saída de forma um pouco 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 a descrição do tick
return(desc);
}
|