Экспорт тиков в SQL из MQL5: Скрипт реального времени

Экспорт тиков в SQL из MQL5: Скрипт реального времени MQL4 / MQL5 (MetaTrader)
Пошаговое руководство по созданию MQL5-скрипта для экспорта тиковых данных (Bid/Ask) в реальном времени в базу данных SQL без использования сторонних DLL.
Суть: Высокопроизводительный сборщик тиков на MQL5, использующий встроенный движок SQLite. Решение работает без внешних DLL, обеспечивает субмиллисекундную задержку при записи и сохраняет структуру данных для последующего квантового анализа.

Исходный код

Для минимизации задержек (latency) и исключения проблем с безопасностью (блокировка вызовов внешних библиотек терминалом) мы будем использовать встроенный в MetaTrader 5 движок SQLite. Данный советник перехватывает каждый входящий тик через событие OnTick и мгновенно записывает его в локальную базу данных.

#property copyright "Quant Developer"
#property link      "https://finfluct.com"
#property version   "1.00"
#property strict

// Входные параметры
input string DB_FileName = "TickData.db"; // Имя файла базы данных
input string DB_TableName = "ticks";     // Имя таблицы

int db_handle = INVALID_HANDLE;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
    // Открываем или создаем базу данных в общей папке всех терминалов
    db_handle = DatabaseOpen(DB_FileName, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE | DATABASE_OPEN_COMMON);
    if(db_handle == INVALID_HANDLE) {
        Print("Ошибка открытия БД: ", GetLastError());
        return INIT_FAILED;
    }

    // Создаем таблицу для хранения тиков, если она не существует
    string query = "CREATE TABLE IF NOT EXISTS " + DB_TableName + " (" 
                   "id INTEGER PRIMARY KEY AUTOINCREMENT," 
                   "symbol TEXT," 
                   "time INT," 
                   "msec INT," 
                   "bid REAL," 
                   "ask REAL," 
                   "volume REAL" 
                   ");";

    if(!DatabaseExecute(db_handle, query)) {
        Print("Ошибка создания таблицы: ", GetLastError());
        DatabaseClose(db_handle);
        return INIT_FAILED;
    }

    // Создаем индекс для оптимизации будущих аналитических выборок
    string index_query = "CREATE INDEX IF NOT EXISTS idx_symbol_time ON " + DB_TableName + " (symbol, time);";
    if(!DatabaseExecute(db_handle, index_query)) {
        Print("Ошибка создания индекса: ", GetLastError());
    }

    Print("Экспорт тиков успешно запущен. БД: ", DB_FileName);
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
    if(db_handle != INVALID_HANDLE) {
        DatabaseClose(db_handle);
        Print("Соединение с БД закрыто.");
    }
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
    MqlTick last_tick;
    if(SymbolInfoTick(_Symbol, last_tick)) {
        // Формируем SQL-запрос на вставку данных
        string query = StringFormat(
            "INSERT INTO %s (symbol, time, msec, bid, ask, volume) VALUES ('%s', %lld, %d, %f, %f, %f);",
            DB_TableName, _Symbol, last_tick.time, last_tick.time_msc % 1000, last_tick.bid, last_tick.ask, (double)last_tick.volume_real
        );

        if(!DatabaseExecute(db_handle, query)) {
            Print("Ошибка записи тика: ", GetLastError());
        }
    }
}

Разбор параметров

  • DB_FileName: Имя файла базы данных SQLite. Использование флага DATABASE_OPEN_COMMON сохраняет файл в общую директорию данных всех терминалов MetaTrader 5, что упрощает доступ внешних скриптов (например, на Python).
  • DB_TableName: Имя таблицы, в которую будут записываться поля тика: символ, Unix-время, миллисекунды, цены Bid/Ask и реальный объем.
  • db_handle: Дескриптор соединения с базой данных, возвращаемый функцией DatabaseOpen. Используется для всех последующих транзакций.
  • MqlTick: Встроенная структура MQL5, содержащая наиболее полную информацию о последнем изменении цены, включая время в миллисекундах (time_msc).

Как запустить

1. Откройте MetaEditor в MetaTrader 5 (клавиша F4) и создайте новый советник (Expert Advisor).

2. Скопируйте представленный выше код, вставьте его в редактор и скомпилируйте (клавиша F7).

3. Перетащите скомпилированный советник на график интересующего вас финансового инструмента. С этого момента каждый новый тик будет мгновенно записываться в базу данных.

4. Найти полученный файл базы данных можно в общей папке терминалов по пути: C:\Users\[Имя_Пользователя]\AppData\Roaming\MetaQuotes\Terminal\Common\Files\.

Для построения распределенных систем сбора данных, где требуется централизованное хранилище корпоративного уровня, рекомендуем использовать PostgreSQL. Подробное руководство по такой архитектуре доступно в нашей статье Интеграция MetaTrader 5 с PostgreSQL через libpq.dll в MQL5.

При разработке сложных сеточных роботов, тестируемых на собранной тиковой истории, часто возникает необходимость оптимизации просадок. Ознакомьтесь с готовым решением в материале MQL4: Алгоритм Частичного Закрытия Сетки для Снижения Просадки (Partial Grid Close).

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

Оцените статью
FinFluct