English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
preview
Desenvolvendo um EA de negociação do zero( Parte 15): Acessando dados na WEB (I)

Desenvolvendo um EA de negociação do zero( Parte 15): Acessando dados na WEB (I)

MetaTrader 5Integração | 18 maio 2022, 14:48
1 408 4
Daniel Jose
Daniel Jose

1.0 - Introdução

A plataforma MetaTrader 5 é a mais versátil e completa plataforma que alguém pode desejar ter, diferente do que muitos mal informados saem por ai dizendo, esta plataforma é extremamente eficiente e poderosa, nos dando possibilidades que vão muito além de simplesmente olhar um gráfico sendo plotado e assim operar comprando ou vendendo um determinado ativo em um dado momento.

Todo este poder vem do fato da plataforma utilizar uma linguagem que praticamente se iguala a mais poderosa linguagem já construída até os dias de hoje, estou falando do C/C++, e o poder que esta linguagem nos dá esta muito além do que meros operadores sem nenhum conhecimento em programação é capaz de perceber ou entender.

Quando estamos operando o mercado, precisamos estar de alguma forma ligados a várias questões envolvidas no âmbito global, não podemos apenas nos apegar ao gráfico, temos que estar de alguma forma ligados a várias outras informações igualmente relevantes e que podem decidir e serem a diferença entre ganhar e perder em uma operação.

Na WEB temos diversos sites e locais onde uma grande e vasta quantidade de informações estão disponíveis e ficam acessíveis a aqueles que sabem onde procurar e como melhor utilizar estas informações. E quanto mais bem informado você estiver, e dentro de um tempo adequado, melhor será, mas se você for utilizar um browser, seja qual for, verá que é muito complicado filtrar de forma adequada certas informações, deixando você com uma grande quantidade de telas, e monitores, e no final apesar da informação está ali, você não consegue tirar proveito de forma adequada da mesma.

Mas graças ao MQL5 que se aproxima em muito ao C/C++, nos programadores de tal linguagem, conseguimos fazer algo que vai muito além de simplesmente operar um gráfico que esta sendo plotado, podemos buscar, filtrar, analisar dados na WEB e assim fazer operações de forma muito mais consistente do que a grande maioria dos operadores de fato conseguem, já que vamos usar todo o poder computacional a nosso favor.


2.0 - Planejamento

A parte do planejamento é algo crucial, devemos primeiramente buscar onde iremos obter as informações que de fato iremos utilizar e precisamos fazer isto com muito mais cuidado do que parece, já que uma boa fonte de informação irá nos dá uma direção correta, esta parte é algo que cada um deverá fazer e de forma individual, já que cada um estará buscando e necessitando de dados específicos em momentos distintos.

Mas independentemente disto o método de se fazer a coisa, uma vez escolhido a fonte será basicamente o mesmo, podendo então este artigo servir como uma fonte de estudo para quem desejar utilizar o método e meios que são possíveis apenas usando o MQL5, sem nenhum programa externo.

Para exemplificar todo o processo, vamos utilizar um site de informações de mercado para mostrar como se dá o processo, desta forma acredito que ficará bem claro como fazer a coisa toda funcionar, e assim você poderá utilizar o método adaptando a suas necessidades em particular.


2.0.1 - Desenvolvendo o programa de captura

Para começar de fato, vamos precisar primeiramente produzir um pequeno programa para capturar os dados para que possamos analisar com calma e exatidão, para isto vamos usar o programa o mais simples quanto for possível, ele é visto logo abaixo:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnStart()
{
        Print(GetDataURL("https://tradingeconomics.com/stocks"));
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout = 750)
{
	string headers;
	char   post[], charResultPage[];
	int    handle;
   
	if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1		return "Bad return";
	if ((handle = FileOpen("url.txt", FILE_WRITE | FILE_BIN)) != INVALID_HANDLE) 
        { 
                FileWriteArray(handle, charResultPage, 0, ArraySize(charResultPage)); 
                FileClose(handle); 
        }else
                return "Error saving file ...";
                
	return "File saved successfully...";
}

Este programa é ultra simples, mas simples que isto acho impossível fazer.

Bem o que fazemos é indicar no ponto destacado qual é o site que queremos adquirir as informações, e por que estamos usando isto e não o browser ?!?! Bem, é verdade que podemos sim capturar as informações no browser, mas utilizaremos ele para nos ajudar a encontrar a informação depois de baixarmos os dados.

Mas não adianta apenas digitar e compilar este programa, é preciso fazer algo a mais, caso contrário ele não irá funcionar.

Dentro da plataforma MetaTrader  , antes de executar este script, devemos habilitar a plataforma a receber dados do site em questão, mas para não precisar ficar fazendo isto toda vez que você precisar instalar a plataforma MetaTrader  , você pode depois de tudo configurado, salvar um backup destes dados, o arquivo que você deverá salvar esta no seguinte caminho:

C:\Users\< USER NAME >\AppData\Roaming\MetaQuotes\Terminal\< CODE PERSONAL >\config\common.ini

USER NAME é o seu nome de usuário dentro do sistema operacional, já CODE PERSONAL é um valor que a plataforma irá criar durante a instalação, desta forma ficará fácil de você encontrar o arquivo necessário para fazer um backup do mesmo ou repor ele depois de uma nova instalação. Um detalhe: Esta localização se refere ao sistema WINDOWS.

Bom, mas voltando ao script que criamos, se você utilizá-lo antes de configurar as coisas irá obter o seguinte resultado na janela de mensagens.

Esta mensagem ocorreu por conta da falta de habilitação do site, dentro da plataforma MetaTrader  , isto deve ser feito conforme mostrado na figura abaixo, observem com atenção o que foi adicionado, e notem que é exatamente o endereço da raiz do site que queremos acessar via plataforma MetaTrader  .

          

Agora ao executamos novamente o mesmo script, obtemos o seguinte resultado informado pela plataforma:

Ou seja, o site foi acessado e os dados foram baixados para o seu computador, com sucesso e já podemos analisar eles, o grande detalhe é que agora não precisamos mais nos preocupar em adicionar novamente o mesmo site na plataforma, desde é claro você faça um backup do arquivo que mostrei onde esta.

Para entender como as coisas funcionarão aqui e assim obter mais detalhes, de uma olhada na função WebRequest, na documentação, apesar de tudo se você deseja se aprofundar neste campo de comunicação via protoloco de rede, aconselho a você dar uma olhada nas demais funções de rede presentes no MQL5, o devido conhecimento sobre tais funções pode lhe tirar de grandes apuros em alguns momentos.

Bem a primeira parte do trabalho esta pronta, conseguir baixar os dados do site desejado, agora temos que passar por uma próxima etapa, igualmente importante.


2.0.2 - Procurando os dados

Para quem não sabe como fazer a procura dos dados a serem capturados pela plataforma MetaTrader 5 dentro de um site, fiz um video curto, onde demonstro de forma bem rápida como proceder esta pesquisa.

É importante que você saiba mexer no seu navegador para poder analisar o código do site que você deseja capturar os dados, não é algo difícil, já que o próprio browser ajuda bastante nesta tarefa, mas é algo que você deve aprender a fazer, e quando entender como fazer, um leque enorme irá se abrir na sua frente.

No caso, estarei utilizando o CHROME para fazer a pesquisa, mas dá para usar qualquer outro navegador que permita acessar o código via ferramentas de desenvolvimento.



Uma vez que você sabe o que procurar e onde procurar, e assim acessar as informações que deseja capturar, é hora de abrir o arquivo que você baixo no site, utilizando a plataforma MetaTrader  , e começar a vasculhar atras dos dados que você precisa, de certa forma ao salvar o arquivo como um documento de texto, poderemos ter o seguinte resultado ao abrir ele no editor.

Nosso interesse está em conseguir os dados deste bloco mostrado abaixo, e este bloco é o mesmo que eu procurei no video logo acima, veja que é importante saber procurar as coisas usando o browser, caso contrário você ficaria perdido no meio a todas aquelas informações baixadas.

Bem, mas em alguns casos apenas olhar os dados desta forma não nos será o bastante, temos que recorrer a um editor hexa para saber exatamente com o que estamos lidando, é verdade que em alguns casos a modelagem dos dados é relativamente simples, mas em outros a coisa é bastante complexa, contendo imagens e links entre outras coisas, e estes podem dificultar o sistema de procura, pois costuma dar falsos positivos, assim temos que saber com o que estamos lidando, então ao procurar estes mesmos dados em um editor hexa, conseguimos os seguintes valores.

Os offsets não nos interessa, neste primeiro momento, já que eles podem mudar em casos de páginas dinâmicas, mas o que nos interessa é ver qual é a modelagem utilizada, e no caso esta bem claro e podemos utilizar um sistema de busca baseado neste tipo de informação encontrada aqui no editor hexadecimal, isto torna a pesquisa por parte do nosso programa levemente mais simples de ser implementada, mesmo que não seja um sistema eficiente neste primeiro momento, então vamos procurar uma base de dados mais simples de ser acessada, e que pode ser informada via input, ou seja nada de caracteres como CARRIAGE ou RETURN, estes mais nos atrapalha do que nos ajuda, então o programa fica conforme pode ser visto abaixo.

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnStart()
{
        while (!IsStopped())
        {
                Print(GetDataURL("https://tradingeconomics.com/stocks"));
                Sleep(200);
        }
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout = 100)
{
        string  headers, szInfo;
        char    post[], charResultPage[];
        int     handle;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1)
                return "Bad return";
   
        szInfo = "";
        for (int c0 = 0, c1 = ArraySize(charResultPage); c0 < c1; c0++) szInfo += CharToString(charResultPage[c0]);
        if ((handle = StringFind(szInfo, "data-symbol=\"INDU:IND\"", 0)) >= 0)
        {
                handle = StringFind(szInfo, "<td id=\"p\" class=\"datatable-item\">", handle);
                for(; charResultPage[handle] != 0x0A; handle++);
                for(handle++; charResultPage[handle] != 0x0A; handle++);
                szInfo = "";
                for(handle++; charResultPage[handle] == 0x20; handle++);
                for(; (charResultPage[handle] != 0x0D) && (charResultPage[handle] != 0x20); handle++) szInfo += CharToString(charResultPage[handle]);
        }
        return szInfo;
}

A ideia do script acima é capturar o valor na página, a vantagem do método mostrado acima é que mesmo que a informação mude de posição, ou seja offset, ainda assim teremos a capacidade de encontrar ela no meio de todos aqueles comandos, mas mesmo que tudo pareça ideal, existe um pequeno delay nas informações, então é preciso mensurar como você irá trabalhar com os dados capturados, quando o script acima é executado, o resultado da execução pode ser visto baixo.

Aconselho a vocês a fazerem suas próprias analises e ver como a informação está sendo capturada, pois é importante saber de detalhes que não são tão simples de descrever em forma de texto, é preciso ver para entender.

Bem, mas vamos pensar no seguinte, o script acima não é muito eficiente em termos de execução, já que ele faz algumas manipulações que de fato não nos é necessário no caso de estarmos usando uma página com uma modelagem estática, porém com conteúdo dinâmico, como é o caso da página em questão, neste caso especifico podemos usar o offset para fazer uma análise mais rápida e assim capturar os dados de uma forma um pouco mais eficiente, se é que posso dizer isto, mas lembre-se o sistema pode manter um cache por alguns instantes as informações, então a informação que esta sendo capturada poderá estar defasada em relação com a mesma informação observada em um browser, neste caso é necessário fazer alguns ajustes internos dentro do sistema para poder corrigir isto, mas este não é o proposito deste artigo.

Então modificando o script acima para algo que irá usa o offset para fazer a pesquisa teremos o código a seguir, e este está na integra:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnStart()
{
        while (!IsStopped())
        {
                Print(GetDataURL("https://tradingeconomics.com/stocks", 100, "INDU:IND", 172783, 173474, 0x0D));
                Sleep(200);
        }
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout, const string szFind, int iPos, int iInfo, char cLimit)
{
        string  headers, szInfo = "";
        char    post[], charResultPage[];
        int     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1)
	        return "Bad return";

        for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error in Position";
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return szInfo;
}

e o resultado da execução do script, pode ser visto logo abaixo, vejam que não temos grandes mudanças, apenas é uma questão de tempo computacional, que usando o modelo de offset estamos reduzindo e assim melhorando levemente o desempenho geral do sistema.

Lembre-se do seguinte, o código acima só funcionou por que a página tem uma modelagem estática, ou seja apesar do conteúdo mudar de forma dinâmica, o layout da mesma não muda, então podemos usar um editor hexa, encontrar onde estão as informações, pegar os valores de offset e ir direto a estas posições, mas para ter um mínimo de garantir de que os offsets ainda são válidos, fazemos um teste simples e isto é feito na seguinte linha:

for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error in Position";

algo bem simples, porém necessário, para que tenhamos o mínimo de segurança quanto as informações que estão sendo capturadas via offset, mas para fazer isto você tem que analisar a página e verificar se é ou não viável utilizar o método de offset para fazer a captura, mas sendo viável você terá o beneficio de ter um tempo de processamento menor.


2.0.3 Um problema a ser administrado

Apesar de muitas vezes o sistema funcionar muito bem, pode acontecer de recebermos o seguinte retorno do servidor:

Esta mensagem é postada pelo servidor no retorno da nossa requisição, apesar da função WebRequest não indicar nenhum erro, e isto por parte da plataforma, o servidor retorna esta mensagem acima, por isto temos que analisar o cabeçario da mensagem de retorno, para que não fiquemos reféns deste tipo de problema, então para resolver isto fazemos uma pequena mudança no script de offset, esta pode ser vista abaixo:

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
void OnStart()
{
        while (!IsStopped())
        {
                Print(GetDataURL("https://tradingeconomics.com/stocks", 100, "<!doctype html>", 2, "INDU:IND", 172783, 173474, 0x0D));
                Sleep(200);
        }
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout, const string szTest, int iTest, const string szFind, int iPos, int iInfo, char cLimit)
{
        string  headers, szInfo = "";
        char    post[], charResultPage[];
        int     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1
                return "Bad";
        for (int c0 = 0, c1 = StringLen(szTest); c0 < c1; c0++) if (szTest[c0] != charResultPage[iTest + c0])
                return "Failed";
        for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0])
                return "Error";
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return szInfo;

A linha em destaque é justamente a que faz o teste, já que quando a mensagem de retorno do servidor é uma mensagem mais complexa, o simples fato de se fazer este teste já nos garante uma boa margem de segurança nos dados que estamos analisando, evitando que venhamos a analisar dados fantasmas, ou lixo de memória caso o sistema venha a passar pelo primeiro teste que já existia no código anterior. Apesar de ser raro, não devemos subestimar a possibilidade de isto acontecer.

Bem o resultado não é diferente, isto pode ser visto abaixo, então o sistema está funcionando conforme o esperado.


Bom, mas até agora não fizemos grandes coisas, apenas estamos lendo valores de uma página da web, e isto não é de grande utilidade, apesar de ser algo bastante curioso de aprender e ver como se faz, não tem grande utilidade prática para quem de fato deseja operar e negociar com base em informações, que a partir deste momento você estará modelando, já que você as captura e as mostra de uma outra maneira, então temos que fazer isto começar a fazer algum sentido dentro de um sistema mais amplo, e no caso vamos levar estas informações capturadas para dentro de um EA, desta forma você poderá fazer coisas ainda mais impressionantes e que de fato torna a plataforma MetaTrader 5 uma plataforma sensacional.


Conclusão

Bem a coisa não termina aqui, no próximo artigo irei mostrar como levar estas informações coletadas na WEB para dentro do EA, e isto irá literalmente lhe tirar do serio, já que será algo muito mais interessante, já que teremos que utilizar recursos muito pouco explorados dentro da plataforma MetaTrader  , então não perca o próximo artigo da serie.

No anexo esta todos os códigos fontes utilizados neste artigo.


Arquivos anexados |
Últimos Comentários | Ir para discussão (4)
felipe ramos
felipe ramos | 18 mai 2022 em 17:04

a algum detalhe que deixei passar?


Daniel Jose
Daniel Jose | 19 mai 2022 em 20:55
felipe ramos #:

a algum detalhe que deixei passar?


Provavelmente SIM ... você precisa ler e ver todo o artigo ... TODO inclusive o video que está presente no artigo, pois lá eu mostro alguns detalhes de como você faz para capturar as informações ... o detalhe é que o sistema é otimizado para ir em um determinado endereço de memória e não ficar procurando a informação, o que seria muito lento, já que estaremos usando um sistema de REAL TIME ... e caso a pagina seja modificada pelo administrador este endereço irá ser diferente, desta forma você terá que pesquisar onde fica o novo endereço, mas no artigo eu mostro detalhadamente como você faz para conseguir encontrar o novo endereço .... e no caso especifico, a observação de uma mensagem de erro indicada que o endereço esta diferente daquele que o sistema esperava encontrar a informação buscada ... LEIA o artigo ... VEJA o video e entenda o que estou explicando nele, mude o endereço que é usado para indicar onde a informação se encontra e você irá conseguir os dados que estão na pagina e de qualquer outra página .... lembre-se a busca tem que ser feita rapidamente já que o sistema é REAL TIME ... se não fosse poderíamos baixar a pagina e usar um loop para procura a informação, mas o tempo é precioso ... 😁👍

AnatoliyFX5
AnatoliyFX5 | 30 jul 2023 em 19:14

Artigo interessante, mas não consigo entender o que significa em amarelo?

GetDataURL("https://tradingeconomics.com/stocks", 100, "INDU:IND", 172783, 173474, 0x0D);

E é um número hexadecimal. Como posicionar corretamente?

...
GetDataURL("https://tradingeconomics.com/stocks", 100, "INDU:IND", 172783, 173474, 0x0D);
...
string GetDataURL(const string url, const int timeout, const string szFind, int iPos, int iInfo, char cLimit)
{
...
...
        for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error in Position";
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return szInfo;
}
Daniel Jose
Daniel Jose | 31 jul 2023 em 14:52
AnatoliyFX5 #:

Artigo interessante, mas não consigo entender o que significa em amarelo?

E é um número hexadecimal. Como posicionar corretamente?

Os valores iniciados em 0x são valores HEXA, já os demais são valores decimais comuns. Você pode usar o valor DECIMAL, mas acho complicado entender isto em alguns momentos. Já que normalmente quando uso valores da tabela ASCII prefiro fazer uso em HEXA. Mas o valor 0x0D é o que representa a tecla ENTER. E o 0x20 a tecla de ESPAÇO. Para encontrar estes valores, e posicionar eles corretamente, você precisa ter o arquivo e um editor HEXADECIMAL. Ai você precisa procurar o valor dentro do arquivo, para dizer ao procedimento, em que posição do arquivo o valor se encontra. Então os valores 172783 e173474 são endereços, ou posição dentro do arquivo que estará sendo baixado.

Procure aprender como usar um EDITOR HEXADECIMAL, pois ficará mais simples entender tais endereços.😁👍

Desenvolvendo um EA de negociação do zero (Parte 16): Acessando dados na WEB (II) Desenvolvendo um EA de negociação do zero (Parte 16): Acessando dados na WEB (II)
Como levar os dados da WEB para dentro de um EA . O caminho para fazer isto não é tão obvio, ou melhor dizendo, tão simples a ponto de você conseguir fazer, sem de fato conhecer e entender todos os recursos que estão presentes no MetaTrader 5.
Desenvolvendo um EA de negociação do zero (Parte 14): Volume at Price (II) Desenvolvendo um EA de negociação do zero (Parte 14): Volume at Price (II)
Aqui vamos adicionar recursos diversos no nosso EA. Este artigo vai ser bastante interessante, podendo direcionar você a novas ideias e métodos de apresentar informações e ao mesmo tempo corrigir pequenas falhas nos seus projetos.
Gráficos na biblioteca DoEasy (Parte 95): Controles de objetos gráficos compostos Gráficos na biblioteca DoEasy (Parte 95): Controles de objetos gráficos compostos
Neste artigo, consideraremos ferramentas para gerenciar objetos gráficos compostos, nomeadamente controles de um objeto gráfico padrão estendido. Hoje vamos nos desviar um pouco do tópico anterior, que era mover um objeto gráfico composto. Em vez disso, vamos fazer um manipulador de eventos de alteração de gráfico que tem algum objeto gráfico composto, e vamos lidar com os objetos de controle do objeto gráfico composto.
Desenvolvendo um EA de negociação do zero (Parte 13): Times And Trade (II) Desenvolvendo um EA de negociação do zero (Parte 13): Times And Trade (II)
Construa um sistema de Times & Trade para analisar o mercado. Esta é a segunda parte. No artigo anterior Times & Trade ( I ) apresentei um sistema alternativo para montar um gráfico de forma a você ter um indicador que lhe permitisse interpretar os negócios que foram executados no mercado de forma o mais rápido possível.