Como conectar o MetaTrader 5 ao PostgreSQL
Introdução
A paisagem do desenvolvimento de software mudou muito nos últimos dez anos. Vimos a popularização da computação em nuvem e acrônimos como IASS, PASS e SAAS são agora ferramentas-chave que devem ser consideradas em qualquer projeto de software. As coisas ficaram mais fáceis tanto para o usuário final quanto para o desenvolvedor de software.
A equipe da MetaQuotes estava ciente dessas mudanças e, desde 2014, temos uma WebRequest nativa para o MetaTrader 5.
Uma das áreas que mais mudou foi a gestão de bancos de dados (BD). Soluções que costumavam ser complexas ou até mesmo "estranhas" de um ponto de vista prático se tornaram não só viáveis, mas a solução preferida para muitos casos de uso. Este foi o caso do acesso a bancos de dados via REST API.
Uma proposta de acesso a bancos de dados via REST API pareceria superdimensionada alguns anos atrás. Hoje, uma rápida busca por "banco de dados gerenciado com acesso via rest API" retornará dezenas de provedores, variando desde alguns dólares/mês em planos básicos até soluções empresariais personalizadas. Muitos desses provedores oferecem generosos níveis gratuitos para prototipagem, testes ou até mesmo implantação de pequenas cargas de trabalho de produção.
Este artigo analisa cinco alternativas padrão para conectar um banco de dados Postgres ao MetaTrader 5, seus requisitos, prós e contras. Além disso, configuraremos um ambiente de desenvolvimento, instalaremos um banco de dados Postgres como remoto, nos conectaremos a ele e inseriremos e recuperaremos dados a serem consumidos por um script ou EA MQL5.
Esta configuração de ambiente de desenvolvimento e respectivos procedimentos podem ser facilmente replicados com qualquer RDBMS, uma vez que a API REST serve como uma camada de abstração entre o sistema de BD e o código do cliente.
MetaTrader 5 e bancos de dados
O MetaTrader 5 já tem as funções de que você pode precisar para trabalhar com um banco de dados e as funções de que você pode precisar para se conectar a um banco de dados via rede.
Desde 2020, a plataforma oferece integração nativa com o SQLite. Você pode usar as funções de banco de dados mencionadas acima para interagir com ele a partir do código. Além disso, você pode interagir com seus bancos de dados através de uma GUI dedicada no MetaEditor, facilitando a criação de tabelas, alteração de tabelas e realização de operações CRUD sem a necessidade de software adicional.
Isso foi uma grande melhoria na experiência do usuário final e uma adição chave ao arsenal do desenvolvedor MQL5.
Entre dezenas de RDBMS disponíveis, muitos deles com licenças de código aberto, SQLite parece ter sido uma escolha inteligente pelos desenvolvedores do MetaTrader 5. Apesar de ser um banco de dados SQL completo, com índices multicolunas, triggers, views, transações acid, busca de texto completo, funções agregadas e mais, é leve, baseado em arquivos, escalável e requer zero manutenção. De acordo com seu site, "parece provável que existam mais de um trilhão (1e12) de bancos de dados SQLite em uso ativo".
Apesar de suas impressionantes características, SQLite é limitado por design a um único usuário e não é destinado a acesso concorrente em implantações web. O grande número de postagens no fórum e artigos no site MQL5 sobre como conectar o MetaTrader 5 ao MySQL revela que há uma demanda por uma solução mais robusta para outros casos de uso.
Este artigo está focado em configurar um ambiente de desenvolvimento para esses casos de uso usando Postgres.
Por que Postgres
Primeiro de tudo, escolhi o Postgres porque a outra alternativa popular de código aberto, o MySQL, já foi extensivamente abordada aqui.
Em segundo lugar, o Postgres é um projeto de código aberto maduro, multiplataforma, é muito bem mantido, com documentação consistente. É popular e você pode encontrar uma infinidade de códigos de exemplo, guias e tutoriais pela web. Da mesma forma, existem muitos provedores de nuvem disponíveis para todas as necessidades e orçamentos.
O Postgres é de nível empresarial e, ao mesmo tempo, pode ser facilmente gerenciado por um único usuário trabalhando sozinho em uma máquina doméstica.
E claro, escolhi o Postgres porque confio nele. Por mais de uma década, sou um usuário satisfeito do Postgres em diferentes projetos.
E, por último, mas não menos importante, atualmente estou implementando a solução que estou compartilhando aqui para o meu ambiente de negociação pessoal. Então, é uma espécie de "dar a cara a tapa".
Quatro maneiras de interagir com Postgres a partir do MQL5
Até onde eu posso ver, existem quatro abordagens principais para chamar o Postgres a partir do MQL5:
- Uma biblioteca/driver MQL5 dedicada
- Um .dll a partir da interface do cliente C++
- Via driver .NET Npgsql
- Uma API REST
Vamos dar uma olhada nos requisitos, prós e contras de cada um. Tenho certeza de que a grande comunidade de desenvolvedores experientes da comunidade MQL5 estará oferecendo soluções fáceis para os contras, bem como apontando as desvantagens que não consegui ver nos prós. Este feedback da comunidade MQL5 é esperado, pois tanto o desenvolvedor menos experiente quanto o trader não desenvolvedor que chega aqui se beneficiarão desta discussão relacionada.
1. Uma biblioteca/driver MQL5 dedicada
Esta biblioteca ainda não existe. Precisa ser desenvolvida e exigiria muitas horas de trabalho duro de um desenvolvedor MQL5 sênior. Isso não seria barato. Precisamos levar em conta os custos de manutenção também. O Postgres é maduro, mas não é de forma alguma estático. É um projeto ativo com lançamentos regulares e alguns desses lançamentos, senão muitos, exigirão atualizações no código do cliente.
Por exemplo: agora, no momento da escrita, a última versão do Postgres (15) exige que usuários regulares de um banco de dados devam ser concedidos alguns privilégios no esquema público (public schema). Este requisito não existia em versões anteriores. Provavelmente, a manutenção é necessária em várias bases de código por aí.
A vantagem de encomendar o desenvolvimento de um driver MQL5 dedicado para o Postgres é que, se compartilhado, poderia ser útil para muitos usuários do MQL5. A desvantagem é bastante óbvia: o custo em tempo/dinheiro.
Por onde começar se você escolher este caminho:
Uma busca genérica por artigos MySQL neste site retornará algumas referências úteis.
Biblioteca de cliente C++ de código abert libpqxx
Biblioteca oficial do cliente em C para Postgres libpq
2. Um .dll a partir da interface do cliente C++
Esta é uma biblioteca oficial externamente mantida em C++, a libpqxx, que é construída sobre a biblioteca oficial em C internamente mantida, a libpq, que é fornecida com a distribuição Postgres.
Pessoalmente, nunca a usei, e tudo o que posso dizer é que ela está lá há muito tempo e parece ser bem mantida. A desvantagem deste método é que o Mercado MQL5 não permite DLL's. Se isso não for um problema para o seu projeto e você estiver à vontade trabalhando com .dll's do MetaTrader, essa pode ser a sua solução.
Por onde começar se você escolher este caminho:
A biblioteca de cliente C++ de código aberto libpqxx
3. Via driver .NET Npgsql
Desde 2018, o MetaTrader 5 adicionou suporte nativo para bibliotecas .NET com importação de funções 'inteligentes'. Com o lançamento da plataforma build 1930, as bibliotecas .NET podem ser usadas sem escrever wrappers especiais - o MetaEditor faz isso por conta própria".
Tudo o que você precisa para usar o driver .NET Npgsql é importar o .dll em si. Existem algumas limitações que você pode verificar nas notas de lançamento oficiais (https://www.mql5.com/ru/forum/285631).
Por onde começar se você escolher este caminho:
O driver Postgres de código aberto para .NET
4. Uma API REST
Se você escolher o caminho "sem .dll", este deve ser o método mais rápido e barato. A API pode ser escrita em qualquer linguagem e você pode ter um protótipo funcionando em um dia ou até mesmo algumas horas.
Além disso, alguns provedores de nuvem oferecem API REST integrada para o Postgres de graça. Tudo o que você precisa para começar é um bom ambiente de desenvolvimento para o seu código MQL5.
Usando este método, o seu código MQL5 pode consumir as respostas do seu Postgres como JSON.
Por onde começar se você escolher este caminho:
Aqui, com este artigo! Basta continuar lendo, seguir os passos abaixo, baixar o código de exemplo e começar a armazenar e consultar seus negócios e negociações em um banco de dados Postgres.
Configurando o ambiente de desenvolvimento
Escolha o método que escolher, você precisará de um ambiente de desenvolvimento em uma máquina Windows com um servidor Postgres em execução. Como diz o ditado, há mais de uma maneira de fazer isso. Lembro-me desses três caminhos, do mais complexo e demorado ao mais simples:
- Compilação a partir do código fonte
- Contêiner docker
- Instalador msi de terceiros
Todos eles são boas maneiras de ter o Postgres no Windows, mas acredite em mim, a compilação a partir do código fonte no Windows deve ser sua última opção, exceto se você estiver disposto a aprender a teoria e a prática da resiliência intermitente no desenvolvimento de software.
O contêiner docker é uma opção muito boa, uma instalação robusta e flexível em que seu servidor de banco de dados estará funcionando em uma "máquina remota", não "localhost" (veja abaixo). Afinal, é fácil. Você só precisa do Docker instalado, e duas a três linhas de comando e você está pronto para ir.
Deixando de lado o inconveniente relativo de software de "terceiros", o instalador msi de terceiros é uma boa alternativa para evitar a aventura de compilar a partir do código-fonte ou a instalação do Docker e gestão de contêineres.
No entanto, eu não recomendaria um ambiente de desenvolvimento para um servidor de banco de dados, ou qualquer tipo de servidor para este assunto, como um "localhost", se for possível desenvolver contra um servidor localizado em uma máquina remota. Isso porque é sempre uma boa prática desenvolver, testar e depurar um servidor em um ambiente remoto, e não em "localhost", a fim de solucionar problemas de configurações de conexão e problemas de autenticação o mais rápido possível.
O que é o WSL
WSL é a sigla para Windows Subsystem For Linux.
Caso você não tenha percebido, desde 2016 você pode executar uma distribuição Linux em uma máquina Windows como um subsistema. Não se preocupe! Não há hacks aqui. O WSL é desenvolvido pela Microsoft e está integrado ao Windows. Você só precisa ativá-lo, como veremos a seguir.
Por que WSL
Por que não simplesmente instalar o Postgres em outra máquina Windows, eventualmente uma máquina virtual?
Porque o Postgres é um sistema nativo Unix, criado e desenvolvido em sistemas \*nix. Ao instalá-lo no Linux, você terá fácil instalação, atualizações fáceis e fácil manutenção. Toda a documentação oficial é direcionada a um sistema Unix. E a maioria do código de exemplo, trechos e ajuda geral que você pode encontrar na web reflete esse fato.
Assim, você terá facilidade para desenvolver em um sistema Linux. E o WSL foi desenvolvido pela Microsoft exatamente para este propósito.
Instale o WSL
Pré-requisitos da documentação da Microsoft:
"Você deve estar executando a versão 2004 do Windows 10 ou superior (Build 19041 e superior) ou Windows 11 para usar os comandos abaixo. Se você estiver em versões anteriores, por favor, veja a página de instalação manual".
Se o seu sistema atender a este pré-requisito, basta abrir um Power Shell como administrador e digitar o comando abaixo para instalar/ativar o WSL:
wsl -install
Este comando instalará o Ubuntu no WSL, pois é a distro padrão.
Reinicie o Windows.
Este deve ser um processo simples. Se não for, você encontrará uma seção com os problemas de instalação mais comuns na documentação oficial da MS, linkada acima.
Depois de reiniciar, você deverá ver algo assim. Vá em frente, crie um novo nome de usuário e senha UNIX.
Agora que você tem o WSL/Ubuntu instalado e funcionando, vamos instalar o Postgres nele.
No WSL, instale o Postgres
Digite o comando abaixo.
sudo apt install postgresql postgresql-contrib
Este comando instalará a última versão estável do pacote PostgreSQL disponível nos repositórios do Ubuntu. Ele inclui o servidor, o cliente pgsql, binários convenientes e algumas utilidades. Tudo o que você precisa para começar.
Se você quiser instalar a última versão estável do Postgres - geralmente diferente da última versão estável nos repositórios do Ubuntu - você pode incluir o repositório oficial do Postgres na lista de fontes do seu gerenciador de pacotes. Você pode encontrar instruções detalhadas na documentação oficial do Postgres.
Se tudo estiver ok, ao digitar o comando
psql --version
deverá retornar a versão instalada do seu banco de dados Postgres.
Inicie o servidor
Digite este comando para iniciar o servidor.
sudo service postgresql start
Por padrão, uma nova instalação do Postgres só aceita conexões do "localhost". Vamos mudar isso.
Encontre o arquivo de configuração do Postgres.
sudo -u postgres psql -c "SHOW config_file"
Edite o arquivo de configuração para aceitar conexões fora do localhost. Mude a linha listen_addresses.
Encontre o arquivo de configuração pg_hba.
sudo -u postgres psql -c "SHOW hba_file"
Edite o arquivo pg_hba.conf para permitir autenticação por senha tanto em IPv4 quanto em IPv6.
Agora acesse a utilidade psql como o usuário Postgres padrão criado pela instalação. Ele é chamado de 'postgres'.
sudo -u postgres psql
Crie um usuário regular de banco de dados com privilégio CREATEDB. Até agora só existe o usuário 'postgres' criado pela instalação.
Conceda todos os privilégios no esquema público para mt5_user. Isso não é necessário se a sua versão do Postgres for inferior a 15.
CREATE USER mt5_user PASSWORD '123' CREATEDB;
GRANT ALL ON SCHEMA public TO mt5_user;
Crie um banco de dados my_remote_db e conceda todos os privilégios a mt5_user.
GRANT ALL PRIVILEGES ON DATABASE my_remote_db TO mt5_user;
Conecte ao Postgres
A esta altura, você deve ter um servidor de banco de dados rodando em uma máquina remota, com um IP diferente do seu localhost do Windows e pronto para aceitar conexões via rede. Podemos conectar via socket ou HTTP. Como vamos interagir com uma API REST, neste exemplo usaremos o último.
Vamos ver se conseguimos nos conectar ao my_remote_db como mt5_user com a senha 123 no host WSL.
Digite este comando para obter o nome do host (IP) do seu WSL.
hostname -I
Verifique o status do servidor Postgres. Inicie-o se estiver desligado. Você pode usar este comando para iniciar, reiniciar ou parar o servidor.
sudo service postgresql {status, start, stop}
No terminal MetaTrader 5, vá para Ferramentas > Opções > guia Expert Advisors e inclua o IP do host WSL na lista dos permitidos.
O terminal MetaTrader 5 aceita conexões HTTP e HTTPS apenas nas portas 80 e 443, respectivamente. Apenas as portas 80 e 443. Você deve levar em conta este recurso de segurança se estiver desenvolvendo sua API. Normalmente, antes de passar para um servidor real em produção, o servidor de desenvolvimento estará ouvindo em uma porta não privilegiada, como 3000 ou 5000. Assim, para poder enviar solicitações para o IP que você declarou nas configurações do seu terminal acima, você precisa redirecionar o tráfego que chega na porta do servidor de desenvolvimento para a porta 80 para solicitações HTTP e/ou 443 para solicitações HTTPS.
Para manter as coisas simples, você encontrará instruções no README do aplicativo Python anexo sobre como realizar este redirecionamento no WSL.
Iniciando o aplicativo de demonstração
Como este artigo é sobre MQL5, não discutirei os detalhes da implementação da API. Em vez disso, fiz um aplicativo de demonstração que você pode baixar e instalar como um pacote Python para testar as interações do seu código MQL5 com a API.
Para iniciar o aplicativo de demonstração, você só precisa do Python instalado no WSL. Ele já deve estar lá.
É altamente recomendável que você crie um ambiente virtual Python ('venv') para instalar o aplicativo. Isso garantirá que a instalação do Python no seu sistema não seja afetada. Após brincar com o aplicativo, você pode simplesmente excluir o ambiente virtual.
Você pode criar o ambiente virtual com este comando.
python3 -m venv 'venv'
Portanto, depois de ter instalado o aplicativo de demonstração, para começar a desenvolver seu código MQL5, você irá:
- iniciar o WSL
- iniciar o servidor Postgres
- iniciar o aplicativo de demonstração
- obter o IP do nome do host a partir da saída do aplicativo de demonstração
- adicionar IP do host aos endereços permitidos no terminal
Tanto o WSL quanto o servidor Postgres podem ser configurados para iniciar na inicialização do Windows.
Inserindo dados de MQL5
Vamos tentar inserir alguns dados. Primeiro, as informações da nossa conta. No seu terminal MT5, crie um novo script e adicione o seguinte código.
//+------------------------------------------------------------------+ //| post_acc_info.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <JAson.mqh> //--- include the JSON library //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- gathering the data - Account Info CJAVal data; CJAVal acc_info; //--- doubles data["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); data["credit"] = AccountInfoDouble(ACCOUNT_CREDIT); data["profit"] = AccountInfoDouble(ACCOUNT_PROFIT); data["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); data["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); data["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); data["margin_level"] = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); data["margin_so_call"] = AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL); data["margin_so_so"] = AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); //--- integers data["login"] = AccountInfoInteger(ACCOUNT_LOGIN); data["leverage"] = AccountInfoInteger(ACCOUNT_LEVERAGE); data["trade_allowed"] = AccountInfoInteger(ACCOUNT_TRADE_ALLOWED); data["ea_allowed"] = AccountInfoInteger(ACCOUNT_TRADE_EXPERT); data["trade_mode"] = AccountInfoInteger(ACCOUNT_TRADE_MODE); data["margin_so_mode"] = AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); //-- strings data["company"] = AccountInfoString(ACCOUNT_COMPANY); data["currency"] = AccountInfoString(ACCOUNT_CURRENCY); data["name"] = AccountInfoString(ACCOUNT_NAME); data["server"] = AccountInfoString(ACCOUNT_SERVER); //--- fill in the acc_info array with Account Info data acc_info["acc_info"].Add(data); //--- WebRequest arguments string method = "POST"; string url = "http://172.22.18.235/accs"; string headers = "Content-Type: application/json"; int timeout = 500; char post[], result[]; string result_headers; //--- prepare JSON data to send string json = acc_info.Serialize(); ArrayResize(post, json.Length(), 0); StringToCharArray(json, post, 0, StringLen(json), CP_UTF8); ResetLastError(); //--- send the request int res = WebRequest(method, url, headers, timeout, post, result, result_headers); if(res == -1) { Print("Error in WebRequest =", GetLastError()); MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION); } else { Print("Starting post..."); if(res == 201)// HTTP result code 201 (created) { Print("posted accs"); } } }
Como você pode ver a partir do início do arquivo, estamos usando uma biblioteca auxiliar para serializar/desserializar nossos dados JSON. Ela foi desenvolvida por um membro da comunidade MQL5 e você pode encontrar a biblioteca no seu repositório no GitHub.
Agora, vamos inserir nossos negócios a partir do histórico do MetaTrader 5. Crie um novo script e adicione o seguinte código.
//+------------------------------------------------------------------+ //| post_deals.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <JAson.mqh> //--- include the JSON library //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- gathering the data - Deals CJAVal data; CJAVal deals; //--- request trade history HistorySelect(0, TimeCurrent()); int deals_total = HistoryDealsTotal(); //--- iterate over all deals to get data //--- of each deal from its ticket number for(int i = 0; i < deals_total; i++) { //-- integers ulong deal_ticket = HistoryDealGetTicket(i); data["ticket"] = (int) deal_ticket; data["order"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_ORDER); data["position"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID); data["time"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_TIME); data["type"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_TYPE); data["entry"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_ENTRY); data["magic"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_MAGIC); data["reason"] = (int) HistoryDealGetInteger(deal_ticket, DEAL_REASON); //--- strings data["symbol"] = (string) HistoryDealGetString(deal_ticket, DEAL_SYMBOL); //--- doubles data["volume"] = (double) HistoryDealGetDouble(deal_ticket, DEAL_VOLUME); data["price"] = (double) HistoryDealGetDouble(deal_ticket, DEAL_PRICE); data["profit"] = (double) HistoryDealGetDouble(deal_ticket, DEAL_PROFIT); data["swap"] = (double) HistoryDealGetDouble(deal_ticket, DEAL_SWAP); data["comission"] = (double) HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION); //--- fill in the deals array with each deal data deals["deals"].Add(data); } //--- WebRequest arguments string method = "POST"; string url = "http://172.22.18.235/deals"; string headers = "Content-Type: application/json"; int timeout = 500; char post[], result[]; string result_headers; //--- prepare JSON data to send string json = deals.Serialize(); ArrayResize(post, json.Length(), 0); StringToCharArray(json, post, 0, StringLen(json), CP_UTF8); ResetLastError(); //--- send the request int res = WebRequest(method, url, headers, timeout, post, result, result_headers); if(res == -1) { Print("Error in WebRequest =", GetLastError()); MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION); } else { Print("Starting post..."); if(res == 201)// HTTP result code 201 (created) { Print("posted deals"); } } }
Consultando dados a partir do MQL5
Agora vamos consultar os dados que acabamos de inserir. No seu terminal MetaTrader 5, crie um novo script e adicione o seguinte código.
//+------------------------------------------------------------------+ //| get_endpoint.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <JAson.mqh> //--- include the JSON library //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- choose the testing endpoint string endpoint = "accs"; // or "deals" //--- WebRequest arguments string method = "GET"; string url = "http://172.22.18.235/" + endpoint; string cookie = NULL, headers; int timeout = 500; char post[], result[]; ResetLastError(); //--- send the request int res = WebRequest(method, url, cookie, NULL, timeout, post, 0, result, headers); if(res == -1) { Print("Error in WebRequest =", GetLastError()); MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION); } else { Print("Starting get..."); if(res == 200)// HTTP result code 200 (OK) { PrintFormat("Server headers: %s", headers); ResetLastError(); // save the returned JSON in a file string terminal_data_path = TerminalInfoString(TERMINAL_DATA_PATH); string subfolder = "TutoPostgres"; string filename = endpoint + "_fromserver.json"; int filehandle = FileOpen(subfolder + "\\" + filename, FILE_WRITE | FILE_BIN); if(filehandle != INVALID_HANDLE) { FileWriteArray(filehandle, result, 0, ArraySize(result)); FileClose(filehandle); Print(filename + " created at " + terminal_data_path + "\\" + subfolder); } else Print("File open failed with error ", GetLastError()); } else PrintFormat("Request to '%s' failed with error code %d", url, res); } }
Ao mudar o endpoint de "accs" para "deals", você pode consultar suas negociações recém-inseridas. Verifique o seu <caminho do terminal MT5>\Files\TutoPostgres. Se tudo correu bem, deve haver pelo menos dois arquivos lá: accs_fromserver.json e deals_fromserver.json.
Consumindo dados JSON em Expert Advisors
Para consumir os dados JSON retornados pelo servidor, você precisa desserializá-los. A biblioteca auxiliar mencionada acima pode fazer isso.
Se você olhou para os arquivos JSON salvos após consultar o banco de dados com o código de exemplo acima, você pode ter visto uma string JSON como esta:
[ { "a_balance": "10005.93", "a_company": "MetaQuotes Software Corp.", "a_credit": "0.0", "a_currency": "USD", "a_ea_allowed": true, "a_equity": "10005.93", "a_id": 3, "a_leverage": 100, "a_login": 66744794, "a_margin": "0.0", "a_margin_free": "10005.93", "a_margin_level": "0.0", "a_margin_so_call": "50.0", "a_margin_so_mode": "0", "a_margin_so_so": "30.0", "a_name": "MetaTrader 5 Desktop Demo", "a_profit": "0.0", "a_server": "MetaQuotes-Demo", "a_trade_allowed": true, "a_trade_mode": "0" }, { (...)
Estaremos usando estas chaves para acessar os dados desserializados. O '0' retornará todas as contas e você pode acessar cada uma delas iterando sobre a matriz por este índice.
//+------------------------------------------------------------------+ //| consume_json.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include <JAson.mqh> //--- include the JSON library //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- choose the testing endpoint string endpoint = "accs"; // or "deals" //--- WebRequest arguments string method = "GET"; string url = "http://172.22.18.235/" + endpoint; string cookie = NULL, headers; int timeout = 500; char post[], result[]; ResetLastError(); //--- send the request int res = WebRequest(method, url, cookie, NULL, timeout, post, 0, result, headers); if(res == -1) { Print("Error in WebRequest =", GetLastError()); MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION); } else { Print("Starting get..."); if(res == 200)// HTTP result code 200 (OK) { CJAVal data; data.Deserialize(result); //--- doubles double a_balance = data[0]["a_balance"].ToDbl(); double a_credit = data[0]["a_credit"].ToDbl(); double a_profit = data[0]["a_profit"].ToDbl(); double a_equity = data[0]["a_equity"].ToDbl(); double a_margin = data[0]["a_margin"].ToDbl(); double a_margin_free = data[0]["a_margin_free"].ToDbl(); double a_margin_level = data[0]["a_margin_level"].ToDbl(); double a_margin_so_call = data[0]["a_margin_so_call"].ToDbl(); double a_margin_so_so = data[0]["a_margin_so_so"].ToDbl(); //--- longs long a_login = data[0]["a_login"].ToInt(); long a_leverage = data[0]["a_leverage"].ToInt(); long a_trade_mode = data[0]["a_trade_mode"].ToInt(); long a_margin_so_mode = data[0]["a_margin_so_mode"].ToInt(); long a_id = data[0]["a_id"].ToInt(); //--- database generated ID //--- strings string a_company = data[0]["a_company"].ToStr(); string a_currency = data[0]["a_currency"].ToStr(); string a_name = data[0]["a_name"].ToStr(); string a_server = data[0]["a_server"].ToStr(); //--- booleans bool a_ea_allowed = data[0]["a_ea_allowed"].ToBool(); bool a_trade_allowed = data[0]["a_trade_allowed"].ToBool(); //printf("Server headers: %s", headers); //--- doubles printf("Balance: %d", a_balance); printf("Credit: %d", a_credit); printf("Profit: %d", a_profit); printf("Equity: %d", a_equity); printf("Margin: %d", a_margin); printf("Margin Free: %d", a_margin_free); printf("Margin Level: %d", a_margin_level); printf("Margin Call Level: %d", a_margin_so_call); printf("Margin Stop Out Level: %d", a_margin_so_so); //--- longs printf("Login: %d", a_login); printf("Leverage: %d", a_leverage); printf("Trade Mode: %d", a_trade_mode); printf("Margin Stop Out Mode: %d", a_margin_so_mode); printf("Database ID: %d", a_id); //--- strings printf("Company: %s", a_company); printf("Currency: %s", a_currency); printf("Platform Name: %s", a_name); printf("Server: %s", a_server); //--- booleans printf("Expert Advisor Allowed: %d", a_ea_allowed); printf("Trade Allowed: %d", a_trade_allowed); Print("Done!"); } else PrintFormat("Request to '%s' failed with error code %d", url, res); } }
SQLite como um espelho do Postgres
Também é possível aproveitar a infraestrutura existente do MQL5 usando os dados remotos como um banco de dados SQLite local. Para implementar essa funcionalidade, precisamos sincronizar os bancos de dados. Esta sincronização seria quase em tempo real, com apenas alguns segundos de atraso. Mas melhoraria o desempenho, evitaria a latência da rede, e permitiria o acesso aos dados via GUI padrão do MetaEditor e o uso das Funções de Banco de Dados MQL5 no seu código MQL5.
Se você achar essa funcionalidade útil, por favor me avise. Ficarei feliz em escrever um tutorial detalhado com código de exemplo para essa sincronização entre os bancos de dados Postgres remoto e SQLite local.
Considerações finais
Nestas notas revisamos alguns métodos atualmente disponíveis para conectar uma instância de código MQL5 a um banco de dados Postgres. Escolhemos uma API REST como uma alternativa viável e rápida ao desenvolvimento de driver dedicado mais caro ou ao uso de .dll's. Além disso, desenvolvemos um aplicativo de demonstração básico como exemplo de como configurar um ambiente de desenvolvimento para MQL5/Postgres no Subsistema Windows Para Linux.
Agora você pode começar a desenvolver! Escolha um bom provedor de nuvem e aproveite todo o poder das análises do Postgres, automação, escalabilidade web e extensões de aprendizado de máquina para potencializar suas negociações.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/12308
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso