English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Utilizando WinInet.dll para a troca de dados entre plataformas via internet

Utilizando WinInet.dll para a troca de dados entre plataformas via internet

MetaTrader 5Integração | 4 março 2014, 10:05
3 069 2
---
---

O Metatrader abre oportunidades únicas para os usuários, utilizando um número de novos elementos da interface do usuário em seu arsenal. Por essa razão, as funções que estavam indisponíveis anteriormente podem agora serem usadas ao máximo.

Nesta lição iremos aprender a:

  • usar as tecnologias básicas de internet;
  • trocar os dados entre as plataformas via servidor;
  • criar uma biblioteca genérica para trabalhar com a internet no ambiente do MQL5.

O CodeBase do MQL5 contém um exemplo de script, que trabalha com a biblioteca wininet.dll e mostra um exemplo de solicitação da página do servidor. Mas hoje iremos muito mais longe, e faremos o servidor, não apenas nos dar a página, mas também enviar e armazenar esses dados para transferências posteriores a outras plataformas solicitantes.

Nota: para aqueles que não possuem acesso ao servidor, configurado com PHP, sugerimos baixar o kit Denwer, e usá-lo como uma plataforma de trabalho. Também, recomendamos o uso do servidor Apache e do PHP em seu localhost para teste.

Para enviar qualquer solicitação ao servidor, iremos precisar das 7 principais funções da biblioteca.

InternetAttemptConnect Tenta localizar uma conexão com a Internet e a estabelecer.
InternetOpen
Inicializa a estrutura para o trabalho das funções da biblioteca WinInet. Essa função deve ser ativada antes de quaisquer outras funções da biblioteca.
InternetConnect Abre o recurso especificado pelos endereços HTTP URL ou FTP. Retorna o descritor para uma conexão aberta
HttpOpenRequest Cria um descritor para as solicitações HTTP para configurar uma conexão
HttpSendRequest Envia uma consulta usando o descritor criado
InternetReadFile Lê os dados recebidos do servidor após a consulta ter sido processada
InternetCloseHandle Libera o descritor transferido


Uma descrição detalhada de todas as funções e seus parâmetros deve ser encontrada no sistema de ajuda MSDN.

A declaração das funções permaneceram as mesmas como no MQL4, com a exceção do uso das ativações do Unicode e das linhas de transferência pelo link.

#import "wininet.dll"
int InternetAttemptConnect(int x);
int InternetOpenW(string &sAgent,int lAccessType,string &sProxyName,string &sProxyBypass,int lFlags);
int InternetConnectW(int hInternet,string &szServerName,int nServerPort,string &lpszUsername,string &lpszPassword,int dwService,int dwFlags,int dwContext);
int HttpOpenRequestW(int hConnect,string &Verb,string &ObjectName,string &Version,string &Referer,string &AcceptTypes,uint dwFlags,int dwContext);
int HttpSendRequestW(int hRequest,string &lpszHeaders,int dwHeadersLength,uchar &lpOptional[],int dwOptionalLength);
int HttpQueryInfoW(int hRequest,int dwInfoLevel,int &lpvBuffer[],int &lpdwBufferLength,int &lpdwIndex);
int InternetReadFile(int hFile,uchar &sBuffer[],int lNumBytesToRead,int &lNumberOfBytesRead);
int InternetCloseHandle(int hInet);
#import

//To make it clear, we will use the constant names from wininet.h.
#define OPEN_TYPE_PRECONFIG     0           // use the configuration by default
#define FLAG_KEEP_CONNECTION    0x00400000  // do not terminate the connection
#define FLAG_PRAGMA_NOCACHE     0x00000100  // no cashing of the page
#define FLAG_RELOAD             0x80000000  // receive the page from the server when accessing it
#define SERVICE_HTTP            3           // the required protocol

Uma descrição detalhada dos sinalizadores é localizada na mesma seção MSDN para cada uma das funções. Se você desejar ver a declaração de outras constantes e funções, então você pode baixar o arquivo original wininet.h, localizado nos anexos do artigo.

1. Guias para criar e apagar a sessão de internet

A primeira coisa que devemos fazer é criar uma sessão e abrir uma conexão com o host. Uma sessão deve ser criada preferencialmente apenas uma vez durante a inicialização do programa (por exemplo, na função OnInit). Ou isso pode ser feito no começo da inicialização do Conselheiro Especialista, mas é importante certificar-se de que a criação bem sucedida foi feita apenas uma vez antes do fechamento da sessão. E isso não deve ser invocado repetido e sem necessidade, com cada nova iteração da implementação OnStart ou OnTimer. é importante evitar ativações frequentes e a criação das estruturas necessárias para cada ativação.

Portanto, usaremos apenas a instância da classe global para descrever a sessão e as descrições da conexão.

   string            Host;       // host name
   int               Port;       // port
   int               Session;    // session descriptor
   int               Connect;    // connection descriptor

bool MqlNet::Open(string aHost,int aPort)
  {
   if(aHost=="")
     {
      Print("-Host is not specified");
      return(false);
     }
   // checking the DLL resolution in the terminal  
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
     {
      Print("-DLL is not allowed");
      return(false);
     }
   // if the session was identifies, then we close
   if(Session>0 || Connect>0) Close();
   // record of attempting to open into the journal
   Print("+Open Inet...");
   // if we were not able to check for the presence of an Internet connection, then we exit
   if(InternetAttemptConnect(0)!=0)
     {
      Print("-Err AttemptConnect");
      return(false);
     }
   string UserAgent="Mozilla"; string nill="";
   // open a session
   Session=InternetOpenW(UserAgent,OPEN_TYPE_PRECONFIG,nill,nill,0);
   // if we were not able to open a session, then exit
   if(Session<=0)
     {
      Print("-Err create Session");
      Close();
      return(false);
     }
   Connect=InternetConnectW(Session,aHost,aPort,nill,nill,SERVICE_HTTP,0,0);
   if(Connect<=0)
     {
      Print("-Err create Connect");
      Close();
      return(false);
     }
   Host=aHost; Port=aPort;
   // otherwise all attempts were successful
   return(true);
  }

Após a inicialização os descritores Session e Connect podem ser usados em todas as seguintes funções. Uma vez que todo o trabalho estiver completo e os programas MQL estiverem desinstalados, eles devem ser removidos. Isso é feito pelo uso da função InternetCloseHandle.

void MqlNet::CloseInet()
  {
   Print("-Close Inet...");
   if(Session>0) InternetCloseHandle(Session); Session=-1;
   if(Connect>0) InternetCloseHandle(Connect); Connect=-1;
  }

Atenção! Ao trabalhar com as funções de internet, é necessário disponibilizar todos os descritores derivados delas, usando a InternetCloseHandle.

2. Enviando uma solicitação ao servidor e recebendo a página

Para enviar uma solicitação e receber uma página em resposta à solicitação, iremos precisar das três funções restantes HttpOpenRequest, HttpSendRequest и InternetReadFile. A essência do recebimento da página em resposta à uma solicitação é basicamente o simples processo de salvar seu conteúdo em um arquivo local.


Pela conveniência de trabalhar com solicitações e conteúdos criaremos duas funções universais.

Enviando uma solicitação:

bool MqlNet::Request(string Verb,string Object,string &Out,bool toFile=false,string addData="",bool fromFile=false)
  {
   if(toFile && Out=="")
     {
      Print("-File is not specified ");
      return(false);
     }
   uchar data[];
   int hRequest,hSend,h;
   string Vers="HTTP/1.1";
   string nill="";
   if(fromFile)
     {
      if(FileToArray(addData,data)<0)
        {
         Print("-Err reading file "+addData);

         return(false);
        }
     } // read file in the array
   else StringToCharArray(addData,data);

   if(Session<=0 || Connect<=0)
     {
      Close();
      if(!Open(Host,Port))
        {
         Print("-Err Connect");
         Close();
         return(false);
        }
     }
   // create a request descriptor
   hRequest=HttpOpenRequestW(Connect,Verb,Object,Vers,nill,nill,FLAG_KEEP_CONNECTION|FLAG_RELOAD|FLAG_PRAGMA_NOCACHE,0);
   if(hRequest<=0)
     {
      Print("-Err OpenRequest");
      InternetCloseHandle(Connect);
      return(false);
     }
   // send request
   // headline for request
   string head="Content-Type: application/x-www-form-urlencoded";
   // sent file
   hSend=HttpSendRequestW(hRequest,head,StringLen(head),data,ArraySize(data)-1);
   if(hSend<=0)
     {
      Print("-Err SendRequest");
      InternetCloseHandle(hRequest);
      Close();
     }
   // read the page 
   ReadPage(hRequest,Out,toFile);
   // close all handles
   InternetCloseHandle(hRequest); 
   InternetCloseHandle(hSend);
   return(true);
  }

Os parâmetros da função MqlNet:: Solicitação:

  • string Verb – tipo de solicitação “GET” ou “POST”;
  • string Object – nome da página com sua transmissão nos parâmetros;
  • string &Out – linha para qual a resposta é recebida;
  • bool toFile – se toFile=true, então Out indica o nome do arquivo onde a resposta deve ser recebida.
  • string addData - dados adicionais;
  • bool fromFile - se fromFile = true, então addData é o nome do arquivo que precisa ser enviado.

Lendo os conteúdos do descritor recebido

void MqlNet::ReadPage(int hRequest,string &Out,bool toFile)
  {
   // read the page 
   uchar ch[100];
   string toStr="";
   int dwBytes,h;
   while(InternetReadFile(hRequest,ch,100,dwBytes))
     {
      if(dwBytes<=0) break;
      toStr=toStr+CharArrayToString(ch,0,dwBytes);
     }
   if(toFile)
     {
      h=FileOpen(Out,FILE_BIN|FILE_WRITE);
      FileWriteString(h,toStr);
      FileClose(h);
     }
   else Out=toStr;
  }

Os parâmetros da função MqlNet:: ReadPage:

  • Int hRequest - descritor da solicitação a partir do qual os dados são lidos;
  • string &Out – linha para qual a resposta é recebida;
  • bool toFile - se oFile = true, então Out é o nome do arquivo onde a resposta será recebida.

E reunindo tudo isso em um, iremos obter uma classe de biblioteca MqlNet para trabalhar com a internet.

class MqlNet
  {
   string            Host;     // host name
   int               Port;     // port
   int               Session; // session descriptor
   int               Connect; // connection descriptor
public:
                     MqlNet(); // class constructor
                    ~MqlNet(); // destructor
   bool              Open(string aHost,int aPort); // create a session and open a connection
   void              Close(); // close session and connection
   bool              Request(string Verb,string Request,string &Out,bool toFile=false,string addData="",bool fromFile=false); // send request
   bool              OpenURL(string URL,string &Out,bool toFile); // somply read the page into the file or the variable
   void              ReadPage(int hRequest,string &Out,bool toFile); // read the page
   int               FileToArray(string FileName,uchar &data[]); // copy the file into the array for sending
  };

Essas são basicamente todas as funções necessárias que provavelmente satisfazem as necessidades diversificadas para trabalhar com a internet. Examine os exemplos de seu uso.

Exemplo 1. Transferência automática dos programas MQL dentro das pastas das plataformas. MetaGrabber script

Para iniciar nosso teste do trabalho da classe, vamos começar com as tarefas mais fáceis - ler a página e salvar seu conteúdo em uma pasta especificada. Mas uma simples leitura das páginas é improvável ser interessante, então para ganhar algo do trabalho do script, vamos atribuir a ele uma função do grabber dos programas mql dos sites. A tarefa do MetaGrabber script será:

  • a análise do URL e a separação dele dentro do host, da solicitação, e do nome do arquivo;
  • enviar uma solicitação ao host, receber e salvar o arquivo dentro da pasta da plataforma \\ Files;
  • movê-la da File para uma das pastas de dados solicitada:
    \Experts, \Indicators, \Scripts, \Include, \Libraries, \Tester(set), \Templates.

Para resolver o segundo problema usamos a classe MqlNet. Para a terceira tarefa usamos a função MoveFileEx da Kernel32.dll

#import "Kernel32.dll"
bool MoveFileExW(string &lpExistingFileName, string &lpNewFileName, int dwFlags);
#import "Kernel32.dll"

Para o primeiro problema, vamos fazer uma função de serviço pequena de análise da linha URL.

Precisamos alocar três linhas do endereço: o host, o caminho para o site, e o nome do arquivo.
Por exemplo, na linha http://www.mysite.com/folder/page.html

- o host = www.mysite.com
- a solicitação = / folder / page.html
- o nome do arquivo = page.html

No caso de CodeBase no site do MQL5, os caminhos tem a mesma estrutura. Por exemplo, o caminho para a biblioteca ErrorDescription.mq5 na página https://www.mql5.com/ru/code/79 aparece como http://p.mql5.com/data/18/79/ErrorDescription.mqh. Esse caminho é facilmente obtido clicando com o botão direito no link e selecionando "Copiar Link". Assim, o URL é separado em duas partes, uma para a solicitação e outra para o nome do arquivo pela conveniência de armazenamento do arquivo.

- Host = p.mql5.com
- solicitação = / data/18/79/5/ErrorDescription.mqh
- nome do arquivo = ErrorDescription.mqh

Esse é o tipo de análise de linha que a seguinte função ParseURL estará lidando.

void ParseURL(string path,string &host,string &request,string &filename)
  {
   host=StringSubstr(URL,7);
   // removed
   int i=StringFind(host,"/"); 
   request=StringSubstr(host,i);
   host=StringSubstr(host,0,i);
   string file="";
   for(i=StringLen(URL)-1; i>=0; i--)
      if(StringSubstr(URL,i,1)=="/")
        {
         file=StringSubstr(URL,i+1);
         break;
        }
   if(file!="") filename=file;
  }

Nos parâmetros externos do script (roteiro) faremos apenas dois parâmetros - URL (caminho do arquivo mql5) e o tipo de pasta do posicionamento posterior - ou seja, em qual pasta da plataforma você deseja colocá-lo.

Como resultado, obtemos um script breve mas muito útil.

//+------------------------------------------------------------------+
//|                                                  MetaGrabber.mq5 |
//|                                 Copyright © 2010 www.fxmaster.de |
//|                                         Coding by Sergeev Alexey |
//+------------------------------------------------------------------+
#property copyright "www.fxmaster.de  © 2010"
#property link      "www.fxmaster.de"
#property version               "1.00"
#property description  "Download files from internet"

#property script_show_inputs

#include <InternetLib.mqh>

#import "Kernel32.dll"
bool MoveFileExW(string &lpExistingFileName,string &lpNewFileName,int dwFlags);
#import
#define MOVEFILE_REPLACE_EXISTING 0x1

enum _FolderType
  {
   Experts=0,
   Indicators=1,
   Scripts=2,
   Include=3,
   Libraries=4,
   Files=5,
   Templates=6,
   TesterSet=7
  };

input string URL="";
input _FolderType FolderType=0;
//------------------------------------------------------------------ OnStart
int OnStart()
  {
   MqlNet INet; // variable for working in the Internet
   string Host,Request,FileName="Recieve_"+TimeToString(TimeCurrent())+".mq5";

   // parse url
   ParseURL(URL,Host,Request,FileName);

   // open session
   if(!INet.Open(Host,80)) return(0);
   Print("+Copy "+FileName+" from  http://"+Host+" to "+GetFolder(FolderType));

   // obtained file
   if(!INet.Request("GET",Request,FileName,true))
     {
      Print("-Err download "+URL);
      return(0);
     }
   Print("+Ok download "+FileName);

   // move to the target folder
   string to,from,dir;
   // if there is no need to move it elsewhere
   if(FolderType==Files) return(0);

   // from
   from=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\"+FileName;

   // to
   to=TerminalInfoString(TERMINAL_DATA_PATH)+"\\";
   if(FolderType!=Templates && FolderType!=TesterSet) to+="MQL5\\";
   to+=GetFolder(FolderType)+"\\"+FileName;

   // move file 
   if(!MoveFileExW(from,to,MOVEFILE_REPLACE_EXISTING))
     {
      Print("-Err move to "+to);
      return(0);
     }
   Print("+Ok move "+FileName+" to "+GetFolder(FolderType));

   return(0);
  }
//------------------------------------------------------------------ GetFolder
string GetFolder(_FolderType foldertype)
  {
   if(foldertype==Experts) return("Experts");
   if(foldertype==Indicators) return("Indicators");
   if(foldertype==Scripts) return("Scripts");
   if(foldertype==Include) return("Include");
   if(foldertype==Libraries) return("Libraries");
   if(foldertype==Files) return("Files");
   if(foldertype==Templates) return("Profiles\\Templates");
   if(foldertype==TesterSet) return("Tester");
   return("");
  }
//------------------------------------------------------------------ ParseURL
void ParseURL(string path,string &host,string &request,string &filename)
  {
   host=StringSubstr(URL,7);
   // removed
   int i=StringFind(host,"/"); 
   request=StringSubstr(host,i);
   host=StringSubstr(host,0,i);
   string file="";
   for(i=StringLen(URL)-1; i>=0; i--)
      if(StringSubstr(URL,i,1)=="/")
        {
         file=StringSubstr(URL,i+1);
         break;
        }
   if(file!="") filename=file;
  }
//+------------------------------------------------------------------+


Vamos conduzir os experimentos em nossa seção favorita, https://www.mql5.com/pt/code. Os arquivos baixados irão aparecer imediatamente no navegador do editor, e eles podem ser compilados sem reiniciar a plataforma ou o editor. E eles não irão vagar através dos longos caminhos do sistema de arquivos na busca pela pasta desejada para colocar os arquivos dentro.

Atenção! Muitos sites aumentam a segurança contra a maciça transferência de conteúdos, e seu endereço de IP, no caso de transferência maciça, deve ser bloqueado por esse recurso. Portanto, preste bastante atenção ao uso da "máquina" de transferência dos arquivos a partir dos recursos, os quais você frequentemente acessa e não quer ser proibido de usar.

Aqueles que desejam ir mais longe, melhorando o serviço proposto, podem usar o script Clipboard com a interceptação dos conteúdos da área de transferência e transferência automática posterior.

Exemplo 2. Monitorando as citações de múltiplos agentes em um único gráfico.

Então aprendemos a obter arquivos da internet. Agora vamos examinar uma questão mais importante - como enviar e armazenar esses dados no servidor. Para isso, precisamos de um pequeno PHP-script adicional, que será localizado no servidor. Usando a classe escrita MqlNet, criamos um Consultor Especialista para o monitoramento - o MetaArbitrage. A tarefa do especialista juntamente com o PHP-script será:

  • Envio de uma solicitação do Consultor Especialista ao servidor;
  • formação da página de resposta (PHP) no servidor;
  • recepção dessa página através do Consultor Especialista;
  • sua análise e a entrega dos resultados para a tela.

O diagrama esquemático da interação entre o MQL-module e o PHP-script aparece a seguir:


Usaremos a classe MqlNet para resolver as seguintes tarefas.

Para evitar a duplicação dos dados, assim como para excluir as cotações desatualizadas - mandaremos 4 parâmetros principais: o nome do servidor do agente (a fonte dos preços correntes), a moeda, o preço e o tempo das cotações em UTC. Por exemplo, uma solicitação para acessar o script a partir dos recursos de nossa empresa é a seguinte:

www.fxmaster.de/metaarbitr.php?server=Metaquotes&pair=EURUSD&bid=1.4512&time=13286794

Esses parâmetros e a cotação real estão armazenados no servidor e serão baixados na página de resposta, junto com todas as outras cotações armazenadas desta moeda.

A conveniência "colateral" dessa troca é que as cotações podem ser enviadas do MT5, assim como do MT4!

A página que é formada a partir do servidor, é um arquivo CSV regular. Nesse script ela aparece assim:

ServerName1; Bid1; Time1
ServerName 2; Bid2; Time2
ServerName 3; Bid3; Time3

ServerName N; BidN; TimeN

Mas você pode adicionar a ela seus próprios parâmetros adicionais (por exemplo, o tipo de servidor - demo ou real). Armazenamos esse arquivo CSV e o analisamos linha por linha, com o resultado de uma tabela de valor e os preços da linha mostrados na tela.

O processamento desse arquivo pode ser realizado de várias maneiras diferentes, uma vez que a escolha seja solicitada em cada caso específico. Por exemplo, filtre as cotações recebidas do servidor demo do MetaTrader 4, etc.


As vantagens de usar o servidor de internet são óbvias - você está enviando suas cotações, as quais podem ser recebidas e vistas por um outro negociante. Da mesma forma, você receberá cotações que são enviadas por outros negociantes. Ou seja, a interação entre as plataformas é bilateral, a troca de dados é realizada como mostrada no seguinte esquema:


Esse esquema serve como base para o princípio da troca de informações entre qualquer número de plataformas. Um Conselheiro Especialista MetaArbitrage completo e o PHP-script com comentários pode ser baixado a partir do link nos anexos. Mais sobre as funções usadas em PHP pode ser lido no seguinte site php.su

Exemplo 3. Troca de mensagens (mini chat) dentro da plataforma. MetaChat Consultor Especialista

Vamos nos afastar um pouco das negociações e dos números, e criar um aplicativo que irá nos permitir conversar com várias pessoas ao mesmo tempo sem sair da plataforma. Para fazer isso iremos precisar de mais um script PHP, o qual em geral é muito similar ao anterior. Exceto pelo fato de que neste script, ao invés de analisar cotações de tempo, iremos analisar o número de linhas em um arquivo. A tarefa do Consultor Especialista será:

  • Enviar uma linha de texto ao servidor;
  • adicionar essa linha dentro do arquivo compartilhado, controlar o tamanho do arquivo, emitir o arquivo de resposta (php);
  • receber a conversa atual e exibí-la na tela.

O trabalho do Metachat não irá se diferenciar daquele do Consultor Especialista anterior. O mesmo princípio, e o mesmo arquivo CSV simples para saída.


O MetaChat e o MetaArbitrage são mantidos no site de seus desenvolvedores. Os PHP-scripts para seu trabalho também estão localizados aqui.
Portanto, se você quiser testar um trabalho ou usar esse serviço, você pode acessá-lo através do seguinte link:
MetaСhat - www.fxmaster.de/metachat.php
MetaArbitrage - www.fxmaster.de/metaarbitr.php

Conclusão

E assim nos familiarizamos com as HTTP-requests. Adquirimos a habilidade de enviar e receber os dados através da internet, e de organizar o processo de trabalho mais confortavelmente. Mas quaisquer capacidades podem sempre ser melhoradas. As seguintes podem ser consideradas as novas orientações possíveis de seus melhoramentos:

  • ler as notícias ou receber outras informações diretamente na plataforma para a análise dos Consultores Especialistas;
  • gerenciamento remoto dos Consultores Especialistas;
  • atualizações automáticas dos Consultores Especialistas/indicadores;
  • copiadores/conversores de negociações, sinais de envio;
  • baixar modelos junto com as luzes e conjuntos de arquivos para os Consultores Especialistas:
  • E muito, muito mais...

Neste artigo usamos o tipo GET de solicitações. Elas cumprem adequadamente a tarefa quando você precisa obter um arquivo, ou enviar uma solicitação, com um pequeno número de parâmetros, para uma análise do servidor.

Em nossa próxima lição, iremos olhar cuidadosamente as solicitações POST - enviar arquivos para o servidor ou o compartilhamento de arquivos entre as plataformas, e iremos examinar os exemplos de seu uso.

Recursos úteis

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/73

Arquivos anexados |
internetlib.mqh (8.35 KB)
metaarbitrage.mq5 (9.27 KB)
metachat.mq5 (5.68 KB)
metagrabber.mq5 (3.24 KB)
metaarbitr.zip (0.72 KB)
wininet.zip (12.81 KB)
Últimos Comentários | Ir para discussão (2)
Placido Mitoso
Placido Mitoso | 31 jul 2017 em 07:45

No código baixo, eu troquei a variável URL por path, pois URL é variável externa a função ParseURL : 

void ParseURL(string path,string &host,string &request,string &filename)

  {

   host=StringSubstr(path,7);

   // remove

   int i=StringFind(host,"/"); 

   request=StringSubstr(host,i);

   host=StringSubstr(host,0,i);

   string file="";

   for(i=StringLen(path)-1; i>=0; i--)

      if(StringSubstr(path,i,1)=="/")

        {

         file=StringSubstr(path,i+1);

         break;

        }

   if(file!="") filename=file;

  }

felipe.resilva
felipe.resilva | 25 ago 2017 em 03:44

Boa noite!!

Utilizei o XAMPP para instalar o php e apache. Porém, não estou conseguindo acessar a página via GET pelo MQL5.

Segue abaixo o erro retornado:

Access forbidden!

You don't have permission to access the requested object.

It is either read-protected or not readable by the server.

Alguém sabe como resolver este problema?
O algoritmo de geração de pontos (ticks) dentro do examinador de estratégia da plataforma MetaTrader 5 O algoritmo de geração de pontos (ticks) dentro do examinador de estratégia da plataforma MetaTrader 5
O MetaTrader 5 nos permite simular negociação automática, dentro de um verificador de estratégia incorporado, utilizando Expert Advisors e a linguagem MQL5. Este tipo de simulação é chamada de teste dos Expert Advisors, e pode ser implementado utilizando a otimização multitarefa, também como simultaneamente sobre um número de instrumentos. A fim de oferecer um teste rigoroso, uma geração de pontos (ticks) baseada no histórico por minuto disponível, precisa ser executada. Este artigo fornece uma descrição detalhada do algoritmo, pelo qual os ticks (pontos) são gerados para o teste histórico no terminal do cliente do MetaTrader 5.
Nota de usuário - MQL5.community Nota de usuário - MQL5.community
Você acabou de registrar e, provavelmente, você tem perguntas como: "Como faço para inserir uma imagem na minha mensagem?", "Como faço para formatar meu código fonte MQL5?", "Onde são mantidas minhas mensagens pessoais?". Você pode ter muitas outras perguntas. Neste artigo, nós preparamos algumas dicas práticas que ajudarão você a se acostumar com o MQL5.community e tirar o máximo proveito de seus recursos disponíveis.
Análise técnica: O que analisamos? Análise técnica: O que analisamos?
Este artigo tenta analisar diversas peculiaridades da representação de cotações disponível no terminal cliente do MetaTrader. O artigo é geral, ele não diz respeito à programação.
Documentação gerada automaticamente para o código MQL5 Documentação gerada automaticamente para o código MQL5
A maioria dos codificadores Java estará familiarizada com a documentação gerada automaticamente com o JavaDocs. A ideia é adicionar comentários no código de uma maneira semi-estruturada que possam ser extraídos em um arquivo de ajuda fácil de navegar. O mundo do C++ também possui vários geradores automáticos de documentação, com os dois líderes sendo o SandCastle da Microsoft e o Doxygen. O artigo descreve o uso do Doxygen para criar o arquivo de ajuda HTML a partir dos comentários estruturados no código MQL5. O experimento funcionou muito bem, acredito que a documentação de ajuda que o Doxygen produz do código MQL5 irá agregar uma grande quantidade de valor.