libpq.dll (официальный C-интерфейс PostgreSQL), функции которой импортируются в MQL5 через директиву #import. Это позволяет MQL5-программам устанавливать соединения, выполнять SQL-запросы и обрабатывать результаты напрямую из торгового терминала.Исходный код
Для успешной интеграции нам потребуется два основных файла: заголовочный файл PostgreSQL.mqh, который объявляет функции из libpq.dll, и пример эксперта PostgreSQL_Example.mq5, демонстрирующий их использование.
1. PostgreSQL.mqh (для MQL5/Include/PostgreSQL/PostgreSQL.mqh)
//+------------------------------------------------------------------+
//| PostgreSQL.mqh |
//| Copyright 2023, Finfluct.com |
//| https://finfluct.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Finfluct.com"
#property link "https://finfluct.com"
#property version "1.00"
#ifndef POSTGRESQL_MQH
#define POSTGRESQL_MQH
//--- Определения типов данных для libpq
typedef long PGconn; // Указатель на объект соединения
typedef long PGresult; // Указатель на объект результата запроса
//--- Статусы результата запроса
enum ExecStatusType
{
PGRES_EMPTY_QUERY = 0, // Пустой запрос
PGRES_COMMAND_OK, // Команда выполнена успешно (без возврата данных)
PGRES_TUPLES_OK, // Запрос выполнен успешно (с возвратом данных)
PGRES_COPY_OUT, // COPY OUT
PGRES_COPY_IN, // COPY IN
PGRES_BAD_RESPONSE, // Плохой ответ от сервера
PGRES_NONFATAL_ERROR, // Нефатальная ошибка
PGRES_FATAL_ERROR, // Фатальная ошибка
PGRES_COPY_BOTH, // COPY BOTH
PGRES_SINGLE_TUPLE // Одиночная строка результата
};
//--- Импорт функций из libpq.dll
// Убедитесь, что libpq.dll находится в MQL5/Libraries/
#import "libpq.dll"
// Устанавливает новое соединение с базой данных
// conninfo: строка соединения (e.g., "host=localhost port=5432 dbname=mydb user=myuser password=mypass")
// Возвращает PGconn (указатель на соединение) или NULL при ошибке
PGconn PQconnectdb(string conninfo);
// Закрывает соединение с базой данных
// conn: указатель на соединение
void PQfinish(PGconn conn);
// Выполняет SQL-команду
// conn: указатель на соединение
// command: SQL-команда для выполнения
// Возвращает PGresult (указатель на результат запроса) или NULL при ошибке
PGresult PQexec(PGconn conn, string command);
// Возвращает статус результата запроса
// res: указатель на результат запроса
// Возвращает ExecStatusType
ExecStatusType PQresultStatus(PGresult res);
// Возвращает сообщение об ошибке, связанное с соединением
// conn: указатель на соединение
// Возвращает строку с сообщением об ошибке
string PQerrorMessage(PGconn conn);
// Возвращает количество строк (кортежей) в результате запроса
// res: указатель на результат запроса
// Возвращает количество строк
int PQntuples(PGresult res);
// Возвращает количество полей (столбцов) в результате запроса
// res: указатель на результат запроса
// Возвращает количество столбцов
int PQnfields(PGresult res);
// Возвращает значение поля (столбца) для указанной строки и столбца
// res: указатель на результат запроса
// row_number: номер строки (начиная с 0)
// column_number: номер столбца (начиная с 0)
// Возвращает строковое значение поля
string PQgetvalue(PGresult res, int row_number, int column_number);
// Возвращает имя поля (столбца) по его номеру
// res: указатель на результат запроса
// column_number: номер столбца (начиная с 0)
// Возвращает имя столбца
string PQfname(PGresult res, int column_number);
// Освобождает память, занятую объектом результата запроса
// res: указатель на результат запроса
void PQclear(PGresult res);
#import
#endif
2. PostgreSQL_Example.mq5 (для MQL5/Experts/PostgreSQL_Example.mq5)
//+------------------------------------------------------------------+
//| PostgreSQL_Example.mq5 |
//| Copyright 2023, Finfluct.com |
//| https://finfluct.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Finfluct.com"
#property link "https://finfluct.com"
#property version "1.00"
#property description "Пример интеграции MT5 с PostgreSQL через libpq.dll"
//--- Включаем наш заголовочный файл с объявлениями функций libpq
#include
//--- Входные параметры для подключения к базе данных
input string Inp_DBHost = "localhost"; // Хост базы данных
input int Inp_DBPort = 5432; // Порт базы данных
input string Inp_DBName = "mt5_data"; // Имя базы данных
input string Inp_DBUser = "mt5_user"; // Пользователь базы данных
input string Inp_DBPassword = "mt5_password"; // Пароль пользователя
input string Inp_TableName = "trade_history"; // Имя таблицы для записи данных
//--- Глобальная переменная для хранения указателя на соединение с БД
PGconn g_conn = 0;
//+------------------------------------------------------------------+
//| Инициализация эксперта |
//+------------------------------------------------------------------+
int OnInit()
{
// Формируем строку подключения
string conninfo = StringFormat("host=%s port=%d dbname=%s user=%s password=%s",
Inp_DBHost, Inp_DBPort, Inp_DBName, Inp_DBUser, Inp_DBPassword);
// Устанавливаем соединение с PostgreSQL
g_conn = PQconnectdb(conninfo);
// Проверяем успешность соединения
if (g_conn == 0)
{
Print("Ошибка: Не удалось подключиться к PostgreSQL. Проверьте параметры и libpq.dll.");
return INIT_FAILED;
}
// Проверяем статус соединения (PQstatus не импортирован, используем PQerrorMessage для проверки)
// Если PQerrorMessage возвращает непустую строку, значит есть ошибка
if (StringLen(PQerrorMessage(g_conn)) > 0)
{
Print("Ошибка подключения к PostgreSQL: ", PQerrorMessage(g_conn));
PQfinish(g_conn);
g_conn = 0;
return INIT_FAILED;
}
Print("Успешно подключено к PostgreSQL.");
// Создаем таблицу, если она не существует
string create_table_sql = StringFormat(
"CREATE TABLE IF NOT EXISTS %s (",
Inp_TableName
) +
" id SERIAL PRIMARY KEY,"
" symbol VARCHAR(16) NOT NULL,"
" ticket BIGINT NOT NULL,"
" order_type VARCHAR(10) NOT NULL,"
" volume DOUBLE PRECISION NOT NULL,"
" price DOUBLE PRECISION NOT NULL,"
" time_open TIMESTAMP WITH TIME ZONE NOT NULL,"
" comment VARCHAR(255)"
");";
PGresult res = PQexec(g_conn, create_table_sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
Print("Ошибка при создании таблицы: ", PQerrorMessage(g_conn));
PQclear(res);
PQfinish(g_conn);
g_conn = 0;
return INIT_FAILED;
}
Print("Таблица '", Inp_TableName, "' проверена/создана.");
PQclear(res);
// Пример записи данных (можно вызывать в OnTick или OnTrade)
// Для демонстрации, запишем текущую цену BID/ASK в таблицу
MqlTick tick;
if (SymbolInfoTick(_Symbol, tick))
{
string insert_sql = StringFormat(
"INSERT INTO %s (symbol, ticket, order_type, volume, price, time_open, comment) VALUES ('%s', %d, '%s', %f, %f, NOW(), '%s');",
Inp_TableName,
_Symbol,
(long)TimeCurrent(), // Используем текущее время как 'ticket' для примера
"DEMO_BUY",
0.1,
tick.bid,
"Demo entry"
);
res = PQexec(g_conn, insert_sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
Print("Ошибка при вставке данных: ", PQerrorMessage(g_conn));
}
else
{
Print("Данные успешно вставлены в таблицу '", Inp_TableName, "'.");
}
PQclear(res);
}
// Пример чтения данных
string select_sql = StringFormat("SELECT id, symbol, price, time_open FROM %s ORDER BY time_open DESC LIMIT 5;", Inp_TableName);
res = PQexec(g_conn, select_sql);
if (PQresultStatus(res) == PGRES_TUPLES_OK)
{
int rows = PQntuples(res);
int cols = PQnfields(res);
Print("--- Последние 5 записей из '", Inp_TableName, "' ---");
for (int r = 0; r < rows; r++)
{
string row_data = "";
for (int c = 0; c < cols; c++)
{
row_data += StringFormat("%s: %s ", PQfname(res, c), PQgetvalue(res, r, c));
}
Print(row_data);
}
}
else
{
Print("Ошибка при чтении данных: ", PQerrorMessage(g_conn));
}
PQclear(res);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Деинициализация эксперта |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Закрываем соединение с базой данных при деинициализации
if (g_conn != 0)
{
PQfinish(g_conn);
g_conn = 0;
Print("Соединение с PostgreSQL закрыто.");
}
}
//+------------------------------------------------------------------+
//| OnTick функция |
//+------------------------------------------------------------------+
void OnTick()
{
// В реальном приложении здесь можно записывать данные по каждому тику
// или выполнять другие операции с БД. Для примера, мы сделали это в OnInit.
}
//+------------------------------------------------------------------+
//| OnTrade функция |
//+------------------------------------------------------------------+
void OnTrade()
{
// Здесь можно записывать информацию о каждой торговой операции в БД.
// Например, для анализа эффективности алгоритмов, таких как описанный в статье
// MQL4: Алгоритм Частичного Закрытия Сетки для Снижения Просадки (Partial Grid Close),
// или для сбора данных для мультивалютного тестирования, как в
// Мультивалютное тестирование в MT5: обход ограничений тестера.
}
Разбор параметров
Inp_DBHost: IP-адрес или имя хоста, на котором запущен сервер PostgreSQL. По умолчаниюlocalhost.Inp_DBPort: Порт, на котором PostgreSQL принимает соединения. Стандартный порт —5432.Inp_DBName: Имя базы данных PostgreSQL, к которой будет устанавливаться соединение. Убедитесь, что эта база данных существует.Inp_DBUser: Имя пользователя PostgreSQL, имеющего права доступа к указанной базе данных.Inp_DBPassword: Пароль для указанного пользователя PostgreSQL.Inp_TableName: Имя таблицы, в которую будут записываться и из которой будут читаться данные. Если таблица не существует, эксперт попытается ее создать.
Как запустить
Для успешной интеграции и запуска примера выполните следующие шаги:
-
Установите PostgreSQL: Если у вас еще нет PostgreSQL, загрузите и установите его с официального сайта. В процессе установки создайте суперпользователя (например,
postgres) и запомните пароль. -
Создайте базу данных и пользователя: Откройте
psqlили любой другой клиент PostgreSQL (например, pgAdmin) и выполните следующие команды для создания базы данных и пользователя, которые будут использоваться MQL5:CREATE DATABASE mt5_data; CREATE USER mt5_user WITH PASSWORD 'mt5_password'; GRANT ALL PRIVILEGES ON DATABASE mt5_data TO mt5_user;Замените
mt5_data,mt5_userиmt5_passwordна желаемые значения, соответствующие входным параметрам эксперта. -
Получите
libpq.dll:- Если у вас установлен PostgreSQL, найдите
libpq.dllв папке установки (обычноC:\Program Files\PostgreSQL\<версия>\bin). - Если PostgreSQL не установлен на той же машине, где MT5, или вы хотите более легковесный вариант, вы можете найти скомпилированную версию
libpq.dllдля Windows (например, на сайте PostgreSQL или через поисковик, ища "libpq.dll download"). Убедитесь, что версия DLL соответствует архитектуре вашего MT5 (32-бит или 64-бит). MT5 обычно 64-битный.
- Если у вас установлен PostgreSQL, найдите
-
Разместите
libpq.dll: Скопируйте файлlibpq.dllв папкуMQL5\Librariesвашего терминала MetaTrader 5. Путь к этой папке можно найти через MetaEditor: Файл -> Открыть каталог данных -> MQL5 -> Libraries. -
Разместите MQL5-файлы:
- Создайте папку
PostgreSQLвнутриMQL5\Include. СкопируйтеPostgreSQL.mqhвMQL5\Include\PostgreSQL\. - Скопируйте
PostgreSQL_Example.mq5вMQL5\Experts\.
- Создайте папку
-
Скомпилируйте в MetaEditor: Откройте
PostgreSQL_Example.mq5в MetaEditor и нажмите "Компилировать" (F7). Убедитесь, что нет ошибок компиляции. -
Запустите эксперта в MetaTrader 5:
- Откройте MetaTrader 5.
- Перетащите
PostgreSQL_Exampleиз окна "Навигатор" на любой график. - В окне настроек эксперта перейдите на вкладку "Общие" и убедитесь, что установлен флажок "Разрешить импорт DLL".
- На вкладке "Входные параметры" проверьте и при необходимости измените параметры подключения к базе данных (
Inp_DBHost,Inp_DBPort,Inp_DBName,Inp_DBUser,Inp_DBPassword,Inp_TableName) в соответствии с вашей конфигурацией PostgreSQL. - Нажмите "ОК".
-
Проверьте результат: Откройте вкладку "Эксперты" в окне "Терминал" (Ctrl+T). Вы должны увидеть сообщения об успешном подключении, создании таблицы и вставке/чтении данных. Также вы можете проверить базу данных PostgreSQL через
psqlили pgAdmin, чтобы убедиться, что данные были записаны.
Эта интеграция открывает широкие возможности для хранения исторических данных, результатов тестирования, торговой статистики и многого другого, позволяя вам использовать мощь реляционных баз данных в ваших MQL5-проектах.




