Создание системы торговой аналитики (Часть 4): Сводные метрики и дашборд
Введение
В предыдущих частях этой серии мы создали пайплайн обработки закрытых сделок в MetaTrader 5. Советник определяет закрытие позиции, извлекает сведения о сделке и отправляет их на сервер в формате JSON. Бэкенд проверяет полезную нагрузку и сохраняет ее в базе данных SQLite. Теперь данные о закрытых сделках надежно фиксируются вне терминала.
Однако само по себе хранение данных не приносит особой пользы, если эти данные невозможно интерпретировать. В настоящее время система хранит бессистемный набор сделок и не имеет четкого механизма оценки эффективности. С помощью агрегирования и обобщения данных мы можем превратить эту необработанную информацию в полезные торговые инсайты.
В этой серии статей мы поставили перед собой цель создать систему торговой аналитики для MetaTrader 5. Мы уже создали уровни сбора, передачи и хранения данных. В этой заключительной части основное внимание уделяется использованию сохраненных данных для расчета значимых метрик эффективности и их представления в простой и доступной форме.
Здесь цель сугубо практическая. Мы расширим существующую аналитическую конечную точку, чтобы рассчитывать сводную статистику на основе сохраненных сделок и возвращать ее в формате JSON. Кроме того, мы обновим корневой маршрут API, чтобы он отображал минималистичную веб-страницу с этой статистикой для быстрого просмотра в браузере. Таким образом, система становится завершенной: сохраненные данные связываются с наглядным и удобным для использования представлением.
Необходимые условия
Прежде чем продолжить, убедитесь, что вы хорошо разбираетесь в следующих вопросах:
- Базовая разработка на Python и Flask. Вам необходимо понимать, как устроены маршруты, обработка запросов, ответы в формате JSON и простые запросы к базе данных.
- Знакомство с предыдущими частями этой серии. В этой части мы будем опираться на уже имеющийся советник, бэкенд на Flask и базу данных SQLite, созданные ранее.
- Базовые знания MetaTrader 5 и MQL5. В этой части вам не нужно существенно изменять советник-мост, но будет полезно понимать, как данные о сделках поступают в бэкенд.
- Базовые знания HTML и CSS. Мы создадим простую страницу в браузере для отображения сводной статистики. Опыт работы с фронтендом на продвинутом уровне не требуется.
- Рабочая локальная среда. Бэкенд Flask должен работать корректно, а база данных SQLite должна уже содержать записи о сделках или быть готова к их приему.
Краткий обзор текущей системы
Советник работает внутри MetaTrader 5 и отслеживает события закрытия сделок. Как только позиция закрывается, советник извлекает необходимую информацию о сделке, форматирует ее как JSON и передает в бэкенд по HTTP. Фиксация только завершенных сделок упрощает рабочий процесс на стороне бэкенда и позволяет избежать обработки данных о незавершенных позициях. Полная реализация этого советника-моста, разработанного ранее в части 2 данной серии, содержится в прилагаемом исходном файле tradeAnalyticsBridge.mq5.
Каждая запись о закрытой сделке содержит идентификаторы и поля результативности: символ; тикеты ордера, сделки и позиции; тип и причина открытия позиции; объем в лотах; цена входа; уровни стоп-лосса и тейк-профита; прибыль; время открытия и закрытия; а также магический номер. Эти поля дают полную картину каждой сделки и позволяют рассчитать значимые показатели эффективности.
После сбора данные форматируются как JSON и отправляются на сервер по HTTP. В частности, советник отправляет POST-запрос в конечную точку API. Это позволяет бэкенду получать структурированные данные в унифицированном формате, который легко разбирать и обрабатывать.
На стороне бэкенда приложение Flask принимает входящий запрос, проверяет полезную нагрузку и при необходимости преобразует данные в соответствующие типы. Затем обработанные данные сохраняются в базе данных SQLite. Каждая сделка записывается как строка в таблице trades, что обеспечивает постоянное хранение данных и доступ к ним для будущих запросов и анализа.
Роль советника Bridge
Советник Bridge обеспечивает связь между MetaTrader 5 и бэкендом Flask. Он выявляет закрытые позиции, извлекает их данные и отправляет записи о сделках в бэкенд для хранения и анализа.
Без него бэкенд не имел бы прямого доступа к данным о завершенной торговой активности, происходящей внутри терминала. Советник позволяет экспортировать за пределы MetaTrader 5 структурированные данные о завершенных сделках, такие как: символ; тип позиции; объем в лотах; цена входа; прибыль; временные метки; и идентификаторы тикетов.
Советник работает по событийной модели, используя обработчик события OnTradeTransaction. Каждый раз, когда позиция закрывается, советник фиксирует соответствующее торговое событие, считывает связанную с ним информацию о сделке из торговой истории и извлекает необходимые значения. К ним относятся: тикет ордера; тикет сделки; тикет позиции; символ; тип позиции; причина открытия позиции; стоп-лосс; тейк-профит; прибыль; время открытия; время закрытия; и магический номер.
После сбора обязательных полей советник форматирует данные как JSON и отправляет их в бэкенд с помощью HTTP POST-запроса через WebRequest. Это позволяет приложению Flask получать информацию о сделках в унифицированной структуре, которую можно проверить, преобразовать и сохранить в базе данных SQLite.
Чтобы использовать советник-мост, его необходимо добавить на график MetaTrader 5 и включить разрешения WebRequest для URL-адреса бэкенда. После запуска советник автоматически отслеживает закрытые позиции и передает записи о них в бэкенд всякий раз, когда сделка завершается.
Полная реализация этого компонента, ранее разработанного в части 2 данной серии, включена в прилагаемый исходный файл tradeAnalyticsBridge.mq5.
Как разобраться в сохраненных торговых данных
На данном этапе система способна собирать и сохранять данные о закрытых сделках. Хотя это и является важным шагом, сами по себе сохраненные данные не дают четкого представления о результатах торговли.
Просматривать записи по каждой сделке по отдельности нецелесообразно, особенно по мере увеличения количества сделок. Трейдер редко интересуется отдельной сделкой в отрыве от других. Вместо этого внимание обычно уделяется общим показателям эффективности, например количеству совершенных сделок, количеству прибыльных сделок и тому, приносит ли стратегия стабильные результаты.
Чтобы это стало возможным, необходимо агрегировать сохраненные данные. Это предполагает объединение отдельных записей сделок и расчет сводных показателей, характеризующих общие торговые результаты. В этой части серии мы воспользуемся сохраненными данными о сделках для расчета ряда простых показателей эффективности, которые позволяют получить более четкое представление о торговой деятельности.
Будут реализованы следующие показатели:
- Общее количество сделок: общее количество закрытых сделок, хранящихся в базе данных.
- Общая прибыль: сумма прибыли по всем сделкам.
- Прибыльные сделки: количество сделок, по которым прибыль превышает ноль.
- Убыточные сделки: количество сделок, по которым прибыль меньше нуля.
- Доля прибыльных сделок: отношение количества прибыльных сделок к общему количеству сделок.
- Средняя прибыль на сделку: общая прибыль, деленная на количество сделок.
- Средняя продолжительность сделки: среднее время между открытием и закрытием сделки.
- Максимальная продолжительность сделки: самая длительная зарегистрированная продолжительность сделки.
- Минимальная продолжительность сделки: самая короткая зарегистрированная продолжительность сделки.
Эти показатели рассчитываются непосредственно на основе сохраненных данных о сделках и дают компактную сводку по результатам без внесения ненужной сложности.
Разработка логики аналитики
На данном этапе нет необходимости менять структуру бэкенда. Введенных ранее эндпоинтов по-прежнему достаточно для расчета и представления торговой статистики. Цель здесь — расширить существующую логику, а не добавлять новые маршруты.
Конечная точка аналитики уже существует и определена так, чтобы возвращать ответ по адресу /api/v1/analytics/summary. В текущем виде эта конечная точка содержит логику-заглушку. В этой части эта заглушка будет заменена вычислениями на основе сохраненных данных о сделках. Конечная точка выполнит запрос к сохраненным записям, рассчитает сводные показатели, описанные в предыдущем разделе, и вернет результаты в виде ответа JSON.
Эта конечная точка по-прежнему служит машиночитаемым интерфейсом. Любая внешняя система, скрипт или инструмент может обратиться к этому маршруту и получить структурированные данные. Сохранение этой конечной точки в неизменном виде гарантирует, что API останется согласованным и пригодным для повторного использования.
Для отображения результатов в браузере мы будем использовать существующий корневой маршрут API по адресу /api/v1. Вместо того чтобы возвращать простое сообщение, этот маршрут будет формировать минимальную HTML-страницу, на которой те же сводные показатели представлены в удобочитаемом формате. Это позволяет избежать добавления дополнительных конечных точек и при этом обеспечивает возможность просматривать результаты напрямую.
Такой подход обеспечивает четкое разделение ответственности. Конечная точка аналитики отвечает за вычисление и возврат данных, тогда как корневой маршрут API отвечает за представление этих данных в простой визуальной форме. Логика остается централизованной, а общая архитектура — компактной и простой в сопровождении.
Реализация сводных показателей
Теперь мы реализуем сводные показатели внутри существующей конечной точки аналитики. Откройте файл app.py и найдите следующий маршрут:
@app.route("/api/v1/analytics/summary", methods=["GET"]) def analytics_summary():
Этот маршрут уже возвращает основную информацию, но логика по-прежнему минимальна. Мы расширим его, чтобы рассчитывать полный набор показателей эффективности, описанных ранее. Первый шаг — извлечь из базы данных все сохраненные записи о сделках:
trades = Trade.query.all()
Этот запрос возвращает список объектов Trade, каждый из которых представляет закрытую сделку. На основе этой коллекции мы можем вычислить агрегированные значения.
Расчет основных метрик
Первым делом необходимо определить, сколько сделок содержится в базе данных. Для этого подсчитывается количество объектов Trade, возвращенных запросом. Кроме того, мы рассчитываем общую прибыль, суммируя значение поля profit по всем сделкам. Эти два показателя дают общее представление о торговой активности и общей эффективности.
total_trades = len(trades) total_profit = sum(trade.profit for trade in trades)
Сделка считается прибыльной, если её прибыль больше нуля, и убыточной — если её прибыль меньше нуля. Эта классификация позволяет оценить, как часто сделки приносят прибыль или убытки.
Чтобы выполнить эту классификацию, мы проходим по списку сделок и подсчитываем, сколько из них удовлетворяют каждому условию. В приведенном ниже коде для эффективного вычисления этих количеств используются выражения-генераторы:
winning_trades = sum(1 for trade in trades if trade.profit > 0) losing_trades = sum(1 for trade in trades if trade.profit < 0)
Каждое выражение проверяет значение прибыли по каждой сделке и увеличивает счетчик при выполнении условия. В результате получаются два отдельных значения, отражающие количество прибыльных и убыточных сделок. Эти значения будут использованы позже для расчета дополнительных метрик эффективности, таких как доля прибыльных сделок.
Доля прибыльных сделок позволяет быстро оценить, как часто сделки приносят прибыль. Она рассчитывается как отношение прибыльных сделок к общему количеству сделок. Этот показатель позволяет обобщить результаты работы в виде одной цифры и широко используется для оценки стабильности.
Чтобы рассчитать долю прибыльных сделок, мы делим количество прибыльных сделок на общее количество сделок. Однако следует проявлять осторожность в тех случаях, когда в базе данных отсутствуют сделки. В таком случае деление на ноль привело бы к ошибке. Чтобы этого не произошло, мы добавляем простое условие, которое возвращает ноль, если общее количество сделок равно нулю.
Расчет выполняется следующим образом:
win_rate = (winning_trades / total_trades) if total_trades > 0 else 0
Это гарантирует, что вычисление остается безопасным и при этом возвращает допустимое значение. Полученную долю прибыльных сделок можно интерпретировать как пропорцию: более высокое значение указывает на больший процент прибыльных сделок.
Помимо доли прибыльных сделок, полезно понимать, какой вклад в среднем вносит каждая сделка. Для этого рассчитывается средняя прибыль на одну сделку, что дает простой показатель общей эффективности.
Средняя прибыль рассчитывается путем деления общей прибыли на количество сделок. Как и в предыдущем вычислении, нам необходимо учесть случай, когда сделок нет, чтобы избежать деления на ноль. Если сделок нет, значение устанавливается равным нулю.
Реализация выглядит следующим образом:
average_profit = (total_profit / total_trades) if total_trades > 0 else 0
Расчет метрик на основе времени
Каждая запись о сделке содержит как время открытия, так и время закрытия. Эти два значения можно использовать, чтобы определить, как долго удерживалась сделка. Эта продолжительность полезна при анализе торгового поведения, поскольку она помогает понять, насколько быстро открываются и закрываются позиции.
Для расчета продолжительности сделок мы вычитаем время открытия из времени закрытия каждой сделки. Эта операция возвращает разницу во времени, которая затем преобразуется в секунды для единообразия и упрощения вычислений. В результате получается список значений продолжительности, где каждое значение отражает время существования одной сделки.
Реализация выглядит следующим образом:
durations = [ (trade.close_time - trade.open_time).total_seconds() for trade in trades ]
Это списковое включение проходит по всем сделкам и вычисляет продолжительность каждой из них. Полученный список служит основой для дальнейших расчетов.
Как только данные о продолжительности становятся доступны, мы рассчитываем сводные показатели, характеризующие общее поведение времени удержания сделок. К ним относятся средняя продолжительность, а также максимальная и минимальная зафиксированные продолжительности:
average_duration = sum(durations) / len(durations) if durations else 0 max_duration = max(durations) if durations else 0 min_duration = min(durations) if durations else 0
Средняя продолжительность дает общее представление о том, как долго обычно удерживаются сделки. Максимальная продолжительность указывает на самую длительную зарегистрированную сделку, а минимальная — на самую короткую. В совокупности эти показатели дают краткое представление о временных характеристиках сделок без необходимости подробно изучать отдельные записи.
Итоговая реализация конечной точки
Далее мы объединяем расчёты в итоговой аналитической конечной точке. Она извлекает данные о сохраненных сделках, вычисляет сводные показатели и возвращает их в формате JSON.
Откройте файл app.py и найдите маршрут analytics. Замените его содержимое следующей реализацией:
@app.route("/api/v1/analytics/summary", methods=["GET"]) def analytics_summary(): trades = Trade.query.all() total_trades = len(trades) total_profit = sum(trade.profit for trade in trades) winning_trades = sum(1 for trade in trades if trade.profit > 0) losing_trades = sum(1 for trade in trades if trade.profit < 0) win_rate = (winning_trades / total_trades) if total_trades > 0 else 0 average_profit = (total_profit / total_trades) if total_trades > 0 else 0 durations = [ (trade.close_time - trade.open_time).total_seconds() for trade in trades ] average_duration = sum(durations) / len(durations) if durations else 0 max_duration = max(durations) if durations else 0 min_duration = min(durations) if durations else 0 summary = { "total_trades": total_trades, "total_profit": total_profit, "winning_trades": winning_trades, "losing_trades": losing_trades, "win_rate": win_rate, "average_profit": average_profit, "average_trade_duration": average_duration, "max_trade_duration": max_duration, "min_trade_duration": min_duration } return jsonify(summary), 200
В данной реализации все ранее определенные вычисления объединены в один ответ. Маршрут начинается с извлечения всех сохраненных сделок, после чего каждый показатель рассчитывается непосредственно на основе этих данных. Результаты сгруппированы в словарь, который возвращается в виде ответа в формате JSON.
На этом этапе аналитическая конечная точка полностью готова к работе. Эта конечная точка предоставляет краткую сводку результатов торговли, к которой можно получить доступ через браузер и которую могут использовать другие приложения. Это также подготавливает систему к следующему этапу, на котором эти же данные будут отображаться в простом веб-интерфейсе.
Тестирование конечной точки сводной аналитики
После реализации аналитической конечной точки проверьте её работу на реальных сохранённых сделках. Убедитесь, что в базе данных есть несколько закрытых сделок; если она пуста, откройте и закройте тестовые сделки в MetaTrader 5 и дайте советнику-мосту передать их на бэкенд.
В ходе тестирования я уже открыл и закрыл несколько сделок, и шесть записей о сделках были сохранены в базе данных SQLite. Это позволило получить достаточно данных, чтобы подтвердить, что конечная точка корректно считывает сохранённые записи и вычисляет сводные значения.
Выполните следующие действия, чтобы повторить тест.
Запустите Flask-бэкенд из каталога проекта:
flask --app app run --host 0.0.0.0 --debug
- Откройте MetaTrader 5 и прикрепите советник-мост только к одному графику.
- Откройте несколько тестовых сделок и закройте их. Каждая закрытая сделка должна передаваться в бэкенд и сохраняться в базе данных.
- Убедитесь в наличии записей, открыв в браузере конечную точку trades:
http://127.0.0.1:5000/api/v1/trades
Убедившись, что сделки сохранены, откройте конечную точку аналитики:
http://127.0.0.1:5000/api/v1/analytics/summary Браузер должен отобразить ответ в формате JSON, содержащий рассчитанные сводные показатели. В моём случае ответ подтвердил, что в базе данных было доступно шесть сделок и что конечная точка смогла рассчитать статистику на основе этих записей.

Это подтверждает, что конечная точка работает должным образом. Она извлекает сохранённые записи о сделках, выполняет расчёты метрик и возвращает результаты в структурированном формате JSON, который может использоваться браузером, скриптом или дашбордом.
Создание простого веб-дашборда для торговой аналитики
Теперь конечная точка аналитики возвращает сводные метрики в формате JSON. Это полезно для программных клиентов, но не является самым удобным способом визуального просмотра результатов. Чтобы результаты было проще читать в браузере, мы сформируем простой дашборд с помощью шаблонов Flask.
Мы не будем размещать HTML-код непосредственно в маршруте. Вместо этого мы вынесем структуру страницы и стили в отдельные файлы. Это помогает сохранить логику бэкенда более чистой и соответствует стандартной структуре проекта Flask.
Откройте терминал в каталоге проекта бэкенда:
cd mt5TradeAnalyticsBackend
Создайте папку с именем templates:
mkdir templates
В этой папке создайте HTML-файл:
touch templates/index.html
Далее создайте папку с именем static для файлов стилей:
mkdir static В папке static создайте таблицу стилей CSS:
touch static/style.css На данный момент проект должен содержать следующие новые файлы:
mt5TradeAnalyticsBackend/
app.py
templates/
index.html
static/
style.css Теперь откройте app.py и обновите строку импорта Flask, добавив render_template и url_for:
from flask import Flask, jsonify, request, redirect, render_template, url_for
Функция render_template позволяет Flask загружать HTML-файл из папки templates и передавать в него значения. Затем эти значения можно отобразить с помощью синтаксиса шаблонов Jinja. Функция url_for используется для создания динамических URL-адресов.
Далее найдите текущий корневой маршрут API:
@app.route("/api/v1")
def api_root():
return "<p>MT5 Trade Analytics API v1 is running.</p>" Мы обновим этот маршрут так, чтобы он вычислял те же сводные метрики и передавал их в файл index.html:
@app.route("/api/v1") def api_root(): trades = Trade.query.all() total_trades = len(trades) total_profit = sum(trade.profit for trade in trades) winning_trades = sum(1 for trade in trades if trade.profit > 0) losing_trades = sum(1 for trade in trades if trade.profit < 0) win_rate = (winning_trades / total_trades) if total_trades > 0 else 0 average_profit = (total_profit / total_trades) if total_trades > 0 else 0 durations = [ (trade.close_time - trade.open_time).total_seconds() for trade in trades ] average_duration = sum(durations) / len(durations) if durations else 0 max_duration = max(durations) if durations else 0 min_duration = min(durations) if durations else 0 return render_template( "index.html", total_trades=total_trades, total_profit=round(total_profit, 2), winning_trades=winning_trades, losing_trades=losing_trades, win_rate=round(win_rate * 100, 2), average_profit=round(average_profit, 2), average_duration=round(average_duration, 2), max_duration=round(max_duration, 2), min_duration=round(min_duration, 2) )
В этом маршруте по-прежнему используется существующая конечная точка /api/v1. Разница заключается в том, что теперь вместо обычного текстового сообщения возвращается HTML-дашборд.
Теперь откройте файл templates/index.html и добавьте структуру страницы:
<!DOCTYPE html> <html> <head> <title>MT5 Trade Analytics Dashboard</title> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> </head> <body> <div class="container"> <h1>MT5 Trade Analytics Dashboard</h1> <p class="subtitle">Summary statistics computed from stored closed trade records.</p> <div class="section"> <h2>Performance Summary</h2> <div class="grid"> <div class="card"> <span class="label">Total Trades</span> <strong>{{ total_trades }}</strong> </div> <div class="card"> <span class="label">Total Profit</span> <strong>{{ total_profit }}</strong> </div> <div class="card"> <span class="label">Win Rate</span> <strong>{{ win_rate }}%</strong> </div> </div> </div> <div class="section"> <h2>Trade Breakdown</h2> <div class="grid"> <div class="card"> <span class="label">Winning Trades</span> <strong>{{ winning_trades }}</strong> </div> <div class="card"> <span class="label">Losing Trades</span> <strong>{{ losing_trades }}</strong> </div> <div class="card"> <span class="label">Average Profit</span> <strong>{{ average_profit }}</strong> </div> </div> </div> <div class="section"> <h2>Trade Duration</h2> <div class="grid"> <div class="card"> <span class="label">Average Duration</span> <strong>{{ average_duration }} sec</strong> </div> <div class="card"> <span class="label">Maximum Duration</span> <strong>{{ max_duration }} sec</strong> </div> <div class="card"> <span class="label">Minimum Duration</span> <strong>{{ min_duration }} sec</strong> </div> </div> </div> </div> </body> </html>
Значения внутри двойных фигурных скобок — это заполнители, обрабатываемые Jinja. Когда Flask отрисовывает страницу, каждый заполнитель заменяется значением, переданным из маршрута api_root.
Наконец, откройте файл static/style.css и добавьте базовые стили:
body {
font-family: Arial, sans-serif;
background: #f5f7fa;
margin: 0;
padding: 40px;
}
.container {
max-width: 1000px;
margin: auto;
}
h1 {
margin-bottom: 8px;
color: #222;
}
.subtitle {
color: #666;
margin-bottom: 30px;
}
.section {
margin-bottom: 32px;
}
.section h2 {
color: #333;
margin-bottom: 14px;
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
.card {
background: white;
padding: 22px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.label {
display: block;
color: #666;
font-size: 14px;
margin-bottom: 8px;
}
.card strong {
color: #111;
font-size: 24px;
} Такое оформление позволяет сохранить лаконичность страницы и одновременно облегчить восприятие показателей. Дашборд состоит из разделов, посвящённых показателям эффективности, разбивке сделок и статистике продолжительности сделок. Каждый показатель отображается в виде карточки, что придаёт странице достаточную структурированность, не превращая её при этом в полноценный фронтенд-проект.
После этого обновления бэкенд теперь предоставляет два представления одной и той же рассчитанной статистики. Конечная точка /api/v1/analytics/summary возвращает JSON для программных клиентов, а /api/v1 отображает простой дашборд в браузере для быстрого визуального просмотра.
Тестирование веб-дашборда
Дашборд формируется с помощью маршрута /api/v1, который извлекает сохранённые записи о сделках, вычисляет те же сводные показатели и передаёт их в HTML-шаблон для отображения.
Выполните следующие действия, чтобы проверить дашборд:
- Убедитесь, что приложение Flask запущено:
flask --app app run --host 0.0.0.0 --debug
- Откройте браузер и перейдите по адресу:
http://127.0.0.1:5000/ - Корневой маршрут перенаправляет на:
http://127.0.0.1:5000/api/v1 - Страница дашборда должна загрузиться и отобразить сводные показатели в структурированном виде.
Если вы выполнили предыдущий тест, в базе данных уже должно быть несколько записей о сделках. В моём случае было сохранено шесть сделок, и на дашборде отображались соответствующие значения для общего количества сделок, прибыли, доли прибыльных сделок и показателей продолжительности сделок.

Чтобы убедиться в правильности результатов, сравните значения, отображаемые на дашборде, со значениями, которые возвращает:
http://127.0.0.1:5000/api/v1/analytics/summary Оба результата должны совпадать, поскольку они вычисляются на основе одних и тех же сохранённых данных.
Это подтверждает, что:
- Маршрут дашборда корректно рендерит HTML-шаблон.
- Бэкенд передаёт вычисленные значения в шаблон с помощью функции render_template.
- Отображаемые значения точно отражают сохранённые данные о сделках.
- Теперь система поддерживает как вывод данных в формате JSON для использования в API, так и просмотр в браузере для быстрого ознакомления.
На данный момент веб-дашборд полностью готов к работе и наглядно представляет рассчитанные торговые показатели.
Текущие ограничения
На данном этапе система успешно собирает, хранит и обобщает данные о закрытых сделках, а также представляет результаты как через конечные точки API, так и через простой веб-дашборд. Хотя на этом основной конвейер считается завершённым, в текущей реализации всё ещё имеется ряд ограничений.
- Логика проверки ориентирована на обязательные поля и базовое преобразование типов данных. Пока в ней не предусмотрены строгие ограничения значений, такие как допустимые диапазоны цен, размеров лота или временных меток.
- В API не реализованы аутентификация и контроль доступа. Все конечные точки находятся в открытом доступе, что может не подходить для развертывания за пределами локальной или контролируемой среды.
- Система обрабатывает каждый запрос со сделкой независимо, без механизмов повторных попыток или очередей. Если запрос завершится сбоем из-за проблем с сетью или сервером, данные могут быть утеряны, если это не обрабатывается внешними средствами.
- Конечная точка аналитики рассчитывает только основные сводные показатели. В данной реализации не предусмотрены более сложные статистические вычисления, фильтрация или анализ на основе времени.
- Веб-дашборд намеренно сделан минималистичным. Он предоставляет статическое представление метрик без интерактивных функций, графиков или обновлений в режиме реального времени.
- Бэкенд использует один файл базы данных SQLite. Хотя такая конфигурация вполне подходит для разработки и тестирования, она может оказаться недостаточно масштабируемой для высокочастотной торговли или многопользовательских сред.
Эти ограничения не влияют на корректность текущего конвейера, но указывают на направления для его совершенствования. Они задают чёткое направление для расширения системы в последующих итерациях.
Заключение
В этой заключительной части основное внимание уделялось работе с сохраненными торговыми данными и приведению их к пригодному для использования виду. Бэкенд был расширен, чтобы рассчитывать сводные показатели на основе имеющихся записей и предоставлять их как через конечную точку API, так и через простой веб-дашборд.
В данной статье были реализованы и проверены следующие функции:
- Запрос "GET /api/v1/analytics/summary" извлекает сохраненные записи о сделках, вычисляет сводные показатели и возвращает их в формате JSON.
- Рассчитанные показатели включают общее количество сделок, общую прибыль, процент прибыльных сделок, среднюю прибыль и статистику продолжительности сделок.
- Конечная точка была протестирована с использованием имеющихся в базе данных записей о сделках, что позволило подтвердить соответствие возвращаемых значений сохраненным данным.
- /api/v1 отображает веб-дашборд с помощью шаблонов Flask, представляя те же показатели в удобном для просмотра в браузере формате.
- Было подтверждено, что на дашборде отображаются те же значения, что и в ответе аналитической конечной точки.
Чтобы воспроизвести эти результаты, необходимо убедиться, что в базе данных сохранено несколько сделок, выполнить запрос GET /api/v1/analytics/summary для проверки вывода в формате JSON, а затем открыть /api/v1 для проверки отображения данных на дашборде.
На этом реализация, описанная в данной статье, завершена. Теперь бэкенд не только хранит данные о сделках, но и обобщает их, а также представляет в удобном для использования виде. В рамках всей серии это знаменует переход от простого сбора торговых данных к полноценному рабочему пайплайну торговой аналитики.
Прикрепленные файлы
В эту статью включены все файлы, необходимые для воспроизведения итоговой реализации системы торговой аналитики. В приложениях содержатся советник-мост для MetaTrader 5, исходный код бэкенда Flask, файлы дашборда и база данных SQLite, использовавшаяся в ходе тестирования.
В приведенной ниже таблице представлена краткая информация о прикрепленных файлах и их назначении.
| Название файла | Описание |
|---|---|
| tradeAnalyticsBridge.mq5 | Советник-мост для MetaTrader 5, отвечающий за обнаружение закрытых сделок, извлечение информации о сделках и передачу данных в бэкенд Flask с помощью HTTP-запросов. |
| app.py | Основной исходный файл бэкенда Flask, содержащий маршруты API, логику валидации, логику сохранения данных в базе, конечную точку аналитической сводки и логику отображения дашборда, разработанные в ходе этой серии статей. |
| mt5TradeAnalyticsBackend.zip | Полный каталог проекта бэкенда, содержащий приложение Flask, шаблоны, статические ресурсы, базу данных SQLite и все вспомогательные файлы, необходимые для локального запуска бэкенда. |
ZIP-архив также содержит следующие важные файлы проекта:
| Внутренний файл | Описание |
|---|---|
| mt5TradeAnalyticsBackend/templates/index.html | HTML-шаблон, используемый для отображения браузерного аналитического дашборда, представленного в этой части. |
| mt5TradeAnalyticsBackend/static/style.css | Таблица стилей CSS, используемая для задания макета дашборда и его визуального оформления. |
| mt5TradeAnalyticsBackend/instance/data.db | Файл базы данных SQLite, содержащий примеры записей о сделках, использованные в ходе тестирования и демонстраций отображения дашборда в этой статье. |
Эти файлы представляют собой полный рабочий эталонный пример окончательной реализации, разработанной в ходе всей серии.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/22449
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Особенности написания Пользовательских Индикаторов
От клонирования и коммитов к CI: Расширенные возможности MQL5 Algo Forge
Альтернатива тиковому объему: Измерение рыночной активности по интервалам ожидания между котировками
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования