English Deutsch 日本語
preview
CRUD-операции в Firebase с использованием MQL

CRUD-операции в Firebase с использованием MQL

MetaTrader 5Интеграция |
63 1
Chioma Obunadike
Chioma Obunadike

Введение

Если вы когда-либо пробовали создавать мобильное или веб-приложение, вы знаете, что управление серверными задачами может быть одной из самых сложных и затратных по времени частей разработки. Именно здесь Firebase, популярная платформа Google типа BaaS (backend-as-a-service), проявляет себя особенно хорошо. Она избавляет от значительной части рутинной серверной работы, позволяя разработчикам больше сосредоточиться на реализации функций и меньше — на администрировании инфраструктуры.

Firebase предлагает широкий инструментарий для разработки приложений — аутентификацию, облачные функции, аналитику, хостинг, отчеты о сбоях и многое другое. Однако к числу самых мощных и часто используемых возможностей относятся инструменты работы с базами данных. Firebase предоставляет две основные NoSQL-базы данных: Firebase Realtime Database и Cloud Firestore. Хотя они решают похожие задачи, у каждой есть свои сильные стороны, а выбор между ними в значительной степени зависит от требований конкретного проекта.



Firebase Realtime Database

Firebase Realtime Database существует с ранних дней Firebase и особенно хорошо подходит для приложений, где критичны низкая задержка и мгновенная синхронизация данных между клиентами. Это делает ее хорошим выбором для чатов, многопользовательских игр, панелей мониторинга в реальном времени и любых других приложений, где пользователи должны видеть обновления в реальном времени без перезагрузки экрана.

Realtime Database использует простое плоское JSON-дерево для хранения данных. Благодаря простоте с ней легко начать работу, а обновления могут выполняться очень быстро даже при медленном соединении. Однако из-за плоской структуры по мере усложнения данных работать с ней становится сложнее. Вложенные данные, глубокие связи и фильтрованные запросы требуют более тщательного планирования по сравнению с традиционной базой данных.



Cloud Firestore

Cloud Firestore, часто называемый просто Firestore, — более новый из двух инструментов Firebase для работы с базами данных. Он создавался с учетом масштабирования, структурированного хранения данных и расширенных запросов. Firestore поддерживает более иерархическую документную модель данных. Он организует данные в коллекции и документы, предоставляя разработчикам более структурированный и масштабируемый способ управления сложными связями данных.

Firestore также включает мощные возможности, такие как:

  • Расширенные запросы — фильтрация по нескольким полям, сортировка результатов, пагинация запросов
  • Офлайн-поддержка данных — автоматическая синхронизация данных после повторного подключения устройства
  • Серверные временные метки и атомарные операции
  • Более детализированные правила безопасности
  • Более тесная интеграция с другими сервисами Google Cloud

В целом, если ваше приложение относительно небольшое и в нем важны скорость и простота, Realtime Database может оказаться более подходящим вариантом. Если вы создаете более амбициозный проект, которому нужны сложное моделирование данных и поддержка работы на больших масштабах, вероятнее всего, стоит выбрать Firestore.



Настройка проекта Firebase и базы данных (пошагово)

Теперь, когда у вас есть более четкое представление о базах данных Firebase и различиях между ними, разберем настройку с нуля. Мы рассмотрим, как создать проект Firebase, выбрать базу данных и настроить базовые параметры, такие как правила безопасности и структура данных.

Шаг 1: создайте проект Firebase
Чтобы начать использовать Firebase, вам понадобится аккаунт Google. Перейдите в Firebase Console и нажмите кнопку «Add Project». Вам будет предложено указать имя проекта (оно может быть любым), а также при желании включить Google Analytics для проекта. На этом этапе его можно пропустить или включить, если в дальнейшем вы хотите отслеживать поведение пользователей.

После нажатия «Create Project» Firebase выполнит подготовку ресурсов в фоновом режиме. Через несколько секунд проект будет готов.

Шаг 2: добавьте приложение в Firebase
Прежде чем использовать возможности Firebase, необходимо зарегистрировать приложение — веб-приложение, Android или iOS. Нажмите соответствующую иконку платформы (например, символ веб-приложения </>) и следуйте шагам регистрации. Для веб-приложения будет выдан конфигурационный фрагмент с параметрами проекта Firebase, который нужно вставить в код.

Конфигурационный фрагмент (snippet) может выглядеть так:

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

Используйте эту конфигурацию для инициализации Firebase в своем приложении.

Шаг 3: включите нужную базу данных
После настройки проекта и приложения пора выбрать базу данных. В Firebase Console найдите раздел «Build» в левом меню и выберите Realtime Database или Cloud Firestore, в зависимости от того, что вы хотите использовать.

Нажмите «Create Database» и выберите местоположение данных. Для большинства приложений подойдет регион по умолчанию, но для лучшей производительности можно выбрать регион ближе к вашей пользовательской базе.

Шаг 4: настройте правила безопасности
Базы данных Firebase очень гибкие, однако такая гибкость требует ответственного подхода. По умолчанию Firebase ограничивает доступ к базе данных из соображений безопасности. Во время настройки вам предложат выбрать режим правил безопасности. Для разработки или тестирования можно временно использовать «test mode», который делает базу данных общедоступной для чтения и записи. Главное — не используйте этот режим в рабочей среде!

Так выглядит тестовый режим:

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

Для рабочей среды следует написать более точные правила, которые определяют, кто и какие части данных может читать или записывать. Правила безопасности Firebase могут основываться на аутентификации пользователя, полях документа, параметрах запроса и других условиях.

Рис. 1. Создание базы данных

  • URL базы данных и API-ключ: для аутентификации запросов вам понадобятся API-ключ проекта Firebase и URL базы данных. Они находятся в настройках проекта в разделах «Web API Key» и «Realtime Database URL» (или REST-эндпоинт Firestore).

  • Понимание REST-эндпоинтов: базы данных Firebase доступны через REST API. Например:

    • 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

Чтобы показать, как работают операции чтения и записи, мы начнем с создания новой коллекции — логического контейнера для организации документов — и вручную заполним ее тестовыми записями пользователей. Эта настройка станет основой для дальнейшей практики получения данных и даст целостное представление о том, как работает Firestore. 



Создайте первую коллекцию

Нажмите кнопку Start Collection. Откроется модальное окно, где нужно указать имя коллекции. Назовем ее users, поскольку мы будем имитировать небольшую базу пользователей.

После задания имени коллекции вам предложат создать первый документ внутри нее. Firestore автоматически генерирует случайный ID документа, если вы не хотите задавать его вручную, но для наглядности создадим его сами — используем простой вариант, например users .

Добавьте поля в документ
После того как документ получил ID, нужно заполнить его полями. Думайте о них как о столбцах в традиционной базе данных, но с гораздо большей гибкостью.

Можно начать, например, с такого поля:

  • name → "Jane Doe"

Поскольку наша цель — автоматически добавлять данные с помощью кода MQL5, описанная выше ручная часть не так важна. Теперь подключимся к базе данных.

Подключение к базе данных
REST-эндпоинт для нашей базы данных "my-users-mql5" будет таким:

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

Если вставить этот URL в браузер сейчас, вы, скорее всего, увидите:

Рис. 2. Пустая база данных

Когда коллекция users настроена, вы готовы начать изучать чтение данных из Firestore с помощью кода. На следующих шагах мы разберем, как добавлять данные, получать документы, отслеживать обновления в реальном времени и использовать запросы для фильтрации и сортировки данных.


Создание данных

HTTP-метод POST предназначен для отправки данных в указанный ресурс, другими словами — для передачи данных на сервер. При выполнении POST-запроса данные обычно передаются в теле запроса, а сервер затем обрабатывает их и создает новый ресурс (например, новый аккаунт пользователя, новую запись блога или новую запись в базе данных).

Это отличается от GET-запроса, который используется только для получения данных и не должен ничего изменять на сервере. POST, напротив, связан с отправкой и изменением — он создает что-то новое.

В каждом случае клиент отправляет структурированные данные (обычно в формате JSON) на сервер или напрямую в бессерверную функцию, которая затем сохраняет эти данные где-либо — часто в базе данных вроде 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));
     }
  }

Рис. 3. Создание новых записей

С помощью приведенного выше кода мы добавили новую запись "Jane Doe" с уникальным ID, сгенерированным Firebase, что предотвращает конфликты ключей даже при одновременном добавлении данных. Можно добавлять сколько угодно записей, включая вложенные поля вроде email, age или timestamp, задавая их как пары «ключ — значение» в соответствующей структуре данных. Следующий шаг — получить эти данные.



Чтение данных

Теперь, когда база данных уже создана и содержит данные, пора начать полноценно с ней работать. Мы уже создали коллекцию с тестовыми документами и научились отправлять данные в Firestore методом POST. Это хорошее начало, но чтение данных не менее важно, чем запись. Во многих приложениях именно получение и отображение данных является основой пользовательского опыта.

Загружаете ли вы список пользователей, показываете новостную ленту или выводите каталог товаров, вам понадобится способ получать информацию из базы данных. Здесь и применяется метод GET.

GET — один из основных методов HTTP-запросов. В отличие от POST, который используется для отправки данных и создания новых ресурсов, GET применяется для получения информации с сервера. По сути, это операция только для чтения: отправляя GET-запрос, вы просите сервер вернуть данные, но не меняете ничего на стороне сервера.

Простая аналогия: POST-запрос похож на отправку формы для создания нового аккаунта, а GET-запрос — на вход в систему и просмотр информации профиля. Вы ничего не меняете, а только получаете уже существующие данные.

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

Всего несколькими строками кода мы получили файл, содержащий всю информацию из базы данных "firebase-temp.txt" 

Права доступа: убедитесь, что правила безопасности Firestore разрешают чтение там, где это необходимо. Для публичного тестирования можно использовать открытые правила ( allow read: if true; ), но для рабочей среды их нужно ужесточить!



Обновление данных

Как вы, вероятно, уже заметили, каждый раз при добавлении нового документа в базу данных Firestore — вручную через консоль или программно с помощью Firebase SDK — ему назначается уникальный ID документа. Такой ID может выглядеть как случайная строка букв и цифр, например kJ73sd98ASQv, и на первый взгляд может показаться не таким важным.

Firestore устроен вокруг коллекций и документов. Коллекция содержит несколько документов, а каждый документ хранит данные в виде пар ключ-значение. При добавлении документа в коллекцию можно либо позволить Firestore автоматически сгенерировать ID, либо указать его вручную.

Например, при добавлении пользователя в коллекцию users у вас может получиться такой путь:

users/kJ73sd98ASQv

Это означает, что документ этого пользователя находится внутри коллекции users и однозначно идентифицируется ID kJ73sd98ASQv. Если позже нужно получить, обновить или удалить именно этот документ, необходимо сослаться на полный путь, включая ID документа.

Но важно понимать: ID документа критически важен. Фактически это уникальный идентификатор, который позволяет Firestore (и, соответственно, вашему приложению) эффективно находить, изменять или удалять конкретную часть данных. Думайте о нем как об отпечатке пальца: у двух документов не бывает одного и того же ID, и именно этот ID обеспечивает прямое и точное взаимодействие с каждым отдельным документом.

Поэтому при обновлении или удалении данных в Firestore знание и использование ID документа абсолютно необходимо.

В примере с "Jane Doe" REST-эндпоинт добавленного документа выглядит так: 

https://firestore.googleapis.com/v1/projects/my-users-mql5/databases/(default)/documents/users/NoQ8m2vYLnGkykNhUjFE
Итак, ID нашего документа:       
NoQ8m2vYLnGkykNhUjFE

Чтобы обновить эти данные, можно использовать метод "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
     }
  }

С помощью этого кода мы обновим имя с "Jane Doe" на "Princess Doe".

Рис. 4. Обновление записей



Удаление записей

Последняя операция в этой серии — удаление записи. Чтобы удалить запись вроде "Jane Doe" из Cloud Firestore, можно использовать метод DELETE для конкретного пути к документу, указывающего на уникальный ID записи. Например, DELETE-запрос к документу с автоматически сгенерированным ID навсегда удалит эту запись из базы данных. Обработку успешного выполнения и ошибок можно добавить в код приложения, чтобы пользователь получал корректную обратную связь. Кроме того, правила безопасности Firebase должны ограничивать права на удаление, предотвращая случайное или злонамеренное удаление данных неавторизованными пользователями.

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

При указании ID документа запись будет удалена. 



Использование Firebase в алгоритмической торговле

Теперь, когда мы изучили применение простых CRUD-функций в MQL, можно рассмотреть практический пример использования этих знаний в алгоритмической торговле. В этом примере мы будем отправлять торговую информацию из терминала в Firebase, а затем отображать сигнал на панели мониторинга.

Отправка торговой информации в Firebase
Мы можем использовать базовый код MQL5 для получения информации о закрытых позициях, после чего эти данные будут отправляться в базу данных для обработки. 

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

Синхронизация портфеля из MQL5 в Firestore
Каждая отправленная запись может быть сохранена, загружена и даже прочитана построчно перед отображением на панели мониторинга. Такой подход дает понятный и организованный способ анализа торговой истории без бесконечной прокрутки журналов или использования скриншотов. Благодаря такой структуре трейдеры могут эффективнее визуализировать свою результативность и находить закономерности, которые иначе могли бы остаться незамеченными.

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

Результат выглядит так:



Заключение

Базы данных — основа современных приложений, и их освоение является обязательным навыком для разработчиков. Научившись взаимодействовать с Firebase — будь то мгновенная синхронизация Realtime Database или мощные запросы Firestore, — вы осваиваете важный инструментарий для создания динамических приложений, работающих с данными. 

Имя файла Описание
 firebase-users.mq5  Файл с кодом для выполнения CRUD-операций в Firestore.
Download_Infor.mq5  Файл с кодом для загрузки информации из Firestore и отображения ее на графике.
 Sending_Trading_Info.mq5  Файл с кодом для отправки торговой информации в Firestore.


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/17854

Прикрепленные файлы |
Download_Info.mq5 (5.93 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (1)
joaopedrodev
joaopedrodev | 26 авг. 2025 в 16:43
Я увидел, что вы интегрируетесь с Firebase, используя родные функции HTTP-запросов в MQL5.

Я бы посоветовал вам взглянуть на Connexus, библиотеку, которую я разработал для HTTP-запросов. Она была создана специально для упрощения такого типа интеграции, делая код более чистым, многократно используемым и простым в сопровождении.
MetaTrader и Google Таблицы через PythonAnywhere: Руководство по безопасному потоку данных MetaTrader и Google Таблицы через PythonAnywhere: Руководство по безопасному потоку данных
В этой статье показан безопасный способ экспорта данных MetaTrader в Google Таблицы. Google Таблицы — очень ценное решение, поскольку оно работает в облаке, а сохраненные там данные доступны в любое время и из любого места. Поэтому трейдеры могут получать доступ к торговым и связанным с торговлей данным, экспортированным в Google Таблицы, и выполнять дальнейший анализ для будущей торговли в любое время, где бы они ни находились.
Торговые инструменты MQL5 (Часть 22): Построение гистограммы и функции вероятностной массы (PMF) биномиального распределения Торговые инструменты MQL5 (Часть 22): Построение гистограммы и функции вероятностной массы (PMF) биномиального распределения
В этой статье разрабатывается интерактивный график на MQL5 для биномиального распределения, объединяющий гистограмму смоделированных исходов с теоретической функцией массы вероятности. Он реализует расчеты среднего значения, стандартного отклонения, коэффициента асимметрии, коэффициента эксцесса, процентилей и доверительных интервалов, а также настраиваемые темы и метки, поддерживает перетаскивание, изменение размера и изменение параметров в реальном времени. Используйте его для оценки ожидаемых выигрышных сделок, вероятных просадок и доверительных диапазонов при проверке торговых стратегий.
Повышение эффективности торговли с использованием Smart Money Concepts (SMC): OB, BOS и FVG Повышение эффективности торговли с использованием Smart Money Concepts (SMC): OB, BOS и FVG
Повысьте эффективность торговли с помощью Smart Money Concepts (SMC), объединив блоки ордеров (Order Blocks, OB), пробой структуры (Break of Structure, BOS) и разрывы справедливой стоимости (Fair Value Gaps, FVG) в одном мощном советнике. Выбирайте автоматическое исполнение или работайте с отдельной концепцией SMC для более гибкой и точной торговли.
От начального до среднего уровня: Объекты (IV) От начального до среднего уровня: Объекты (IV)
Пожалуй, это самая веселая статья на данный момент. Так происходит, потому что здесь мы реализуем модификацию объекта, присутствующего в MetaTrader 5, чтобы создать другой, изначально отсутствующий на платформе. Конечно, то, что мы здесь рассмотрим, может показаться безумием, но это работает и имеет очень интересное цель.