Реализация отображения результатов бэктестинга в мобильном приложении
Бэктест запускается часами на сервере, перебирая исторические данные. Мобильное приложение получает готовые результаты и должно их показать так, чтобы трейдер понял: стратегия работает или нет, при каких условиях просаживается, насколько хуже реальной торговли.
Структура результатов бэктеста
Результат бэктеста — это не одно число PnL. Полный отчёт содержит:
{
"summary": {
"totalPnl": 4820.50,
"winRate": 0.62,
"profitFactor": 1.94,
"maxDrawdown": -0.183,
"sharpeRatio": 1.42,
"totalTrades": 847,
"avgTradeReturn": 0.0057,
"period": { "from": "2023-01-01", "to": "2024-01-01" }
},
"equityCurve": [
{ "ts": 1672531200, "equity": 10000.0 },
{ "ts": 1672617600, "equity": 10084.5 }
],
"trades": [...],
"monthlyBreakdown": [
{ "month": "2023-01", "pnl": 342.5, "trades": 68, "winRate": 0.59 }
],
"drawdownPeriods": [
{ "from": "2023-03-10", "to": "2023-03-25", "depth": -0.183 }
]
}
Объём equityCurve и trades может быть большим — 10,000+ точек за год поминутного бэктеста. Загружаем постранично: сначала summary и equity curve (основной экран), детальные сделки — по запросу пользователя.
Equity Curve и Drawdown
Два графика, которые отвечают на главный вопрос — «как вёл себя счёт»:
Equity Curve — рост начального капитала во времени. Идеально — плавная линия вверх. На практике — пилообразная с drawdown-периодами.
Drawdown — площадь под equity curve, показывающая насколько глубоко счёт падал от предыдущего максимума. Обычно показывают как отдельный график ниже equity curve. Красная область: чем глубже и длиннее — тем хуже.
На Flutter оба графика через fl_chart, LineChart с belowBarData для drawdown:
// Equity curve
LineChartBarData(
spots: equityCurve.map((p) => FlSpot(p.ts.toDouble(), p.equity)).toList(),
isCurved: false,
color: Colors.green,
barWidth: 1.5,
dotData: const FlDotData(show: false),
)
// Drawdown как отдельный LineChart с отрицательными значениями
// equityMax[i] = max(equity[0..i]), drawdown[i] = (equity[i] - equityMax[i]) / equityMax[i]
10,000 FlSpot — это много. На слабых устройствах рендеринг просядет. Решение: downsampling через LTTB-алгоритм (Largest Triangle Three Buckets) до 500–1000 точек. LTTB сохраняет визуальную форму кривой при кратном уменьшении числа точек.
Monthly Breakdown
Таблица по месяцам — быстрый способ увидеть сезонность стратегии:
| Месяц | PnL | Сделки | Win Rate |
|---|---|---|---|
| Янв 2023 | +342 USDT | 68 | 59% |
| Фев 2023 | +128 USDT | 71 | 54% |
| Мар 2023 | −280 USDT | 64 | 41% |
| ... |
Ячейки PnL с цветовой кодировкой: зелёный градиент для профитных месяцев, красный — для убыточных. Интенсивность цвета — нормализованная величина PnL относительно лучшего/худшего месяца.
Сравнение бэктестов
Пользователь запустил один бэктест с параметрами A и другой с параметрами B. Экран сравнения — два equity curve на одном графике плюс сводная таблица метрик.
// iOS — сравнение двух бэктестов
struct BacktestCompareView: View {
let testA: BacktestResult
let testB: BacktestResult
var body: some View {
VStack {
ComparisonChart(curveA: testA.equityCurve, curveB: testB.equityCurve)
ComparisonMetricsTable(rows: [
("Win Rate", testA.summary.winRate.pct, testB.summary.winRate.pct),
("Max DD", testA.summary.maxDrawdown.pct, testB.summary.maxDrawdown.pct),
("Profit Factor", testA.summary.profitFactor.fmt, testB.summary.profitFactor.fmt),
("Sharpe", testA.summary.sharpeRatio.fmt, testB.summary.sharpeRatio.fmt),
])
}
}
}
Что входит в работу
- Дашборд summary с ключевыми метриками
- Equity curve с LTTB-downsampling для производительности
- Drawdown chart
- Monthly breakdown таблица с цветовой кодировкой
- История сделок с пагинацией
- Экран сравнения двух бэктестов (опционально)
Сроки
5–8 рабочих дней в зависимости от набора графиков и наличия сравнения. Стоимость рассчитывается индивидуально после анализа требований.







