Сырые тики похожи на сырую муку: есть можно, но не хочется. Цена Биткоина в $68 500 сама по себе ничего не говорит алгоритму. Чтобы извлечь пользу, нужно посчитать, как эта цена соотносится с исторической волатильностью, риском и просадками.
Новички часто пытаются делать это в цикле for прямо внутри потока приёма данных. Получается медленно, с задержками, и бот пропускает нужный момент для сделки. Продвинутые торговые системы спускают тяжёлую математику в векторизованные библиотеки.
Одна из таких библиотек — finkit. Она с открытым исходным кодом, создана специально для быстрых расчётов над потоковыми рыночными данными.
Скользящее окно вместо бесконечного DataFrame
Первая проблема — перевести поток тиков в матрицу. Если тик приходит каждые 50 миллисекунд, добавлять строки в обычный pandas DataFrame — это постоянные перераспределения памяти.
В finkit используется Pre-Allocated Sliding DataFrame Wrapper. Это фиксированное по размеру окно, которое затирает старые индексы через операции в памяти без копирования. Создаётся просто: fk.DataFrame(max_rows=1000, columns=['timestamp', 'close', 'volume']). Дальше каждый тик добавляется через append_row().
Когда окно наполнилось, можно запускать расчёты.
Три метрики, которые спасают бота
Реализованная волатильность
Не та, что из дневной статистики, а интрадейная. Она показывает, как разброс цен меняется внутри дня, и позволяет подстраивать стоп-лоссы под текущий характер рынка.
Максимальная просадка
Самое большое падение от пика до минимума перед новым максимумом. Это защита от структурных обвалов, а не от шума.
Sharpe Ratio
Отношение избыточной доходности к волатильности. Если бот зарабатывает только потому, что агрессивно лезет в рискованные активы, Sharpe это покажет.
| Метрика | Что измеряет | Зачем нужна |
|---|---|---|
| Реализованная волатильность | Разброс доходности за скользящее окно | Динамически менять стоп-лоссы |
| Максимальная просадка (MDD) | Крупнейшее падение от пика до впадины | Защита от структурных крахов |
| Sharpe Ratio | Избыточная доходность на единицу риска | Отличить реальный альфа от перекоса в риск |
Формула Sharpe простая: (Rp - Rf) / sigma_p. Rp — доходность стратегии, Rf — безрисковая ставка, sigma_p — стандартное отклонение доходности.
Как это выглядит в коде
В finkit не нужно собирать формулу руками. Вызываете df.indicators.realized_volatility(window=60), df.risk.max_drawdown() и df.risk.sharpe_ratio(risk_free_rate=0.04). Последний метод принимает безрисковую ставку — в примере это 4% годовых.
Код получается компактным. Сначала проверяете, что окно наполнилось, затем запускаете execute_risk_metrics(data_frame). Внутри — один вызов на метрику и печать результата. Если просадка превысила порог, срабатывает аварийная остановка.
Индикаторный демон-сканер
Единичный скрипт — это хорошо, но для реальной работы нужен фоновый процесс. Идея в том, чтобы выделить отдельный демон, который слушает поток по нескольким активам, держит в памяти словарь DataFrame для каждого тикера и периодически запускает расчёты. Результаты уходят основному торговому боту через быстрые IPC-каналы.
Например, можно создать класс с реестром ticker → fk.DataFrame(max_rows=500). В цикле демон обходит все тикеры, обновляет окна и считает метрики. Когда просадка по какому-то активу превышает 15%, отправляется команда на ликвидацию.
Типичные ошибки
- Добавлять строки в неограниченный DataFrame. Память фрагментируется, производительность падает.
- Считать метрики на лету в потоке WebSocket. Лучше предварительно выделить окно и обновлять по готовности.
- Игнорировать безрисковую ставку в Sharpe. Сравнивать доходность с нулём бессмысленно, когда есть альтернатива с гарантией.
- Не задавать порог просадки. Бот без MDD-лимита пережидает обвал вместо выхода.
Рынок не прощает медленных расчётов. Переход от циклов к векторизованным библиотекам — это не оптимизация ради красоты, а вопрос того, успеет ли бот выйти из сделки до того, как цена улетит. finkit решает конкретную задачу: превращает сырые тики в метрики, с которыми уже можно принимать решения.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.