Se você é trader e utiliza o MetaTrader 5, vai adorar essa dica! Com um sistema de download que desenvolvemos, você pode escanear a lista de símbolos do seu corretor e baixar todos os ticks disponíveis, ou até mesmo até uma data específica.
Isso é extremamente útil para quem quer fazer backtests ou criar gráficos personalizados a partir desses dados de ticks.
Lembre-se de que os ticks serão armazenados na pasta de dados do terminal, então, não esqueça de verificar se há espaço suficiente no seu HD.
Para facilitar o download dos símbolos, começamos com um gerenciador de downloads. A estrutura CDownloadManager contém todas as informações necessárias que vamos utilizar.
struct CDownloadManager { bool m_started, m_finished; string m_symbols[], m_current; int m_index; }
O que essa estrutura guarda?
- O estado do download (iniciado/terminado)
- A lista de símbolos a serem escaneados
- O símbolo atual
- O índice do símbolo que está sendo escaneado
Precisaremos também de funções para ler e escrever no HD, pois estamos lidando com símbolos. Então, criamos duas funções rápidas para gravar e ler strings de arquivos binários.
Função para salvar uma string em um arquivo:
void writeStringToFile(int f, string thestring) { //salva a string do símbolo char sysave[]; int charstotal = StringToCharArray(thestring, sysave, 0, StringLen(thestring), CP_ACP); FileWriteInteger(f, charstotal, INT_VALUE); for(int i = 0; i < charstotal; i++) { FileWriteInteger(f, sysave[i], CHAR_VALUE); } }
Essa função recebe:
- O manipulador do arquivo f, que deve estar aberto para escrita e com a flag binária FILE_WRITE|FILE_BIN
- A string que você deseja escrever no arquivo
Ela grava um inteiro que representa a quantidade de caracteres na string e depois armazena cada um deles.
Função para carregar uma string de um arquivo:
string readStringFromFile(int f) { string result = ""; //carrega a string do símbolo char syload[]; int charstotal = (int)FileReadInteger(f, INT_VALUE); if(charstotal > 0) { ArrayResize(syload, charstotal, 0); for(int i = 0; i < charstotal; i++) { syload[i] = (char)FileReadInteger(f, CHAR_VALUE); } result = CharArrayToString(syload, 0, charstotal, CP_ACP); } return(result); }
Essa função recebe:
- O manipulador do arquivo f, que deve estar aberto para leitura como binário, com as flags FILE_READ|FILE_BIN
Ela lê um inteiro que representa a quantidade de caracteres que você pode esperar naquele ponto do arquivo. Em seguida, lê cada caractere e o coloca em um array de caracteres, criando uma string a partir desse array, que é retornada como resultado.
Agora, vamos voltar à estrutura CDownloadManager. Precisamos de uma forma de inicializar o gerenciador e preenchê-lo a partir da lista de símbolos:
//+------------------------------------------------------------------+ //| Captura os símbolos da lista de mercado | //+------------------------------------------------------------------+ void grab_symbols() { //! apenas da lista de mercado! int s = SymbolsTotal(true); ArrayResize(m_symbols, s, 0); for(int i = 0; i < ArraySize(m_symbols); i++) { m_symbols[i] = SymbolName(i, true); } }
É bem simples:
- Pede quantos símbolos estão na lista de mercado (ativos)
- Redimensiona nosso array m_symbols para acomodá-los
- Faz um loop pelos símbolos e solicita o nome de cada um
Agora, precisamos gerenciar o download dos dados dos símbolos, então, precisamos de uma função que seja essencialmente o gerenciador:
//+------------------------------------------------------------------+ //| Gerencia o processo de download dos símbolos | //+------------------------------------------------------------------+ void manage(string folder, string filename) { // essencialmente, isso inicia ou navega para o próximo símbolo // caso esteja definido if(ArraySize(m_symbols) > 0) { // se não começou if(!m_started) { m_started = true; // vai para o primeiro símbolo m_current = m_symbols[0]; m_index = 1; save(folder, filename); if(_Symbol != m_current) { ChartSetSymbolPeriod(ChartID(), m_current, _Period); } else { ENUM_TIMEFRAMES new_period = PERIOD_M1; for(int p = 0; p < ArraySize(TFS); p++) { if(_Period != TFS[p]) { new_period = TFS[p]; break; } } ChartSetSymbolPeriod(ChartID(), m_current, new_period); } return; } // se começou else { m_index++; if(m_index <= ArraySize(m_symbols)) { m_current = m_symbols[m_index - 1]; save(folder, filename); if(_Symbol != m_current) { ChartSetSymbolPeriod(ChartID(), m_current, _Period); } return; } else { m_finished = true; FileDelete(folder + "\" + filename); Print("Finalizado"); ExpertRemove(); return; } } else { Print("Por favor, capture os símbolos primeiro"); } // fim do set }
Como o sistema funciona:
- O gráfico é aberto, precisamos de apenas um gráfico, e um timer é definido.
- Esse timer executa, cancelamos o timer.
- Verificamos se é um download novo ou um download contínuo.
- Se for um download novo, configuramos tudo pegando todos os símbolos.
- Se for um download contínuo, baixamos os dados do símbolo atual.
Essa parte do código realiza o download no timer:
//+------------------------------------------------------------------+ //| Timer | //+------------------------------------------------------------------+ void OnTimer() { //--- se sincronizado if(SymbolIsSynchronized(_Symbol) && TerminalInfoInteger(TERMINAL_CONNECTED) == 1) { EventKillTimer(); //--- carrega o sistema aqui if(MANAGER.load(MANAGER_FOLDER, MANAGER_STATUS_FILE)) { //--- sistema carregado, então estamos escaneando um símbolo aqui Comment("Sistema carregado e estamos processando " + MANAGER.m_current); //--- carregamento de ticks //--- encontra o tick mais antigo disponível no corretor primeiro int attempts = 0; int ping = -1; datetime cursor = flatten(TimeTradeServer()); long cursorMSC = ((long)cursor) * 1000; long jump = 2592000000;//60*60*24*30*1000; MqlTick receiver[]; long oldest = LONG_MAX; Comment("Por favor, aguarde"); while(attempts < 5) { ping = CopyTicks(_Symbol, receiver, COPY_TICKS_ALL, cursorMSC, 1); if(ping == 1) { if(receiver[0].time_msc == oldest) { attempts++; } else { attempts = 0; } if(receiver[0].time_msc < oldest) { oldest = receiver[0].time_msc; } cursorMSC -= jump; if(limitDate && receiver[0].time <= oldestLimit) { break; } } else { attempts++; } Sleep(44); Comment("Tick mais antigo: " + TimeToString((datetime)(oldest / 1000), TIME_DATE | TIME_MINUTES | TIME_SECONDS) + "\nCursor(" + TimeToString((datetime)(cursorMSC / 1000), TIME_DATE | TIME_MINUTES | TIME_SECONDS) + ")\nTentativas(" + IntegerToString(attempts) + ")\nPor favor, aguarde a resposta..."); } //--- nesse ponto temos o tick mais antigo //--- comece a solicitar ticks do mais antigo para o mais novo if(oldest != LONG_MAX) { ArrayFree(receiver); datetime newest_tick = 0; //--- recebe o tempo do último tick para este símbolo armazenado em symbol_time datetime most_recent_candle = (datetime)SymbolInfoInteger(_Symbol, SYMBOL_TIME); while(newest_tick < most_recent_candle) { //--- solicita um novo lote a partir do tempo mais antigo com o limite de ticks especificado int pulled = CopyTicks(_Symbol, receiver, COPY_TICKS_ALL, oldest, tick_packets); if(pulled > 0) { //--- se puxarmos um novo lote, atualizamos nossos tempos baixados newest_tick = receiver[pulled - 1].time; oldest = receiver[pulled - 1].time_msc; ArrayFree(receiver); } //--- tempo limite para solicitações ao servidor, altere se quiser Sleep(44); Comment("Puxamos até " + TimeToString(newest_tick, TIME_DATE | TIME_MINUTES | TIME_SECONDS) + " até agora"); } } else { Alert("Por favor, feche o terminal \n vá até a pasta de ticks \n e delete as pastas vazias"); ExpertRemove(); } //--- atualiza o gerenciador e segue em frente MANAGER.manage(MANAGER_FOLDER, MANAGER_STATUS_FILE); } else { //--- capturando os símbolos da lista de mercado para iniciar o download Comment("Capturando a lista de mercado e iniciando"); MANAGER.grab_symbols(); MANAGER.manage(MANAGER_FOLDER, MANAGER_STATUS_FILE); } }
Com essas dicas, você estará pronto para baixar todos os ticks de um símbolo e aprimorar suas análises e estratégias de trading. Aproveite e bons trades!
Publicações relacionadas
- MACD Sample: Um Guia Prático para o Expert Advisor no MetaTrader 5
- MasterMind 2: O Robô de Trading para MetaTrader 4 que Você Precisa Conhecer
- MACD Stochastic: Um Sistema de Trading para MetaTrader 5
- Template de EA para Notícias sem DLL - MetaTrader 4
- Template de EA para Análise de Notícias no MetaTrader 4 sem DLL