Разработка визуализации результатов бэктеста
Бэктест сам по себе — это набор цифр: equity curve, drawdown, Sharpe, win rate, список сделок. Без грамотной визуализации это непригодно для анализа. Разработчики алготрейдинговых платформ часто недооценивают эту часть и получают в итоге таблицу с тысячей строк, по которой невозможно понять, почему стратегия провалилась на конкретном периоде.
Ключевые компоненты визуализации
Equity Curve — основной график роста капитала по времени. Строится как line chart на базе TradingView Lightweight Charts или Recharts. Обязательно показываем на том же временном масштабе benchmark (BTC/ETH hold или индекс). Без benchmark equity curve ничего не говорит — стратегия могла вырасти на 40% пока рынок вырос на 200%.
Drawdown Chart — отдельный график под equity curve. Показывает текущую просадку от последнего исторического максимума в процентах. Вычисляется как:
const computeDrawdown = (equity: number[]): number[] => {
let peak = equity[0];
return equity.map((value) => {
if (value > peak) peak = value;
return ((value - peak) / peak) * 100;
});
};
Критически важно синхронизировать временную шкалу equity curve и drawdown — пользователь должен видеть одновременно: "вот здесь был drawdown -35%, и вот что происходило с ценой в этот момент".
Таблица сделок — виртуализированный список (react-virtual или TanStack Virtual) с сортировкой и фильтрацией. При тысячах сделок обычный DOM-рендеринг убивает производительность. Колонки: дата входа/выхода, направление (long/short), размер позиции, цена входа/выхода, P&L в абсолюте и процентах, комиссии.
Агрегированная статистика
Метрики разбиваем на несколько групп:
| Группа | Метрики |
|---|---|
| Доходность | Total Return, CAGR, Monthly Returns heatmap |
| Риск | Max Drawdown, Avg Drawdown Duration, VaR 95% |
| Качество | Sharpe Ratio, Sortino Ratio, Calmar Ratio |
| Торговля | Win Rate, Profit Factor, Avg Win/Loss, Max Consecutive Losses |
Monthly Returns Heatmap — особенно полезный компонент. Матрица год × месяц, каждая ячейка окрашена от красного (убыток) до зелёного (прибыль). Позволяет мгновенно увидеть сезонность и проблемные периоды.
// Структура данных для heatmap
type MonthlyReturn = {
year: number;
month: number; // 0-11
return: number; // в процентах
};
Реализуется через кастомный SVG-компонент или библиотеку типа @nivo/heatmap.
Интерактивность
Критичная функция: клик на любую точку equity curve должен раскрывать список сделок за этот период. Клик на строку сделки — подсвечивать её на графике цены маркером входа и выхода.
Это требует двунаправленной связи между компонентами: selection state в общем store (Zustand или Recoil), subscription на hover/click события в chart через LWC API, динамическая фильтрация таблицы.
Экспорт и шаринг
Пользователи хотят делиться результатами. Минимальный set: экспорт в CSV (таблица сделок), экспорт в PDF с ключевыми графиками и метриками (html2canvas + jsPDF), permalink на конкретный бэктест через hash-based state в URL.
Производительность с большими датасетами
При 50k+ точках на графике нативный rendering начинает тормозить. Стратегии:
- Decimation — при zoom-out показываем агрегированные данные (OHLC per day вместо per minute), при zoom-in — полную детализацию
- Web Worker — вычисление метрик и трансформация данных выносятся в воркер, чтобы не блокировать main thread
-
Incremental updates — если бэктест запускается в реальном времени и данные поступают потоком, обновляем последнюю точку через
series.update()вместо полногоsetData







