English Русский 中文 Español Deutsch 日本語
preview
Operações CRUD no Firebase usando MQL

Operações CRUD no Firebase usando MQL

MetaTrader 5 — Integração |
21 1
Chioma Obunadike
Chioma Obunadike

Introdução

Se você já tentou desenvolver uma aplicação móvel ou web, sabe que lidar com tarefas de backend pode ser uma das etapas mais complexas e demoradas do desenvolvimento. É nesse ponto que o Firebase, uma popular plataforma de backend como serviço (BaaS, backend-as-a-service) do Google, se destaca. Ele elimina boa parte das tarefas rotineiras do backend, permitindo que os desenvolvedores se concentrem mais na implementação das funcionalidades e menos na administração da infraestrutura.

O Firebase oferece uma ampla variedade de ferramentas para o desenvolvimento de aplicações, incluindo autenticação, funções em nuvem, Analytics, hospedagem, relatórios de falhas e muito mais. No entanto, entre seus recursos mais poderosos e utilizados estão as ferramentas de banco de dados. O Firebase disponibiliza dois bancos de dados NoSQL principais: Firebase Realtime Database e Cloud Firestore. Embora atendam a necessidades semelhantes, cada um tem seus pontos fortes, e a escolha entre eles depende, em grande parte, dos requisitos específicos de cada projeto.



Firebase Realtime Database

O Firebase Realtime Database existe desde os primeiros anos do Firebase e é especialmente indicado para aplicações em que a baixa latência e a sincronização imediata de dados entre clientes são essenciais. Isso o torna uma boa opção para chats, jogos multijogador, painéis de monitoramento em tempo real e outras aplicações em que os usuários precisam acompanhar as atualizações instantaneamente, sem recarregar a tela.

O Realtime Database utiliza uma estrutura simples de árvore JSON plana para armazenar os dados. Essa simplicidade facilita os primeiros passos e permite atualizações muito rápidas, mesmo com conexões lentas. No entanto, à medida que os dados se tornam mais complexos, essa estrutura plana pode dificultar seu gerenciamento. Dados aninhados, relacionamentos com vários níveis de profundidade e consultas com filtros exigem um planejamento mais cuidadoso em comparação com os bancos de dados tradicionais.



Cloud Firestore

O Cloud Firestore, frequentemente chamado apenas de Firestore, é a mais recente das duas soluções de banco de dados do Firebase. Ele foi desenvolvido com foco em escalabilidade, armazenamento estruturado de dados e consultas avançadas. O Firestore utiliza um modelo de dados baseado em documentos, com uma estrutura mais hierárquica. Ele organiza os dados em coleções e documentos, oferecendo aos desenvolvedores uma maneira mais estruturada e escalável de gerenciar relacionamentos complexos entre os dados.

O Firestore também oferece recursos avançados, como:

  • Consultas avançadas: filtros por vários campos, ordenação de resultados e paginação dos resultados das consultas.
  • Suporte ao acesso offline aos dados: sincronização automática dos dados quando o dispositivo se reconecta.
  • Marcas de tempo geradas pelo servidor e operações atômicas.
  • Regras de segurança mais detalhadas.
  • Integração mais estreita com outros serviços do Google Cloud.

De modo geral, se sua aplicação for relativamente pequena e priorizar velocidade e simplicidade, o Realtime Database pode ser a opção mais adequada. Por outro lado, se você estiver desenvolvendo um projeto mais ambicioso, que exija modelagem complexa de dados e escalabilidade, o Firestore provavelmente será a melhor escolha.



Configuração do projeto Firebase e do banco de dados (passo a passo)

Agora que você já conhece melhor os bancos de dados do Firebase e suas diferenças, vamos configurar tudo do zero. Veremos como criar um projeto Firebase, escolher um banco de dados e definir configurações básicas, como regras de segurança e estrutura de dados.

Passo 1: crie um projeto Firebase
Para começar a usar o Firebase, você precisará de uma conta Google. Acesse o Firebase Console e clique em "Add Project". Em seguida, será solicitado que você informe o nome do projeto (pode ser qualquer um) e, opcionalmente, ative o Google Analytics. Você pode deixar essa configuração para depois ou ativá-la agora, caso queira acompanhar o comportamento dos usuários.

Depois de clicar em "Create Project", o Firebase preparará os recursos necessários em segundo plano. Em poucos segundos, o projeto estará pronto.

Passo 2: adicione sua aplicação ao Firebase
Antes de utilizar os recursos do Firebase, é necessário registrar sua aplicação, seja ela web, Android ou iOS. Clique no ícone correspondente à plataforma (por exemplo, o símbolo de aplicação web </>) e siga as etapas de registro. No caso de uma aplicação web, o Firebase fornecerá um trecho de código de configuração com os parâmetros do projeto, que deverá ser inserido no código da aplicação.

O trecho de configuração (snippet) pode ter a seguinte aparência:

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "your-app.firebaseapp.com",
  projectId: "your-app",
  storageBucket: "your-app.appspot.com",
  messagingSenderId: "SENDER_ID",
  appId: "APP_ID"
};

Utilize essa configuração para inicializar o Firebase em sua aplicação.

Passo 3: ative o banco de dados desejado
Depois de configurar o projeto e registrar a aplicação, é hora de escolher o banco de dados. No Firebase Console, localize a seção "Build" no menu à esquerda e selecione Realtime Database ou Cloud Firestore, conforme a solução que pretende utilizar.

Clique em "Create Database" e escolha a região onde os dados serão armazenados. Para a maioria das aplicações, a região padrão é suficiente, mas selecionar uma região mais próxima dos usuários pode melhorar o desempenho.

Passo 4: configure as regras de segurança
Os bancos de dados do Firebase são bastante flexíveis, mas essa flexibilidade exige cuidados com a segurança. Por padrão, o Firebase restringe o acesso ao banco de dados por motivos de segurança. Durante a configuração, você deverá selecionar um dos modos de configuração das regras de segurança. Para desenvolvimento ou testes, é possível utilizar temporariamente o "test mode", que permite acesso público de leitura e gravação ao banco de dados. O mais importante é nunca utilizar esse modo em produção!

É assim que o modo de teste se apresenta:

{
  "rules": {
    ".read": "true",
    ".write": "true"
  }
}

Em produção, é necessário definir regras mais específicas para determinar quem pode ler ou gravar cada parte dos dados. As regras de segurança do Firebase podem se basear na autenticação do usuário, nos campos dos documentos, nos parâmetros das consultas e em outras condições.

Fig. 1. Criação do banco de dados

  • URL do banco de dados e chave de API: para autenticar as requisições, você precisará da chave de API do projeto Firebase e da URL do banco de dados. Essas informações estão disponíveis nas configurações do projeto, nos campos "Web API Key" e "Realtime Database URL" (ou no endpoint REST do Firestore).

  • Entendendo os endpoints REST: os bancos de dados do Firebase podem ser acessados por meio de uma API REST. Por exemplo:

    • Realtime Database: https://PROJECT_ID.firebaseio.com/path/to/data.json

    • Firestore: https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases/(default)/documents/path/to/document

Para demonstrar como funcionam as operações de leitura e gravação, começaremos criando uma coleção, um contêiner lógico que agrupa documentos, e adicionaremos manualmente alguns registros de usuários para teste. Essa configuração servirá de base para as próximas operações práticas de leitura de dados e ajudará a compreender melhor o funcionamento do Firestore.



Crie sua primeira coleção

Clique no botão Start Collection. Será aberta uma janela modal na qual você deverá informar o nome da coleção. Vamos chamá-la de users, pois simularemos um pequeno banco de dados de usuários.

Depois de definir o nome da coleção, você deverá criar o primeiro documento. Se você não definir o ID manualmente, o Firestore gerará automaticamente um ID aleatório para o documento. No entanto, para facilitar a compreensão, vamos atribuir um ID por conta própria, usando um valor simples, como users.

Adicione campos ao documento
Depois de atribuir um ID ao documento, precisamos adicionar seus campos. Eles podem ser comparados às colunas de um banco de dados tradicional, mas oferecem muito mais flexibilidade.

Podemos começar, por exemplo, com o seguinte campo:

  • name → "Jane Doe"

Como nosso objetivo é adicionar dados automaticamente por meio de código MQL5, essa etapa de configuração manual não é tão importante. Agora vamos estabelecer a conexão com o banco de dados.

Conexão com o banco de dados
O endpoint REST do nosso banco de dados "my-users-mql5" será o seguinte:

 https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users/

Se você inserir esse URL no navegador agora, provavelmente verá:

Fig. 2. Banco de dados vazio

Com a coleção users configurada, podemos começar a aprender como ler dados do Firestore usando código. Nas próximas etapas, veremos como adicionar dados, recuperar documentos, acompanhar atualizações em tempo real e utilizar consultas para filtrar e ordenar os dados.


Criação de dados

O método HTTP POST é utilizado para enviar dados a um recurso específico, ou seja, para encaminhar informações ao servidor. Em uma requisição POST, os dados geralmente são enviados no corpo da requisição. O servidor então os processa e cria um novo recurso, como uma conta de usuário, uma publicação de blog ou um registro no banco de dados.

Isso difere de uma requisição GET, que serve apenas para recuperar dados e não deve provocar alterações no servidor. Já o POST permite enviar dados e realizar alterações, criando um novo recurso.

Em todos os casos, o cliente envia dados estruturados (geralmente em formato JSON) ao servidor ou diretamente a uma função serverless, que então armazena esses dados, normalmente em um banco de dados como o Firestore.

void add_data()
  {
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users";
   string jsonData = "{\"fields\":{\"Name\":{\"stringValue\":\"Jane Doe\"}}}";
   uchar postData[], result[];
   StringToCharArray(jsonData, postData, 0, StringLen(jsonData), CP_UTF8);
   string header;
   int res = WebRequest("POST", url, "Content-Type: application/json\r\n", 5000, postData, result, header);
   if(res == 200)
     {
      Print("Success: ", CharArrayToString(result));
     }
   else
     {
      Print("Error ", res, ": ", CharArrayToString(result));
     }
  }

Fig. 3. Criação de novos registros

Com o código apresentado acima, adicionamos um novo registro "Jane Doe" com um ID exclusivo gerado pelo Firebase, evitando colisões de identificadores mesmo quando vários registros são adicionados simultaneamente. É possível adicionar quantos registros forem necessários, incluindo campos aninhados, como email, age ou marca de tempo, definidos como pares de chave e valor na estrutura de dados correspondente. O próximo passo é recuperar esses dados.



Leitura de dados

Agora que o banco de dados foi criado e já contém registros, podemos começar a utilizá-lo de forma mais completa. Já criamos uma coleção com documentos de teste e aprendemos a enviar dados ao Firestore usando o método POST. Esse é um bom começo, mas a leitura é tão importante quanto a gravação. Em muitas aplicações, a recuperação e a exibição de dados são fundamentais para a experiência do usuário.

Seja para carregar uma lista de usuários, exibir um feed de notícias ou apresentar um catálogo de produtos, você precisará de uma maneira de consultar as informações armazenadas no banco de dados. É nesse momento que entra o método GET.

GET é um dos principais métodos HTTP. Diferentemente do POST, utilizado para enviar dados e criar novos recursos, o GET serve para recuperar informações do servidor. Em essência, é uma operação somente de leitura: ao enviar uma requisição GET, você solicita que o servidor retorne os dados, sem modificar nada no servidor.

Uma analogia simples: uma requisição POST é como enviar um formulário para criar uma nova conta, enquanto uma requisição GET equivale a entrar no sistema e visualizar as informações do perfil. Nesse segundo caso, você não altera nada, apenas consulta os dados ex istentes.

void authorize()
  {

// 1. Construct Firestore URL
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users/";
// 2. Prepare headers
   string headers;
   headers += "Content-Type: application/json\r\n";
// 3. Send request
   char data[], result[];
   int timeout = 5000;
   int status = WebRequest("GET", url, headers, timeout, data, result, headers);
// 4. Handle response
   if(status == 200)
     {
      // Print("Firestore Data Received:");
      int filehandle = FileOpen("firebase-temp.txt", FILE_WRITE | FILE_BIN);
      if(filehandle != INVALID_HANDLE)
        {
         //--- Saving the contents of the result[] array to a file
         FileWriteArray(filehandle, result, 0, ArraySize(result));
         //--- Closing the file
         FileFlush(filehandle);
         FileClose(filehandle);
        }
      else
         Print("Error in FileOpen. Error code =", GetLastError());
     }
   else
     {
      Print("Error Code: ", status);
      Print("Response: ", CharArrayToString(result));
     }
  }

Com apenas algumas linhas de código, obtivemos um arquivo chamado "firebase-temp.txt", contendo todas as informações do banco de dados.

Permissões de acesso: certifique-se de que as regras de segurança do Firestore permitam a leitura dos dados quando necessário. Para testes públicos, é possível utilizar regras abertas (allow read: if true;), mas em produção é fundamental restringir essas permissões!



Atualização de dados

Como você provavelmente já percebeu, sempre que um novo documento é adicionado ao banco de dados Firestore, seja manualmente pelo console ou programaticamente com o Firebase SDK, ele recebe um ID exclusivo. Esse identificador pode ser uma sequência aparentemente aleatória de letras e números, como kJ73sd98ASQv, e à primeira vista pode não parecer tão importante.

O Firestore é estruturado em coleções e documentos. Cada coleção contém vários documentos, e cada documento armazena informações na forma de pares de chave e valor. Ao adicionar um documento a uma coleção, você pode deixar que o Firestore gere seu ID automaticamente ou defini-lo manualmente.

Por exemplo, ao adicionar um usuário à coleção users, você pode obter um caminho como este:

users/kJ73sd98ASQv

Isso significa que o documento desse usuário está armazenado na coleção users e é identificado de forma exclusiva pelo ID kJ73sd98ASQv. Se posteriormente você precisar recuperar, atualizar ou excluir esse documento específico, será necessário informar seu caminho completo, incluindo o ID do documento.

Mas é importante entender que o ID do documento é fundamental. Na prática, ele funciona como um identificador exclusivo que permite ao Firestore (e, consequentemente, à sua aplicação) localizar, atualizar ou excluir um documento específico de forma eficiente. Pense nele como uma impressão digital: dois documentos não compartilham o mesmo ID, e é esse identificador que permite acessar e manipular cada documento de maneira direta e precisa.

Por isso, ao atualizar ou excluir dados no Firestore, é indispensável conhecer e utilizar o ID do documento.

No exemplo de "Jane Doe", o endpoint REST do documento adicionado é o seguinte:

https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users/NoQ8m2vYLnGkykNhUjFE
Portanto, o ID do nosso documento é:
NoQ8m2vYLnGkykNhUjFE

Para atualizar esses dados, podemos utilizar o método PATCH:

void update_entry(string doc_id)
  {
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users/" + doc_id; //end point url
   string jsonData = "{\"fields\":{\"exampleField\":{\"stringValue\":\"Princess Doe\"}}}"; //specifiy data to be added
   uchar postData[], result[];
   StringToCharArray(jsonData, postData, 0, StringLen(jsonData), CP_UTF8); //convert plain string to char array to be sent to the db
   string header;
   int res = WebRequest("PATCH", url, "Content-Type: application/json\r\n", 5000, postData, result, header);
   if(res == 200)
     {
      Print("Success: ", CharArrayToString(result)); //if successful, print
     }
   else
     {
      Print("Error ", res, ": ", CharArrayToString(result)); //return error
     }
  }

Com esse código, atualizaremos o nome de "Jane Doe" para "Princess Doe".

Fig. 4. Atualização de registros



Exclusão de registros

A última operação desta série é a exclusão de registros. Para excluir um registro como "Jane Doe" do Cloud Firestore, podemos utilizar o método DELETE, informando o caminho completo do documento, incluindo seu ID exclusivo. Por exemplo, uma requisição DELETE direcionada a um documento com ID gerado automaticamente excluirá permanentemente esse registro do banco de dados. Também podemos implementar no código da aplicação o tratamento dos casos de sucesso e de erro para fornecer ao usuário informações adequadas sobre o resultado da operação. Além disso, as regras de segurança do Firebase devem restringir as permissões de exclusão para impedir que usuários não autorizados removam dados acidentalmente ou de forma mal-intencionada.

void delete_entry(string documentId)
  {
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5" +
                "/databases/(default)/documents/users/" + documentId; //end point url with specified document ID
   uchar result[];
   uchar postData[]; // Empty payload for DELETE
   string headers = "Content-Type: application/json\r\n";
   string responseHeaders; // To store response headers (unused here)
// Correct WebRequest overload:
   int res = WebRequest(
                "DELETE",       // HTTP method
                url,            // Full URL with document ID
                headers,        // Request headers
                5000,           // Timeout (5 seconds)
                postData,       // Empty payload (uchar array, not NULL)
                result,         // Response data
                responseHeaders // Response headers (ignored)
             );
   if(res == 200)
     {
      Print("Document deleted"); //sucess
     }
   else
     {
      Print("Error ", res, ": ", CharArrayToString(result));
     }
  }

Ao informar o ID do documento, o registro será excluído.



Uso do Firebase em trading algorítmico

Agora que aprendemos a utilizar as operações CRUD básicas em MQL, podemos explorar uma aplicação prática desses conhecimentos no trading algorítmico. Neste exemplo, enviaremos informações de negociação do terminal para o Firebase e, em seguida, exibiremos um sinal em um painel de monitoramento.

Envio de informações de negociação para o Firebase
Podemos utilizar um código básico em MQL5 para obter informações sobre posições encerradas e enviar esses dados ao banco de dados para processamento.

datetime last_closed_time;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   last_closed_time = TimeCurrent();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void add_data(ulong ticket, string symbol, double lot, double profit)
  {
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users";
// Build JSON dynamically using function parameters
   string trade_id = "Trade_" + IntegerToString((int)ticket);
   string jsonData =
      "{"
      "\"fields\":{"
      "\"" + trade_id + "\":{"
      "\"mapValue\":{"
      "\"fields\":{"
      "\"symbol\":{\"stringValue\":\"" + symbol + "\"},"
      "\"lot\":{\"doubleValue\":" + DoubleToString(lot, 2) + "},"
      "\"profit\":{\"doubleValue\":" + DoubleToString(profit, 2) + "}"
      "}"
      "}"
      "}"
      "}"
      "}";
   uchar postData[], result[];
   StringToCharArray(jsonData, postData, 0, StringLen(jsonData), CP_UTF8);
   string header;
   int res = WebRequest("POST", url, "Content-Type: application/json\r\n", 5000, postData, result, header);
   if(res == 200)
     {
      Print("Success: ", CharArrayToString(result));
     }
   else
     {
      Print("Error ", res, ": ", CharArrayToString(result));
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTrade()
  {
   HistorySelect(0, TimeCurrent());
   for(int i = 0; i < HistoryDealsTotal(); i++)
     {
      if(deal.SelectByIndex(i))
        {
         if(deal.Time() >= last_closed_time && last_closed_time != 0)
           {
            if(deal.Entry() == DEAL_ENTRY_OUT)
              {
               add_data(deal.Ticket(), deal.Symbol(), deal.Volume(), deal.Profit());
              }
           }
        }
     }
   last_closed_time = TimeCurrent();
  }

Sincronização dos dados da carteira do MQL5 para o Firestore
Cada registro enviado pode ser armazenado, baixado e até mesmo lido linha por linha antes de ser exibido no painel de monitoramento. Essa abordagem oferece uma maneira clara e estruturada de analisar o histórico de negociações, sem precisar percorrer intermináveis registros de log ou recorrer a capturas de tela. Com essa estrutura, os traders podem visualizar melhor seu desempenho e identificar padrões que, de outra forma, poderiam passar despercebidos.

int OnInit()
  {
//---
   draw_dashboard();
   get_data();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void draw_dashboard()
  {
   ObjectCreate(0, "dash-board", OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, "dash-board", OBJPROP_XDISTANCE, 20);
   ObjectSetInteger(0, "dash-board", OBJPROP_YDISTANCE, 20);
   ObjectSetInteger(0, "dash-board", OBJPROP_XSIZE, 250);
   ObjectSetInteger(0, "dash-board", OBJPROP_YSIZE, 150);
   ObjectSetInteger(0, "dash-board", OBJPROP_BGCOLOR, clrDarkSlateGray);
   ObjectCreate(0, "dash-tv", OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, "dash-tv", OBJPROP_XDISTANCE, 50);
   ObjectSetInteger(0, "dash-tv", OBJPROP_YDISTANCE, 40);
   ObjectSetString(0, "dash-tv", OBJPROP_TEXT, "Total Volume: " +  DoubleToString(trading_volume_from_file(), 2));
   ObjectSetInteger(0, "dash-tv", OBJPROP_COLOR, clrWhite);
   ObjectCreate(0, "dash-profit", OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, "dash-profit", OBJPROP_XDISTANCE, 50);
   ObjectSetInteger(0, "dash-profit", OBJPROP_YDISTANCE, 80);
   ObjectSetString(0, "dash-profit", OBJPROP_TEXT, "Total Profit: " + DoubleToString(pnl_from_file(), 2));
   ObjectSetInteger(0, "dash-profit", OBJPROP_COLOR, clrWhite);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Get total trading volume                                         |
//+------------------------------------------------------------------+
double trading_volume_from_file(string filename = "firebase-temp-trade.txt")
  {
   double tv = 0;
   int filehandle = FileOpen(filename, FILE_READ | FILE_TXT | FILE_ANSI);
   if(filehandle == INVALID_HANDLE)
     {
      Print("Error opening file: ", GetLastError());
      return 0;
     }
   string line;
   while(!FileIsEnding(filehandle))
     {
      line = FileReadString(filehandle);
      // Look for lot values
      if(StringFind(line, "lot") != -1)
        {
         string raw0 = FileReadString(filehandle);
         int stat_int = StringFind(raw0, "d", 0);
         string raw = StringSubstr(raw0, stat_int + 14, -1);
         double profit = StringToDouble(raw);
         //---
         tv += NormalizeDouble(profit, 2);
        }
     }
   FileClose(filehandle);
   return tv;
  }

//+------------------------------------------------------------------+
//| Get total PnL                                                    |
//+------------------------------------------------------------------+
double pnl_from_file(string filename = "firebase-temp-trade.txt")
  {
   double p_l = 0;
   int filehandle = FileOpen(filename, FILE_READ | FILE_TXT | FILE_ANSI);
   if(filehandle == INVALID_HANDLE)
     {
      Print("Error opening file: ", GetLastError());
      return 0;
     }
   int line_no = 0;
   while(!FileIsEnding(filehandle))
     {
      string line = FileReadString(filehandle);
      line_no++;
      // Look for profit values
      if(StringFind(line, "profit") != -1)
        {
         string raw0 = FileReadString(filehandle);
         int stat_int = StringFind(raw0, "d", 0);
         string raw = StringSubstr(raw0, stat_int + 14, -1);
         double profit = StringToDouble(raw);
         //---
         p_l += profit;
        }
     }
   FileClose(filehandle);
   return p_l;
  }

//+------------------------------------------------------------------+
void get_data()
  {
// 1. Construct Firestore URL
   string url = "https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users";
// 2. Prepare headers
   string headers;
   headers += "Content-Type: application/json\r\n";
// 3. Send request
   char data[], result[];
   int timeout = 5000;
   int status = WebRequest("GET", url, headers, timeout, data, result, headers);
// 4. Handle response
   if(status == 200)
     {
      // Print("Firestore Data Received:");
      int filehandle = FileOpen("firebase-temp-trade.txt", FILE_WRITE | FILE_BIN);
      if(filehandle != INVALID_HANDLE)
        {
         //--- Saving the contents of the result[] array to a file
         FileWriteArray(filehandle, result, 0, ArraySize(result));
         //--- Closing the file
         FileFlush(filehandle);
         FileClose(filehandle);
        }
      else
         Print("Error in FileOpen. Error code =", GetLastError());
     }
   else
     {
      Print("Error Code: ", status);
      Print("Response: ", CharArrayToString(result));
     }
  }
//+------------------------------------------------------------------+

O resultado é o seguinte:



Conclusão

Os bancos de dados são fundamentais para as aplicações modernas, e saber trabalhar com eles é uma habilidade essencial para os desenvolvedores. Ao aprender a utilizar o Firebase, seja pela sincronização instantânea de dados do Realtime Database ou pelos recursos avançados de consulta do Firestore, você aprende a utilizar um conjunto importante de ferramentas para desenvolver aplicações dinâmicas que trabalham com dados.

Nome do arquivo Descrição
firebase-users.mq5 Arquivo com o código para executar operações CRUD no Firestore.
Download_Infor.mq5 Arquivo com o código para baixar informações do Firestore e exibi-las no gráfico.
Sending_Trading_Info.mq5 Arquivo com o código para enviar informações de negociação ao Firestore.


Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/17854

Arquivos anexados |
Download_Info.mq5 (5.93 KB)
Últimos Comentários | Ir para discussão (1)
joaopedrodev
joaopedrodev | 26 ago. 2025 em 16:43
Vi que você está fazendo a integração com o Firebase usando funções nativas de solicitação HTTP no MQL5.

Sugiro que você dê uma olhada no Connexus, uma biblioteca que desenvolvi para solicitações HTTP. Ela foi projetada especificamente para simplificar esse tipo de integração, tornando o código mais limpo, mais reutilizável e mais fácil de manter.
Desenvolvimento de ferramentas para análise de Price Action (Parte 37): Indicador de viés do sentimento de mercado Desenvolvimento de ferramentas para análise de Price Action (Parte 37): Indicador de viés do sentimento de mercado
O sentimento de mercado é uma das forças mais subestimadas e, ao mesmo tempo, mais influentes sobre o movimento dos preços. Enquanto a maioria dos traders depende de indicadores defasados ou de suposições, o EA Sentiment Tilt Meter (STM) transforma os dados de mercado em uma referência visual clara, mostrando em tempo real se o mercado apresenta um viés de alta, de baixa ou permanece neutro. Isso facilita a confirmação das operações, ajuda a evitar entradas em falso e permite escolher com mais precisão o momento de entrar no mercado.
EAs com auto-otimização em MQL5 (Parte 12): Construção de classificadores lineares por meio da fatoração de matrizes EAs com auto-otimização em MQL5 (Parte 12): Construção de classificadores lineares por meio da fatoração de matrizes
Neste artigo, exploraremos o papel fundamental da fatoração de matrizes no trading algorítmico, especialmente em aplicações MQL5. Dos modelos de regressão aos classificadores multiclasse, apresentaremos exemplos práticos que mostram como é simples integrar esses métodos usando as funções nativas do MQL5. Seja para prever a direção dos preços ou modelar o comportamento de indicadores, este guia fornecerá uma base sólida para desenvolver sistemas de negociação inteligentes com métodos matriciais.
Repensando as estratégias clássicas (Parte 15): Estratégia de rompimento da faixa de preços do dia anterior Repensando as estratégias clássicas (Parte 15): Estratégia de rompimento da faixa de preços do dia anterior
Muito antes do surgimento dos computadores, os traders já atuavam nos mercados financeiros e desenvolviam regras práticas para orientar suas decisões. Neste artigo, voltaremos a examinar uma conhecida estratégia de rompimento para avaliar se essa lógica de mercado, adquirida por meio da experiência, pode competir com abordagens sistemáticas. Nossos resultados mostram que, embora a estratégia original apresentasse uma elevada taxa de acerto, seus resultados eram instáveis e sua gestão de risco era deficiente. Ao aperfeiçoar essa abordagem, demonstraremos como o conhecimento acumulado pelos traders discricionários pode ser incorporado a estratégias de trading algorítmico mais robustas.
Oscilador Parafrac: combinação dos indicadores Parabolic SAR e Fractals Oscilador Parafrac: combinação dos indicadores Parabolic SAR e Fractals
Neste artigo, veremos como combinar o Parabolic SAR e o indicador Fractals para criar um novo indicador do tipo oscilador. Ao aproveitar os pontos fortes de ambas as ferramentas, os traders podem desenvolver uma estratégia de negociação mais precisa e eficiente.