VIZANIXРазработка торгового ПО
Bybit APIBybit API9 мин чтения

Bybit V5 API: что на самом деле меняется при переезде бота

Одна модель аккаунта, один набор эндпоинтов и несколько деталей, которые тихо ломают ботов, перенесённых с прошлых версий.

Инженеры Vizanix · об авторе

МАТЕРИАЛ
9 минвремя чтения
РАЗДЕЛ
Bybit API
ОПУБЛИКОВАНО
2026-08-28
ГЛАВ
7
ЧИТАТЬ ДАЛЬШЕ
3
ЯЗЫК
написано на русском
Инженерный разбор, а не пересказ документации.
V5UNIFIED ACCOUNTRESTSIGNINGRECV_WINDOW

Bybit V5 свёл несколько параллельных API в одну поверхность. Для автора бота это в основном хорошая новость: одна схема подписи, одно пространство ошибок, одна модель аккаунта. Проблема в том, что при переезде ломается редко то, что видно на первом же запросе, — оно всплывает в три часа ночи, когда существует позиция, которую никто не планировал.

Сначала модель аккаунта

До первого запроса решите, с каким типом аккаунта работает бот. В Unified Trading Account спот, USDT-перпетуалы и опционы делят общий пул маржи. Это удобно — и это связность: убыточная позиция по перпетуалу уменьшает маржу, доступную всему остальному в аккаунте.

Для кода риска это принципиально. Бот, который считает доступную маржу как баланс кошелька минус мои собственные позиции, прав на выделенном аккаунте и не прав на едином, где человек может держать в том же пуле что-то ещё. Читайте баланс, который отдаёт биржа, а не восстанавливайте его.

Категория запроса — не косметика

Почти каждый эндпоинт V5 принимает параметр category: linear, spot, inverse, option. Он решает, в какой рынок попадёт запрос. Бот, у которого зашит linear, а потом его направляют на спотовый символ, не упадёт громко — он получит ошибку «инструмент не найден», похожую на опечатку в символе.

Держите категорию рядом с символом в реестре инструментов с самого начала. Выводить её потом из имени символа — гадание, которое ломается в первый же раз, когда площадка листит символ, существующий в двух категориях.

Подпись и двое часов

V5 подписывает строку, собранную из метки времени, ключа, recv-окна и тела запроса — именно в этом порядке. Два сценария дают большинство ошибок подписи:

  • Сериализация при подписи и при отправке различается. Если подпись строится по одному JSON-дампу, а HTTP-библиотека сериализует тело заново, порядок ключей или пробелы могут разойтись — и подпись не сойдётся. Подписывайте ровно те байты, которые отправляете.
  • Расхождение часов. Подпись несёт метку времени, и биржа отклоняет запросы за пределами recv_window. Сервер, у которого часы уходят на секунду-две, работает прекрасно — ровно до того момента, когда перестаёт.

Второе стоит измерять, а не предполагать. В нашем исполнителе под Bybit расхождение локального времени с биржевым пишется на каждом ответе и выводится в health: в нормальной работе оно держится примерно в пределах ±40 мс. Дрейф, который начал расти, виден задолго до того, как превратится в отклонённый ордер.

python
# Подписываем ровно то, что собираемся отправить.
raw = json.dumps(payload, separators=(",", ":"))   # одна каноническая форма
sign_payload = f"{ts}{api_key}{recv_window}{raw}"
signature = hmac.new(secret, sign_payload.encode(), hashlib.sha256).hexdigest()

resp = session.post(url, data=raw, headers={          # data=raw, а не json=payload
    "X-BAPI-API-KEY": api_key,
    "X-BAPI-TIMESTAMP": ts,
    "X-BAPI-RECV-WINDOW": recv_window,
    "X-BAPI-SIGN": signature,
    "Content-Type": "application/json",
})

Расширять recv_window, чтобы спрятать дрейф, — ловушка. Симптом действительно уходит, но заодно расширяется окно, в котором повторно отправленный запрос остаётся валидным. Чините часы: chrony или systemd-timesyncd ничего не стоят.

Фильтры инструмента решают, существует ли ваш ордер

У каждого символа есть фильтры: qtyStep, minOrderQty, tickSize, minNotionalValue. Объём, не прошедший любой из них, отклоняется. Обработать это легко и легко же ошибиться в мелочи:

  • Округляйте количество вниз до qtyStep, а не до ближайшего шага. Округление вверх может увести требуемую маржу за доступный баланс.
  • Округляйте цену до tickSize в консервативную для вашей стороны сторону: вниз для лимитной покупки, вверх для лимитной продажи.
  • Проверяйте minNotionalValue после округления, а не до. Округление вниз может увести под минимум.
  • Обновляйте таблицу фильтров периодически. Площадки меняют лотность, и фильтр, закэшированный в день деплоя, со временем начинает врать.

Маржа резервируется вместе с комиссиями

Это удивляет тех, кто переносит бота, считавшего объём «на 100% свободных средств». Биржа держит начальную маржу плюс комиссию по номиналу. Поэтому реальный потолок — не свободный баланс, а примерно свободные / (1 + плечо × ставка_комиссии). На 10× это около 99% баланса, на 50× ближе к 96%.

Бот, который это игнорирует, получает 110004 недостаточно средств ровно на тех ордерах, которые больше всего хотел поставить, — на крупных. Наш исполнитель решает это лестницей повторов: взять свежий остаток, ужать объём, переставить — до пяти попыток, останавливаясь на минимальном лоте биржи. Жёсткий отказ превращается в позицию поменьше, а это почти всегда то, чего оператор и хотел.

Коды ошибок — это поток управления, а не строчка в логе

V5 возвращает числовой retCode. Считать всё ненулевое «ошибкой, надо повторить» — именно так боты создают дублирующие позиции. Коды делятся на группы, требующие разного поведения:

ГруппаПримерПравильная реакция
Параметры и валидация10001, 170137Не повторять. Чинить запрос; алерт, если это неожиданно.
Авторизация и права10003, 10005, 10018Не повторять. Остановиться и позвать человека — обычно проблема в ключе или белом списке IP.
Лимит запросов10006Отступ с джиттером. Никогда не повторять в плотном цикле.
Баланс и риск-лимит110004, 110045Ужать объём и переставить либо отказаться от сигнала.
Идемпотентный no-op110043 плечо не измененоСчитать успехом. Нужное состояние уже достигнуто.
Таймаут и сервер10016Повторять только с клиентским ID ордера, затем сверяться.

Последняя строка — самая важная. Таймаут это не отказ, это неизвестность. Запрос мог исполниться. Повтор без клиентского ID ордера — это то, как бот получает две позиции там, где стратегия просила одну. Более полную карту мы держим в справочнике ошибок Bybit API.

Что писать первым

  1. Реестр инструментов с фильтрами и категорией, обновляемый по расписанию.
  2. Функцию подписи с тестом, сверяющим подпись с известным вектором.
  3. Метрику расхождения часов, выведенную в health.
  4. Классификатор ошибок, отображающий retCode в одно из поведений выше.
  5. И только потом — постановку ордеров.

Боты, написанные в этом порядке, скучны в эксплуатации. Боты, которые начинают с постановки ордера и добирают остальное под давлением, — это те, за которыми кто-то должен смотреть.

Статья описывает инженерную практику. Это не инвестиционная рекомендация. Vizanix разрабатывает программное обеспечение и не обещает торговую доходность.

Блог

Читать дальше

Хотите такое у себя?

Мы пишем о том, что строим. Если нужно построить — напишите, разбор бесплатный.

Бриф

Получить оценку проекта

Четыре вопроса и контакт. Предоплата для разговора не нужна — если задача не наша, скажем сразу.

01Что вам нужно
02Биржа
03Рынок
04Стратегия
05Контакты

Проще написать напрямую? Telegram @vx_ceo

Обсудить систему