Operações CRUD no Firebase usando MQL
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.

-
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á:

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)); } }

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/NoQ8m2vYLnGkykNhUjFEPortanto, 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".

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
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.