Jesse: крипто-алготрейдинг фреймворк с минутным движком на Python и Rust

Большинство open-source бэктестеров делятся на два лагеря: академические стеки, которые прекрасно тестируют, но непригодны для реальной торговли, и боевые терминалы, которые торгуют, но не дают нормально исследовать. Jesse пытается быть и тем, и другим — фреймворк для крипто-трейдинга с единым движком для бэктеста, оптимизации и (через плагин) живой торговли.
Под капотом — конкретные инженерные решения, которые стоит понять, прежде чем писать свою первую стратегию.
Архитектура: не библиотека, а контур
Jesse — это связка движка исполнения + API + UI:
- CLI (
jesse run) поднимает uvicorn с FastAPI - Роутеры для бэктеста, оптимизации, Monte Carlo, стратегий
- PostgreSQL через Peewee для хранения свечей
- LSP для редактора стратегий в браузерном UI
- Плагин jesse-live для реальной торговли (отдельный репозиторий)
Карта ответственности прямо зафиксирована в AGENTS.md: правка бэктеста может ударить по live, а изменения индикаторов на Rust требуют пересборки нативной части.
Минутная симуляция: «источник истины»

Критический инвариант Jesse зашит в assert: в бэктест можно передать только 1-минутные свечи. Если подсунете 5m-ряд — получите ValueError.
Почему это важно:
- Движок мыслит минутной сеткой. Старшие таймфреймы — это агрегаты: стратегия на 1h вызывается каждые 60 минут, но ордера исполняются внутри каждой минуты по high/low.
- Нет «параллельных миров данных». Все таймфреймы — виды одного потока, что уменьшает класс ошибок при смешивании дискретизаций.
- Предсказуемый детерминизм. Если несколько ордеров попадают в один high-low диапазон, они сортируются по эвристике (направление свечи), а не моделированием стакана.
from jesse.research import backtest
result = backtest(
config,
routes=[("Binance", "BTC-USDT", "4h", "MyStrategy")],
candles=candles_1m, # строго 60_000 мс между свечами
)
Перед каждым прогоном свечи копируются через deepcopy, а после — store.reset(). Один процесс может гнать сотни trials без накопления мусора в глобальном состоянии.
Strategy: конечный автомат с декларативными ордерами
Strategy — центральный класс Jesse. Несколько принципов, которые стоит знать:
Кэш цены
Внутри одного вызова _execute() цена фиксируется в _cached_price = self.close. Цена не «плавает» из-за побочных эффектов — защита от тонких гонок.
Декларативные ордера
Вместо императивного broker.buy(100) Jesse использует декларативный подход:
def go_long(self):
qty = utils.size_to_qty(self.balance * 0.5, self.price)
self.buy = qty, self.price # entry
self.stop_loss = qty, self.price * 0.97 # stop
self.take_profit = qty, self.price * 1.05 # target
Система сама решает: market, limit или stop — в зависимости от положения цены заявки относительно текущей. В live цена округляется по precision биржи.
Спот vs фьючерсы
take_profit/stop_loss внутри go_long() на споте запрещены — нужно переносить в on_open_position(). Это не придирка: маржинальная логика на споте и фьючерсах различается, и смешивание API привело бы к немым багам.
Фильтры с защитой от ошибок
def filters(self):
return [self.filter_1()]
def filters(self):
return [self.filter_1]
Jesse ловит эту ошибку и выдаёт готовый пример — мелочь, которая экономит часы в Discord.
Оптимизация: не максимум прибыли, а отсечение мусора
Функция пригодности (fitness) борется с переобучением на нескольких уровнях:
-
Минимум сделок. Если меньше 5 — конфигурация невалидна (score ≈ 0). Грубый, но рабочий фильтр против «стратегии из трёх сделок на удаче».
-
Нормализация объёма.
log10(total_trades)относительно оптимума, чтобы не раздувать вес количества. -
Выбор метрики. Sharpe, Calmar, Sortino, Omega, Serenity — каждая нормализуется своим диапазоном.
-
Двухэтапная проверка. Сначала оптимизация на training-свечах, затем бэктест на отдельном testing-периоде. Не «подогнали под одну кривую».
«Умный» Sharpe
Sharpe и Sortino имеют флаг smart: стандартное отклонение умножается на штраф за автокорреляцию доходностей. Идея: ряд, который выглядит «гладким», но зависит от прошлого, не должен получать тот же Sharpe, что и ряд ближе к IID.
Rust под капотом
Индикаторы (EMA, RSI, MACD, ATR…) массово используют jesse-rust. Даже базовая арифметика — subtract_floats, sum_floats — вынесена в Rust: накопление ошибки float на тысячах сделок превращает бэктест в фантастику.
Граница open-source и live
- Live-торговля подключается только через плагин
jesse-live(отдельный репозиторий, коммерческий). - В live баланс и маржа приходят с биржи, а не из симулятора.
- Часть логики стратегии отключается в live (
if jh.is_livetrading(): return).
Не копируйте вслепую ветки «не live» в продакшен.
Сильные стороны и ограничения
| ✅ Плюсы | ⚠️ Минусы |
|---|---|
| Единая минутная симуляция | Только крипто (нет акций, фьючерсов CME) |
| Чистый research API | Live — отдельный платный плагин |
| Rust в горячих местах | Фреймворк диктует свою дисциплину |
| Осмысленная функция оптимизации | Нет модели проскальзывания и ликвидности |
| Явное разделение live/sandbox | MIT лицензия не гарантирует поддержку |
Ссылки
- 💻 GitHub: jesse-ai/jesse
- 🌐 Сайт: jesse.trade
- 📦 Документация: docs.jesse.trade
- 📄 Лицензия: MIT
Вывод
Jesse — это попытка свести крипто-алготрейдинг к повторяемому контуру: минутный движок, строгий Strategy, Rust на индикаторах, research API без утечек, оптимизация с тестовым периодом. Репозиторий читается как учебник по тому, какие инварианты нужно зафиксировать, пока пользователи пишут «ещё одну стратегию в пять строк» — и где эти инварианты спасут от собственной уверенности в бэктесте.
MarketMaker.cc Team
Количественные исследования и стратегии