preview
Алготрейдинг без рутины: быстрый анализ сделок в MetaTrader 5 с SQLite

Алготрейдинг без рутины: быстрый анализ сделок в MetaTrader 5 с SQLite

MetaTrader 5Примеры |
117 0
MetaQuotes
MetaQuotes

Проблема обратной связи в алгоритмической торговле

Алгоритмическая торговля требует не только разработки конкурентных стратегий, но и постоянного контроля результатов. Без обратной связи торговая система может стать неуправляемой. Пока вы не видите, как ведёт себя стратегия в реальном времени, вы управляете не системой, а набором догадок.

На современных биржевых рынках и на FOREX частота сделок выросла многократно. Данные устаревают быстрее, чем вы успеваете сделать выводы. А вместе с ними устаревает и актуальность ваших выводов. Вдобавок к этому, повторяющиеся рутинные ручные действия неизбежно порождают задержки и ошибки. Они появляются просто потому, что человек устал, отвлёкся или поспешил.

Именно здесь особенно важны возможности MetaTrader 5. Встроенная поддержка SQLite — локальной базы данных — меняет правила игры. База данных становится не внешним хранилищем, а органической частью торгового процесса. Запросы выполняются практически мгновенно, статистика обновляется автоматически, анализ торговли занимает секунды вместо часов. И результат анализа оказывается там, где он действительно нужен — рядом с торговлей, а не где-то за пределами терминала.

В статье разобран "минимальный рабочий набор" алготрейдера: структура базы данных торгового журнала, безопасная быстрая запись данных, аналитические SQL-запросы и вывод ключевой статистики на интерактивную панель в MetaTrader 5. Это позволит убрать большую часть рутины и сосредоточиться на творческом процессе: анализе и развитии торговой системы.


Зачем алгоритмическому трейдеру локальная база данных

Разработка и тестирование торговых стратегий порождают колоссальные объёмы данных. Результаты оптимизаций, истории сделок, сигналы индикаторов, макроэкономические события — всё это требует не просто хранения, но и структурирования, и быстрого доступа. Локальная база данных решает эти задачи, с которыми сталкивается любой серьёзный алготрейдер.

Сохранение результатов тестирования и оптимизации

Оптимизация стратегии с перебором параметров генерирует сотни, а то и тысячи вариантов параметров. Каждый проход — это набор метрик, значений параметров, результатов. Как сравнить их между собой? Как отследить эволюцию стратегии во времени? База данных позволяет хранить полную историю оптимизаций и анализировать её в любых разрезах — от простых таблиц до сложных корреляций.

Автоматический торговый журнал

Вместо рутинного ведения журнала в электронной таблице запустите эксперт в терминале и получите автоматическую фиксацию каждой сделки с полным набором атрибутов: символ, «магик», объём, цена, время, результат, комментарий. Данные попадают в базу в реальном времени и становятся доступны для анализа мгновенно — без дополнительных действий со стороны трейдера.

Анализ торговых сигналов

Сохранение и анализ торговых сигналов открывает возможности, недоступные при работе с обычными логами. Какова эффективность сигналов? Какие индикаторы коррелируют между собой? В каких условиях входы и выходы оптимальны? Все трейдеры хотят знать ответы на эти вопросы. SQL-запросы предоставляют мощнейший инструмент анализа без необходимости писать дополнительный код.

Для начала работы с SQLite нужны всего три функции:

  1. DatabaseOpen — открыть базу данных
  2. DatabaseExecute — выполнить запрос к таблице
  3. DatabaseClose — закрыть базу данных

И этого достаточно для решения 90% задач, стоящих перед алготрейдером.

Пример открытия и закрытия базы данных:

int db = DatabaseOpen("trading.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(db == INVALID_HANDLE)
 {
  Print("Error opening Database: ", GetLastError());
  return;
 }
// ... работа с базой данных ...
DatabaseClose(db);     // закрытие базы данных

Главное: SQLite встроен в систему MetaTrader 5, что называется, «из коробки» и работает напрямую с ядром терминала. В то время как Excel и другие электронные таблицы — это внешние программы, к которым эксперт на MQL5 обращается либо через устаревшие «костыли» вроде OLE-автоматизации, либо через внешний CSV-файл. Разница в пользу SQLite в MetaTrader 5 колоссальная — и по скорости, и по удобству, и по надёжности.


Схема таблиц: архитектура торгового журнала

Проектирование базы данных начинается с вопроса: что именно нужно хранить? Для торгового журнала ответ очевиден — историю сделок, сигналы и события. Но почему именно три таблицы, а не одна «большая и универсальная»? Разделение на DEALS, SIGNALS и EVENTS — это не прихоть, а необходимость. Каждая сущность живёт своей жизнью и связывается с другими при запросе. Хотите узнать «все сделки после сигнала с уверенностью выше 80%»? SQLite справится с этим легко и элегантно и при этом не выходя за пределы торгового терминала.

Таблица DEALS — хронология торговли

Содержит полную информацию о каждой сделке: идентификатор, тикеты, символ, «магический» номер (идентификатор стратегии), объём, цены открытия и закрытия, время, финансовый результат и произвольный комментарий. Это «скелет» торгового журнала — основа для любого анализа.

Таблица SIGNALS — история сигналов

Хранит сигналы от индикаторов и торговых систем: символ, таймфрейм, тип сигнала (покупка/продажа), цену, время возникновения и дополнительные параметры. Позволяет анализировать качество сигналов и их связь с реальными сделками — ключ к пониманию, работает ли ваша стратегия.

Таблица EVENTS — новостной контекст

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

На рисунке ниже представлена ER-диаграмма (Entity-Relationship Diagram) — визуальное отображение структуры базы данных и взаимосвязей между таблицами:

Entity-Relationship Diagram

Рис. 1: ER-диаграмма таблиц торгового журнала

Код создания таблиц:

   //  Таблица истории сделок - DEALS:
   string createDeals = "CREATE TABLE IF NOT EXISTS DEALS ("
                       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                       "deal_ticket INTEGER UNIQUE, "
                       "order_ticket INTEGER, "
                       "symbol TEXT NOT NULL, "
                       "type INTEGER, "                // 0=BUY, 1=SELL
                       "direction INTEGER, "           // 0=IN, 1=OUT, 2=IN/OUT
                       "volume REAL, "
                       "price_open REAL, "
                       "price_close REAL, "
                       "profit REAL, "
                       "swap REAL, "
                       "commission REAL, "
                       "sl REAL, "
                       "tp REAL, "
                       "magic INTEGER, "
                       "comment TEXT, "
                       "time INTEGER, "                // Unix timestamp
                       "time_msc INTEGER, "
                       "reason INTEGER"
                       ");";
   
   //  Таблица торговых сигналов - SIGNALS:
   string createSignals = "CREATE TABLE IF NOT EXISTS SIGNALS ("
                         "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                         "symbol TEXT NOT NULL, "
                         "signal_type TEXT, "          // 'BUY', 'SELL', 'CLOSE'
                         "price REAL, "
                         "stop_loss REAL, "
                         "take_profit REAL, "
                         "strength REAL, "             // 0.0 - 1.0
                         "source TEXT, "               // Strategy name
                         "notes TEXT, "
                         "time INTEGER"
                         ");";
   
   //  Таблица событий - EVENTS:
   string createEvents = "CREATE TABLE IF NOT EXISTS EVENTS ("
                        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        "event_type TEXT, "            // 'NEWS', 'ERROR', 'NOTE', etc.
                        "symbol TEXT, "
                        "description TEXT, "
                        "importance INTEGER, "         // 1=Low, 2=Medium, 3=High
                        "time INTEGER,"
                        "actual REAL, "
                        "previous REAL, "
                        "forecast REAL "
                        ");";
   
   //  Индексы для ускорения поисковых запросов:
   string createIndexes[] = 
    {
      "CREATE INDEX IF NOT EXISTS idx_deals_symbol ON DEALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_deals_magic ON DEALS(magic);",
      "CREATE INDEX IF NOT EXISTS idx_deals_time ON DEALS(time);",
      "CREATE INDEX IF NOT EXISTS idx_signals_symbol ON SIGNALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_signals_time ON SIGNALS(time);"
    };
   
   //  Создание таблиц в БД:
   if(!DatabaseExecute(database, createDeals))
    {
      Print("Error creating DEALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createSignals))
    {
      Print("Error creating SIGNALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createEvents))
    {
      Print("Error creating EVENTS table: ", GetLastError());
      return(false);
    }
   
   //  Создание индексов:
   for(int i = 0; i < ArraySize(createIndexes); i++)
    {
      DatabaseExecute(database, createIndexes[i]);
    }

Обратите внимание на индексы: idx_deals_symbol, idx_deals_magic, idx_deals_time, idx_signals_symbol, idx_signals_time. Они ускоряют запросы по ключевым полям: symbol, magic, time в таблице DEALS и symbol, time в SIGNALS. Индексы — это инвестиция в производительность, которая окупается при каждом аналитическом запросе.


Вставка данных и транзакции: скорость имеет значение

MQL5 предоставляет два способа вставки данных в таблицы: прямое выполнение SQL-запроса и использование подготовленных запросов. Какой выбрать? Ответ однозначен: подготовленные запросы предпочтительнее и с точки зрения безопасности, и с точки зрения производительности.

Прямая вставка через DatabaseExecute:

string sql = StringFormat(
                         "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                         "VALUES (%d, '%s', %d, %.2f, %.5f, %I64d, %.2f)",
                         ticket, symbol, magic, volume, price, TimeCurrent(), profit);
DatabaseExecute(db, sql);

Параметризованный запрос через DatabasePrepare:

//  Создадим параметризованный запрос:
int request = DatabasePrepare(db,
                             "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                             "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)");

//  Установим значение первого параметра запроса - в функции DatabaseBind индексация полей в записи начинается с нуля:
DatabaseBind(request, 0, ticket);
DatabaseTransactionBegin(db);

//  Устанавливаем значения остальных параметров перед добавлением записи:
DatabaseBind(request, 1, symbol);
DatabaseBind(request, 2, magic);
DatabaseBind(request, 3, volume);
DatabaseBind(request, 4, price);
DatabaseBind(request, 5, TimeCurrent());
DatabaseBind(request, 6, profit);

//  Выполним запрос на вставку записи:
DatabaseRead(request);
DatabaseFinalize(request);
DatabaseTransactionCommit(db);

Использование транзакций — это не опция, а необходимость. При массовых операциях вставки и обновления транзакции ускоряют работу в сотни и даже тысячи раз. Почему? Без транзакции каждая операция фиксируется на диск отдельно. С транзакцией — все операции группируются и записываются одним блоком.

Результаты наших тестов впечатляют: производительность SQLite в MQL5 сопоставима с нативным C++ кодом (LLVM 9.0). В большинстве тестов разница составляет менее 5%, а в некоторых сценариях MQL5 даже превосходит C++. На диаграмме ниже показано сравнение времени вставки 1000 записей без транзакций против 25000 записей с транзакциями — разница более чем в 3500 раз в пересчёте на одну запись!

Transactions Comparison

Рис. 2: Сравнение скорости вставки: без транзакций/с транзакциями

Пример использования транзакции при массовой вставке:

DatabaseTransactionBegin(db);
for(int i = 0; i < ArraySize(deals); i++)
 {
  InsertDeal(db, deals[i]);  // вставка очередной сделки - элемента массива структур deals[]
 }
DatabaseTransactionCommit(db);

Все тесты можно изучить (и самим проверить!) в разделе MQL5-форума: SQLite в MQL5: новые функции и тестирование производительности.


SQL-запросы: аналитика без программирования

Одно из главных преимуществ SQL — возможность получения сложной аналитики одним запросом. В MetaTrader 5 это доступно напрямую. Никаких циклов, никаких условий, никаких временных переменных. Один запрос — и готовый результат. Рассмотрим несколько типичных сценариев.

Статистика по торговым символам

Какие инструменты приносят прибыль, а какие — тихо «съедают» депозит? Этот вопрос, а за ним и SQL-запрос должен быть первым в арсенале любого трейдера. Он показывает сводную информацию по каждому символу: количество сделок, суммарную прибыль и средний результат.

string sql = "SELECT symbol, COUNT(*) as deals, "
             "SUM(profit) as total_profit, "
             "AVG(profit) as avg_profit "
             "FROM DEALS GROUP BY symbol "
             "ORDER BY total_profit DESC";
DatabasePrint(db, sql);

Разбор элементов запроса:

Элемент запроса Описание
SELECT symbol Выбирает колонку с названием инструмента
COUNT(*) Подсчитывает количество сделок для инструмента
SUM(profit) Суммирует прибыль по всем сделкам инструмента
GROUP BY symbol Группирует результаты по инструменту
ORDER BY total_profit DESC Сортирует по убыванию общей прибыли

Анализ по стратегиям («магическим» номерам)

«Магический» номер — это уникальный идентификатор эксперта, добавляемый к каждой сделке. Если на одном счёте работает несколько стратегий, этот запрос покажет, какая из них эффективнее. Особенность — использование условного выражения CASE для подсчёта прибыльных сделок.

string sql = "SELECT magic, COUNT(*) as trades, "
             "SUM(CASE WHEN profit > 0 THEN 1 ELSE 0 END) as wins, "
             "SUM(profit) as net_profit "
             "FROM DEALS GROUP BY magic";
DatabasePrint(db, sql);

Разбор элементов запроса:

Элемент запроса Описание
SELECT magic Выбирает колонку с «магическим» номером
COUNT(*) Общее количество сделок по выбранной стратегии
CASE WHEN profit > 0 Условие: если прибыль положительна
THEN 1 ELSE 0 END Возвращает 1 для прибыльных сделок и 0 для убыточных сделок
SUM(wins) Суммирует единицы — получаем количество прибыльных сделок wins

Разделив число прибыльных сделок (wins) на общее число (trades), получаем процент прибыльных сделок — ключевую метрику качества стратегии. Вы получили высокий процент при отрицательной суммарной прибыли? Это сигнал о проблеме с управлением рисками — убыточные сделки крупнее прибыльных.

Распределение торговли по часам

Когда стратегия работает лучше всего? Во время европейской сессии? Американской? Или, может быть, в «тихие часы»? Функция strftime извлекает час из времени открытия сделки (формат 00--23), позволяя выявить наиболее и наименее прибыльные временные интервалы.

string sql = "SELECT strftime('%H', time, 'unixepoch') as hour, "
             "COUNT(*) as trades, SUM(profit) as profit "
             "FROM DEALS GROUP BY hour";
DatabasePrint(db, sql);

Важно: в MQL5 и SQLite время хранится как Unix timestamp (секунды с 1970-01-01). Поэтому добавлен модификатор 'unixepoch'. Аналогично можно анализировать распределение по дню недели strftime('%w', ...), месяцу strftime('%m', ...) или комбинациям.

Разбор элементов запроса:

Элемент запроса Описание
strftime('%H', ...) Извлекает час из времени открытия сделки (00-23)
time Колонка с временем открытия сделки
GROUP BY hour Группирует сделки по часу открытия


Панель статистики: визуализация внутри терминала

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

Показанная ниже панель отображает суммарный результат за заданное число дней (SUMMARY), раздельный результат по инструментам (BY SYMBOL) и лучшие часы для торговли (BEST HOURS). Для чтения данных в структуру используется функция DatabaseReadBind:

Statistical Panel

Рис. 3: Интерактивная панель статистики в терминале

struct DealStats
 {
  string symbol;
  int count;
  double total_profit;
  double avg_profit;
 };

int request = DatabasePrepare(db,
                             "SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, "
                             "AVG(profit) as avg_profit FROM DEALS GROUP BY symbol");
DealStats stats;
while(DatabaseReadBind(request, stats))
 {
  //  Вывод в таблицу на панели:
  AddRowToTable(stats);
 }
DatabaseFinalize(request);

Функция DatabaseReadBind автоматически сопоставляет поля структуры с колонками запроса по именам. Достаточно объявить структуру с полями, соответствующими именам колонок в SQL-запросе.

Управление панелью

Кнопка [Refresh] обновляет статистику с полным пересчетом. Кнопка [Export] выводит рассчитанные данные в CSV-файлы из таблиц базы данных: общий результат работы, сделки, события и сигналы. Пример экспорта:

(#),symbol,trades,total_profit,avg_profit,wins,losses
1,XAGUSD,196,322.25,1.64,14,181
2,AUDUSD,196,-12.0,-0.06,82,99
3,EURUSD,58,-38.5,-0.66,23,35
4,GBPUSD,57,-43.2,-0.75,17,40

«Горячие» клавиши для быстрого управления:

  • 'A' или 'a' — обновить аналитику,
  • 'E' или 'e' — вывести данные в CSV-файл,
  • 'R' или 'r' — считать историю сделок,
  • 'P' или 'p' — включить/выключить показ панели.

Настройки эксперта:

  • «Database file name» — название файла базы данных (по умолчанию: «TradingJournal.db»),
  • «Auto-import trade history» — автоматическая загрузка истории (по умолчанию: true),
  • «History depth in days» — глубина истории (по умолчанию: 30 дней),
  • «Export path» — путь к CSV-файлам (по умолчанию: «MQL5/Files»),
  • «Export to CSV format» — экспорт в CSV (по умолчанию: true),
  • «Show statistics panel on chart» — показ панели (по умолчанию: true).


MetaEditor: инструмент работы с базой данных

Редактор MetaEditor, входящий в состав MetaTrader 5, имеет встроенный инструмент для работы с SQLite: открытие и редактирование таблиц, выполнение SQL-запросов, откат изменений. Поскольку база данных SQLite хранится в единственном файле на компьютере пользователя, к ней можно получить доступ в любой момент через навигатор MetaEditor — проконтролировать структуру и содержимое таблиц, выполнить отладочные запросы.

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

Посмотрим, как легко это сделать на примере базы данных, которая создаётся тестовым экспертом «TradingJournalSQLite-EA» из данной статьи. Откроем базу данных и таблицы в ней, запустим несколько SQL-запросов и закроем. Можно долго объяснять все это словами, но лучше один раз увидеть...

1. Начните с самого простого — откройте базу данных и выберите нужную таблицу:

    Open/Select/Close

    Рис. 4:  Открыть/Выбрать таблицу/Закрыть

    Таблица 'DEALS' выбирается двойным кликом левой кнопки мыши на её названии. Это эквивалентно выполнению SQL-запроса  в навигаторе:

    SELECT * FROM 'DEALS';
    2. Настройте формат времени:

      Time Format

      Рис. 5: Формат времени

      3. Основной вопрос: Кто сколько зарабатывает? Узнайте ответ за миллисекунды:
        SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

        Для тех, кто не любит длинные строки:

        SELECT symbol,
        COUNT(*) as count,
        SUM(profit) as total_profit,
        AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

        PnL

        Рис. 6: Кто сколько зарабатывает

        4. Отсортируйте по убыванию заработка:
          SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol
          ORDER BY total_profit DESC;

          PnL Ordered

          Рис. 7: По убыванию заработка


          5. А сколько заработал «Итого»? Сейчас узнаем:
            SELECT  SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit FROM DEALS;

            NetPnL

            Рис. 8: Итого

            Хотите отладить сложный запрос? Не проблема:

            SELECT   COUNT(*) as total_deals, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END) as closed_trades, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_wins, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_losses, 
                            ROUND(100.0 * SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) / 
                            NULLIF(SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END), 0), 2) as overall_win_rate, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN swap ELSE 0 END) as total_swap,
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN commission ELSE 0 END) as total_commission, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE 0 END) as net_result, 
                            ROUND(AVG(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE NULL END), 2) as avg_profit_per_trade, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) as gross_profit, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) as gross_loss, 
                            CASE WHEN SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) > 0 
                            THEN ROUND(SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) / 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END), 2) 
                            ELSE 0 END as profit_factor, 
                            COUNT(DISTINCT symbol) as symbols_traded, 
                            COUNT(DISTINCT magic) as strategies_used 
                            FROM DEALS;

            Complex Request

            Рис. 9: Сложный SQL-запрос

            Данный SQL-запрос взят без изменений из тестового эксперта «TradingJournalSQLite-EA», приложенного к статье.


            Заключение: торгово-аналитическая система прямо в MetaTrader 5

            Торговый журнал перестал быть статическим файлом, который нужно экспортировать, открывать в сторонней программе и вручную приводить к удобному виду. В MetaTrader 5 он стал частью торгово-аналитической системы — точной, надёжной, реагирующей на изменения в реальном времени. Это сделано нативно SQLite интегрирован в терминал MetaTrader 5 на уровне ядра.

            Это позволяет использовать MetaTrader 5 как самодостаточную торгово-аналитическую систему и применять всю мощь SQL‑запросов. С возможностью расширения и изменения под новые идеи. Вот что получает трейдер:

              • данные сохраняются автоматически и доступны для анализа сразу после появления;
              • аналитические SQL-запросы можно менять быстро и гибко, без усложнения кода эксперта;
              • панель с аналитикой доступна прямо на графике в терминале — там, где идёт торговля;
              • система легко расширяется под новые идеи, метрики и срезы анализа — без обращения к сторонним приложениям.

              Именно поэтому встроенная поддержка SQLite в MetaTrader 5 — это не просто удобное хранилище данных, а крепкий фундамент для полноценной торгово‑аналитической инфраструктуры, где торговля и анализ работают в одной среде, на одном языке и с нативной поддержкой SQL.


              Рекомендуемые материалы для углублённого изучения SQLite в MQL5:

              Список файлов, приложенных к статье:

              Название файла Описание
              TradingJournalSQLite-EA.mq5 Файл, содержащий код тестового эксперта, создающего панель со статистикой торговли
              Прикрепленные файлы |
              Статистический арбитраж на основе коинтегрированных акций (Часть 5): Отбор активов Статистический арбитраж на основе коинтегрированных акций (Часть 5): Отбор активов
              В данной статье предлагается процесс отбора активов для стратегии торговли на основе статистического арбитража с использованием коинтегрированных акций. Система начинается с обычной фильтрации по экономическим факторам, таким как сектор активов и отрасль, и заканчивается составлением перечня критериев для системы оценки. Для каждого статистического теста, использованного в скрининге, был разработан соответствующий класс на языке Python: Коэффициент корреляции Пирсона, коинтеграция Энгл-Грейнджера, коинтеграция Йохансена и стационарность по ADF/KPSS. Эти классы Python сопровождаются личным комментарием автора об использовании ИИ-помощников в разработке программного обеспечения.
              Моделирование рынка (Часть 24): Первые шаги на SQL (VII) Моделирование рынка (Часть 24): Первые шаги на SQL (VII)
              В предыдущей статье мы завершили необходимое введение в тему SQL. И то, что мы хотели показать и объяснить о SQL, на мой взгляд, мы разъяснили должным образом. Так было сделано для того, чтобы каждый, кто придет посмотреть на строящуюся систему репликации/моделирования, мог хотя бы получить представление о том, что там может происходить. Дело в том, что нет смысла программировать вещи, с которыми SQL справляется идеально.
              Создание самооптимизирующихся советников на MQL5 (Часть 15): Идентификация линейных систем Создание самооптимизирующихся советников на MQL5 (Часть 15): Идентификация линейных систем
              Усовершенствовать торговые стратегии бывает непросто, поскольку мы зачастую не до конца понимаем, в чём именно заключается их недостаток. В данном разделе мы познакомимся с идентификацией линейных систем — одной из областей теории управления. Линейные системы с обратной связью способны на основе данных выявлять ошибки системы и корректировать её поведение для достижения заданных результатов. Хотя эти методы, возможно, и не дают полностью понятных объяснений, они гораздо ценнее, чем полное отсутствие системы управления. Давайте рассмотрим идентификацию линейных систем и посмотрим, как она может помочь нам, алгоритмическим трейдерам, сохранить контроль над нашими торговыми приложениями.
              Упрощение работы с базами данных в MQL5 (Часть 1): Введение в базы данных и SQL Упрощение работы с базами данных в MQL5 (Часть 1): Введение в базы данных и SQL
              Мы рассмотрим, как работать с базами данных в MQL5, используя встроенные функции языка. Мы рассмотрим все аспекты, от создания, вставки, обновления и удаления таблиц до импорта и экспорта данных, и все это с примерами кода. Данный материал служит прочной основой для понимания внутренних механизмов доступа к данным, подготавливая почву для обсуждения ORM (Object-Relational Mapping, объектно-реляционное отображение), где мы создадим его на языке MQL5.